diff options
Diffstat (limited to 'test/Transforms/InstCombine')
39 files changed, 840 insertions, 124 deletions
diff --git a/test/Transforms/InstCombine/2003-09-09-VolatileLoadElim.ll b/test/Transforms/InstCombine/2003-09-09-VolatileLoadElim.ll index 3297919..7f73908 100644 --- a/test/Transforms/InstCombine/2003-09-09-VolatileLoadElim.ll +++ b/test/Transforms/InstCombine/2003-09-09-VolatileLoadElim.ll @@ -2,6 +2,6 @@ define void @test(i32* %P) { ; Dead but not deletable! - %X = volatile load i32* %P ; <i32> [#uses=0] + %X = load volatile i32* %P ; <i32> [#uses=0] ret void } diff --git a/test/Transforms/InstCombine/2007-09-11-Trampoline.ll b/test/Transforms/InstCombine/2007-09-11-Trampoline.ll deleted file mode 100644 index 6190aa9..0000000 --- a/test/Transforms/InstCombine/2007-09-11-Trampoline.ll +++ /dev/null @@ -1,24 +0,0 @@ -; RUN: opt < %s -instcombine -S | grep {call i32 @f} - - %struct.FRAME.nest = type { i32, i32 (i32)* } - %struct.__builtin_trampoline = type { [10 x i8] } - -declare i8* @llvm.init.trampoline(i8*, i8*, i8*) - -declare i32 @f(%struct.FRAME.nest* nest , i32 ) - -define i32 @nest(i32 %n) { -entry: - %FRAME.0 = alloca %struct.FRAME.nest, align 8 ; <%struct.FRAME.nest*> [#uses=3] - %TRAMP.216 = alloca [10 x i8], align 16 ; <[10 x i8]*> [#uses=1] - %TRAMP.216.sub = getelementptr [10 x i8]* %TRAMP.216, i32 0, i32 0 ; <i8*> [#uses=1] - %tmp3 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 0 ; <i32*> [#uses=1] - store i32 %n, i32* %tmp3, align 8 - %FRAME.06 = bitcast %struct.FRAME.nest* %FRAME.0 to i8* ; <i8*> [#uses=1] - %tramp = call i8* @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest* , i32)* @f to i8*), i8* %FRAME.06 ) ; <i8*> [#uses=1] - %tmp7 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 1 ; <i32 (i32)**> [#uses=1] - %tmp89 = bitcast i8* %tramp to i32 (i32)* ; <i32 (i32)*> [#uses=2] - store i32 (i32)* %tmp89, i32 (i32)** %tmp7, align 8 - %tmp2.i = call i32 %tmp89( i32 1 ) ; <i32> [#uses=1] - ret i32 %tmp2.i -} diff --git a/test/Transforms/InstCombine/2007-10-28-stacksave.ll b/test/Transforms/InstCombine/2007-10-28-stacksave.ll index 76bceb6..4c5c367 100644 --- a/test/Transforms/InstCombine/2007-10-28-stacksave.ll +++ b/test/Transforms/InstCombine/2007-10-28-stacksave.ll @@ -26,7 +26,7 @@ lab: ; preds = %cleanup31, %entry %tmp21 = getelementptr i32* %tmp1819, i32 0 ; <i32*> [#uses=1] store i32 1, i32* %tmp21, align 4 %tmp2223 = bitcast i32* %tmp1819 to i8* ; <i8*> [#uses=1] - volatile store i8* %tmp2223, i8** @p, align 4 + store volatile i8* %tmp2223, i8** @p, align 4 %tmp25 = add i32 %n.0, 1 ; <i32> [#uses=2] %tmp27 = icmp sle i32 %tmp25, 999999 ; <i1> [#uses=1] %tmp2728 = zext i1 %tmp27 to i8 ; <i8> [#uses=1] diff --git a/test/Transforms/InstCombine/2008-01-14-DoubleNest.ll b/test/Transforms/InstCombine/2008-01-14-DoubleNest.ll deleted file mode 100644 index 6401dfd..0000000 --- a/test/Transforms/InstCombine/2008-01-14-DoubleNest.ll +++ /dev/null @@ -1,24 +0,0 @@ -; RUN: opt < %s -instcombine -disable-output - - %struct.FRAME.nest = type { i32, i32 (i32*)* } - %struct.__builtin_trampoline = type { [10 x i8] } - -declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind - -declare i32 @f(%struct.FRAME.nest* nest , i32*) - -define i32 @nest(i32 %n) { -entry: - %FRAME.0 = alloca %struct.FRAME.nest, align 8 ; <%struct.FRAME.nest*> [#uses=3] - %TRAMP.216 = alloca [10 x i8], align 16 ; <[10 x i8]*> [#uses=1] - %TRAMP.216.sub = getelementptr [10 x i8]* %TRAMP.216, i32 0, i32 0 ; <i8*> [#uses=1] - %tmp3 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 0 ; <i32*> [#uses=1] - store i32 %n, i32* %tmp3, align 8 - %FRAME.06 = bitcast %struct.FRAME.nest* %FRAME.0 to i8* ; <i8*> [#uses=1] - %tramp = call i8* @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest*, i32*)* @f to i8*), i8* %FRAME.06 ) ; <i8*> [#uses=1] - %tmp7 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 1 ; <i32 (i32*)**> [#uses=1] - %tmp89 = bitcast i8* %tramp to i32 (i32*)* ; <i32 (i32*)*> [#uses=2] - store i32 (i32*)* %tmp89, i32 (i32*)** %tmp7, align 8 - %tmp2.i = call i32 %tmp89( i32* nest null ) ; <i32> [#uses=1] - ret i32 %tmp2.i -} diff --git a/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll b/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll index 6847f5e..de08c32 100644 --- a/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll +++ b/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll @@ -2,7 +2,7 @@ define void @test() { %votf = alloca <4 x float> ; <<4 x float>*> [#uses=1] - volatile store <4 x float> zeroinitializer, <4 x float>* %votf, align 16 + store volatile <4 x float> zeroinitializer, <4 x float>* %votf, align 16 ret void } diff --git a/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll b/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll index a24f307..1286e3d 100644 --- a/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll +++ b/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll @@ -6,17 +6,17 @@ target triple = "i386-apple-darwin8" define i32 @main() nounwind { entry: %tmp93 = icmp slt i32 0, 10 ; <i1> [#uses=0] - %tmp34 = volatile load i32* @g_1, align 4 ; <i32> [#uses=1] + %tmp34 = load volatile i32* @g_1, align 4 ; <i32> [#uses=1] br label %bb bb: ; preds = %bb, %entry %b.0.reg2mem.0 = phi i32 [ 0, %entry ], [ %tmp6, %bb ] ; <i32> [#uses=1] %tmp3.reg2mem.0 = phi i32 [ %tmp34, %entry ], [ %tmp3, %bb ] ; <i32> [#uses=1] %tmp4 = add i32 %tmp3.reg2mem.0, 5 ; <i32> [#uses=1] - volatile store i32 %tmp4, i32* @g_1, align 4 + store volatile i32 %tmp4, i32* @g_1, align 4 %tmp6 = add i32 %b.0.reg2mem.0, 1 ; <i32> [#uses=2] %tmp9 = icmp slt i32 %tmp6, 10 ; <i1> [#uses=1] - %tmp3 = volatile load i32* @g_1, align 4 ; <i32> [#uses=1] + %tmp3 = load volatile i32* @g_1, align 4 ; <i32> [#uses=1] br i1 %tmp9, label %bb, label %bb11 bb11: ; preds = %bb diff --git a/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll b/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll index 5fb11ff..ebbd3a7 100644 --- a/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll +++ b/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll @@ -7,11 +7,11 @@ target triple = "i386-apple-darwin8" define i32 @main(i32 %i) nounwind { entry: %tmp93 = icmp slt i32 %i, 10 ; <i1> [#uses=0] - %tmp34 = volatile load i32* @g_1, align 4 ; <i32> [#uses=1] + %tmp34 = load volatile i32* @g_1, align 4 ; <i32> [#uses=1] br i1 %tmp93, label %bb11, label %bb bb: ; preds = %bb, %entry - %tmp3 = volatile load i32* @g_1, align 4 ; <i32> [#uses=1] + %tmp3 = load volatile i32* @g_1, align 4 ; <i32> [#uses=1] br label %bb11 bb11: ; preds = %bb diff --git a/test/Transforms/InstCombine/2008-06-24-StackRestore.ll b/test/Transforms/InstCombine/2008-06-24-StackRestore.ll index 8307834..4f4709b 100644 --- a/test/Transforms/InstCombine/2008-06-24-StackRestore.ll +++ b/test/Transforms/InstCombine/2008-06-24-StackRestore.ll @@ -10,7 +10,7 @@ entry: %tmp2752 = alloca i32 ; <i32*> [#uses=2] %tmpcast53 = bitcast i32* %tmp2752 to i8* ; <i8*> [#uses=1] store i32 2, i32* %tmp2752, align 4 - volatile store i8* %tmpcast53, i8** @p, align 4 + store volatile i8* %tmpcast53, i8** @p, align 4 br label %bb44 bb: ; preds = %bb44 @@ -29,7 +29,7 @@ bb44: ; preds = %bb44, %entry store i32 1, i32* %tmp27, align 4 %tmp34 = getelementptr i32* %tmp27, i32 %tmp4 ; <i32*> [#uses=1] store i32 2, i32* %tmp34, align 4 - volatile store i8* %tmpcast, i8** @p, align 4 + store volatile i8* %tmpcast, i8** @p, align 4 %exitcond = icmp eq i32 %tmp3857, 999999 ; <i1> [#uses=1] br i1 %exitcond, label %bb, label %bb44 } diff --git a/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll b/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll index 8104408..1ed5323 100644 --- a/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll +++ b/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll @@ -7,17 +7,17 @@ target triple = "i386-apple-darwin8" define i32 @main() nounwind { entry: %tmp93 = icmp slt i32 0, 10 ; <i1> [#uses=0] - %tmp34 = volatile load i32* @g_1, align 4 ; <i32> [#uses=1] + %tmp34 = load volatile i32* @g_1, align 4 ; <i32> [#uses=1] br label %bb bb: ; preds = %bb, %entry %b.0.reg2mem.0 = phi i32 [ 0, %entry ], [ %tmp6, %bb ] ; <i32> [#uses=1] %tmp3.reg2mem.0 = phi i32 [ %tmp3, %bb ], [ %tmp34, %entry ] %tmp4 = add i32 %tmp3.reg2mem.0, 5 ; <i32> [#uses=1] - volatile store i32 %tmp4, i32* @g_1, align 4 + store volatile i32 %tmp4, i32* @g_1, align 4 %tmp6 = add i32 %b.0.reg2mem.0, 1 ; <i32> [#uses=2] %tmp9 = icmp slt i32 %tmp6, 10 ; <i1> [#uses=1] - %tmp3 = volatile load i32* @g_1, align 4 ; <i32> [#uses=1] + %tmp3 = load volatile i32* @g_1, align 4 ; <i32> [#uses=1] br i1 %tmp9, label %bb, label %bb11 bb11: ; preds = %bb diff --git a/test/Transforms/InstCombine/2012-01-11-OpaqueBitcastCrash.ll b/test/Transforms/InstCombine/2012-01-11-OpaqueBitcastCrash.ll new file mode 100644 index 0000000..abab9dc --- /dev/null +++ b/test/Transforms/InstCombine/2012-01-11-OpaqueBitcastCrash.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -instcombine -disable-output + +%opaque_struct = type opaque + +@G = external global [0 x %opaque_struct] + +declare void @foo(%opaque_struct*) + +define void @bar() { + call void @foo(%opaque_struct* bitcast ([0 x %opaque_struct]* @G to %opaque_struct*)) + ret void +} diff --git a/test/Transforms/InstCombine/2012-02-13-FCmp.ll b/test/Transforms/InstCombine/2012-02-13-FCmp.ll new file mode 100644 index 0000000..39b0594 --- /dev/null +++ b/test/Transforms/InstCombine/2012-02-13-FCmp.ll @@ -0,0 +1,35 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s +; Radar 10803727 +@.str = private unnamed_addr constant [35 x i8] c"\0Ain_range input (should be 0): %f\0A\00", align 1 +@.str1 = external hidden unnamed_addr constant [35 x i8], align 1 + +declare i32 @printf(i8*, ...) +define i64 @_Z8tempCastj(i32 %val) uwtable ssp { +entry: + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([35 x i8]* @.str1, i64 0, i64 0), i32 %val) + %conv = uitofp i32 %val to double + %call.i = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([35 x i8]* @.str, i64 0, i64 0), double %conv) + %cmp.i = fcmp oge double %conv, -1.000000e+00 + br i1 %cmp.i, label %land.rhs.i, label %if.end.critedge +; CHECK: br i1 true, label %land.rhs.i, label %if.end.critedge + +land.rhs.i: ; preds = %entry + %cmp1.i = fcmp olt double %conv, 1.000000e+00 + br i1 %cmp1.i, label %if.then, label %if.end + +if.then: ; preds = %land.rhs.i + %add = fadd double %conv, 5.000000e-01 + %conv3 = fptosi double %add to i64 + br label %return + +if.end.critedge: ; preds = %entry + br label %if.end + +if.end: ; preds = %if.end.critedge, %land.rhs.i + br label %return + +return: ; preds = %if.end, %if.then + %retval.0 = phi i64 [ %conv3, %if.then ], [ -1, %if.end ] + ret i64 %retval.0 +} + diff --git a/test/Transforms/InstCombine/2012-02-28-ICmp.ll b/test/Transforms/InstCombine/2012-02-28-ICmp.ll new file mode 100644 index 0000000..82cf85f --- /dev/null +++ b/test/Transforms/InstCombine/2012-02-28-ICmp.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; <rdar://problem/10803154> + +; There should be no transformation. +; CHECK: %a = trunc i32 %x to i8 +; CHECK: %b = icmp ne i8 %a, 0 +; CHECK: %c = and i32 %x, 16711680 +; CHECK: %d = icmp ne i32 %c, 0 +; CHECK: %e = and i1 %b, %d +; CHECK: ret i1 %e + +define i1 @f1(i32 %x) { + %a = trunc i32 %x to i8 + %b = icmp ne i8 %a, 0 + %c = and i32 %x, 16711680 + %d = icmp ne i32 %c, 0 + %e = and i1 %b, %d + ret i1 %e +} diff --git a/test/Transforms/InstCombine/2012-03-10-InstCombine.ll b/test/Transforms/InstCombine/2012-03-10-InstCombine.ll new file mode 100644 index 0000000..58ccf12 --- /dev/null +++ b/test/Transforms/InstCombine/2012-03-10-InstCombine.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -S -instcombine | FileCheck %s + +; Derived from gcc.c-torture/execute/frame-address.c + +; CHECK: @func +; CHECK: return: +; CHECK-NOT: ret i32 0 +; CHECK: ret i32 %retval + +define i32 @func(i8* %c, i8* %f) nounwind uwtable readnone noinline ssp { +entry: + %d = alloca i8, align 1 + store i8 0, i8* %d, align 1 + %cmp = icmp ugt i8* %d, %c + br i1 %cmp, label %if.else, label %if.then + +if.then: ; preds = %entry + %cmp2 = icmp ule i8* %d, %f + %not.cmp1 = icmp uge i8* %c, %f + %.cmp2 = and i1 %cmp2, %not.cmp1 + %land.ext = zext i1 %.cmp2 to i32 + br label %return + +if.else: ; preds = %entry + %cmp5 = icmp uge i8* %d, %f + %not.cmp3 = icmp ule i8* %c, %f + %.cmp5 = and i1 %cmp5, %not.cmp3 + %land.ext7 = zext i1 %.cmp5 to i32 + br label %return + +return: ; preds = %if.else, %if.then + %retval.0 = phi i32 [ %land.ext, %if.then ], [ %land.ext7, %if.else ] + ret i32 %retval.0 +} + diff --git a/test/Transforms/InstCombine/2012-3-15-or-xor-constant.ll b/test/Transforms/InstCombine/2012-3-15-or-xor-constant.ll new file mode 100644 index 0000000..c1602da --- /dev/null +++ b/test/Transforms/InstCombine/2012-3-15-or-xor-constant.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; PR12234 + +@g = extern_weak global i32 +define i32 @function(i32 %x) nounwind { +entry: + %xor = xor i32 %x, 1 + store volatile i32 %xor, i32* inttoptr (i64 1 to i32*), align 4 + %or4 = or i32 or (i32 zext (i1 icmp eq (i32* @g, i32* null) to i32), i32 1), %xor + ret i32 %or4 +} +; CHECK: define i32 @function diff --git a/test/Transforms/InstCombine/LandingPadClauses.ll b/test/Transforms/InstCombine/LandingPadClauses.ll index 055bdcc..de3b2d3 100644 --- a/test/Transforms/InstCombine/LandingPadClauses.ll +++ b/test/Transforms/InstCombine/LandingPadClauses.ll @@ -6,6 +6,7 @@ declare i32 @generic_personality(i32, i64, i8*, i8*) declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*) +declare i32 @__objc_personality_v0(i32, i64, i8*, i8*) declare void @bar() @@ -179,3 +180,54 @@ lpad.d: ; CHECK-NEXT: null ; CHECK-NEXT: unreachable } + +define void @foo_objc() { +; CHECK: @foo_objc + invoke void @bar() + to label %cont.a unwind label %lpad.a +cont.a: + invoke void @bar() + to label %cont.b unwind label %lpad.b +cont.b: + invoke void @bar() + to label %cont.c unwind label %lpad.c +cont.c: + invoke void @bar() + to label %cont.d unwind label %lpad.d +cont.d: + ret void + +lpad.a: + %a = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__objc_personality_v0 + catch i32* null + catch i32* @T1 + unreachable +; CHECK: %a = landingpad +; CHECK-NEXT: null +; CHECK-NEXT: unreachable + +lpad.b: + %b = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__objc_personality_v0 + filter [1 x i32*] zeroinitializer + unreachable +; CHECK: %b = landingpad +; CHECK-NEXT: cleanup +; CHECK-NEXT: unreachable + +lpad.c: + %c = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__objc_personality_v0 + filter [2 x i32*] [i32* @T1, i32* null] + unreachable +; CHECK: %c = landingpad +; CHECK-NEXT: cleanup +; CHECK-NEXT: unreachable + +lpad.d: + %d = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__objc_personality_v0 + cleanup + catch i32* null + unreachable +; CHECK: %d = landingpad +; CHECK-NEXT: null +; CHECK-NEXT: unreachable +} diff --git a/test/Transforms/InstCombine/align-external.ll b/test/Transforms/InstCombine/align-external.ll index 6e8ad87..d4a5d42 100644 --- a/test/Transforms/InstCombine/align-external.ll +++ b/test/Transforms/InstCombine/align-external.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s -; Don't assume that external global variables have their preferred -; alignment. They may only have the ABI minimum alignment. +; Don't assume that external global variables or those with weak linkage have +; their preferred alignment. They may only have the ABI minimum alignment. ; CHECK: %s = shl i64 %a, 3 ; CHECK: %r = or i64 %s, ptrtoint (i32* @A to i64) @@ -11,7 +11,7 @@ target datalayout = "-i32:8:32" @A = external global i32 -@B = external global i32 +@B = weak_odr global i32 0 define i64 @foo(i64 %a) { %t = ptrtoint i32* @A to i64 @@ -20,3 +20,10 @@ define i64 @foo(i64 %a) { %q = add i64 %r, 1 ret i64 %q } + +define i32 @bar() { +; CHECK: @bar + %r = load i32* @B, align 1 +; CHECK: align 1 + ret i32 %r +} diff --git a/test/Transforms/InstCombine/alloca.ll b/test/Transforms/InstCombine/alloca.ll index e4d1367..ef7185c 100644 --- a/test/Transforms/InstCombine/alloca.ll +++ b/test/Transforms/InstCombine/alloca.ll @@ -44,3 +44,47 @@ define i32* @test4(i32 %n) { %A = alloca i32, i32 %n ret i32* %A } + +; Allocas which are only used by GEPs, bitcasts, and stores (transitively) +; should be deleted. +define void @test5() { +; CHECK: @test5 +; CHECK-NOT: alloca +; CHECK-NOT: store +; CHECK: ret + +entry: + %a = alloca { i32 } + %b = alloca i32* + %a.1 = getelementptr { i32 }* %a, i32 0, i32 0 + store i32 123, i32* %a.1 + store i32* %a.1, i32** %b + %b.1 = bitcast i32** %b to i32* + store i32 123, i32* %b.1 + %a.2 = getelementptr { i32 }* %a, i32 0, i32 0 + store atomic i32 2, i32* %a.2 unordered, align 4 + %a.3 = getelementptr { i32 }* %a, i32 0, i32 0 + store atomic i32 3, i32* %a.3 release, align 4 + %a.4 = getelementptr { i32 }* %a, i32 0, i32 0 + store atomic i32 4, i32* %a.4 seq_cst, align 4 + ret void +} + +declare void @f(i32* %p) + +; Check that we don't delete allocas in some erroneous cases. +define void @test6() { +; CHECK: @test6 +; CHECK-NOT: ret +; CHECK: alloca +; CHECK-NEXT: alloca +; CHECK: ret + +entry: + %a = alloca { i32 } + %b = alloca i32 + %a.1 = getelementptr { i32 }* %a, i32 0, i32 0 + store volatile i32 123, i32* %a.1 + tail call void @f(i32* %b) + ret void +} diff --git a/test/Transforms/InstCombine/apint-shl-trunc.ll b/test/Transforms/InstCombine/apint-shl-trunc.ll index 8163e6d..f2dc7d5 100644 --- a/test/Transforms/InstCombine/apint-shl-trunc.ll +++ b/test/Transforms/InstCombine/apint-shl-trunc.ll @@ -1,13 +1,24 @@ -; RUN: opt < %s -instcombine -S | grep shl -; END. +; RUN: opt < %s -instcombine -S | FileCheck %s define i1 @test0(i39 %X, i39 %A) { +; CHECK: @test0 +; CHECK: %[[V1:.*]] = shl i39 1, %A +; CHECK: %[[V2:.*]] = and i39 %[[V1]], %X +; CHECK: %[[V3:.*]] = icmp ne i39 %[[V2]], 0 +; CHECK: ret i1 %[[V3]] + %B = lshr i39 %X, %A %D = trunc i39 %B to i1 ret i1 %D } define i1 @test1(i799 %X, i799 %A) { +; CHECK: @test1 +; CHECK: %[[V1:.*]] = shl i799 1, %A +; CHECK: %[[V2:.*]] = and i799 %[[V1]], %X +; CHECK: %[[V3:.*]] = icmp ne i799 %[[V2]], 0 +; CHECK: ret i1 %[[V3]] + %B = lshr i799 %X, %A %D = trunc i799 %B to i1 ret i1 %D diff --git a/test/Transforms/InstCombine/bitcount.ll b/test/Transforms/InstCombine/bitcount.ll index f75ca2d..a6fd837 100644 --- a/test/Transforms/InstCombine/bitcount.ll +++ b/test/Transforms/InstCombine/bitcount.ll @@ -4,13 +4,13 @@ ; RUN: grep -v declare | not grep llvm.ct declare i31 @llvm.ctpop.i31(i31 %val) -declare i32 @llvm.cttz.i32(i32 %val) -declare i33 @llvm.ctlz.i33(i33 %val) +declare i32 @llvm.cttz.i32(i32 %val, i1) +declare i33 @llvm.ctlz.i33(i33 %val, i1) define i32 @test(i32 %A) { %c1 = call i31 @llvm.ctpop.i31(i31 12415124) - %c2 = call i32 @llvm.cttz.i32(i32 87359874) - %c3 = call i33 @llvm.ctlz.i33(i33 87359874) + %c2 = call i32 @llvm.cttz.i32(i32 87359874, i1 true) + %c3 = call i33 @llvm.ctlz.i33(i33 87359874, i1 true) %t1 = zext i31 %c1 to i32 %t3 = trunc i33 %c3 to i32 %r1 = add i32 %t1, %c2 diff --git a/test/Transforms/InstCombine/constant-fold-gep.ll b/test/Transforms/InstCombine/constant-fold-gep.ll index c679226..e5b16ea 100644 --- a/test/Transforms/InstCombine/constant-fold-gep.ll +++ b/test/Transforms/InstCombine/constant-fold-gep.ll @@ -9,7 +9,7 @@ target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3 @Y = internal global [3 x %struct.X] zeroinitializer define void @frob() { -; CHECK: store i32 1, i32* getelementptr inbounds ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 0), align 8 +; CHECK: store i32 1, i32* getelementptr inbounds ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 0), align 16 store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 0), align 4 ; CHECK: store i32 1, i32* getelementptr inbounds ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 1), align 4 store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 1), align 4 @@ -33,7 +33,7 @@ define void @frob() { store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 10), align 4 ; CHECK: store i32 1, i32* getelementptr inbounds ([3 x %struct.X]* @Y, i64 0, i64 1, i32 1, i64 2), align 4 store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 11), align 4 -; CHECK: store i32 1, i32* getelementptr inbounds ([3 x %struct.X]* @Y, i64 0, i64 2, i32 0, i64 0), align 8 +; CHECK: store i32 1, i32* getelementptr inbounds ([3 x %struct.X]* @Y, i64 0, i64 2, i32 0, i64 0), align 16 store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 12), align 4 ; CHECK: store i32 1, i32* getelementptr inbounds ([3 x %struct.X]* @Y, i64 0, i64 2, i32 0, i64 1), align 4 store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 13), align 4 @@ -47,7 +47,7 @@ define void @frob() { store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 17), align 8 ; CHECK: store i32 1, i32* getelementptr inbounds ([3 x %struct.X]* @Y, i64 1, i64 0, i32 0, i64 0), align 8 store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 18), align 8 -; CHECK: store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 2, i64 0, i32 0, i64 0), align 8 +; CHECK: store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 2, i64 0, i32 0, i64 0), align 16 store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 36), align 8 ; CHECK: store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 1, i64 0, i32 0, i64 1), align 8 store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 19), align 8 diff --git a/test/Transforms/InstCombine/crash.ll b/test/Transforms/InstCombine/crash.ll index 54a77aa..d5af532 100644 --- a/test/Transforms/InstCombine/crash.ll +++ b/test/Transforms/InstCombine/crash.ll @@ -165,20 +165,19 @@ entry: br i1 %tobool, label %cond.end, label %cond.false terminate.handler: ; preds = %ehcleanup - %exc = call i8* @llvm.eh.exception() ; <i8*> [#uses=1] - %0 = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exc, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i32 1) ; <i32> [#uses=0] + %exc = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup call void @_ZSt9terminatev() noreturn nounwind unreachable ehcleanup: ; preds = %cond.false - %exc1 = call i8* @llvm.eh.exception() ; <i8*> [#uses=2] - %1 = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exc1, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null) ; <i32> [#uses=0] + %exc1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null invoke void @_ZN6UStackD1Ev(%class.UStack* %breaks) to label %cont unwind label %terminate.handler cont: ; preds = %ehcleanup - call void @_Unwind_Resume_or_Rethrow(i8* %exc1) - unreachable + resume { i8*, i32 } %exc1 cond.false: ; preds = %entry %tmp4 = getelementptr inbounds %class.RuleBasedBreakIterator* %this, i32 0, i32 0 ; <i64 ()**> [#uses=1] @@ -199,10 +198,6 @@ declare void @_ZN6UStackD1Ev(%class.UStack*) declare i32 @__gxx_personality_v0(...) -declare i8* @llvm.eh.exception() nounwind readonly - -declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind - declare void @_ZSt9terminatev() declare void @_Unwind_Resume_or_Rethrow(i8*) diff --git a/test/Transforms/InstCombine/dg.exp b/test/Transforms/InstCombine/dg.exp deleted file mode 100644 index f200589..0000000 --- a/test/Transforms/InstCombine/dg.exp +++ /dev/null @@ -1,3 +0,0 @@ -load_lib llvm.exp - -RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/test/Transforms/InstCombine/extractvalue.ll b/test/Transforms/InstCombine/extractvalue.ll index cf36b8f..5e4c677 100644 --- a/test/Transforms/InstCombine/extractvalue.ll +++ b/test/Transforms/InstCombine/extractvalue.ll @@ -88,7 +88,7 @@ define i32 @doubleextract2gep({i32, {i32, i32}}* %arg) { ; CHECK-NEXT: ret define i32 @nogep-multiuse({i32, i32}* %pair) { ; The load should be left unchanged since both parts are needed. - %L = volatile load {i32, i32}* %pair + %L = load volatile {i32, i32}* %pair %LHS = extractvalue {i32, i32} %L, 0 %RHS = extractvalue {i32, i32} %L, 1 %R = add i32 %LHS, %RHS @@ -100,8 +100,8 @@ define i32 @nogep-multiuse({i32, i32}* %pair) { ; CHECK-NEXT: extractvalue ; CHECK-NEXT: ret define i32 @nogep-volatile({i32, i32}* %pair) { - ; The volatile load should be left unchanged. - %L = volatile load {i32, i32}* %pair + ; The load volatile should be left unchanged. + %L = load volatile {i32, i32}* %pair %E = extractvalue {i32, i32} %L, 1 ret i32 %E } diff --git a/test/Transforms/InstCombine/fold-sqrt-sqrtf.ll b/test/Transforms/InstCombine/fold-sqrt-sqrtf.ll new file mode 100644 index 0000000..bd92b4a --- /dev/null +++ b/test/Transforms/InstCombine/fold-sqrt-sqrtf.ll @@ -0,0 +1,17 @@ +; RUN: opt -instcombine -S -disable-simplify-libcalls < %s | FileCheck %s +; rdar://10466410 + +; Instcombine tries to fold (fptrunc (sqrt (fpext x))) -> (sqrtf x), but this +; shouldn't fold when sqrtf isn't available. +define float @foo(float %f) uwtable ssp { +entry: +; CHECK: %conv = fpext float %f to double +; CHECK: %call = tail call double @sqrt(double %conv) +; CHECK: %conv1 = fptrunc double %call to float + %conv = fpext float %f to double + %call = tail call double @sqrt(double %conv) + %conv1 = fptrunc double %call to float + ret float %conv1 +} + +declare double @sqrt(double) diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index 77ca62c..a9ae221 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -121,8 +121,8 @@ define i1 @test12(i1 %A) { %B = icmp ne i64 bitcast (<2 x i32> <i32 1, i32 -1> to i64), %S ret i1 %B ; CHECK: @test12 -; CHECK-NEXT: %B = select i1 -; CHECK-NEXT: ret i1 %B +; CHECK-NEXT: = xor i1 %A, true +; CHECK-NEXT: ret i1 } ; PR6481 @@ -524,7 +524,7 @@ define i1 @test53(i32 %a, i32 %b) nounwind { ; CHECK: @test54 ; CHECK-NEXT: %and = and i8 %a, -64 -; CHECK-NEXT icmp eq i8 %and, -128 +; CHECK-NEXT: icmp eq i8 %and, -128 define i1 @test54(i8 %a) nounwind { %ext = zext i8 %a to i32 %and = and i32 %ext, 192 @@ -559,3 +559,81 @@ define i1 @test57(i32 %a) { call void @foo(i32 %and) ret i1 %cmp } + +; rdar://problem/10482509 +; CHECK: @cmpabs1 +; CHECK-NEXT: icmp ne +define zeroext i1 @cmpabs1(i64 %val) { + %sub = sub nsw i64 0, %val + %cmp = icmp slt i64 %val, 0 + %sub.val = select i1 %cmp, i64 %sub, i64 %val + %tobool = icmp ne i64 %sub.val, 0 + ret i1 %tobool +} + +; CHECK: @cmpabs2 +; CHECK-NEXT: icmp ne +define zeroext i1 @cmpabs2(i64 %val) { + %sub = sub nsw i64 0, %val + %cmp = icmp slt i64 %val, 0 + %sub.val = select i1 %cmp, i64 %val, i64 %sub + %tobool = icmp ne i64 %sub.val, 0 + ret i1 %tobool +} + +; CHECK: @test58 +; CHECK-NEXT: call i32 @test58_d(i64 36029346783166592) +define void @test58() nounwind { + %cast = bitcast <1 x i64> <i64 36029346783166592> to i64 + %call = call i32 @test58_d( i64 %cast) nounwind + ret void +} +declare i32 @test58_d(i64) + +define i1 @test59(i8* %foo) { + %bit = bitcast i8* %foo to i32* + %gep1 = getelementptr inbounds i32* %bit, i64 2 + %gep2 = getelementptr inbounds i8* %foo, i64 10 + %cast1 = bitcast i32* %gep1 to i8* + %cmp = icmp ult i8* %cast1, %gep2 + %use = ptrtoint i8* %cast1 to i64 + %call = call i32 @test58_d(i64 %use) nounwind + ret i1 %cmp +; CHECK: @test59 +; CHECK: ret i1 true +} + +define i1 @test60(i8* %foo, i64 %i, i64 %j) { + %bit = bitcast i8* %foo to i32* + %gep1 = getelementptr inbounds i32* %bit, i64 %i + %gep2 = getelementptr inbounds i8* %foo, i64 %j + %cast1 = bitcast i32* %gep1 to i8* + %cmp = icmp ult i8* %cast1, %gep2 + ret i1 %cmp +; CHECK: @test60 +; CHECK-NEXT: %gep1.idx = shl nuw i64 %i, 2 +; CHECK-NEXT: icmp slt i64 %gep1.idx, %j +; CHECK-NEXT: ret i1 +} + +define i1 @test61(i8* %foo, i64 %i, i64 %j) { + %bit = bitcast i8* %foo to i32* + %gep1 = getelementptr i32* %bit, i64 %i + %gep2 = getelementptr i8* %foo, i64 %j + %cast1 = bitcast i32* %gep1 to i8* + %cmp = icmp ult i8* %cast1, %gep2 + ret i1 %cmp +; Don't transform non-inbounds GEPs. +; CHECK: @test61 +; CHECK: icmp ult i8* %cast1, %gep2 +; CHECK-NEXT: ret i1 +} + +define i1 @test62(i8* %a) { + %arrayidx1 = getelementptr inbounds i8* %a, i64 1 + %arrayidx2 = getelementptr inbounds i8* %a, i64 10 + %cmp = icmp slt i8* %arrayidx1, %arrayidx2 + ret i1 %cmp +; CHECK: @test62 +; CHECK-NEXT: ret i1 true +} diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index f033e51..382e6b3 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/test/Transforms/InstCombine/intrinsics.ll @@ -5,10 +5,10 @@ declare %overflow.result @llvm.uadd.with.overflow.i8(i8, i8) declare %overflow.result @llvm.umul.with.overflow.i8(i8, i8) declare double @llvm.powi.f64(double, i32) nounwind readonly -declare i32 @llvm.cttz.i32(i32) nounwind readnone -declare i32 @llvm.ctlz.i32(i32) nounwind readnone +declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone +declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone declare i32 @llvm.ctpop.i32(i32) nounwind readnone -declare i8 @llvm.ctlz.i8(i8) nounwind readnone +declare i8 @llvm.ctlz.i8(i8, i1) nounwind readnone define i8 @uaddtest1(i8 %A, i8 %B) { %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 %B) @@ -142,13 +142,13 @@ define i32 @umultest4(i32 %n) nounwind { define void @powi(double %V, double *%P) { entry: %A = tail call double @llvm.powi.f64(double %V, i32 -1) nounwind - volatile store double %A, double* %P + store volatile double %A, double* %P %B = tail call double @llvm.powi.f64(double %V, i32 0) nounwind - volatile store double %B, double* %P + store volatile double %B, double* %P %C = tail call double @llvm.powi.f64(double %V, i32 1) nounwind - volatile store double %C, double* %P + store volatile double %C, double* %P ret void ; CHECK: @powi ; CHECK: %A = fdiv double 1.0{{.*}}, %V @@ -161,7 +161,7 @@ define i32 @cttz(i32 %a) { entry: %or = or i32 %a, 8 %and = and i32 %or, -8 - %count = tail call i32 @llvm.cttz.i32(i32 %and) nounwind readnone + %count = tail call i32 @llvm.cttz.i32(i32 %and, i1 true) nounwind readnone ret i32 %count ; CHECK: @cttz ; CHECK-NEXT: entry: @@ -172,7 +172,7 @@ define i8 @ctlz(i8 %a) { entry: %or = or i8 %a, 32 %and = and i8 %or, 63 - %count = tail call i8 @llvm.ctlz.i8(i8 %and) nounwind readnone + %count = tail call i8 @llvm.ctlz.i8(i8 %and, i1 true) nounwind readnone ret i8 %count ; CHECK: @ctlz ; CHECK-NEXT: entry: @@ -181,15 +181,15 @@ entry: define void @cmp.simplify(i32 %a, i32 %b, i1* %c) { entry: - %lz = tail call i32 @llvm.ctlz.i32(i32 %a) nounwind readnone + %lz = tail call i32 @llvm.ctlz.i32(i32 %a, i1 false) nounwind readnone %lz.cmp = icmp eq i32 %lz, 32 - volatile store i1 %lz.cmp, i1* %c - %tz = tail call i32 @llvm.cttz.i32(i32 %a) nounwind readnone + store volatile i1 %lz.cmp, i1* %c + %tz = tail call i32 @llvm.cttz.i32(i32 %a, i1 false) nounwind readnone %tz.cmp = icmp ne i32 %tz, 32 - volatile store i1 %tz.cmp, i1* %c + store volatile i1 %tz.cmp, i1* %c %pop = tail call i32 @llvm.ctpop.i32(i32 %b) nounwind readnone %pop.cmp = icmp eq i32 %pop, 0 - volatile store i1 %pop.cmp, i1* %c + store volatile i1 %pop.cmp, i1* %c ret void ; CHECK: @cmp.simplify ; CHECK-NEXT: entry: @@ -201,16 +201,22 @@ entry: ; CHECK-NEXT: store volatile i1 %pop.cmp, i1* %c } - -define i32 @cttz_simplify1(i32 %x) nounwind readnone ssp { - %tmp1 = tail call i32 @llvm.ctlz.i32(i32 %x) ; <i32> [#uses=1] - %shr3 = lshr i32 %tmp1, 5 ; <i32> [#uses=1] +define i32 @cttz_simplify1a(i32 %x) nounwind readnone ssp { + %tmp1 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false) + %shr3 = lshr i32 %tmp1, 5 ret i32 %shr3 - -; CHECK: @cttz_simplify1 + +; CHECK: @cttz_simplify1a ; CHECK: icmp eq i32 %x, 0 -; CHECK-NEXT: zext i1 +; CHECK-NEXT: zext i1 ; CHECK-NEXT: ret i32 } +define i32 @cttz_simplify1b(i32 %x) nounwind readnone ssp { + %tmp1 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) + %shr3 = lshr i32 %tmp1, 5 + ret i32 %shr3 +; CHECK: @cttz_simplify1b +; CHECK-NEXT: ret i32 0 +} diff --git a/test/Transforms/InstCombine/lit.local.cfg b/test/Transforms/InstCombine/lit.local.cfg new file mode 100644 index 0000000..19eebc0 --- /dev/null +++ b/test/Transforms/InstCombine/lit.local.cfg @@ -0,0 +1 @@ +config.suffixes = ['.ll', '.c', '.cpp'] diff --git a/test/Transforms/InstCombine/mul.ll b/test/Transforms/InstCombine/mul.ll index 53a5643..edb5305 100644 --- a/test/Transforms/InstCombine/mul.ll +++ b/test/Transforms/InstCombine/mul.ll @@ -1,116 +1,184 @@ ; This test makes sure that mul instructions are properly eliminated. -; RUN: opt < %s -instcombine -S | not grep mul +; RUN: opt < %s -instcombine -S | FileCheck %s define i32 @test1(i32 %A) { +; CHECK: @test1 %B = mul i32 %A, 1 ; <i32> [#uses=1] ret i32 %B +; CHECK: ret i32 %A } define i32 @test2(i32 %A) { +; CHECK: @test2 ; Should convert to an add instruction %B = mul i32 %A, 2 ; <i32> [#uses=1] ret i32 %B +; CHECK: shl i32 %A, 1 } define i32 @test3(i32 %A) { +; CHECK: @test3 ; This should disappear entirely %B = mul i32 %A, 0 ; <i32> [#uses=1] ret i32 %B +; CHECK: ret i32 0 } define double @test4(double %A) { +; CHECK: @test4 ; This is safe for FP %B = fmul double 1.000000e+00, %A ; <double> [#uses=1] ret double %B +; CHECK: ret double %A } define i32 @test5(i32 %A) { +; CHECK: @test5 %B = mul i32 %A, 8 ; <i32> [#uses=1] ret i32 %B +; CHECK: shl i32 %A, 3 } define i8 @test6(i8 %A) { +; CHECK: @test6 %B = mul i8 %A, 8 ; <i8> [#uses=1] %C = mul i8 %B, 8 ; <i8> [#uses=1] ret i8 %C +; CHECK: shl i8 %A, 6 } define i32 @test7(i32 %i) { +; CHECK: @test7 %tmp = mul i32 %i, -1 ; <i32> [#uses=1] ret i32 %tmp +; CHECK: sub i32 0, %i } define i64 @test8(i64 %i) { - ; tmp = sub 0, %i +; CHECK: @test8 %j = mul i64 %i, -1 ; <i64> [#uses=1] ret i64 %j +; CHECK: sub i64 0, %i } define i32 @test9(i32 %i) { - ; %j = sub 0, %i +; CHECK: @test9 %j = mul i32 %i, -1 ; <i32> [#uses=1] ret i32 %j +; CHECJ: sub i32 0, %i } define i32 @test10(i32 %a, i32 %b) { +; CHECK: @test10 %c = icmp slt i32 %a, 0 ; <i1> [#uses=1] %d = zext i1 %c to i32 ; <i32> [#uses=1] ; e = b & (a >> 31) %e = mul i32 %d, %b ; <i32> [#uses=1] ret i32 %e +; CHECK: [[TEST10:%.*]] = ashr i32 %a, 31 +; CHECK-NEXT: %e = and i32 [[TEST10]], %b +; CHECK-NEXT: ret i32 %e } define i32 @test11(i32 %a, i32 %b) { +; CHECK: @test11 %c = icmp sle i32 %a, -1 ; <i1> [#uses=1] %d = zext i1 %c to i32 ; <i32> [#uses=1] ; e = b & (a >> 31) %e = mul i32 %d, %b ; <i32> [#uses=1] ret i32 %e +; CHECK: [[TEST11:%.*]] = ashr i32 %a, 31 +; CHECK-NEXT: %e = and i32 [[TEST11]], %b +; CHECK-NEXT: ret i32 %e } -define i32 @test12(i8 %a, i32 %b) { - %c = icmp ugt i8 %a, 127 ; <i1> [#uses=1] +define i32 @test12(i32 %a, i32 %b) { +; CHECK: @test12 + %c = icmp ugt i32 %a, 2147483647 ; <i1> [#uses=1] %d = zext i1 %c to i32 ; <i32> [#uses=1] - ; e = b & (a >> 31) %e = mul i32 %d, %b ; <i32> [#uses=1] ret i32 %e +; CHECK: [[TEST12:%.*]] = ashr i32 %a, 31 +; CHECK-NEXT: %e = and i32 [[TEST12]], %b +; CHECK-NEXT: ret i32 %e + } ; PR2642 define internal void @test13(<4 x float>*) { +; CHECK: @test13 load <4 x float>* %0, align 1 fmul <4 x float> %2, < float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00 > store <4 x float> %3, <4 x float>* %0, align 1 ret void +; CHECK-NEXT: ret void } define <16 x i8> @test14(<16 x i8> %a) { +; CHECK: @test14 %b = mul <16 x i8> %a, zeroinitializer ret <16 x i8> %b +; CHECK-NEXT: ret <16 x i8> zeroinitializer } ; rdar://7293527 define i32 @test15(i32 %A, i32 %B) { +; CHECK: @test15 entry: %shl = shl i32 1, %B %m = mul i32 %shl, %A ret i32 %m +; CHECK: shl i32 %A, %B } ; X * Y (when Y is 0 or 1) --> x & (0-Y) define i32 @test16(i32 %b, i1 %c) { +; CHECK: @test16 %d = zext i1 %c to i32 ; <i32> [#uses=1] ; e = b & (a >> 31) %e = mul i32 %d, %b ; <i32> [#uses=1] ret i32 %e +; CHECK: [[TEST16:%.*]] = sext i1 %c to i32 +; CHECK-NEXT: %e = and i32 [[TEST16]], %b +; CHECK-NEXT: ret i32 %e } ; X * Y (when Y is 0 or 1) --> x & (0-Y) define i32 @test17(i32 %a, i32 %b) { +; CHECK: @test17 %a.lobit = lshr i32 %a, 31 %e = mul i32 %a.lobit, %b ret i32 %e +; CHECK: [[TEST17:%.*]] = ashr i32 %a, 31 +; CHECK-NEXT: %e = and i32 [[TEST17]], %b +; CHECK-NEXT: ret i32 %e +} + +define i32 @test18(i32 %A, i32 %B) { +; CHECK: @test18 + %C = and i32 %A, 1 + %D = and i32 %B, 1 + + %E = mul i32 %C, %D + %F = and i32 %E, 16 + ret i32 %F +; CHECK-NEXT: ret i32 0 } +declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) +declare void @use(i1) +define i32 @test19(i32 %A, i32 %B) { +; CHECK: @test19 + %C = and i32 %A, 1 + %D = and i32 %B, 1 +; It would be nice if we also started proving that this doesn't overflow. + %E = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %C, i32 %D) + %F = extractvalue {i32, i1} %E, 0 + %G = extractvalue {i32, i1} %E, 1 + call void @use(i1 %G) + %H = and i32 %F, 16 + ret i32 %H +; CHECK: ret i32 0 +} diff --git a/test/Transforms/InstCombine/overflow.ll b/test/Transforms/InstCombine/overflow.ll index 9123283..81ceef8 100644 --- a/test/Transforms/InstCombine/overflow.ll +++ b/test/Transforms/InstCombine/overflow.ll @@ -130,4 +130,26 @@ entry: ret i64 %Q } +; CHECK: @test8 +; PR11438 +; This is @test1, but the operands are not sign-extended. Make sure +; we don't transform this case. +define i32 @test8(i64 %a, i64 %b) nounwind ssp { +entry: +; CHECK-NOT: llvm.sadd +; CHECK: add i64 %a, %b +; CHECK-NOT: llvm.sadd +; CHECK: ret + %add = add i64 %a, %b + %add.off = add i64 %add, 2147483648 + %0 = icmp ugt i64 %add.off, 4294967295 + br i1 %0, label %if.then, label %if.end + +if.then: + tail call void @throwAnExceptionOrWhatever() nounwind + br label %if.end +if.end: + %conv9 = trunc i64 %add to i32 + ret i32 %conv9 +} diff --git a/test/Transforms/InstCombine/pr12251.ll b/test/Transforms/InstCombine/pr12251.ll new file mode 100644 index 0000000..74a41eb --- /dev/null +++ b/test/Transforms/InstCombine/pr12251.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define zeroext i1 @_Z3fooPb(i8* nocapture %x) { +entry: + %a = load i8* %x, align 1, !range !0 + %b = and i8 %a, 1 + %tobool = icmp ne i8 %b, 0 + ret i1 %tobool +} + +; CHECK: %a = load i8* %x, align 1, !range !0 +; CHECK-NEXT: %tobool = icmp ne i8 %a, 0 +; CHECK-NEXT: ret i1 %tobool + +!0 = metadata !{i8 0, i8 2} diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index 4661561..4baae26 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -809,3 +809,23 @@ define i32 @test61(i32* %ptr) { ; CHECK: @test61 ; CHECK: ret i32 10 } + +define i1 @test62(i1 %A, i1 %B) { + %not = xor i1 %A, true + %C = select i1 %A, i1 %not, i1 %B + ret i1 %C +; CHECK: @test62 +; CHECK: %not = xor i1 %A, true +; CHECK: %C = and i1 %not, %B +; CHECK: ret i1 %C +} + +define i1 @test63(i1 %A, i1 %B) { + %not = xor i1 %A, true + %C = select i1 %A, i1 %B, i1 %not + ret i1 %C +; CHECK: @test63 +; CHECK: %not = xor i1 %A, true +; CHECK: %C = or i1 %B, %not +; CHECK: ret i1 %C +} diff --git a/test/Transforms/InstCombine/sext.ll b/test/Transforms/InstCombine/sext.ll index f49a2ef..f198797 100644 --- a/test/Transforms/InstCombine/sext.ll +++ b/test/Transforms/InstCombine/sext.ll @@ -3,8 +3,8 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" declare i32 @llvm.ctpop.i32(i32) -declare i32 @llvm.ctlz.i32(i32) -declare i32 @llvm.cttz.i32(i32) +declare i32 @llvm.ctlz.i32(i32, i1) +declare i32 @llvm.cttz.i32(i32, i1) define i64 @test1(i32 %x) { %t = call i32 @llvm.ctpop.i32(i32 %x) @@ -16,7 +16,7 @@ define i64 @test1(i32 %x) { } define i64 @test2(i32 %x) { - %t = call i32 @llvm.ctlz.i32(i32 %x) + %t = call i32 @llvm.ctlz.i32(i32 %x, i1 true) %s = sext i32 %t to i64 ret i64 %s @@ -25,7 +25,7 @@ define i64 @test2(i32 %x) { } define i64 @test3(i32 %x) { - %t = call i32 @llvm.cttz.i32(i32 %x) + %t = call i32 @llvm.cttz.i32(i32 %x, i1 true) %s = sext i32 %t to i64 ret i64 %s diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index 132d51a..52310e3 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -542,3 +542,75 @@ define i32 @test45(i32 %a) nounwind { ; CHECK-NEXT: %y = lshr i32 %a, 5 ; CHECK-NEXT: ret i32 %y } + +define i32 @test46(i32 %a) { + %y = ashr exact i32 %a, 3 + %z = shl i32 %y, 1 + ret i32 %z +; CHECK: @test46 +; CHECK-NEXT: %z = ashr exact i32 %a, 2 +; CHECK-NEXT: ret i32 %z +} + +define i32 @test47(i32 %a) { + %y = lshr exact i32 %a, 3 + %z = shl i32 %y, 1 + ret i32 %z +; CHECK: @test47 +; CHECK-NEXT: %z = lshr exact i32 %a, 2 +; CHECK-NEXT: ret i32 %z +} + +define i32 @test48(i32 %x) { + %A = lshr exact i32 %x, 1 + %B = shl i32 %A, 3 + ret i32 %B +; CHECK: @test48 +; CHECK-NEXT: %B = shl i32 %x, 2 +; CHECK-NEXT: ret i32 %B +} + +define i32 @test49(i32 %x) { + %A = ashr exact i32 %x, 1 + %B = shl i32 %A, 3 + ret i32 %B +; CHECK: @test49 +; CHECK-NEXT: %B = shl i32 %x, 2 +; CHECK-NEXT: ret i32 %B +} + +define i32 @test50(i32 %x) { + %A = shl nsw i32 %x, 1 + %B = ashr i32 %A, 3 + ret i32 %B +; CHECK: @test50 +; CHECK-NEXT: %B = ashr i32 %x, 2 +; CHECK-NEXT: ret i32 %B +} + +define i32 @test51(i32 %x) { + %A = shl nuw i32 %x, 1 + %B = lshr i32 %A, 3 + ret i32 %B +; CHECK: @test51 +; CHECK-NEXT: %B = lshr i32 %x, 2 +; CHECK-NEXT: ret i32 %B +} + +define i32 @test52(i32 %x) { + %A = shl nsw i32 %x, 3 + %B = ashr i32 %A, 1 + ret i32 %B +; CHECK: @test52 +; CHECK-NEXT: %B = shl nsw i32 %x, 2 +; CHECK-NEXT: ret i32 %B +} + +define i32 @test53(i32 %x) { + %A = shl nuw i32 %x, 3 + %B = lshr i32 %A, 1 + ret i32 %B +; CHECK: @test53 +; CHECK-NEXT: %B = shl nuw i32 %x, 2 +; CHECK-NEXT: ret i32 %B +} diff --git a/test/Transforms/InstCombine/sign-test-and-or.ll b/test/Transforms/InstCombine/sign-test-and-or.ll index 47f5f30..a6066d8 100644 --- a/test/Transforms/InstCombine/sign-test-and-or.ll +++ b/test/Transforms/InstCombine/sign-test-and-or.ll @@ -77,3 +77,103 @@ if.then: if.end: ret void } + +define void @test5(i32 %a) nounwind { + %and = and i32 %a, 134217728 + %1 = icmp eq i32 %and, 0 + %2 = icmp sgt i32 %a, -1 + %or.cond = and i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test5 +; CHECK-NEXT: %1 = and i32 %a, -2013265920 +; CHECK-NEXT: %2 = icmp eq i32 %1, 0 +; CHECK-NEXT: br i1 %2, label %if.then, label %if.end + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test6(i32 %a) nounwind { + %1 = icmp sgt i32 %a, -1 + %and = and i32 %a, 134217728 + %2 = icmp eq i32 %and, 0 + %or.cond = and i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test6 +; CHECK-NEXT: %1 = and i32 %a, -2013265920 +; CHECK-NEXT: %2 = icmp eq i32 %1, 0 +; CHECK-NEXT: br i1 %2, label %if.then, label %if.end + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test7(i32 %a) nounwind { + %and = and i32 %a, 134217728 + %1 = icmp ne i32 %and, 0 + %2 = icmp slt i32 %a, 0 + %or.cond = or i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test7 +; CHECK-NEXT: %1 = and i32 %a, -2013265920 +; CHECK-NEXT: %2 = icmp eq i32 %1, 0 +; CHECK-NEXT: br i1 %2, label %if.end, label %if.the + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test8(i32 %a) nounwind { + %1 = icmp slt i32 %a, 0 + %and = and i32 %a, 134217728 + %2 = icmp ne i32 %and, 0 + %or.cond = or i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test8 +; CHECK-NEXT: %1 = and i32 %a, -2013265920 +; CHECK-NEXT: %2 = icmp eq i32 %1, 0 +; CHECK-NEXT: br i1 %2, label %if.end, label %if.the + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test9(i32 %a) nounwind { + %1 = and i32 %a, 1073741824 + %2 = icmp ne i32 %1, 0 + %3 = icmp sgt i32 %a, -1 + %or.cond = and i1 %2, %3 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test9 +; CHECK-NEXT: %1 = and i32 %a, -1073741824 +; CHECK-NEXT: %2 = icmp eq i32 %1, 1073741824 +; CHECK-NEXT: br i1 %2, label %if.then, label %if.end + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} diff --git a/test/Transforms/InstCombine/sub-xor.ll b/test/Transforms/InstCombine/sub-xor.ll new file mode 100644 index 0000000..279e4ac --- /dev/null +++ b/test/Transforms/InstCombine/sub-xor.ll @@ -0,0 +1,37 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +define i32 @test1(i32 %x) nounwind { + %and = and i32 %x, 31 + %sub = sub i32 63, %and + ret i32 %sub + +; CHECK: @test1 +; CHECK-NEXT: and i32 %x, 31 +; CHECK-NEXT: xor i32 %and, 63 +; CHECK-NEXT: ret +} + +declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone + +define i32 @test2(i32 %x) nounwind { + %count = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) nounwind readnone + %sub = sub i32 31, %count + ret i32 %sub + +; CHECK: @test2 +; CHECK-NEXT: ctlz +; CHECK-NEXT: xor i32 %count, 31 +; CHECK-NEXT: ret +} + +define i32 @test3(i32 %x) nounwind { + %and = and i32 %x, 31 + %sub = xor i32 31, %and + %add = add i32 %sub, 42 + ret i32 %add + +; CHECK: @test3 +; CHECK-NEXT: and i32 %x, 31 +; CHECK-NEXT: sub i32 73, %and +; CHECK-NEXT: ret +} diff --git a/test/Transforms/InstCombine/sub.ll b/test/Transforms/InstCombine/sub.ll index 37de328..b71ec8c 100644 --- a/test/Transforms/InstCombine/sub.ll +++ b/test/Transforms/InstCombine/sub.ll @@ -301,3 +301,29 @@ define i32 @test28(i32 %x, i32 %y, i32 %z) { ; CHECK-NEXT: add i32 ; CHECK-NEXT: ret i32 } + +define i64 @test29(i8* %foo, i64 %i, i64 %j) { + %gep1 = getelementptr inbounds i8* %foo, i64 %i + %gep2 = getelementptr inbounds i8* %foo, i64 %j + %cast1 = ptrtoint i8* %gep1 to i64 + %cast2 = ptrtoint i8* %gep2 to i64 + %sub = sub i64 %cast1, %cast2 + ret i64 %sub +; CHECK: @test29 +; CHECK-NEXT: sub i64 %i, %j +; CHECK-NEXT: ret i64 +} + +define i64 @test30(i8* %foo, i64 %i, i64 %j) { + %bit = bitcast i8* %foo to i32* + %gep1 = getelementptr inbounds i32* %bit, i64 %i + %gep2 = getelementptr inbounds i8* %foo, i64 %j + %cast1 = ptrtoint i32* %gep1 to i64 + %cast2 = ptrtoint i8* %gep2 to i64 + %sub = sub i64 %cast1, %cast2 + ret i64 %sub +; CHECK: @test30 +; CHECK-NEXT: %gep1.idx = shl nuw i64 %i, 2 +; CHECK-NEXT: sub i64 %gep1.idx, %j +; CHECK-NEXT: ret i64 +} diff --git a/test/Transforms/InstCombine/vec_shuffle.ll b/test/Transforms/InstCombine/vec_shuffle.ll index 896cb88..8f78c2e 100644 --- a/test/Transforms/InstCombine/vec_shuffle.ll +++ b/test/Transforms/InstCombine/vec_shuffle.ll @@ -98,6 +98,17 @@ define <4 x i8> @test9a(<16 x i8> %tmp6) nounwind { ret <4 x i8> %tmp9 } +; Test fold of two shuffles where the first shuffle vectors inputs are a +; different length then the second. +define <4 x i8> @test9b(<4 x i8> %tmp6, <4 x i8> %tmp7) nounwind { +; CHECK: @test9 +; CHECK-NEXT: shufflevector +; CHECK-NEXT: ret + %tmp1 = shufflevector <4 x i8> %tmp6, <4 x i8> %tmp7, <8 x i32> <i32 0, i32 1, i32 4, i32 5, i32 4, i32 5, i32 2, i32 3> ; <<4 x i8>> [#uses=1] + %tmp9 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <4 x i32> <i32 0, i32 1, i32 4, i32 5> ; <<4 x i8>> [#uses=1] + ret <4 x i8> %tmp9 +} + ; Redundant vector splats should be removed. Radar 8597790. define <4 x i32> @test10(<4 x i32> %tmp5) nounwind { ; CHECK: @test10 @@ -107,3 +118,38 @@ define <4 x i32> @test10(<4 x i32> %tmp5) nounwind { %tmp7 = shufflevector <4 x i32> %tmp6, <4 x i32> undef, <4 x i32> zeroinitializer ret <4 x i32> %tmp7 } + +; Test fold of two shuffles where the two shufflevector inputs's op1 are +; the same +define <8 x i8> @test11(<16 x i8> %tmp6) nounwind { +; CHECK: @test11 +; CHECK-NEXT: shufflevector <16 x i8> %tmp6, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> +; CHECK-NEXT: ret + %tmp1 = shufflevector <16 x i8> %tmp6, <16 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> ; <<4 x i8>> [#uses=1] + %tmp2 = shufflevector <16 x i8> %tmp6, <16 x i8> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7> ; <<4 x i8>> [#uses=1] + %tmp3 = shufflevector <4 x i8> %tmp1, <4 x i8> %tmp2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> ; <<8 x i8>> [#uses=1] + ret <8 x i8> %tmp3 +} + +; Test fold of two shuffles where the first shufflevector's inputs are +; the same as the second +define <8 x i8> @test12(<8 x i8> %tmp6, <8 x i8> %tmp2) nounwind { +; CHECK: @test12 +; CHECK-NEXT: shufflevector <8 x i8> %tmp6, <8 x i8> %tmp2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 9, i32 8, i32 11, i32 12> +; CHECK-NEXT: ret + %tmp1 = shufflevector <8 x i8> %tmp6, <8 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7> ; <<8 x i8>> [#uses=1] + %tmp3 = shufflevector <8 x i8> %tmp1, <8 x i8> %tmp2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 9, i32 8, i32 11, i32 12> ; <<8 x i8>> [#uses=1] + ret <8 x i8> %tmp3 +} + +; Test fold of two shuffles where the first shufflevector's inputs are +; the same as the second +define <8 x i8> @test12a(<8 x i8> %tmp6, <8 x i8> %tmp2) nounwind { +; CHECK: @test12a +; CHECK-NEXT: shufflevector <8 x i8> %tmp2, <8 x i8> %tmp6, <8 x i32> <i32 0, i32 3, i32 1, i32 4, i32 8, i32 9, i32 10, i32 11> +; CHECK-NEXT: ret + %tmp1 = shufflevector <8 x i8> %tmp6, <8 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7> ; <<8 x i8>> [#uses=1] + %tmp3 = shufflevector <8 x i8> %tmp2, <8 x i8> %tmp1, <8 x i32> <i32 0, i32 3, i32 1, i32 4, i32 8, i32 9, i32 10, i32 11> ; <<8 x i8>> [#uses=1] + ret <8 x i8> %tmp3 +} + diff --git a/test/Transforms/InstCombine/vector_gep1.ll b/test/Transforms/InstCombine/vector_gep1.ll new file mode 100644 index 0000000..6523622 --- /dev/null +++ b/test/Transforms/InstCombine/vector_gep1.ll @@ -0,0 +1,37 @@ +; RUN: opt -instcombine %s -disable-output +; RUN: opt -instsimplify %s -disable-output +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@G1 = global i8 zeroinitializer + +define <2 x i1> @test(<2 x i8*> %a, <2 x i8*> %b) { + %A = icmp eq <2 x i8*> %a, %b + ret <2 x i1> %A +} + +define <2 x i1> @test2(<2 x i8*> %a) { + %A = inttoptr <2 x i32> <i32 1, i32 2> to <2 x i8*> + %B = icmp ult <2 x i8*> %A, zeroinitializer + ret <2 x i1> %B +} + +define <2 x i1> @test3(<2 x i8*> %a) { + %g = getelementptr <2 x i8*> %a, <2 x i32> <i32 1, i32 0> + %B = icmp ult <2 x i8*> %g, zeroinitializer + ret <2 x i1> %B +} + +define <1 x i1> @test4(<1 x i8*> %a) { + %g = getelementptr <1 x i8*> %a, <1 x i32> <i32 1> + %B = icmp ult <1 x i8*> %g, zeroinitializer + ret <1 x i1> %B +} + +define <2 x i1> @test5(<2 x i8*> %a) { + %w = getelementptr <2 x i8*> %a, <2 x i32> zeroinitializer + %e = getelementptr <2 x i8*> %w, <2 x i32> <i32 5, i32 9> + %g = getelementptr <2 x i8*> %e, <2 x i32> <i32 1, i32 0> + %B = icmp ult <2 x i8*> %g, zeroinitializer + ret <2 x i1> %B +} diff --git a/test/Transforms/InstCombine/volatile_store.ll b/test/Transforms/InstCombine/volatile_store.ll index 0518e5a..2256678 100644 --- a/test/Transforms/InstCombine/volatile_store.ll +++ b/test/Transforms/InstCombine/volatile_store.ll @@ -5,8 +5,8 @@ define void @self_assign_1() { entry: - %tmp = volatile load i32* @x ; <i32> [#uses=1] - volatile store i32 %tmp, i32* @x + %tmp = load volatile i32* @x ; <i32> [#uses=1] + store volatile i32 %tmp, i32* @x br label %return return: ; preds = %entry |