Alireza.Moshtaghi at microchip.com
2009-Mar-13 19:21 UTC
[LLVMdev] promotion of return value.
Some targets want to do the promotion in the callee and some in the caller. Now what you are discussing in your bug is we shouldn't do in both... Now the tricky part is that many targets (not for the sake of promotion, but for the sake of performance) return a smaller value in a larger register (say if the function is to return char, they return it in 32 bit register); So they are effectively promoting the return value on the callee side, then the caller takes the part that it needs and again promotes it to comply with the rules of integer promotion stuff, hence double promotion. What we are trying to do is to add new attributes (more maybe added later):> sign_ext_from_i8, sign_ext_from_i16 > zero_ext_from_i8, zero_ext_from_i16to function definition so (assuming that both caller and callee are generated in the same front-end) the caller will know if the callee has already extended the return value or not, then it can promote only if needed. You may argue that this all can be done per a target-defined convention and I think that is the theory behind the patches that are used to fix your bug. However, we had this discussion last year, and it was decided to make things more transparent by adding the aforementioned attributes. Please look at the thread: http://www.nabble.com/Troubling-promotion-of-return-value-to-Integer-... -to17237327.html#a17237327 Regards, Ali> -----Original Message----- > From: llvmdev-bounces at cs.uiuc.edu [mailto:llvmdev-bounces at cs.uiuc.edu]On> Behalf Of Rafael Espindola > Sent: Friday, March 13, 2009 2:07 AM > To: LLVM Developers Mailing List > Subject: Re: [LLVMdev] promotion of return value. > > 2009/3/12 <Alireza.Moshtaghi at microchip.com>: > > What I was planning to do is to provide a default behavior that is > > consistent with what currently llvm does (promote to 32 bit) > > And then there will be control in clang for targets to do things > > differently. > > But I also understand you concern about gcc frontend; because thesame> > thing has to also take place there.... > > We had long discussions about this last year, and this is what hasbeen> > decided. Maybe Chris is in a better position to decide what to do. > > Can you take a look at my last post on the bug and see if that couldwork> for all the cases you have? Since llvm-gcc and clang are the onesdoing> the lowering, i think it would. Consider the code > > ---------------------- > short x; > void g(int); > short h(void); > short f(void) { > g(h()); > return x; > } > -------------------- > > For X86, I think llvm IL for f can be > ------------------------------------------ > define i16 @f() nounwind { > entry: > %0 = tail call i16 @h() nounwind > %1 = sext i16 %0 to i32 > tail call void @g(i32 %1) nounwind > %2 = load i16* @x, align 2 > ret i16 %2 > } > -------------------------------------- > > and for arm it can be > > ---------------------------------------- > define i32 @f() nounwind { > entry: > %0 = tail call i32 @h() nounwind > tail call void @g(i32 %0) nounwind > %2 = load i16* @x, align 2 > %3 = sext i16 %2 to i32 > ret i32 %3 > } > -------------------------------------- > > Note that for X86 only the caller does extension. For ARM only the > callee does it. > > > A. > > Cheers, > -- > Rafael Avila de Espindola > > Google | Gordon House | Barrow Street | Dublin 4 | Ireland > Registered in Dublin, Ireland | Registration Number: 368047 > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
2009/3/13 <Alireza.Moshtaghi at microchip.com>:> Some targets want to do the promotion in the callee and some in the > caller. Now what you are discussing in your bug is we shouldn't do in > both...exactly.> Now the tricky part is that many targets (not for the sake of promotion, > but for the sake of performance) return a smaller value in a larger > register (say if the function is to return char, they return it in 32 > bit register); > So they are effectively promoting the return value on the callee side, > then the caller takes the part that it needs and again promotes it to > comply with the rules of integer promotion stuff, hence double > promotion. > > What we are trying to do is to add new attributes (more maybe added > later): > >> sign_ext_from_i8, sign_ext_from_i16 >> zero_ext_from_i8, zero_ext_from_i16 > > to function definition so (assuming that both caller and callee are > generated in the same front-end) the caller will know if the callee has > already extended the return value or not, then it can promote only if > needed. > > You may argue that this all can be done per a target-defined convention > and I think that is the theory behind the patches that are used to fix > your bug. > However, we had this discussion last year, and it was decided to make > things more transparent by adding the aforementioned attributes. Please > look at the thread:My proposal is to make the extension as explicit as possible. If the callee is extending an char to an int, the generated llvm code should return an i32 and the caller can assume that the extension has been done. Are you saying that the decision to do the extension in the callee happens after we have generated llvm? That is, an optimization is transforming a function that would return an i8 into one that returns i16 or i32? Do you have a testcase for the problem you are trying to solve?> http://www.nabble.com/Troubling-promotion-of-return-value-to-Integer-... > -to17237327.html#a17237327I am sorry I missed the thread. I will take a look.> Regards, > AliCheers, -- Rafael Avila de Espindola Google | Gordon House | Barrow Street | Dublin 4 | Ireland Registered in Dublin, Ireland | Registration Number: 368047
Rafael Espindola a écrit :> My proposal is to make the extension as explicit as possible. If the > callee is extending an char to an int, the generated llvm code should > return an i32 and the caller can assume that the extension has been done. > > Are you saying that the decision to do the extension in the callee happens > after we have generated llvm? That is, an optimization is transforming > a function that would return an i8 into one that returns i16 or i32? > > Do you have a testcase for the problem you are trying to solve? >I think the problem was that some target don't support i32 natively (in hadware) like for exemple the PIC16. To force an extension to i32 is expensive on these target and may pose ABI compatibility problems. Anyways, i32 on 64 bits targets may be inefficient, so solving the problem in a more general way is better. Impossing i32 as *the* default size used by everyone is wrong. just my 2cents Cédric
Hi,> What we are trying to do is to add new attributes (more maybe added > later): > > > sign_ext_from_i8, sign_ext_from_i16 > > zero_ext_from_i8, zero_ext_from_i16 > > to function definition so (assuming that both caller and callee are > generated in the same front-end) the caller will know if the callee has > already extended the return value or not, then it can promote only if > needed.I don't understand what the point of this is. Surely this can all be handled by the calling convention and the signext/zeroext attributes? For example, suppose a function returns a short, but on the target that means being returned in an i32, with sign extension. Then in the IR the function is defined as returning an i16 with the signext attribute: define signext i16 @f(... The target calling convention specifies that i16's are returned in i32's. When code is generated for @f this means that you get something like: 0x2696eb8: i16,ch = ... <= the i16 value 0x2696fb0: i32 = sign_extend 0x2696eb8 <= sign extended to i32 0x26970a8: ch = ArgFlags < > 0x26971a0: ch = ret 0x2696ad8, 0x2696fb0, 0x26970a8 <= here returned Perfect! Ciao, Duncan.
Alireza.Moshtaghi at microchip.com
2009-Mar-16 18:38 UTC
[LLVMdev] promotion of return value.
Although ABIs define the calling convention to facilitate cross language function call on the same target, the rules of the game for return statement in C language is also somewhat influenced by the standard and it requirement for integer promotion, which makes it a language issue. (if you are interested, we can discuss this later) So in this particular issue, there is an overlap between ABI's calling convention and C language standard for return statement. This is not a definitive conclusion as whether we should implement return statement by the ABI's calling convention, or by the standard. However, if we consider practical issues such as functions without prototype, then using the proposed attributes makes it much easier to diagnose discrepancies in user code than if we were to rely only on the calling convention. For example, if a function without prototype is called, the caller assumes int as return value, and has no information on whether the callee has promoted the result or it is an actual int. But if we use these attributes, then the linker would be able to set the correct attribute on the call node once it sees the implementation of the callee, and later optimization on the return value promotion would be possible. By the way, I should refine my previous assumption... Caller and callee may very well be compiled in the different front-ends maybe even different languages. Regards Ali> -----Original Message----- > From: Duncan Sands [mailto:baldrick at free.fr] > Sent: Saturday, March 14, 2009 3:19 AM > To: llvmdev at cs.uiuc.edu > Cc: Alireza Moshtaghi - C13012 > Subject: Re: [LLVMdev] promotion of return value. > > Hi, > > > What we are trying to do is to add new attributes (more maybe added > > later): > > > > > sign_ext_from_i8, sign_ext_from_i16 > > > zero_ext_from_i8, zero_ext_from_i16 > > > > to function definition so (assuming that both caller and callee are > > generated in the same front-end) the caller will know if the calleehas> > already extended the return value or not, then it can promote onlyif> > needed. > > I don't understand what the point of this is. Surely this can all be > handled by the calling convention and the signext/zeroext attributes? > For example, suppose a function returns a short, but on the targetthat> means being returned in an i32, with sign extension. Then in the IRthe> function is defined as returning an i16 with the signext attribute: > > define signext i16 @f(... > > The target calling convention specifies that i16's are returned in > i32's. When code is generated for @f this means that you getsomething> like: > > 0x2696eb8: i16,ch = ... <= the i16 value > 0x2696fb0: i32 = sign_extend 0x2696eb8 <= sign extendedto> i32 > 0x26970a8: ch = ArgFlags < > > 0x26971a0: ch = ret 0x2696ad8, 0x2696fb0, 0x26970a8 <= here returned > > Perfect! > > Ciao, > > Duncan.