Arsenault, Matthew
2013-May-30 00:40 UTC
[LLVMdev] Expected behavior of calling bitcasted functions?
Hi, I'm not sure what the expected behavior of calling a bitcasted function is. Suppose you have a case like this (which you get on the source level from attribute alias): @alias_f32 = alias bitcast (i32 (i32)* @func_i32 to float (float)*) define internal i32 @func_i32(i32 %v) noinline nounwind { entry: ret i32 %v } define void @bitcast_alias_scalar(float* noalias %source, float* noalias %dest) nounwind { entry: %arrayidx = getelementptr float* %source, i32 0 %tmp2 = load float* %arrayidx, align 8 %call = call float @alias_f32(float %tmp2) nounwind %arrayidx8 = getelementptr float* %dest, i32 0 store float %call, float* %arrayidx8, align 8 ret void } If you run opt -instcombine on this, this transforms into define void @bitcast_alias_scalar(float* noalias %source, float* noalias %dest) nounwind { entry: %tmp2 = load float* %source, align 8 %0 = fptoui float %tmp2 to i32 %call = call i32 @func_i32(i32 %0) nounwind %1 = uitofp i32 %call to float store float %1, float* %dest, align 8 ret void } Note the fptoui / uitofp conversions to the underlying function's argument / return type. I would expect this to bitcast the arguments and call the underlying function. This transformation happens in InstCombiner::transformConstExprCastCall. This kind of thing almost seems intentional though from some of the comments and tests, so I'm not sure what's supposed to be going on. A conversion that changes the bits doesn't make any sense to me.
Pete Couperus
2013-May-30 13:12 UTC
[LLVMdev] Expected behavior of calling bitcasted functions?
Hello, This is an interesting example. Whenever I see strange things like this, I use opt's -lint. In this case, opt -lint reports: Undefined behavior: Call return type mismatches callee return type %call = call float @alias_f32(float %tmp2) #1 You'll get a similar report when the parameter types mismatch. Pete On Wed, May 29, 2013 at 5:40 PM, Arsenault, Matthew < Matthew.Arsenault at amd.com> wrote:> Hi, > > I'm not sure what the expected behavior of calling a bitcasted function > is. Suppose you have a case like this (which you get on the source level > from attribute alias): > > @alias_f32 = alias bitcast (i32 (i32)* @func_i32 to float (float)*) > > define internal i32 @func_i32(i32 %v) noinline nounwind { > entry: > ret i32 %v > } > > define void @bitcast_alias_scalar(float* noalias %source, float* noalias > %dest) nounwind { > entry: > %arrayidx = getelementptr float* %source, i32 0 > %tmp2 = load float* %arrayidx, align 8 > %call = call float @alias_f32(float %tmp2) nounwind > %arrayidx8 = getelementptr float* %dest, i32 0 > store float %call, float* %arrayidx8, align 8 > ret void > } > > If you run opt -instcombine on this, this transforms into > define void @bitcast_alias_scalar(float* noalias %source, float* noalias > %dest) nounwind { > entry: > %tmp2 = load float* %source, align 8 > %0 = fptoui float %tmp2 to i32 > %call = call i32 @func_i32(i32 %0) nounwind > %1 = uitofp i32 %call to float > store float %1, float* %dest, align 8 > ret void > } > > > Note the fptoui / uitofp conversions to the underlying function's argument > / return type. I would expect this to bitcast the arguments and call the > underlying function. This transformation happens in > InstCombiner::transformConstExprCastCall. This kind of thing almost seems > intentional though from some of the comments and tests, so I'm not sure > what's supposed to be going on. A conversion that changes the bits doesn't > make any sense to me. > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130530/9b04f436/attachment.html>
Matt Arsenault
2013-May-30 18:41 UTC
[LLVMdev] Expected behavior of calling bitcasted functions?
On 05/30/2013 06:12 AM, Pete Couperus wrote:> Hello, > > This is an interesting example. Whenever I see strange things like > this, I use opt's -lint. > In this case, opt -lint reports: > Undefined behavior: Call return type mismatches callee return type > %call = call float @alias_f32(float %tmp2) #1 > > You'll get a similar report when the parameter types mismatch. > > PeteIs it really supposed to be undefined? The tests are checking for specific behavior in these "undefined" cases. opt -lint < test/Transforms/InstCombine/call.ll Undefined behavior: Call argument type mismatches callee parameter type call void bitcast (void (i8*)* @test1a to void (i32*)*)(i32* %A) Undefined behavior: Call argument type mismatches callee parameter type call void bitcast (void (i8)* @test2a to void (i32)*)(i32 %A) Undefined behavior: Call return type mismatches callee return type %X = call i32 bitcast (i8 ()* @test4a to i32 ()*)() Undefined behavior: Call argument count mismatches callee argument count %X = call i32 bitcast (i32 (i32)* @test6a to i32 ()*)() Undefined behavior: Call argument count mismatches callee argument count call void bitcast (void ()* @test7a to void (i32)*)(i32 5) -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130530/bf6747e1/attachment.html>
Duncan Sands
2013-May-31 14:58 UTC
[LLVMdev] Expected behavior of calling bitcasted functions?
Hi Matthew, On 30/05/13 02:40, Arsenault, Matthew wrote:> Hi, > > I'm not sure what the expected behavior of calling a bitcasted function is. Suppose you have a case like this (which you get on the source level from attribute alias): > > @alias_f32 = alias bitcast (i32 (i32)* @func_i32 to float (float)*) > > define internal i32 @func_i32(i32 %v) noinline nounwind { > entry: > ret i32 %v > } > > define void @bitcast_alias_scalar(float* noalias %source, float* noalias %dest) nounwind { > entry: > %arrayidx = getelementptr float* %source, i32 0 > %tmp2 = load float* %arrayidx, align 8 > %call = call float @alias_f32(float %tmp2) nounwind > %arrayidx8 = getelementptr float* %dest, i32 0 > store float %call, float* %arrayidx8, align 8 > ret void > } > > If you run opt -instcombine on this, this transforms into > define void @bitcast_alias_scalar(float* noalias %source, float* noalias %dest) nounwind { > entry: > %tmp2 = load float* %source, align 8 > %0 = fptoui float %tmp2 to i32 > %call = call i32 @func_i32(i32 %0) nounwind > %1 = uitofp i32 %call to float > store float %1, float* %dest, align 8 > ret void > } > > > Note the fptoui / uitofp conversions to the underlying function's argument / return type. I would expect this to bitcast the arguments and call the underlying function. This transformation happens in InstCombiner::transformConstExprCastCall. This kind of thing almost seems intentional though from some of the comments and tests, so I'm not sure what's supposed to be going on. A conversion that changes the bits doesn't make any sense to me.I would also expect bitcast to be used here. This may just be a bug. Ciao, Duncan.
Reasonably Related Threads
- [LLVMdev] Expected behavior of calling bitcasted functions?
- [LLVMdev] Expected behavior of calling bitcasted functions?
- [LLVMdev] [PATCH] Protection against stack-based memory corruption errors using SafeStack
- [LLVMdev] Function pointers bitcasted to varargs
- [LLVMdev] Function pointers bitcasted to varargs