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.

llvm-svn: 190885
This commit is contained in:
Matt Arsenault 2013-09-17 21:10:14 +00:00
parent cccf2cc8c1
commit e6952f28ca
2 changed files with 150 additions and 25 deletions

View File

@ -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()) {

View File

@ -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
}