From: Matt Arsenault Date: Tue, 17 Sep 2013 21:10:14 +0000 (+0000) Subject: Cleanup handling of constant function casts. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=3e1c40de7f33db639698982bb58d8c2c8d7d5780;p=oota-llvm.git Cleanup handling of constant function casts. Some of this code is no longer necessary since int<->ptr casts are no longer occur as of r187444. This also fixes handling vectors of pointers, and adds a bunch of new testcases for vectors and address spaces. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190885 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 9f74fd6b8d0..beb63e8d53d 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -999,20 +999,15 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { // Check to see if we are changing the return type... if (OldRetTy != NewRetTy) { - if (Callee->isDeclaration() && - // Conversion is ok if changing from one pointer type to another or from - // a pointer to an integer of the same size. - !((OldRetTy->isPointerTy() || !TD || - OldRetTy == TD->getIntPtrType(Caller->getContext())) && - (NewRetTy->isPointerTy() || !TD || - NewRetTy == TD->getIntPtrType(Caller->getContext())))) - return false; // Cannot transform this return value. + if (!CastInst::isBitCastable(NewRetTy, OldRetTy)) { + if (Callee->isDeclaration()) + return false; // Cannot transform this return value. - if (!Caller->use_empty() && - // void -> non-void is handled specially - !NewRetTy->isVoidTy() && - !CastInst::isBitCastable(NewRetTy, OldRetTy)) + if (!Caller->use_empty() && + // void -> non-void is handled specially + !NewRetTy->isVoidTy()) return false; // Cannot transform this return value. + } if (!CallerPAL.isEmpty() && !Caller->use_empty()) { AttrBuilder RAttrs(CallerPAL, AttributeSet::ReturnIndex); @@ -1045,9 +1040,8 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { Type *ParamTy = FT->getParamType(i); Type *ActTy = (*AI)->getType(); - if (!CastInst::isBitCastable(ActTy, ParamTy)) { + if (!CastInst::isBitCastable(ActTy, ParamTy)) return false; // Cannot transform this parameter value. - } if (AttrBuilder(CallerPAL.getParamAttributes(i + 1), i + 1). hasAttributes(AttributeFuncs:: @@ -1068,16 +1062,6 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { TD->getTypeAllocSize(ParamPTy->getElementType())) return false; } - - // Converting from one pointer type to another or between a pointer and an - // integer of the same size is safe even if we do not have a body. - bool isConvertible = ActTy == ParamTy || - (TD && ((ParamTy->isPointerTy() || - ParamTy == TD->getIntPtrType(Caller->getContext())) && - (ActTy->isPointerTy() || - ActTy == TD->getIntPtrType(Caller->getContext())))); - if (Callee->isDeclaration() && !isConvertible) - return false; } if (Callee->isDeclaration()) { diff --git a/test/Transforms/InstCombine/call.ll b/test/Transforms/InstCombine/call.ll index 55833fbd1c6..e68c0ad9b20 100644 --- a/test/Transforms/InstCombine/call.ll +++ b/test/Transforms/InstCombine/call.ll @@ -1,7 +1,7 @@ ; Ignore stderr, we expect warnings there ; RUN: opt < %s -instcombine 2> /dev/null -S | FileCheck %s -target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" +target datalayout = "E-p:64:64:64-p1:16:16:16-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" ; Simple case, argument translatable without changing the value declare void @test1a(i8*) @@ -15,6 +15,28 @@ define void @test1(i32* %A) { ret void } + +; Should not do because of change in address space of the parameter +define void @test1_as1_illegal(i32 addrspace(1)* %A) { +; CHECK-LABEL: @test1_as1_illegal( +; CHECK: call void bitcast + call void bitcast (void (i8*)* @test1a to void (i32 addrspace(1)*)*)(i32 addrspace(1)* %A) + ret void +} + +; Test1, but the argument has a different sized address-space +declare void @test1a_as1(i8 addrspace(1)*) + +; This one is OK to perform +define void @test1_as1(i32 addrspace(1)* %A) { +; CHECK-LABEL: @test1_as1( +; CHECK: %1 = bitcast i32 addrspace(1)* %A to i8 addrspace(1)* +; CHECK: call void @test1a_as1(i8 addrspace(1)* %1) +; CHECK: ret void + call void bitcast (void (i8 addrspace(1)*)* @test1a_as1 to void (i32 addrspace(1)*)*)(i32 addrspace(1)* %A ) + ret void +} + ; More complex case, translate argument because of resolution. This is safe ; because we have the body of the function define void @test2a(i8 %A) { @@ -135,3 +157,122 @@ entry: ; CHECK: call i8* bitcast } + +; Parameter that's a vector of pointers +declare void @test10a(<2 x i8*>) + +define void @test10(<2 x i32*> %A) { +; CHECK-LABEL: @test10( +; CHECK: %1 = bitcast <2 x i32*> %A to <2 x i8*> +; CHECK: call void @test10a(<2 x i8*> %1) +; CHECK: ret void + call void bitcast (void (<2 x i8*>)* @test10a to void (<2 x i32*>)*)(<2 x i32*> %A) + ret void +} + +; Don't transform because different address spaces +declare void @test10a_mixed_as(<2 x i8 addrspace(1)*>) + +define void @test10_mixed_as(<2 x i8*> %A) { +; CHECK-LABEL: @test10_mixed_as( +; CHECK: call void bitcast + call void bitcast (void (<2 x i8 addrspace(1)*>)* @test10a_mixed_as to void (<2 x i8*>)*)(<2 x i8*> %A) + ret void +} + +; Return type that's a pointer +define i8* @test11a() { + ret i8* zeroinitializer +} + +define i32* @test11() { +; CHECK-LABEL: @test11( +; CHECK: %X = call i8* @test11a() +; CHECK: %1 = bitcast i8* %X to i32* + %X = call i32* bitcast (i8* ()* @test11a to i32* ()*)() + ret i32* %X +} + +; Return type that's a pointer with a different address space +define i8 addrspace(1)* @test11a_mixed_as() { + ret i8 addrspace(1)* zeroinitializer +} + +define i8* @test11_mixed_as() { +; CHECK-LABEL: @test11_mixed_as( +; CHECK: call i8* bitcast + %X = call i8* bitcast (i8 addrspace(1)* ()* @test11a_mixed_as to i8* ()*)() + ret i8* %X +} + +; Return type that's a vector of pointers +define <2 x i8*> @test12a() { + ret <2 x i8*> zeroinitializer +} + +define <2 x i32*> @test12() { +; CHECK-LABEL: @test12( +; CHECK: %X = call <2 x i8*> @test12a() +; CHECK: %1 = bitcast <2 x i8*> %X to <2 x i32*> + %X = call <2 x i32*> bitcast (<2 x i8*> ()* @test12a to <2 x i32*> ()*)() + ret <2 x i32*> %X +} + +define <2 x i8 addrspace(1)*> @test12a_mixed_as() { + ret <2 x i8 addrspace(1)*> zeroinitializer +} + +define <2 x i8*> @test12_mixed_as() { +; CHECK-LABEL: @test12_mixed_as( +; CHECK: call <2 x i8*> bitcast + %X = call <2 x i8*> bitcast (<2 x i8 addrspace(1)*> ()* @test12a_mixed_as to <2 x i8*> ()*)() + ret <2 x i8*> %X +} + + +; Mix parameter that's a vector of integers and pointers of the same size +declare void @test13a(<2 x i64>) + +define void @test13(<2 x i32*> %A) { +; CHECK-LABEL: @test13( +; CHECK: call void bitcast + call void bitcast (void (<2 x i64>)* @test13a to void (<2 x i32*>)*)(<2 x i32*> %A) + ret void +} + +; Mix parameter that's a vector of integers and pointers of the same +; size, but the other way around +declare void @test14a(<2 x i8*>) + +define void @test14(<2 x i64> %A) { +; CHECK-LABEL: @test14( +; CHECK: call void bitcast + call void bitcast (void (<2 x i8*>)* @test14a to void (<2 x i64>)*)(<2 x i64> %A) + ret void +} + + +; Return type that's a vector +define <2 x i16> @test15a() { + ret <2 x i16> zeroinitializer +} + +define i32 @test15() { +; CHECK-LABEL: @test15( +; CHECK: %X = call <2 x i16> @test15a() +; CHECK: %1 = bitcast <2 x i16> %X to i32 + %X = call i32 bitcast (<2 x i16> ()* @test15a to i32 ()*)( ) + ret i32 %X +} + +define i32 @test16a() { + ret i32 0 +} + +define <2 x i16> @test16() { +; CHECK-LABEL: @test16( +; CHECK: %X = call i32 @test16a() +; CHECK: %1 = bitcast i32 %X to <2 x i16> + %X = call <2 x i16> bitcast (i32 ()* @test16a to <2 x i16> ()*)( ) + ret <2 x i16> %X +}