diff options
Diffstat (limited to 'test/Transforms/InstSimplify')
29 files changed, 1674 insertions, 580 deletions
diff --git a/test/Transforms/InstSimplify/2010-12-20-Boolean.ll b/test/Transforms/InstSimplify/2010-12-20-Boolean.ll index 28c25c0e77ee..33f2176f7c91 100644 --- a/test/Transforms/InstSimplify/2010-12-20-Boolean.ll +++ b/test/Transforms/InstSimplify/2010-12-20-Boolean.ll @@ -1,29 +1,34 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s define i1 @add(i1 %x) { ; CHECK-LABEL: @add( +; CHECK: ret i1 false +; %z = add i1 %x, %x ret i1 %z -; CHECK: ret i1 false } define i1 @sub(i1 %x) { ; CHECK-LABEL: @sub( +; CHECK: ret i1 %x +; %z = sub i1 false, %x ret i1 %z -; CHECK: ret i1 %x } define i1 @mul(i1 %x) { ; CHECK-LABEL: @mul( +; CHECK: ret i1 %x +; %z = mul i1 %x, %x ret i1 %z -; CHECK: ret i1 %x } define i1 @ne(i1 %x) { ; CHECK-LABEL: @ne( +; CHECK: ret i1 %x +; %z = icmp ne i1 %x, 0 ret i1 %z -; CHECK: ret i1 %x } diff --git a/test/Transforms/InstSimplify/AndOrXor.ll b/test/Transforms/InstSimplify/AndOrXor.ll index ce3c2aa6af22..2442e684246f 100644 --- a/test/Transforms/InstSimplify/AndOrXor.ll +++ b/test/Transforms/InstSimplify/AndOrXor.ll @@ -1,205 +1,345 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s define i64 @pow2(i32 %x) { ; CHECK-LABEL: @pow2( +; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, %x +; CHECK-NEXT: [[X2:%.*]] = and i32 %x, [[NEGX]] +; CHECK-NEXT: [[E:%.*]] = zext i32 [[X2]] to i64 +; CHECK-NEXT: ret i64 [[E]] +; %negx = sub i32 0, %x %x2 = and i32 %x, %negx %e = zext i32 %x2 to i64 %nege = sub i64 0, %e %e2 = and i64 %e, %nege ret i64 %e2 -; CHECK: ret i64 %e } define i64 @pow2b(i32 %x) { ; CHECK-LABEL: @pow2b( +; CHECK-NEXT: [[SH:%.*]] = shl i32 2, %x +; CHECK-NEXT: [[E:%.*]] = zext i32 [[SH]] to i64 +; CHECK-NEXT: ret i64 [[E]] +; %sh = shl i32 2, %x %e = zext i32 %sh to i64 %nege = sub i64 0, %e %e2 = and i64 %e, %nege ret i64 %e2 -; CHECK: ret i64 %e } define i32 @sub_neg_nuw(i32 %x, i32 %y) { ; CHECK-LABEL: @sub_neg_nuw( +; CHECK-NEXT: ret i32 %x +; %neg = sub nuw i32 0, %y %sub = sub i32 %x, %neg ret i32 %sub -; CHECK: ret i32 %x } define i1 @and_of_icmps0(i32 %b) { ; CHECK-LABEL: @and_of_icmps0( +; CHECK-NEXT: ret i1 false +; %1 = add i32 %b, 2 %2 = icmp ult i32 %1, 4 %cmp3 = icmp sgt i32 %b, 2 %cmp = and i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 false } define i1 @and_of_icmps1(i32 %b) { ; CHECK-LABEL: @and_of_icmps1( +; CHECK-NEXT: ret i1 false +; %1 = add nsw i32 %b, 2 %2 = icmp slt i32 %1, 4 %cmp3 = icmp sgt i32 %b, 2 %cmp = and i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 false } define i1 @and_of_icmps2(i32 %b) { ; CHECK-LABEL: @and_of_icmps2( +; CHECK-NEXT: ret i1 false +; %1 = add i32 %b, 2 %2 = icmp ule i32 %1, 3 %cmp3 = icmp sgt i32 %b, 2 %cmp = and i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 false } define i1 @and_of_icmps3(i32 %b) { ; CHECK-LABEL: @and_of_icmps3( +; CHECK-NEXT: ret i1 false +; %1 = add nsw i32 %b, 2 %2 = icmp sle i32 %1, 3 %cmp3 = icmp sgt i32 %b, 2 %cmp = and i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 false } define i1 @and_of_icmps4(i32 %b) { ; CHECK-LABEL: @and_of_icmps4( +; CHECK-NEXT: ret i1 false +; %1 = add nuw i32 %b, 2 %2 = icmp ult i32 %1, 4 %cmp3 = icmp ugt i32 %b, 2 %cmp = and i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 false } define i1 @and_of_icmps5(i32 %b) { ; CHECK-LABEL: @and_of_icmps5( +; CHECK-NEXT: ret i1 false +; %1 = add nuw i32 %b, 2 %2 = icmp ule i32 %1, 3 %cmp3 = icmp ugt i32 %b, 2 %cmp = and i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 false } define i1 @or_of_icmps0(i32 %b) { ; CHECK-LABEL: @or_of_icmps0( +; CHECK-NEXT: ret i1 true +; %1 = add i32 %b, 2 %2 = icmp uge i32 %1, 4 %cmp3 = icmp sle i32 %b, 2 %cmp = or i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 true } define i1 @or_of_icmps1(i32 %b) { ; CHECK-LABEL: @or_of_icmps1( +; CHECK-NEXT: ret i1 true +; %1 = add nsw i32 %b, 2 %2 = icmp sge i32 %1, 4 %cmp3 = icmp sle i32 %b, 2 %cmp = or i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 true } define i1 @or_of_icmps2(i32 %b) { ; CHECK-LABEL: @or_of_icmps2( +; CHECK-NEXT: ret i1 true +; %1 = add i32 %b, 2 %2 = icmp ugt i32 %1, 3 %cmp3 = icmp sle i32 %b, 2 %cmp = or i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 true } define i1 @or_of_icmps3(i32 %b) { ; CHECK-LABEL: @or_of_icmps3( +; CHECK-NEXT: ret i1 true +; %1 = add nsw i32 %b, 2 %2 = icmp sgt i32 %1, 3 %cmp3 = icmp sle i32 %b, 2 %cmp = or i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 true } define i1 @or_of_icmps4(i32 %b) { ; CHECK-LABEL: @or_of_icmps4( +; CHECK-NEXT: ret i1 true +; %1 = add nuw i32 %b, 2 %2 = icmp uge i32 %1, 4 %cmp3 = icmp ule i32 %b, 2 %cmp = or i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 true } define i1 @or_of_icmps5(i32 %b) { ; CHECK-LABEL: @or_of_icmps5( +; CHECK-NEXT: ret i1 true +; %1 = add nuw i32 %b, 2 %2 = icmp ugt i32 %1, 3 %cmp3 = icmp ule i32 %b, 2 %cmp = or i1 %2, %cmp3 ret i1 %cmp -; CHECK: ret i1 true } define i32 @neg_nuw(i32 %x) { ; CHECK-LABEL: @neg_nuw( +; CHECK-NEXT: ret i32 0 +; %neg = sub nuw i32 0, %x ret i32 %neg -; CHECK: ret i32 0 } define i1 @and_icmp1(i32 %x, i32 %y) { +; CHECK-LABEL: @and_icmp1( +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 %x, %y +; CHECK-NEXT: ret i1 [[TMP1]] +; %1 = icmp ult i32 %x, %y %2 = icmp ne i32 %y, 0 %3 = and i1 %1, %2 ret i1 %3 } -; CHECK-LABEL: @and_icmp1( -; CHECK: %[[cmp:.*]] = icmp ult i32 %x, %y -; CHECK: ret i1 %[[cmp]] define i1 @and_icmp2(i32 %x, i32 %y) { +; CHECK-LABEL: @and_icmp2( +; CHECK-NEXT: ret i1 false +; %1 = icmp ult i32 %x, %y %2 = icmp eq i32 %y, 0 %3 = and i1 %1, %2 ret i1 %3 } -; CHECK-LABEL: @and_icmp2( -; CHECK: ret i1 false define i1 @or_icmp1(i32 %x, i32 %y) { +; CHECK-LABEL: @or_icmp1( +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 %y, 0 +; CHECK-NEXT: ret i1 [[TMP1]] +; %1 = icmp ult i32 %x, %y %2 = icmp ne i32 %y, 0 %3 = or i1 %1, %2 ret i1 %3 } -; CHECK-LABEL: @or_icmp1( -; CHECK: %[[cmp:.*]] = icmp ne i32 %y, 0 -; CHECK: ret i1 %[[cmp]] define i1 @or_icmp2(i32 %x, i32 %y) { +; CHECK-LABEL: @or_icmp2( +; CHECK-NEXT: ret i1 true +; %1 = icmp uge i32 %x, %y %2 = icmp ne i32 %y, 0 %3 = or i1 %1, %2 ret i1 %3 } -; CHECK-LABEL: @or_icmp2( -; CHECK: ret i1 true define i1 @or_icmp3(i32 %x, i32 %y) { +; CHECK-LABEL: @or_icmp3( +; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i32 %x, %y +; CHECK-NEXT: ret i1 [[TMP1]] +; %1 = icmp uge i32 %x, %y %2 = icmp eq i32 %y, 0 %3 = or i1 %1, %2 ret i1 %3 } -; CHECK-LABEL: @or_icmp3( -; CHECK: %[[cmp:.*]] = icmp uge i32 %x, %y -; CHECK: ret i1 %[[cmp]] + +define i1 @disjoint_cmps(i32 %A) { +; CHECK-LABEL: @disjoint_cmps( +; CHECK-NEXT: ret i1 false +; + %B = icmp eq i32 %A, 1 + %C = icmp sge i32 %A, 3 + %D = and i1 %B, %C + ret i1 %D +} + +define i1 @disjoint_cmps2(i32 %X) { +; CHECK-LABEL: @disjoint_cmps2( +; CHECK-NEXT: ret i1 false +; + %a = icmp ult i32 %X, 31 + %b = icmp slt i32 %X, 0 + %c = and i1 %a, %b + ret i1 %c +} + +; PR27869 - Look through casts to eliminate cmps and bitwise logic. + +define i32 @and_of_zexted_icmps(i32 %i) { +; CHECK-LABEL: @and_of_zexted_icmps( +; CHECK-NEXT: ret i32 0 +; + %cmp0 = icmp eq i32 %i, 0 + %conv0 = zext i1 %cmp0 to i32 + %cmp1 = icmp ugt i32 %i, 4 + %conv1 = zext i1 %cmp1 to i32 + %and = and i32 %conv0, %conv1 + ret i32 %and +} + +; Make sure vectors work too. + +define <4 x i32> @and_of_zexted_icmps_vec(<4 x i32> %i) { +; CHECK-LABEL: @and_of_zexted_icmps_vec( +; CHECK-NEXT: ret <4 x i32> zeroinitializer +; + %cmp0 = icmp eq <4 x i32> %i, zeroinitializer + %conv0 = zext <4 x i1> %cmp0 to <4 x i32> + %cmp1 = icmp slt <4 x i32> %i, zeroinitializer + %conv1 = zext <4 x i1> %cmp1 to <4 x i32> + %and = and <4 x i32> %conv0, %conv1 + ret <4 x i32> %and +} + +; Try a different cast and weird types. + +define i5 @and_of_sexted_icmps(i3 %i) { +; CHECK-LABEL: @and_of_sexted_icmps( +; CHECK-NEXT: ret i5 0 +; + %cmp0 = icmp eq i3 %i, 0 + %conv0 = sext i1 %cmp0 to i5 + %cmp1 = icmp ugt i3 %i, 1 + %conv1 = sext i1 %cmp1 to i5 + %and = and i5 %conv0, %conv1 + ret i5 %and +} + +; Try a different cast and weird vector types. + +define i3 @and_of_bitcast_icmps_vec(<3 x i65> %i) { +; CHECK-LABEL: @and_of_bitcast_icmps_vec( +; CHECK-NEXT: ret i3 0 +; + %cmp0 = icmp sgt <3 x i65> %i, zeroinitializer + %conv0 = bitcast <3 x i1> %cmp0 to i3 + %cmp1 = icmp slt <3 x i65> %i, zeroinitializer + %conv1 = bitcast <3 x i1> %cmp1 to i3 + %and = and i3 %conv0, %conv1 + ret i3 %and +} + +; We can't do this if the casts are different. + +define i16 @and_of_different_cast_icmps(i8 %i) { +; CHECK-LABEL: @and_of_different_cast_icmps( +; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i8 %i, 0 +; CHECK-NEXT: [[CONV0:%.*]] = zext i1 [[CMP0]] to i16 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 %i, 1 +; CHECK-NEXT: [[CONV1:%.*]] = sext i1 [[CMP1]] to i16 +; CHECK-NEXT: [[AND:%.*]] = and i16 [[CONV0]], [[CONV1]] +; CHECK-NEXT: ret i16 [[AND]] +; + %cmp0 = icmp eq i8 %i, 0 + %conv0 = zext i1 %cmp0 to i16 + %cmp1 = icmp eq i8 %i, 1 + %conv1 = sext i1 %cmp1 to i16 + %and = and i16 %conv0, %conv1 + ret i16 %and +} + +define <2 x i3> @and_of_different_cast_icmps_vec(<2 x i8> %i, <2 x i16> %j) { +; CHECK-LABEL: @and_of_different_cast_icmps_vec( +; CHECK-NEXT: [[CMP0:%.*]] = icmp eq <2 x i8> %i, zeroinitializer +; CHECK-NEXT: [[CONV0:%.*]] = zext <2 x i1> [[CMP0]] to <2 x i3> +; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i16> %j, <i16 1, i16 1> +; CHECK-NEXT: [[CONV1:%.*]] = zext <2 x i1> [[CMP1]] to <2 x i3> +; CHECK-NEXT: [[AND:%.*]] = and <2 x i3> [[CONV0]], [[CONV1]] +; CHECK-NEXT: ret <2 x i3> [[AND]] +; + %cmp0 = icmp eq <2 x i8> %i, zeroinitializer + %conv0 = zext <2 x i1> %cmp0 to <2 x i3> + %cmp1 = icmp ugt <2 x i16> %j, <i16 1, i16 1> + %conv1 = zext <2 x i1> %cmp1 to <2 x i3> + %and = and <2 x i3> %conv0, %conv1 + ret <2 x i3> %and +} + diff --git a/test/Transforms/InstSimplify/add-mask.ll b/test/Transforms/InstSimplify/add-mask.ll index 1e53cc5bc7fa..e30a35f53127 100644 --- a/test/Transforms/InstSimplify/add-mask.ll +++ b/test/Transforms/InstSimplify/add-mask.ll @@ -1,8 +1,10 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt -S -instsimplify < %s | FileCheck %s define i1 @test(i32 %a) { -; CHECK-LABEL: @test -; CHECK: ret i1 false +; CHECK-LABEL: @test( +; CHECK: ret i1 false +; %rhs = add i32 %a, -1 %and = and i32 %a, %rhs %res = icmp eq i32 %and, 1 @@ -10,8 +12,9 @@ define i1 @test(i32 %a) { } define i1 @test2(i32 %a) { -; CHECK-LABEL: @test2 -; CHECK: ret i1 false +; CHECK-LABEL: @test2( +; CHECK: ret i1 false +; %rhs = add i32 %a, 1 %and = and i32 %a, %rhs %res = icmp eq i32 %and, 1 @@ -19,8 +22,9 @@ define i1 @test2(i32 %a) { } define i1 @test3(i32 %a) { -; CHECK-LABEL: @test3 -; CHECK: ret i1 false +; CHECK-LABEL: @test3( +; CHECK: ret i1 false +; %rhs = add i32 %a, 7 %and = and i32 %a, %rhs %res = icmp eq i32 %and, 1 @@ -32,8 +36,13 @@ declare void @llvm.assume(i1) ; Known bits without a constant define i1 @test4(i32 %a) { -; CHECK-LABEL: @test4 -; CHECK: ret i1 false +; CHECK-LABEL: @test4( +; CHECK: [[B:%.*]] = load i32, i32* @B +; CHECK-NEXT: [[B_AND:%.*]] = and i32 [[B]], 1 +; CHECK-NEXT: [[B_CND:%.*]] = icmp eq i32 [[B_AND]], 1 +; CHECK-NEXT: call void @llvm.assume(i1 [[B_CND]]) +; CHECK-NEXT: ret i1 false +; %b = load i32, i32* @B %b.and = and i32 %b, 1 %b.cnd = icmp eq i32 %b.and, 1 @@ -47,8 +56,12 @@ define i1 @test4(i32 %a) { ; Negative test - even number define i1 @test5(i32 %a) { -; CHECK-LABEL: @test5 -; CHECK: ret i1 %res +; CHECK-LABEL: @test5( +; CHECK: [[RHS:%.*]] = add i32 %a, 2 +; CHECK-NEXT: [[AND:%.*]] = and i32 %a, [[RHS]] +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[AND]], 1 +; CHECK-NEXT: ret i1 [[RES]] +; %rhs = add i32 %a, 2 %and = and i32 %a, %rhs %res = icmp eq i32 %and, 1 @@ -56,8 +69,9 @@ define i1 @test5(i32 %a) { } define i1 @test6(i32 %a) { -; CHECK-LABEL: @test6 -; CHECK: ret i1 false +; CHECK-LABEL: @test6( +; CHECK: ret i1 false +; %lhs = add i32 %a, -1 %and = and i32 %lhs, %a %res = icmp eq i32 %and, 1 diff --git a/test/Transforms/InstSimplify/apint-or.ll b/test/Transforms/InstSimplify/apint-or.ll index 36844289aaf0..e3dc2c48fb40 100644 --- a/test/Transforms/InstSimplify/apint-or.ll +++ b/test/Transforms/InstSimplify/apint-or.ll @@ -1,7 +1,13 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s ; Test the case where integer BitWidth <= 64 && BitWidth % 2 != 0. define i39 @test1(i39 %V, i39 %M) { +; CHECK-LABEL: @test1( +; CHECK: [[N:%.*]] = and i39 %M, -274877906944 +; CHECK-NEXT: [[A:%.*]] = add i39 %V, [[N]] +; CHECK-NEXT: ret i39 [[A]] +; ;; If we have: ((V + N) & C1) | (V & C2) ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 ;; replace with V+N. @@ -12,28 +18,31 @@ define i39 @test1(i39 %V, i39 %M) { %D = and i39 %V, 274877906943 %R = or i39 %B, %D ret i39 %R -; CHECK-LABEL: @test1 -; CHECK-NEXT: and {{.*}}, -274877906944 -; CHECK-NEXT: add -; CHECK-NEXT: ret } define i7 @test2(i7 %X) { +; CHECK-LABEL: @test2( +; CHECK: ret i7 %X +; %Y = or i7 %X, 0 ret i7 %Y -; CHECK-LABEL: @test2 -; CHECK-NEXT: ret i7 %X } define i17 @test3(i17 %X) { +; CHECK-LABEL: @test3( +; CHECK: ret i17 -1 +; %Y = or i17 %X, -1 ret i17 %Y -; CHECK-LABEL: @test3 -; CHECK-NEXT: ret i17 -1 } -; Test the case where Integer BitWidth > 64 && BitWidth <= 1024. +; Test the case where Integer BitWidth > 64 && BitWidth <= 1024. define i399 @test4(i399 %V, i399 %M) { +; CHECK-LABEL: @test4( +; CHECK: [[N:%.*]] = and i399 %M, 18446742974197923840 +; CHECK-NEXT: [[A:%.*]] = add i399 %V, [[N]] +; CHECK-NEXT: ret i399 [[A]] +; ;; If we have: ((V + N) & C1) | (V & C2) ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 ;; replace with V+N. @@ -44,22 +53,20 @@ define i399 @test4(i399 %V, i399 %M) { %D = and i399 %V, 274877906943 %R = or i399 %B, %D ret i399 %R -; CHECK-LABEL: @test4 -; CHECK-NEXT: and {{.*}}, 18446742974197923840 -; CHECK-NEXT: add -; CHECK-NEXT: ret } define i777 @test5(i777 %X) { +; CHECK-LABEL: @test5( +; CHECK: ret i777 %X +; %Y = or i777 %X, 0 ret i777 %Y -; CHECK-LABEL: @test5 -; CHECK-NEXT: ret i777 %X } define i117 @test6(i117 %X) { +; CHECK-LABEL: @test6( +; CHECK: ret i117 -1 +; %Y = or i117 %X, -1 ret i117 %Y -; CHECK-LABEL: @test6 -; CHECK-NEXT: ret i117 -1 } diff --git a/test/Transforms/InstSimplify/assume.ll b/test/Transforms/InstSimplify/assume.ll index 4dd0a8f4a82d..2487a9c8bb15 100644 --- a/test/Transforms/InstSimplify/assume.ll +++ b/test/Transforms/InstSimplify/assume.ll @@ -1,12 +1,13 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt -instsimplify -S < %s | FileCheck %s define void @test1() { +; CHECK-LABEL: @test1( +; CHECK: ret void +; call void @llvm.assume(i1 1) ret void -; CHECK-LABEL: @test1 -; CHECK-NOT: llvm.assume -; CHECK: ret void } declare void @llvm.assume(i1) nounwind diff --git a/test/Transforms/InstSimplify/bswap.ll b/test/Transforms/InstSimplify/bswap.ll index 7bc3af9e307f..5c67aa0a7643 100644 --- a/test/Transforms/InstSimplify/bswap.ll +++ b/test/Transforms/InstSimplify/bswap.ll @@ -1,10 +1,12 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -S -instsimplify | FileCheck %s declare i16 @llvm.bswap.i16(i16) define i1 @test1(i16 %arg) { -; CHECK-LABEL: @test1 -; CHECK: ret i1 false +; CHECK-LABEL: @test1( +; CHECK: ret i1 false +; %a = or i16 %arg, 1 %b = call i16 @llvm.bswap.i16(i16 %a) %res = icmp eq i16 %b, 0 @@ -12,8 +14,9 @@ define i1 @test1(i16 %arg) { } define i1 @test2(i16 %arg) { -; CHECK-LABEL: @test2 -; CHECK: ret i1 false +; CHECK-LABEL: @test2( +; CHECK: ret i1 false +; %a = or i16 %arg, 1024 %b = call i16 @llvm.bswap.i16(i16 %a) %res = icmp eq i16 %b, 0 @@ -21,8 +24,9 @@ define i1 @test2(i16 %arg) { } define i1 @test3(i16 %arg) { -; CHECK-LABEL: @test3 -; CHECK: ret i1 false +; CHECK-LABEL: @test3( +; CHECK: ret i1 false +; %a = and i16 %arg, 1 %b = call i16 @llvm.bswap.i16(i16 %a) %and = and i16 %b, 1 @@ -31,8 +35,9 @@ define i1 @test3(i16 %arg) { } define i1 @test4(i16 %arg) { -; CHECK-LABEL: @test4 -; CHECK: ret i1 false +; CHECK-LABEL: @test4( +; CHECK: ret i1 false +; %a = and i16 %arg, 511 %b = call i16 @llvm.bswap.i16(i16 %a) %and = and i16 %b, 256 diff --git a/test/Transforms/InstSimplify/call.ll b/test/Transforms/InstSimplify/call.ll index b360ecb84342..988ec2b71c50 100644 --- a/test/Transforms/InstSimplify/call.ll +++ b/test/Transforms/InstSimplify/call.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -instsimplify -S | FileCheck %s +; RUN: opt < %s -passes=instsimplify -S | FileCheck %s declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b) declare {i8, i1} @llvm.usub.with.overflow.i8(i8 %a, i8 %b) @@ -187,4 +188,38 @@ cast.end: ; preds = %cast.notnull, %entr ; CHECK: br i1 %cmp, label %cast.end, label %cast.notnull } +define i32 @call_null() { +entry: + %call = call i32 null() + ret i32 %call +} +; CHECK-LABEL: define i32 @call_null( +; CHECK: ret i32 undef + +define i32 @call_undef() { +entry: + %call = call i32 undef() + ret i32 %call +} +; CHECK-LABEL: define i32 @call_undef( +; CHECK: ret i32 undef + +@GV = private constant [8 x i32] [i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49] + +define <8 x i32> @partial_masked_load() { +; CHECK-LABEL: @partial_masked_load( +; CHECK: ret <8 x i32> <i32 undef, i32 undef, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47> + %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* bitcast (i32* getelementptr ([8 x i32], [8 x i32]* @GV, i64 0, i64 -2) to <8 x i32>*), i32 4, <8 x i1> <i1 false, i1 false, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> undef) + ret <8 x i32> %masked.load +} + +define <8 x i32> @masked_load_undef_mask(<8 x i32>* %V) { +; CHECK-LABEL: @masked_load_undef_mask( +; CHECK: ret <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0> + %masked.load = call <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>* %V, i32 4, <8 x i1> undef, <8 x i32> <i32 1, i32 0, i32 1, i32 0, i32 1, i32 0, i32 1, i32 0>) + ret <8 x i32> %masked.load +} + declare noalias i8* @malloc(i64) + +declare <8 x i32> @llvm.masked.load.v8i32.p0v8i32(<8 x i32>*, i32, <8 x i1>, <8 x i32>) diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll index 6e66fbfede9f..9d6fd74ae56f 100644 --- a/test/Transforms/InstSimplify/compare.ll +++ b/test/Transforms/InstSimplify/compare.ll @@ -333,6 +333,21 @@ define i1 @or(i32 %x) { ; CHECK: ret i1 false } +; Do not simplify if we cannot guarantee that the ConstantExpr is a non-zero +; constant. +@GV = common global i32* null +define i1 @or_constexp(i32 %x) { +; CHECK-LABEL: @or_constexp( +entry: + %0 = and i32 ptrtoint (i32** @GV to i32), 32 + %o = or i32 %x, %0 + %c = icmp eq i32 %o, 0 + ret i1 %c +; CHECK: or +; CHECK-NEXT: icmp eq +; CHECK-NOT: ret i1 false +} + define i1 @shl1(i32 %x) { ; CHECK-LABEL: @shl1( %s = shl i32 1, %x @@ -397,6 +412,22 @@ define i1 @lshr3(i32 %x) { ; CHECK: ret i1 true } +define i1 @lshr4(i32 %X, i32 %Y) { +; CHECK-LABEL: @lshr4( + %A = lshr i32 %X, %Y + %C = icmp ule i32 %A, %X + ret i1 %C +; CHECK: ret i1 true +} + +define i1 @lshr5(i32 %X, i32 %Y) { +; CHECK-LABEL: @lshr5( + %A = lshr i32 %X, %Y + %C = icmp ugt i32 %A, %X + ret i1 %C +; CHECK: ret i1 false +} + define i1 @ashr1(i32 %x) { ; CHECK-LABEL: @ashr1( %s = ashr i32 -1, %x @@ -1172,3 +1203,140 @@ define i1 @tautological9(i32 %x) { ; CHECK-LABEL: @tautological9( ; CHECK: ret i1 true } + +declare void @helper_i1(i1) +; Series of tests for icmp s[lt|ge] (or A, B), A and icmp s[gt|le] A, (or A, B) +define void @icmp_slt_sge_or(i32 %Ax, i32 %Bx) { +; 'p' for positive, 'n' for negative, 'x' for potentially either. +; %D is 'icmp slt (or A, B), A' +; %E is 'icmp sge (or A, B), A' making it the not of %D +; %F is 'icmp sgt A, (or A, B)' making it the same as %D +; %G is 'icmp sle A, (or A, B)' making it the not of %D + %Aneg = or i32 %Ax, 2147483648 + %Apos = and i32 %Ax, 2147483647 + %Bneg = or i32 %Bx, 2147483648 + %Bpos = and i32 %Bx, 2147483647 + + %Cpp = or i32 %Apos, %Bpos + %Dpp = icmp slt i32 %Cpp, %Apos + %Epp = icmp sge i32 %Cpp, %Apos + %Fpp = icmp sgt i32 %Apos, %Cpp + %Gpp = icmp sle i32 %Apos, %Cpp + %Cpx = or i32 %Apos, %Bx + %Dpx = icmp slt i32 %Cpx, %Apos + %Epx = icmp sge i32 %Cpx, %Apos + %Fpx = icmp sgt i32 %Apos, %Cpx + %Gpx = icmp sle i32 %Apos, %Cpx + %Cpn = or i32 %Apos, %Bneg + %Dpn = icmp slt i32 %Cpn, %Apos + %Epn = icmp sge i32 %Cpn, %Apos + %Fpn = icmp sgt i32 %Apos, %Cpn + %Gpn = icmp sle i32 %Apos, %Cpn + + %Cxp = or i32 %Ax, %Bpos + %Dxp = icmp slt i32 %Cxp, %Ax + %Exp = icmp sge i32 %Cxp, %Ax + %Fxp = icmp sgt i32 %Ax, %Cxp + %Gxp = icmp sle i32 %Ax, %Cxp + %Cxx = or i32 %Ax, %Bx + %Dxx = icmp slt i32 %Cxx, %Ax + %Exx = icmp sge i32 %Cxx, %Ax + %Fxx = icmp sgt i32 %Ax, %Cxx + %Gxx = icmp sle i32 %Ax, %Cxx + %Cxn = or i32 %Ax, %Bneg + %Dxn = icmp slt i32 %Cxn, %Ax + %Exn = icmp sge i32 %Cxn, %Ax + %Fxn = icmp sgt i32 %Ax, %Cxn + %Gxn = icmp sle i32 %Ax, %Cxn + + %Cnp = or i32 %Aneg, %Bpos + %Dnp = icmp slt i32 %Cnp, %Aneg + %Enp = icmp sge i32 %Cnp, %Aneg + %Fnp = icmp sgt i32 %Aneg, %Cnp + %Gnp = icmp sle i32 %Aneg, %Cnp + %Cnx = or i32 %Aneg, %Bx + %Dnx = icmp slt i32 %Cnx, %Aneg + %Enx = icmp sge i32 %Cnx, %Aneg + %Fnx = icmp sgt i32 %Aneg, %Cnx + %Gnx = icmp sle i32 %Aneg, %Cnx + %Cnn = or i32 %Aneg, %Bneg + %Dnn = icmp slt i32 %Cnn, %Aneg + %Enn = icmp sge i32 %Cnn, %Aneg + %Fnn = icmp sgt i32 %Aneg, %Cnn + %Gnn = icmp sle i32 %Aneg, %Cnn + + call void @helper_i1(i1 %Dpp) + call void @helper_i1(i1 %Epp) + call void @helper_i1(i1 %Fpp) + call void @helper_i1(i1 %Gpp) + call void @helper_i1(i1 %Dpx) + call void @helper_i1(i1 %Epx) + call void @helper_i1(i1 %Fpx) + call void @helper_i1(i1 %Gpx) + call void @helper_i1(i1 %Dpn) + call void @helper_i1(i1 %Epn) + call void @helper_i1(i1 %Fpn) + call void @helper_i1(i1 %Gpn) + call void @helper_i1(i1 %Dxp) + call void @helper_i1(i1 %Exp) + call void @helper_i1(i1 %Fxp) + call void @helper_i1(i1 %Gxp) + call void @helper_i1(i1 %Dxx) + call void @helper_i1(i1 %Exx) + call void @helper_i1(i1 %Fxx) + call void @helper_i1(i1 %Gxx) + call void @helper_i1(i1 %Dxn) + call void @helper_i1(i1 %Exn) + call void @helper_i1(i1 %Fxn) + call void @helper_i1(i1 %Gxn) + call void @helper_i1(i1 %Dnp) + call void @helper_i1(i1 %Enp) + call void @helper_i1(i1 %Fnp) + call void @helper_i1(i1 %Gnp) + call void @helper_i1(i1 %Dnx) + call void @helper_i1(i1 %Enx) + call void @helper_i1(i1 %Fnx) + call void @helper_i1(i1 %Gnx) + call void @helper_i1(i1 %Dnn) + call void @helper_i1(i1 %Enn) + call void @helper_i1(i1 %Fnn) + call void @helper_i1(i1 %Gnn) +; CHECK-LABEL: @icmp_slt_sge_or +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 %Dpx) +; CHECK: call void @helper_i1(i1 %Epx) +; CHECK: call void @helper_i1(i1 %Fpx) +; CHECK: call void @helper_i1(i1 %Gpx) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 %Dxx) +; CHECK: call void @helper_i1(i1 %Exx) +; CHECK: call void @helper_i1(i1 %Fxx) +; CHECK: call void @helper_i1(i1 %Gxx) +; CHECK: call void @helper_i1(i1 %Dxn) +; CHECK: call void @helper_i1(i1 %Exn) +; CHECK: call void @helper_i1(i1 %Fxn) +; CHECK: call void @helper_i1(i1 %Gxn) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) +; CHECK: call void @helper_i1(i1 false) +; CHECK: call void @helper_i1(i1 true) + ret void +} diff --git a/test/Transforms/InstSimplify/fast-math.ll b/test/Transforms/InstSimplify/fast-math.ll index 90532fa5db84..f4f31236e5cc 100644 --- a/test/Transforms/InstSimplify/fast-math.ll +++ b/test/Transforms/InstSimplify/fast-math.ll @@ -1,44 +1,60 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s ;; x * 0 ==> 0 when no-nans and no-signed-zero -; CHECK: mul_zero_1 define float @mul_zero_1(float %a) { +; CHECK-LABEL: @mul_zero_1( +; CHECK: ret float 0.000000e+00 +; %b = fmul nsz nnan float %a, 0.0 -; CHECK: ret float 0.0 ret float %b } -; CHECK: mul_zero_2 + define float @mul_zero_2(float %a) { +; CHECK-LABEL: @mul_zero_2( +; CHECK: ret float 0.000000e+00 +; %b = fmul fast float 0.0, %a -; CHECK: ret float 0.0 ret float %b } ;; x * 0 =/=> 0 when there could be nans or -0 -; CHECK: no_mul_zero_1 define float @no_mul_zero_1(float %a) { +; CHECK-LABEL: @no_mul_zero_1( +; CHECK: [[B:%.*]] = fmul nsz float %a, 0.000000e+00 +; CHECK-NEXT: ret float [[B]] +; %b = fmul nsz float %a, 0.0 -; CHECK: ret float %b ret float %b } -; CHECK: no_mul_zero_2 + define float @no_mul_zero_2(float %a) { +; CHECK-LABEL: @no_mul_zero_2( +; CHECK: [[B:%.*]] = fmul nnan float %a, 0.000000e+00 +; CHECK-NEXT: ret float [[B]] +; %b = fmul nnan float %a, 0.0 -; CHECK: ret float %b ret float %b } -; CHECK: no_mul_zero_3 + define float @no_mul_zero_3(float %a) { +; CHECK-LABEL: @no_mul_zero_3( +; CHECK: [[B:%.*]] = fmul float %a, 0.000000e+00 +; CHECK-NEXT: ret float [[B]] +; %b = fmul float %a, 0.0 -; CHECK: ret float %b ret float %b } ; fadd [nnan ninf] X, (fsub [nnan ninf] 0, X) ==> 0 ; where nnan and ninf have to occur at least once somewhere in this ; expression -; CHECK: fadd_fsub_0 define float @fadd_fsub_0(float %a) { +; CHECK-LABEL: @fadd_fsub_0( +; CHECK: [[NOFOLD:%.*]] = fsub float 0.000000e+00, %a +; CHECK-NEXT: [[NO_ZERO:%.*]] = fadd nnan float [[NOFOLD]], %a +; CHECK-NEXT: ret float [[NO_ZERO]] +; ; X + -X ==> 0 %t1 = fsub nnan ninf float 0.0, %a %zero1 = fadd nnan ninf float %t1, %a @@ -53,9 +69,7 @@ define float @fadd_fsub_0(float %a) { %zero4 = fadd nnan ninf float %t4, %a ; Dont fold this -; CHECK: %nofold = fsub float 0.0 %nofold = fsub float 0.0, %a -; CHECK: %no_zero = fadd nnan float %nofold, %a %no_zero = fadd nnan float %nofold, %a ; Coalesce the folded zeros @@ -66,108 +80,126 @@ define float @fadd_fsub_0(float %a) { ; Should get folded %ret = fadd nsz float %no_zero, %zero7 -; CHECK: ret float %no_zero ret float %ret } ; fsub nnan x, x ==> 0.0 -; CHECK-LABEL: @fsub_x_x( define float @fsub_x_x(float %a) { +; CHECK-LABEL: @fsub_x_x( +; CHECK: [[NO_ZERO1:%.*]] = fsub ninf float %a, %a +; CHECK-NEXT: [[NO_ZERO2:%.*]] = fsub float %a, %a +; CHECK-NEXT: [[NO_ZERO:%.*]] = fadd float [[NO_ZERO1:%.*]], [[NO_ZERO2:%.*]] +; CHECK-NEXT: ret float [[NO_ZERO]] +; ; X - X ==> 0 %zero1 = fsub nnan float %a, %a ; Dont fold -; CHECK: %no_zero1 = fsub %no_zero1 = fsub ninf float %a, %a -; CHECK: %no_zero2 = fsub %no_zero2 = fsub float %a, %a -; CHECK: %no_zero = fadd %no_zero = fadd float %no_zero1, %no_zero2 ; Should get folded %ret = fadd nsz float %no_zero, %zero1 -; CHECK: ret float %no_zero + ret float %ret +} + +; fsub nsz 0.0, (fsub 0.0, X) ==> X +define float @fsub_0_0_x(float %a) { +; CHECK-LABEL: @fsub_0_0_x( +; CHECK: ret float %a +; + %t1 = fsub float 0.0, %a + %ret = fsub nsz float 0.0, %t1 ret float %ret } ; fadd nsz X, 0 ==> X -; CHECK-LABEL: @nofold_fadd_x_0( define float @nofold_fadd_x_0(float %a) { +; CHECK-LABEL: @nofold_fadd_x_0( +; CHECK: [[NO_ZERO1:%.*]] = fadd ninf float %a, 0.000000e+00 +; CHECK-NEXT: [[NO_ZERO2:%.*]] = fadd nnan float %a, 0.000000e+00 +; CHECK-NEXT: [[NO_ZERO:%.*]] = fadd float [[NO_ZERO1:%.*]], [[NO_ZERO2:%.*]] +; CHECK-NEXT: ret float [[NO_ZERO]] +; ; Dont fold -; CHECK: %no_zero1 = fadd %no_zero1 = fadd ninf float %a, 0.0 -; CHECK: %no_zero2 = fadd %no_zero2 = fadd nnan float %a, 0.0 -; CHECK: %no_zero = fadd %no_zero = fadd float %no_zero1, %no_zero2 - -; CHECK: ret float %no_zero ret float %no_zero } ; fdiv nsz nnan 0, X ==> 0 define double @fdiv_zero_by_x(double %X) { ; CHECK-LABEL: @fdiv_zero_by_x( +; CHECK: ret double 0.000000e+00 +; ; 0 / X -> 0 %r = fdiv nnan nsz double 0.0, %X ret double %r -; CHECK: ret double 0 } define float @fdiv_self(float %f) { +; CHECK-LABEL: @fdiv_self( +; CHECK: ret float 1.000000e+00 +; %div = fdiv nnan float %f, %f ret float %div -; CHECK-LABEL: fdiv_self -; CHECK: ret float 1.000000e+00 } define float @fdiv_self_invalid(float %f) { +; CHECK-LABEL: @fdiv_self_invalid( +; CHECK: [[DIV:%.*]] = fdiv float %f, %f +; CHECK-NEXT: ret float [[DIV]] +; %div = fdiv float %f, %f ret float %div -; CHECK-LABEL: fdiv_self_invalid -; CHECK: %div = fdiv float %f, %f -; CHECK-NEXT: ret float %div } define float @fdiv_neg1(float %f) { +; CHECK-LABEL: @fdiv_neg1( +; CHECK: ret float -1.000000e+00 +; %neg = fsub fast float -0.000000e+00, %f %div = fdiv nnan float %neg, %f ret float %div -; CHECK-LABEL: fdiv_neg1 -; CHECK: ret float -1.000000e+00 } define float @fdiv_neg2(float %f) { +; CHECK-LABEL: @fdiv_neg2( +; CHECK: ret float -1.000000e+00 +; %neg = fsub fast float 0.000000e+00, %f %div = fdiv nnan float %neg, %f ret float %div -; CHECK-LABEL: fdiv_neg2 -; CHECK: ret float -1.000000e+00 } define float @fdiv_neg_invalid(float %f) { +; CHECK-LABEL: @fdiv_neg_invalid( +; CHECK: [[NEG:%.*]] = fsub fast float -0.000000e+00, %f +; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], %f +; CHECK-NEXT: ret float [[DIV]] +; %neg = fsub fast float -0.000000e+00, %f %div = fdiv float %neg, %f ret float %div -; CHECK-LABEL: fdiv_neg_invalid -; CHECK: %neg = fsub fast float -0.000000e+00, %f -; CHECK-NEXT: %div = fdiv float %neg, %f -; CHECK-NEXT: ret float %div } define float @fdiv_neg_swapped1(float %f) { +; CHECK-LABEL: @fdiv_neg_swapped1( +; CHECK: ret float -1.000000e+00 +; %neg = fsub float -0.000000e+00, %f %div = fdiv nnan float %f, %neg ret float %div -; CHECK-LABEL: fdiv_neg_swapped1 -; CHECK: ret float -1.000000e+00 } define float @fdiv_neg_swapped2(float %f) { +; CHECK-LABEL: @fdiv_neg_swapped2( +; CHECK: ret float -1.000000e+00 +; %neg = fsub float 0.000000e+00, %f %div = fdiv nnan float %f, %neg ret float %div -; CHECK-LABEL: fdiv_neg_swapped2 -; CHECK: ret float -1.000000e+00 } diff --git a/test/Transforms/InstSimplify/fdiv.ll b/test/Transforms/InstSimplify/fdiv.ll index 53ad25d07476..bb7f443f4238 100644 --- a/test/Transforms/InstSimplify/fdiv.ll +++ b/test/Transforms/InstSimplify/fdiv.ll @@ -1,17 +1,20 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s define double @fdiv_of_undef(double %X) { ; CHECK-LABEL: @fdiv_of_undef( +; CHECK: ret double undef +; ; undef / X -> undef %r = fdiv double undef, %X ret double %r -; CHECK: ret double undef } define double @fdiv_by_undef(double %X) { ; CHECK-LABEL: @fdiv_by_undef( +; CHECK: ret double undef +; ; X / undef -> undef %r = fdiv double %X, undef ret double %r -; CHECK: ret double undef } diff --git a/test/Transforms/InstSimplify/floating-point-arithmetic.ll b/test/Transforms/InstSimplify/floating-point-arithmetic.ll index b0957a817739..b825ac80b6d6 100644 --- a/test/Transforms/InstSimplify/floating-point-arithmetic.ll +++ b/test/Transforms/InstSimplify/floating-point-arithmetic.ll @@ -1,51 +1,83 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s -; fsub 0, (fsub 0, X) ==> X -; CHECK-LABEL: @fsub_0_0_x( -define float @fsub_0_0_x(float %a) { +; fsub -0.0, (fsub -0.0, X) ==> X +define float @fsub_-0_-0_x(float %a) { +; CHECK-LABEL: @fsub_-0_-0_x( +; CHECK: ret float %a +; %t1 = fsub float -0.0, %a %ret = fsub float -0.0, %t1 + ret float %ret +} + +; fsub 0.0, (fsub -0.0, X) != X +define float @fsub_0_-0_x(float %a) { +; CHECK-LABEL: @fsub_0_-0_x( +; CHECK: [[T1:%.*]] = fsub float 0.000000e+00, %a +; CHECK-NEXT: [[RET:%.*]] = fsub float -0.000000e+00, [[T1]] +; CHECK-NEXT: ret float [[RET]] +; + %t1 = fsub float 0.0, %a + %ret = fsub float -0.0, %t1 + ret float %ret +} -; CHECK: ret float %a +; fsub -0.0, (fsub 0.0, X) != X +define float @fsub_-0_0_x(float %a) { +; CHECK-LABEL: @fsub_-0_0_x( +; CHECK: [[T1:%.*]] = fsub float -0.000000e+00, %a +; CHECK-NEXT: [[RET:%.*]] = fsub float 0.000000e+00, [[T1]] +; CHECK-NEXT: ret float [[RET]] +; + %t1 = fsub float -0.0, %a + %ret = fsub float 0.0, %t1 ret float %ret } ; fsub X, 0 ==> X -; CHECK-LABEL: @fsub_x_0( define float @fsub_x_0(float %a) { +; CHECK-LABEL: @fsub_x_0( +; CHECK: ret float %a +; %ret = fsub float %a, 0.0 -; CHECK: ret float %a ret float %ret } ; fadd X, -0 ==> X -; CHECK-LABEL: @fadd_x_n0( define float @fadd_x_n0(float %a) { +; CHECK-LABEL: @fadd_x_n0( +; CHECK: ret float %a +; %ret = fadd float %a, -0.0 -; CHECK: ret float %a ret float %ret } ; fmul X, 1.0 ==> X -; CHECK-LABEL: @fmul_X_1( define double @fmul_X_1(double %a) { - %b = fmul double 1.000000e+00, %a ; <double> [#uses=1] - ; CHECK: ret double %a +; CHECK-LABEL: @fmul_X_1( +; CHECK: ret double %a +; + %b = fmul double 1.000000e+00, %a ret double %b } ; We can't optimize away the fadd in this test because the input -; value to the function and subsequently to the fadd may be -0.0. +; value to the function and subsequently to the fadd may be -0.0. ; In that one special case, the result of the fadd should be +0.0 ; rather than the first parameter of the fadd. -; Fragile test warning: We need 6 sqrt calls to trigger the bug -; because the internal logic has a magic recursion limit of 6. +; Fragile test warning: We need 6 sqrt calls to trigger the bug +; because the internal logic has a magic recursion limit of 6. ; This is presented without any explanation or ability to customize. declare float @sqrtf(float) define float @PR22688(float %x) { +; CHECK-LABEL: @PR22688( +; CHECK: [[TMP7:%.*]] = fadd float {{%.*}}, 0.000000e+00 +; CHECK-NEXT: ret float [[TMP7]] +; %1 = call float @sqrtf(float %x) %2 = call float @sqrtf(float %1) %3 = call float @sqrtf(float %2) @@ -54,8 +86,5 @@ define float @PR22688(float %x) { %6 = call float @sqrtf(float %5) %7 = fadd float %6, 0.0 ret float %7 - -; CHECK-LABEL: @PR22688( -; CHECK: fadd float %6, 0.0 } diff --git a/test/Transforms/InstSimplify/floating-point-compare.ll b/test/Transforms/InstSimplify/floating-point-compare.ll index b148d9961d33..7c67ffb4be0d 100644 --- a/test/Transforms/InstSimplify/floating-point-compare.ll +++ b/test/Transforms/InstSimplify/floating-point-compare.ll @@ -1,7 +1,8 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s ; These tests choose arbitrarily between float and double, -; and between uge and olt, to give reasonble coverage +; and between uge and olt, to give reasonble coverage ; without combinatorial explosion. declare float @llvm.fabs.f32(float) @@ -15,8 +16,10 @@ declare float @llvm.fma.f32(float,float,float) declare void @expect_equal(i1,i1) -; CHECK-LABEL: @orderedLessZeroTree( define i1 @orderedLessZeroTree(float,float,float,float) { +; CHECK-LABEL: @orderedLessZeroTree( +; CHECK: ret i1 true +; %square = fmul float %0, %0 %abs = call float @llvm.fabs.f32(float %1) %sqrt = call float @llvm.sqrt.f32(float %2) @@ -25,30 +28,33 @@ define i1 @orderedLessZeroTree(float,float,float,float) { %rem = frem float %sqrt, %fma %add = fadd float %div, %rem %uge = fcmp uge float %add, 0.000000e+00 -; CHECK: ret i1 true ret i1 %uge } -; CHECK-LABEL: @orderedLessZeroExpExt( define i1 @orderedLessZeroExpExt(float) { +; CHECK-LABEL: @orderedLessZeroExpExt( +; CHECK: ret i1 true +; %a = call float @llvm.exp.f32(float %0) %b = fpext float %a to double %uge = fcmp uge double %b, 0.000000e+00 -; CHECK: ret i1 true ret i1 %uge } -; CHECK-LABEL: @orderedLessZeroExp2Trunc( define i1 @orderedLessZeroExp2Trunc(double) { +; CHECK-LABEL: @orderedLessZeroExp2Trunc( +; CHECK: ret i1 false +; %a = call double @llvm.exp2.f64(double %0) %b = fptrunc double %a to float %olt = fcmp olt float %b, 0.000000e+00 -; CHECK: ret i1 false ret i1 %olt } -; CHECK-LABEL: @orderedLessZeroPowi( define i1 @orderedLessZeroPowi(double,double) { +; CHECK-LABEL: @orderedLessZeroPowi( +; CHECK: ret i1 false +; ; Even constant exponent %a = call double @llvm.powi.f64(double %0, i32 2) %square = fmul double %1, %1 @@ -56,61 +62,64 @@ define i1 @orderedLessZeroPowi(double,double) { %b = call double @llvm.powi.f64(double %square, i32 3) %c = fadd double %a, %b %olt = fcmp olt double %b, 0.000000e+00 -; CHECK: ret i1 false ret i1 %olt } -; CHECK-LABEL: @orderedLessZeroUIToFP( define i1 @orderedLessZeroUIToFP(i32) { +; CHECK-LABEL: @orderedLessZeroUIToFP( +; CHECK: ret i1 true +; %a = uitofp i32 %0 to float %uge = fcmp uge float %a, 0.000000e+00 -; CHECK: ret i1 true ret i1 %uge } -; CHECK-LABEL: @orderedLessZeroSelect( define i1 @orderedLessZeroSelect(float, float) { +; CHECK-LABEL: @orderedLessZeroSelect( +; CHECK: ret i1 true +; %a = call float @llvm.exp.f32(float %0) %b = call float @llvm.fabs.f32(float %1) %c = fcmp olt float %0, %1 %d = select i1 %c, float %a, float %b %e = fadd float %d, 1.0 %uge = fcmp uge float %e, 0.000000e+00 -; CHECK: ret i1 true ret i1 %uge } -; CHECK-LABEL: @orderedLessZeroMinNum( define i1 @orderedLessZeroMinNum(float, float) { +; CHECK-LABEL: @orderedLessZeroMinNum( +; CHECK: ret i1 true +; %a = call float @llvm.exp.f32(float %0) %b = call float @llvm.fabs.f32(float %1) %c = call float @llvm.minnum.f32(float %a, float %b) %uge = fcmp uge float %c, 0.000000e+00 -; CHECK: ret i1 true ret i1 %uge } -; CHECK-LABEL: @orderedLessZeroMaxNum( define i1 @orderedLessZeroMaxNum(float, float) { +; CHECK-LABEL: @orderedLessZeroMaxNum( +; CHECK: ret i1 true +; %a = call float @llvm.exp.f32(float %0) %b = call float @llvm.maxnum.f32(float %a, float %1) %uge = fcmp uge float %b, 0.000000e+00 -; CHECK: ret i1 true ret i1 %uge } define i1 @nonans1(double %in1, double %in2) { +; CHECK-LABEL: @nonans1( +; CHECK: ret i1 false +; %cmp = fcmp nnan uno double %in1, %in2 ret i1 %cmp - -; CHECK-LABEL: @nonans1 -; CHECK-NEXT: ret i1 false } define i1 @nonans2(double %in1, double %in2) { +; CHECK-LABEL: @nonans2( +; CHECK: ret i1 true +; %cmp = fcmp nnan ord double %in1, %in2 ret i1 %cmp - -; CHECK-LABEL: @nonans2 -; CHECK-NEXT: ret i1 true } diff --git a/test/Transforms/InstSimplify/implies.ll b/test/Transforms/InstSimplify/implies.ll index 2e3c9591b079..56e1e6a29c49 100644 --- a/test/Transforms/InstSimplify/implies.ll +++ b/test/Transforms/InstSimplify/implies.ll @@ -1,9 +1,11 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt -S %s -instsimplify | FileCheck %s ; A ==> A -> true define i1 @test(i32 %length.i, i32 %i) { -; CHECK-LABEL: @test -; CHECK: ret i1 true +; CHECK-LABEL: @test( +; CHECK: ret i1 true +; %var29 = icmp slt i32 %i, %length.i %res = icmp uge i1 %var29, %var29 ret i1 %res @@ -11,8 +13,9 @@ define i1 @test(i32 %length.i, i32 %i) { ; i +_{nsw} C_{>0} <s L ==> i <s L -> true define i1 @test2(i32 %length.i, i32 %i) { -; CHECK-LABEL: @test2 -; CHECK: ret i1 true +; CHECK-LABEL: @test2( +; CHECK: ret i1 true +; %iplus1 = add nsw i32 %i, 1 %var29 = icmp slt i32 %i, %length.i %var30 = icmp slt i32 %iplus1, %length.i @@ -22,8 +25,13 @@ define i1 @test2(i32 %length.i, i32 %i) { ; i + C_{>0} <s L ==> i <s L -> unknown without the nsw define i1 @test2_neg(i32 %length.i, i32 %i) { -; CHECK-LABEL: @test2_neg -; CHECK: ret i1 %res +; CHECK-LABEL: @test2_neg( +; CHECK: [[IPLUS1:%.*]] = add i32 %i, 1 +; CHECK-NEXT: [[VAR29:%.*]] = icmp slt i32 %i, %length.i +; CHECK-NEXT: [[VAR30:%.*]] = icmp slt i32 [[IPLUS1]], %length.i +; CHECK-NEXT: [[RES:%.*]] = icmp ule i1 [[VAR30]], [[VAR29]] +; CHECK-NEXT: ret i1 [[RES]] +; %iplus1 = add i32 %i, 1 %var29 = icmp slt i32 %i, %length.i %var30 = icmp slt i32 %iplus1, %length.i @@ -33,8 +41,13 @@ define i1 @test2_neg(i32 %length.i, i32 %i) { ; sle is not implication define i1 @test2_neg2(i32 %length.i, i32 %i) { -; CHECK-LABEL: @test2_neg2 -; CHECK: ret i1 %res +; CHECK-LABEL: @test2_neg2( +; CHECK: [[IPLUS1:%.*]] = add i32 %i, 1 +; CHECK-NEXT: [[VAR29:%.*]] = icmp slt i32 %i, %length.i +; CHECK-NEXT: [[VAR30:%.*]] = icmp slt i32 [[IPLUS1]], %length.i +; CHECK-NEXT: [[RES:%.*]] = icmp sle i1 [[VAR30]], [[VAR29]] +; CHECK-NEXT: ret i1 [[RES]] +; %iplus1 = add i32 %i, 1 %var29 = icmp slt i32 %i, %length.i %var30 = icmp slt i32 %iplus1, %length.i @@ -44,8 +57,13 @@ define i1 @test2_neg2(i32 %length.i, i32 %i) { ; The binary operator has to be an add define i1 @test2_neg3(i32 %length.i, i32 %i) { -; CHECK-LABEL: @test2_neg3 -; CHECK: ret i1 %res +; CHECK-LABEL: @test2_neg3( +; CHECK: [[IPLUS1:%.*]] = sub nsw i32 %i, 1 +; CHECK-NEXT: [[VAR29:%.*]] = icmp slt i32 %i, %length.i +; CHECK-NEXT: [[VAR30:%.*]] = icmp slt i32 [[IPLUS1]], %length.i +; CHECK-NEXT: [[RES:%.*]] = icmp ule i1 [[VAR30]], [[VAR29]] +; CHECK-NEXT: ret i1 [[RES]] +; %iplus1 = sub nsw i32 %i, 1 %var29 = icmp slt i32 %i, %length.i %var30 = icmp slt i32 %iplus1, %length.i @@ -56,8 +74,9 @@ define i1 @test2_neg3(i32 %length.i, i32 %i) { ; i +_{nsw} C_{>0} <s L ==> i <s L -> true ; With an inverted conditional (ule B A rather than canonical ugt A B define i1 @test3(i32 %length.i, i32 %i) { -; CHECK-LABEL: @test3 -; CHECK: ret i1 true +; CHECK-LABEL: @test3( +; CHECK: ret i1 true +; %iplus1 = add nsw i32 %i, 1 %var29 = icmp slt i32 %i, %length.i %var30 = icmp slt i32 %iplus1, %length.i @@ -67,8 +86,9 @@ define i1 @test3(i32 %length.i, i32 %i) { ; i +_{nuw} C <u L ==> i <u L define i1 @test4(i32 %length.i, i32 %i) { -; CHECK-LABEL: @test4 -; CHECK: ret i1 true +; CHECK-LABEL: @test4( +; CHECK: ret i1 true +; %iplus1 = add nuw i32 %i, 1 %var29 = icmp ult i32 %i, %length.i %var30 = icmp ult i32 %iplus1, %length.i @@ -78,16 +98,19 @@ define i1 @test4(i32 %length.i, i32 %i) { ; A ==> A for vectors define <4 x i1> @test5(<4 x i1> %vec) { -; CHECK-LABEL: @test5 -; CHECK: ret <4 x i1> <i1 true, i1 true, i1 true, i1 true> +; CHECK-LABEL: @test5( +; CHECK: ret <4 x i1> <i1 true, i1 true, i1 true, i1 true> +; %res = icmp ule <4 x i1> %vec, %vec ret <4 x i1> %res } ; Don't crash on vector inputs - pr25040 define <4 x i1> @test6(<4 x i1> %a, <4 x i1> %b) { -; CHECK-LABEL: @test6 -; CHECK: ret <4 x i1> %res +; CHECK-LABEL: @test6( +; CHECK: [[RES:%.*]] = icmp ule <4 x i1> %a, %b +; CHECK-NEXT: ret <4 x i1> [[RES]] +; %res = icmp ule <4 x i1> %a, %b ret <4 x i1> %res } @@ -95,7 +118,8 @@ define <4 x i1> @test6(<4 x i1> %a, <4 x i1> %b) { ; i +_{nsw} 1 <s L ==> i < L +_{nsw} 1 define i1 @test7(i32 %length.i, i32 %i) { ; CHECK-LABEL: @test7( -; CHECK: ret i1 true +; CHECK: ret i1 true +; %iplus1 = add nsw i32 %i, 1 %len.plus.one = add nsw i32 %length.i, 1 %var29 = icmp slt i32 %i, %len.plus.one @@ -104,10 +128,11 @@ define i1 @test7(i32 %length.i, i32 %i) { ret i1 %res } -; i +_{nuw} 1 <s L ==> i < L +_{nuw} 1 +; i +_{nuw} 1 <u L ==> i < L +_{nuw} 1 define i1 @test8(i32 %length.i, i32 %i) { ; CHECK-LABEL: @test8( -; CHECK: ret i1 true +; CHECK: ret i1 true +; %iplus1 = add nuw i32 %i, 1 %len.plus.one = add nuw i32 %length.i, 1 %var29 = icmp ult i32 %i, %len.plus.one @@ -116,10 +141,11 @@ define i1 @test8(i32 %length.i, i32 %i) { ret i1 %res } -; i +_{nuw} C <s L ==> i < L, even if C is negative +; i +_{nuw} C <u L ==> i < L, even if C is negative define i1 @test9(i32 %length.i, i32 %i) { ; CHECK-LABEL: @test9( -; CHECK: ret i1 true +; CHECK: ret i1 true +; %iplus1 = add nuw i32 %i, -100 %var29 = icmp ult i32 %i, %length.i %var30 = icmp ult i32 %iplus1, %length.i @@ -129,8 +155,8 @@ define i1 @test9(i32 %length.i, i32 %i) { define i1 @test10(i32 %length.i, i32 %x.full) { ; CHECK-LABEL: @test10( -; CHECK: ret i1 true - +; CHECK: ret i1 true +; %x = and i32 %x.full, 4294901760 ;; 4294901760 == 0xffff0000 %large = or i32 %x, 100 %small = or i32 %x, 90 @@ -142,9 +168,13 @@ define i1 @test10(i32 %length.i, i32 %x.full) { define i1 @test11(i32 %length.i, i32 %x) { ; CHECK-LABEL: @test11( -; CHECK: %res = icmp ule i1 %known, %to.prove -; CHECK: ret i1 %res - +; CHECK: [[LARGE:%.*]] = or i32 %x, 100 +; CHECK-NEXT: [[SMALL:%.*]] = or i32 %x, 90 +; CHECK-NEXT: [[KNOWN:%.*]] = icmp ult i32 [[LARGE]], %length.i +; CHECK-NEXT: [[TO_PROVE:%.*]] = icmp ult i32 [[SMALL]], %length.i +; CHECK-NEXT: [[RES:%.*]] = icmp ule i1 [[KNOWN]], [[TO_PROVE]] +; CHECK-NEXT: ret i1 [[RES]] +; %large = or i32 %x, 100 %small = or i32 %x, 90 %known = icmp ult i32 %large, %length.i @@ -155,9 +185,14 @@ define i1 @test11(i32 %length.i, i32 %x) { define i1 @test12(i32 %length.i, i32 %x.full) { ; CHECK-LABEL: @test12( -; CHECK: %res = icmp ule i1 %known, %to.prove -; CHECK: ret i1 %res - +; CHECK: [[X:%.*]] = and i32 [[X:%.*]].full, -65536 +; CHECK-NEXT: [[LARGE:%.*]] = or i32 [[X]], 65536 +; CHECK-NEXT: [[SMALL:%.*]] = or i32 [[X]], 90 +; CHECK-NEXT: [[KNOWN:%.*]] = icmp ult i32 [[LARGE]], %length.i +; CHECK-NEXT: [[TO_PROVE:%.*]] = icmp ult i32 [[SMALL]], %length.i +; CHECK-NEXT: [[RES:%.*]] = icmp ule i1 [[KNOWN]], [[TO_PROVE]] +; CHECK-NEXT: ret i1 [[RES]] +; %x = and i32 %x.full, 4294901760 ;; 4294901760 == 0xffff0000 %large = or i32 %x, 65536 ;; 65536 == 0x00010000 %small = or i32 %x, 90 @@ -169,8 +204,8 @@ define i1 @test12(i32 %length.i, i32 %x.full) { define i1 @test13(i32 %length.i, i32 %x) { ; CHECK-LABEL: @test13( -; CHECK: ret i1 true - +; CHECK: ret i1 true +; %large = add nuw i32 %x, 100 %small = add nuw i32 %x, 90 %known = icmp ult i32 %large, %length.i @@ -181,8 +216,8 @@ define i1 @test13(i32 %length.i, i32 %x) { define i1 @test14(i32 %length.i, i32 %x.full) { ; CHECK-LABEL: @test14( -; CHECK: ret i1 true - +; CHECK: ret i1 true +; %x = and i32 %x.full, 4294905615 ;; 4294905615 == 0xffff0f0f %large = or i32 %x, 8224 ;; == 0x2020 %small = or i32 %x, 4112 ;; == 0x1010 @@ -194,9 +229,13 @@ define i1 @test14(i32 %length.i, i32 %x.full) { define i1 @test15(i32 %length.i, i32 %x) { ; CHECK-LABEL: @test15( -; CHECK: %res = icmp ule i1 %known, %to.prove -; CHECK: ret i1 %res - +; CHECK: [[LARGE:%.*]] = add nuw i32 %x, 100 +; CHECK-NEXT: [[SMALL:%.*]] = add nuw i32 %x, 110 +; CHECK-NEXT: [[KNOWN:%.*]] = icmp ult i32 [[LARGE]], %length.i +; CHECK-NEXT: [[TO_PROVE:%.*]] = icmp ult i32 [[SMALL]], %length.i +; CHECK-NEXT: [[RES:%.*]] = icmp ule i1 [[KNOWN]], [[TO_PROVE]] +; CHECK-NEXT: ret i1 [[RES]] +; %large = add nuw i32 %x, 100 %small = add nuw i32 %x, 110 %known = icmp ult i32 %large, %length.i @@ -207,8 +246,9 @@ define i1 @test15(i32 %length.i, i32 %x) { ; X >=(s) Y == X ==> Y (i1 1 becomes -1 for reasoning) define i1 @test_sge(i32 %length.i, i32 %i) { -; CHECK-LABEL: @test_sge -; CHECK: ret i1 true +; CHECK-LABEL: @test_sge( +; CHECK: ret i1 true +; %iplus1 = add nsw nuw i32 %i, 1 %var29 = icmp ult i32 %i, %length.i %var30 = icmp ult i32 %iplus1, %length.i diff --git a/test/Transforms/InstSimplify/load-relative-32.ll b/test/Transforms/InstSimplify/load-relative-32.ll new file mode 100644 index 000000000000..a38de8549dbd --- /dev/null +++ b/test/Transforms/InstSimplify/load-relative-32.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i386-unknown-linux-gnu" + +@a = external global i8 + +@c1 = constant [3 x i32] [i32 0, i32 0, +i32 sub (i32 ptrtoint (i8* @a to i32), i32 ptrtoint (i32* getelementptr ([3 x i32], [3 x i32]* @c1, i32 0, i32 2) to i32)) +] + +; CHECK: @f1 +define i8* @f1() { + ; CHECK: ret i8* @a + %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([3 x i32], [3 x i32]* @c1, i32 0, i32 2) to i8*), i32 0) + ret i8* %l +} + +declare i8* @llvm.load.relative.i32(i8*, i32) diff --git a/test/Transforms/InstSimplify/load-relative.ll b/test/Transforms/InstSimplify/load-relative.ll new file mode 100644 index 000000000000..3074ede2b697 --- /dev/null +++ b/test/Transforms/InstSimplify/load-relative.ll @@ -0,0 +1,75 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@a = external global i8 +@b = external global i8 + +@c1 = constant i32 trunc (i64 sub (i64 ptrtoint (i8* @a to i64), i64 ptrtoint (i32* @c1 to i64)) to i32) +@c2 = constant [7 x i32] [i32 0, i32 0, +i32 trunc (i64 sub (i64 ptrtoint (i8* @a to i64), i64 ptrtoint (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i32 0, i32 2) to i64)) to i32), +i32 trunc (i64 sub (i64 ptrtoint (i8* @b to i64), i64 ptrtoint (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i32 0, i32 2) to i64)) to i32), +i32 trunc (i64 add (i64 ptrtoint (i8* @b to i64), i64 ptrtoint (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i32 0, i32 2) to i64)) to i32), +i32 trunc (i64 sub (i64 ptrtoint (i8* @b to i64), i64 1) to i32), +i32 trunc (i64 sub (i64 0, i64 ptrtoint (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i32 0, i32 2) to i64)) to i32) +] + +; CHECK: @f1 +define i8* @f1() { + ; CHECK: ret i8* @a + %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* @c1 to i8*), i32 0) + ret i8* %l +} + +; CHECK: @f2 +define i8* @f2() { + ; CHECK: ret i8* @a + %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 0) + ret i8* %l +} + +; CHECK: @f3 +define i8* @f3() { + ; CHECK: ret i8* @b + %l = call i8* @llvm.load.relative.i64(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i64 4) + ret i8* %l +} + +; CHECK: @f4 +define i8* @f4() { + ; CHECK: ret i8* % + %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 1) + ret i8* %l +} + +; CHECK: @f5 +define i8* @f5() { + ; CHECK: ret i8* % + %l = call i8* @llvm.load.relative.i32(i8* zeroinitializer, i32 0) + ret i8* %l +} + +; CHECK: @f6 +define i8* @f6() { + ; CHECK: ret i8* % + %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 8) + ret i8* %l +} + +; CHECK: @f7 +define i8* @f7() { + ; CHECK: ret i8* % + %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 12) + ret i8* %l +} + +; CHECK: @f8 +define i8* @f8() { + ; CHECK: ret i8* % + %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 16) + ret i8* %l +} + +declare i8* @llvm.load.relative.i32(i8*, i32) +declare i8* @llvm.load.relative.i64(i8*, i64) diff --git a/test/Transforms/InstSimplify/load.ll b/test/Transforms/InstSimplify/load.ll index ab87d4b9c535..8b2b5a17660f 100644 --- a/test/Transforms/InstSimplify/load.ll +++ b/test/Transforms/InstSimplify/load.ll @@ -1,19 +1,30 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s @zeroinit = constant {} zeroinitializer @undef = constant {} undef define i32 @crash_on_zeroinit() { -; CHECK-LABEL: @crash_on_zeroinit -; CHECK: ret i32 0 +; CHECK-LABEL: @crash_on_zeroinit( +; CHECK: ret i32 0 +; %load = load i32, i32* bitcast ({}* @zeroinit to i32*) ret i32 %load } define i32 @crash_on_undef() { -; CHECK-LABEL: @crash_on_undef -; CHECK: ret i32 undef +; CHECK-LABEL: @crash_on_undef( +; CHECK: ret i32 undef +; %load = load i32, i32* bitcast ({}* @undef to i32*) ret i32 %load } +@GV = private constant [8 x i32] [i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49] + +define <8 x i32> @partial_load() { +; CHECK-LABEL: @partial_load( +; CHECK: ret <8 x i32> <i32 0, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48> + %load = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr ([8 x i32], [8 x i32]* @GV, i64 0, i64 -1) to <8 x i32>*) + ret <8 x i32> %load +} diff --git a/test/Transforms/InstSimplify/maxmin.ll b/test/Transforms/InstSimplify/maxmin.ll index 3c643ed3e03e..3fcbfec2f63a 100644 --- a/test/Transforms/InstSimplify/maxmin.ll +++ b/test/Transforms/InstSimplify/maxmin.ll @@ -1,269 +1,302 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s define i1 @max1(i32 %x, i32 %y) { ; CHECK-LABEL: @max1( +; CHECK: ret i1 false +; %c = icmp sgt i32 %x, %y %m = select i1 %c, i32 %x, i32 %y %r = icmp slt i32 %m, %x ret i1 %r -; CHECK: ret i1 false } define i1 @max2(i32 %x, i32 %y) { ; CHECK-LABEL: @max2( +; CHECK: ret i1 true +; %c = icmp sge i32 %x, %y %m = select i1 %c, i32 %x, i32 %y %r = icmp sge i32 %m, %x ret i1 %r -; CHECK: ret i1 true } define i1 @max3(i32 %x, i32 %y) { ; CHECK-LABEL: @max3( +; CHECK: ret i1 false +; %c = icmp ugt i32 %x, %y %m = select i1 %c, i32 %x, i32 %y %r = icmp ult i32 %m, %x ret i1 %r -; CHECK: ret i1 false } define i1 @max4(i32 %x, i32 %y) { ; CHECK-LABEL: @max4( +; CHECK: ret i1 true +; %c = icmp uge i32 %x, %y %m = select i1 %c, i32 %x, i32 %y %r = icmp uge i32 %m, %x ret i1 %r -; CHECK: ret i1 true } define i1 @max5(i32 %x, i32 %y) { ; CHECK-LABEL: @max5( +; CHECK: ret i1 false +; %c = icmp sgt i32 %x, %y %m = select i1 %c, i32 %x, i32 %y %r = icmp sgt i32 %x, %m ret i1 %r -; CHECK: ret i1 false } define i1 @max6(i32 %x, i32 %y) { ; CHECK-LABEL: @max6( +; CHECK: ret i1 true +; %c = icmp sge i32 %x, %y %m = select i1 %c, i32 %x, i32 %y %r = icmp sle i32 %x, %m ret i1 %r -; CHECK: ret i1 true } define i1 @max7(i32 %x, i32 %y) { ; CHECK-LABEL: @max7( +; CHECK: ret i1 false +; %c = icmp ugt i32 %x, %y %m = select i1 %c, i32 %x, i32 %y %r = icmp ugt i32 %x, %m ret i1 %r -; CHECK: ret i1 false } define i1 @max8(i32 %x, i32 %y) { ; CHECK-LABEL: @max8( +; CHECK: ret i1 true +; %c = icmp uge i32 %x, %y %m = select i1 %c, i32 %x, i32 %y %r = icmp ule i32 %x, %m ret i1 %r -; CHECK: ret i1 true } define i1 @min1(i32 %x, i32 %y) { ; CHECK-LABEL: @min1( +; CHECK: ret i1 false +; %c = icmp sgt i32 %x, %y %m = select i1 %c, i32 %y, i32 %x %r = icmp sgt i32 %m, %x ret i1 %r -; CHECK: ret i1 false } define i1 @min2(i32 %x, i32 %y) { ; CHECK-LABEL: @min2( +; CHECK: ret i1 true +; %c = icmp sge i32 %x, %y %m = select i1 %c, i32 %y, i32 %x %r = icmp sle i32 %m, %x ret i1 %r -; CHECK: ret i1 true } define i1 @min3(i32 %x, i32 %y) { ; CHECK-LABEL: @min3( +; CHECK: ret i1 false +; %c = icmp ugt i32 %x, %y %m = select i1 %c, i32 %y, i32 %x %r = icmp ugt i32 %m, %x ret i1 %r -; CHECK: ret i1 false } define i1 @min4(i32 %x, i32 %y) { ; CHECK-LABEL: @min4( +; CHECK: ret i1 true +; %c = icmp uge i32 %x, %y %m = select i1 %c, i32 %y, i32 %x %r = icmp ule i32 %m, %x ret i1 %r -; CHECK: ret i1 true } define i1 @min5(i32 %x, i32 %y) { ; CHECK-LABEL: @min5( +; CHECK: ret i1 false +; %c = icmp sgt i32 %x, %y %m = select i1 %c, i32 %y, i32 %x %r = icmp slt i32 %x, %m ret i1 %r -; CHECK: ret i1 false } define i1 @min6(i32 %x, i32 %y) { ; CHECK-LABEL: @min6( +; CHECK: ret i1 true +; %c = icmp sge i32 %x, %y %m = select i1 %c, i32 %y, i32 %x %r = icmp sge i32 %x, %m ret i1 %r -; CHECK: ret i1 true } define i1 @min7(i32 %x, i32 %y) { ; CHECK-LABEL: @min7( +; CHECK: ret i1 false +; %c = icmp ugt i32 %x, %y %m = select i1 %c, i32 %y, i32 %x %r = icmp ult i32 %x, %m ret i1 %r -; CHECK: ret i1 false } define i1 @min8(i32 %x, i32 %y) { ; CHECK-LABEL: @min8( +; CHECK: ret i1 true +; %c = icmp uge i32 %x, %y %m = select i1 %c, i32 %y, i32 %x %r = icmp uge i32 %x, %m ret i1 %r -; CHECK: ret i1 true } define i1 @maxmin1(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @maxmin1( +; CHECK: ret i1 true +; %c1 = icmp sge i32 %x, %y %max = select i1 %c1, i32 %x, i32 %y %c2 = icmp sge i32 %x, %z %min = select i1 %c2, i32 %z, i32 %x %c = icmp sge i32 %max, %min ret i1 %c -; CHECK: ret i1 true } define i1 @maxmin2(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @maxmin2( +; CHECK: ret i1 false +; %c1 = icmp sge i32 %x, %y %max = select i1 %c1, i32 %x, i32 %y %c2 = icmp sge i32 %x, %z %min = select i1 %c2, i32 %z, i32 %x %c = icmp sgt i32 %min, %max ret i1 %c -; CHECK: ret i1 false } define i1 @maxmin3(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @maxmin3( +; CHECK: ret i1 true +; %c1 = icmp sge i32 %x, %y %max = select i1 %c1, i32 %x, i32 %y %c2 = icmp sge i32 %x, %z %min = select i1 %c2, i32 %z, i32 %x %c = icmp sle i32 %min, %max ret i1 %c -; CHECK: ret i1 true } define i1 @maxmin4(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @maxmin4( +; CHECK: ret i1 false +; %c1 = icmp sge i32 %x, %y %max = select i1 %c1, i32 %x, i32 %y %c2 = icmp sge i32 %x, %z %min = select i1 %c2, i32 %z, i32 %x %c = icmp slt i32 %max, %min ret i1 %c -; CHECK: ret i1 false } define i1 @maxmin5(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @maxmin5( +; CHECK: ret i1 true +; %c1 = icmp uge i32 %x, %y %max = select i1 %c1, i32 %x, i32 %y %c2 = icmp uge i32 %x, %z %min = select i1 %c2, i32 %z, i32 %x %c = icmp uge i32 %max, %min ret i1 %c -; CHECK: ret i1 true } define i1 @maxmin6(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @maxmin6( +; CHECK: ret i1 false +; %c1 = icmp uge i32 %x, %y %max = select i1 %c1, i32 %x, i32 %y %c2 = icmp uge i32 %x, %z %min = select i1 %c2, i32 %z, i32 %x %c = icmp ugt i32 %min, %max ret i1 %c -; CHECK: ret i1 false } define i1 @maxmin7(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @maxmin7( +; CHECK: ret i1 true +; %c1 = icmp uge i32 %x, %y %max = select i1 %c1, i32 %x, i32 %y %c2 = icmp uge i32 %x, %z %min = select i1 %c2, i32 %z, i32 %x %c = icmp ule i32 %min, %max ret i1 %c -; CHECK: ret i1 true } define i1 @maxmin8(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @maxmin8( +; CHECK: ret i1 false +; %c1 = icmp uge i32 %x, %y %max = select i1 %c1, i32 %x, i32 %y %c2 = icmp uge i32 %x, %z %min = select i1 %c2, i32 %z, i32 %x %c = icmp ult i32 %max, %min ret i1 %c -; CHECK: ret i1 false } define i1 @eqcmp1(i32 %x, i32 %y) { ; CHECK-LABEL: @eqcmp1( +; CHECK: [[C:%.*]] = icmp sge i32 %x, %y +; CHECK-NEXT: ret i1 [[C]] +; %c = icmp sge i32 %x, %y %max = select i1 %c, i32 %x, i32 %y %r = icmp eq i32 %max, %x ret i1 %r -; CHECK: ret i1 %c } define i1 @eqcmp2(i32 %x, i32 %y) { ; CHECK-LABEL: @eqcmp2( +; CHECK: [[C:%.*]] = icmp sge i32 %x, %y +; CHECK-NEXT: ret i1 [[C]] +; %c = icmp sge i32 %x, %y %max = select i1 %c, i32 %x, i32 %y %r = icmp eq i32 %x, %max ret i1 %r -; CHECK: ret i1 %c } define i1 @eqcmp3(i32 %x, i32 %y) { ; CHECK-LABEL: @eqcmp3( +; CHECK: [[C:%.*]] = icmp uge i32 %x, %y +; CHECK-NEXT: ret i1 [[C]] +; %c = icmp uge i32 %x, %y %max = select i1 %c, i32 %x, i32 %y %r = icmp eq i32 %max, %x ret i1 %r -; CHECK: ret i1 %c } define i1 @eqcmp4(i32 %x, i32 %y) { ; CHECK-LABEL: @eqcmp4( +; CHECK: [[C:%.*]] = icmp uge i32 %x, %y +; CHECK-NEXT: ret i1 [[C]] +; %c = icmp uge i32 %x, %y %max = select i1 %c, i32 %x, i32 %y %r = icmp eq i32 %x, %max ret i1 %r -; CHECK: ret i1 %c } diff --git a/test/Transforms/InstSimplify/past-the-end.ll b/test/Transforms/InstSimplify/past-the-end.ll index b676e9db2c77..b47db7defcbd 100644 --- a/test/Transforms/InstSimplify/past-the-end.ll +++ b/test/Transforms/InstSimplify/past-the-end.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s target datalayout = "p:32:32" @@ -9,21 +10,23 @@ target datalayout = "p:32:32" ; Comparing base addresses of two distinct globals. Never equal. define zeroext i1 @no_offsets() { +; CHECK-LABEL: @no_offsets( +; CHECK: ret i1 false +; %t = icmp eq i32* @opte_a, @opte_b ret i1 %t - ; CHECK: no_offsets( - ; CHECK: ret i1 false } ; Comparing past-the-end addresses of two distinct globals. Never equal. define zeroext i1 @both_past_the_end() { +; CHECK-LABEL: @both_past_the_end( +; CHECK: ret i1 icmp eq (i32* getelementptr inbounds (i32, i32* @opte_a, i32 1), i32* getelementptr inbounds (i32, i32* @opte_b, i32 1)) +; %x = getelementptr i32, i32* @opte_a, i32 1 %y = getelementptr i32, i32* @opte_b, i32 1 %t = icmp eq i32* %x, %y ret i1 %t - ; CHECK: both_past_the_end( - ; CHECK-NOT: ret i1 true ; TODO: refine this } @@ -31,35 +34,43 @@ define zeroext i1 @both_past_the_end() { ; of another. Can't fold this. define zeroext i1 @just_one_past_the_end() { +; CHECK-LABEL: @just_one_past_the_end( +; CHECK: ret i1 icmp eq (i32* getelementptr inbounds (i32, i32* @opte_a, i32 1), i32* @opte_b) +; %x = getelementptr i32, i32* @opte_a, i32 1 %t = icmp eq i32* %x, @opte_b ret i1 %t - ; CHECK: just_one_past_the_end( - ; CHECK: ret i1 icmp eq (i32* getelementptr inbounds (i32, i32* @opte_a, i32 1), i32* @opte_b) } ; Comparing base addresses of two distinct allocas. Never equal. define zeroext i1 @no_alloca_offsets() { +; CHECK-LABEL: @no_alloca_offsets( +; CHECK: ret i1 false +; %m = alloca i32 %n = alloca i32 %t = icmp eq i32* %m, %n ret i1 %t - ; CHECK: no_alloca_offsets( - ; CHECK: ret i1 false } ; Comparing past-the-end addresses of two distinct allocas. Never equal. define zeroext i1 @both_past_the_end_alloca() { +; CHECK-LABEL: @both_past_the_end_alloca( +; CHECK: [[M:%.*]] = alloca i32 +; CHECK-NEXT: [[N:%.*]] = alloca i32 +; CHECK-NEXT: [[X:%.*]] = getelementptr i32, i32* [[M]], i32 1 +; CHECK-NEXT: [[Y:%.*]] = getelementptr i32, i32* [[N]], i32 1 +; CHECK-NEXT: [[T:%.*]] = icmp eq i32* [[X]], [[Y]] +; CHECK-NEXT: ret i1 [[T]] +; %m = alloca i32 %n = alloca i32 %x = getelementptr i32, i32* %m, i32 1 %y = getelementptr i32, i32* %n, i32 1 %t = icmp eq i32* %x, %y ret i1 %t - ; CHECK: both_past_the_end_alloca( - ; CHECK-NOT: ret i1 true ; TODO: refine this } @@ -67,11 +78,16 @@ define zeroext i1 @both_past_the_end_alloca() { ; of another. Can't fold this. define zeroext i1 @just_one_past_the_end_alloca() { +; CHECK-LABEL: @just_one_past_the_end_alloca( +; CHECK: [[M:%.*]] = alloca i32 +; CHECK-NEXT: [[N:%.*]] = alloca i32 +; CHECK-NEXT: [[X:%.*]] = getelementptr i32, i32* [[M]], i32 1 +; CHECK-NEXT: [[T:%.*]] = icmp eq i32* [[X]], [[N]] +; CHECK-NEXT: ret i1 [[T]] +; %m = alloca i32 %n = alloca i32 %x = getelementptr i32, i32* %m, i32 1 %t = icmp eq i32* %x, %n ret i1 %t - ; CHECK: just_one_past_the_end_alloca( - ; CHECK: ret i1 %t } diff --git a/test/Transforms/InstSimplify/phi.ll b/test/Transforms/InstSimplify/phi.ll index 5b7aaa93caf1..b0040ffeb033 100644 --- a/test/Transforms/InstSimplify/phi.ll +++ b/test/Transforms/InstSimplify/phi.ll @@ -1,8 +1,11 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s ; PR12189 define i1 @test1(i32 %x) { ; CHECK-LABEL: @test1( +; CHECK: ret i1 %e +; br i1 true, label %a, label %b a: @@ -18,5 +21,4 @@ c: %d = urem i32 %cc, 2 %e = icmp eq i32 %d, 0 ret i1 %e -; CHECK: ret i1 %e } diff --git a/test/Transforms/InstSimplify/ptr_diff.ll b/test/Transforms/InstSimplify/ptr_diff.ll index 6c27e6f44678..c57fab997866 100644 --- a/test/Transforms/InstSimplify/ptr_diff.ll +++ b/test/Transforms/InstSimplify/ptr_diff.ll @@ -1,11 +1,12 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s 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" define i64 @ptrdiff1(i8* %ptr) { ; CHECK-LABEL: @ptrdiff1( -; CHECK-NEXT: ret i64 42 - +; CHECK: ret i64 42 +; %first = getelementptr inbounds i8, i8* %ptr, i32 0 %last = getelementptr inbounds i8, i8* %ptr, i32 42 %first.int = ptrtoint i8* %first to i64 @@ -16,8 +17,8 @@ define i64 @ptrdiff1(i8* %ptr) { define i64 @ptrdiff2(i8* %ptr) { ; CHECK-LABEL: @ptrdiff2( -; CHECK-NEXT: ret i64 42 - +; CHECK: ret i64 42 +; %first1 = getelementptr inbounds i8, i8* %ptr, i32 0 %first2 = getelementptr inbounds i8, i8* %first1, i32 1 %first3 = getelementptr inbounds i8, i8* %first2, i32 2 @@ -35,10 +36,12 @@ define i64 @ptrdiff2(i8* %ptr) { define i64 @ptrdiff3(i8* %ptr) { ; Don't bother with non-inbounds GEPs. ; CHECK-LABEL: @ptrdiff3( -; CHECK: getelementptr -; CHECK: sub -; CHECK: ret - +; CHECK: [[LAST:%.*]] = getelementptr i8, i8* %ptr, i32 42 +; CHECK-NEXT: [[FIRST_INT:%.*]] = ptrtoint i8* %ptr to i64 +; CHECK-NEXT: [[LAST_INT:%.*]] = ptrtoint i8* [[LAST]] to i64 +; CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[LAST_INT]], [[FIRST_INT]] +; CHECK-NEXT: ret i64 [[DIFF]] +; %first = getelementptr i8, i8* %ptr, i32 0 %last = getelementptr i8, i8* %ptr, i32 42 %first.int = ptrtoint i8* %first to i64 @@ -50,7 +53,8 @@ define i64 @ptrdiff3(i8* %ptr) { define <4 x i32> @ptrdiff4(<4 x i8*> %arg) nounwind { ; Handle simple cases of vectors of pointers. ; CHECK-LABEL: @ptrdiff4( -; CHECK: ret <4 x i32> zeroinitializer +; CHECK: ret <4 x i32> zeroinitializer +; %p1 = ptrtoint <4 x i8*> %arg to <4 x i32> %bc = bitcast <4 x i8*> %arg to <4 x i32*> %p2 = ptrtoint <4 x i32*> %bc to <4 x i32> @@ -63,6 +67,10 @@ define <4 x i32> @ptrdiff4(<4 x i8*> %arg) nounwind { @global = internal global %struct.ham zeroinitializer, align 4 define i32 @ptrdiff5() nounwind { +; CHECK-LABEL: @ptrdiff5( +; CHECK: bb: +; CHECK-NEXT: ret i32 0 +; bb: %tmp = getelementptr inbounds %struct.ham, %struct.ham* @global, i32 0, i32 1 %tmp1 = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %tmp, i32 0, i32 0 @@ -73,6 +81,4 @@ bb: %tmp6 = ptrtoint [2 x i32]* %tmp5 to i32 %tmp7 = sub i32 %tmp3, %tmp6 ret i32 %tmp7 -; CHECK-LABEL: @ptrdiff5( -; CHECK: ret i32 0 } diff --git a/test/Transforms/InstSimplify/reassociate.ll b/test/Transforms/InstSimplify/reassociate.ll index d44f7155ffda..335df32a5054 100644 --- a/test/Transforms/InstSimplify/reassociate.ll +++ b/test/Transforms/InstSimplify/reassociate.ll @@ -1,195 +1,223 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s define i32 @add1(i32 %x) { ; CHECK-LABEL: @add1( +; CHECK: ret i32 %x +; ; (X + -1) + 1 -> X %l = add i32 %x, -1 %r = add i32 %l, 1 ret i32 %r -; CHECK: ret i32 %x } define i32 @and1(i32 %x, i32 %y) { ; CHECK-LABEL: @and1( +; CHECK: [[L:%.*]] = and i32 %x, %y +; CHECK-NEXT: ret i32 [[L]] +; ; (X & Y) & X -> X & Y %l = and i32 %x, %y %r = and i32 %l, %x ret i32 %r -; CHECK: ret i32 %l } define i32 @and2(i32 %x, i32 %y) { ; CHECK-LABEL: @and2( +; CHECK: [[R:%.*]] = and i32 %x, %y +; CHECK-NEXT: ret i32 [[R]] +; ; X & (X & Y) -> X & Y %r = and i32 %x, %y %l = and i32 %x, %r ret i32 %l -; CHECK: ret i32 %r } define i32 @or1(i32 %x, i32 %y) { ; CHECK-LABEL: @or1( +; CHECK: [[L:%.*]] = or i32 %x, %y +; CHECK-NEXT: ret i32 [[L]] +; ; (X | Y) | X -> X | Y %l = or i32 %x, %y %r = or i32 %l, %x ret i32 %r -; CHECK: ret i32 %l } define i32 @or2(i32 %x, i32 %y) { ; CHECK-LABEL: @or2( +; CHECK: [[R:%.*]] = or i32 %x, %y +; CHECK-NEXT: ret i32 [[R]] +; ; X | (X | Y) -> X | Y %r = or i32 %x, %y %l = or i32 %x, %r ret i32 %l -; CHECK: ret i32 %r } define i32 @xor1(i32 %x, i32 %y) { ; CHECK-LABEL: @xor1( +; CHECK: ret i32 %y +; ; (X ^ Y) ^ X = Y %l = xor i32 %x, %y %r = xor i32 %l, %x ret i32 %r -; CHECK: ret i32 %y } define i32 @xor2(i32 %x, i32 %y) { ; CHECK-LABEL: @xor2( +; CHECK: ret i32 %y +; ; X ^ (X ^ Y) = Y %r = xor i32 %x, %y %l = xor i32 %x, %r ret i32 %l -; CHECK: ret i32 %y } define i32 @sub1(i32 %x, i32 %y) { ; CHECK-LABEL: @sub1( +; CHECK: ret i32 %y +; %d = sub i32 %x, %y %r = sub i32 %x, %d ret i32 %r -; CHECK: ret i32 %y } define i32 @sub2(i32 %x) { ; CHECK-LABEL: @sub2( +; CHECK: ret i32 -1 +; ; X - (X + 1) -> -1 %xp1 = add i32 %x, 1 %r = sub i32 %x, %xp1 ret i32 %r -; CHECK: ret i32 -1 } define i32 @sub3(i32 %x, i32 %y) { ; CHECK-LABEL: @sub3( +; CHECK: ret i32 %x +; ; ((X + 1) + Y) - (Y + 1) -> X %xp1 = add i32 %x, 1 %lhs = add i32 %xp1, %y %rhs = add i32 %y, 1 %r = sub i32 %lhs, %rhs ret i32 %r -; CHECK: ret i32 %x } define i32 @sdiv1(i32 %x, i32 %y) { ; CHECK-LABEL: @sdiv1( +; CHECK: ret i32 %x +; ; (no overflow X * Y) / Y -> X %mul = mul nsw i32 %x, %y %r = sdiv i32 %mul, %y ret i32 %r -; CHECK: ret i32 %x } define i32 @sdiv2(i32 %x, i32 %y) { ; CHECK-LABEL: @sdiv2( +; CHECK: [[DIV:%.*]] = sdiv i32 %x, %y +; CHECK-NEXT: ret i32 [[DIV]] +; ; (((X / Y) * Y) / Y) -> X / Y %div = sdiv i32 %x, %y %mul = mul i32 %div, %y %r = sdiv i32 %mul, %y ret i32 %r -; CHECK: ret i32 %div } define i32 @sdiv3(i32 %x, i32 %y) { ; CHECK-LABEL: @sdiv3( +; CHECK: ret i32 0 +; ; (X rem Y) / Y -> 0 %rem = srem i32 %x, %y %div = sdiv i32 %rem, %y ret i32 %div -; CHECK: ret i32 0 } define i32 @sdiv4(i32 %x, i32 %y) { ; CHECK-LABEL: @sdiv4( +; CHECK: ret i32 %x +; ; (X / Y) * Y -> X if the division is exact %div = sdiv exact i32 %x, %y %mul = mul i32 %div, %y ret i32 %mul -; CHECK: ret i32 %x } define i32 @sdiv5(i32 %x, i32 %y) { ; CHECK-LABEL: @sdiv5( +; CHECK: ret i32 %x +; ; Y * (X / Y) -> X if the division is exact %div = sdiv exact i32 %x, %y %mul = mul i32 %y, %div ret i32 %mul -; CHECK: ret i32 %x } define i32 @udiv1(i32 %x, i32 %y) { ; CHECK-LABEL: @udiv1( +; CHECK: ret i32 %x +; ; (no overflow X * Y) / Y -> X %mul = mul nuw i32 %x, %y %r = udiv i32 %mul, %y ret i32 %r -; CHECK: ret i32 %x } define i32 @udiv2(i32 %x, i32 %y) { ; CHECK-LABEL: @udiv2( +; CHECK: [[DIV:%.*]] = udiv i32 %x, %y +; CHECK-NEXT: ret i32 [[DIV]] +; ; (((X / Y) * Y) / Y) -> X / Y %div = udiv i32 %x, %y %mul = mul i32 %div, %y %r = udiv i32 %mul, %y ret i32 %r -; CHECK: ret i32 %div } define i32 @udiv3(i32 %x, i32 %y) { ; CHECK-LABEL: @udiv3( +; CHECK: ret i32 0 +; ; (X rem Y) / Y -> 0 %rem = urem i32 %x, %y %div = udiv i32 %rem, %y ret i32 %div -; CHECK: ret i32 0 } define i32 @udiv4(i32 %x, i32 %y) { ; CHECK-LABEL: @udiv4( +; CHECK: ret i32 %x +; ; (X / Y) * Y -> X if the division is exact %div = udiv exact i32 %x, %y %mul = mul i32 %div, %y ret i32 %mul -; CHECK: ret i32 %x } define i32 @udiv5(i32 %x, i32 %y) { ; CHECK-LABEL: @udiv5( +; CHECK: ret i32 %x +; ; Y * (X / Y) -> X if the division is exact %div = udiv exact i32 %x, %y %mul = mul i32 %y, %div ret i32 %mul -; CHECK: ret i32 %x } define i16 @trunc1(i32 %x) { ; CHECK-LABEL: @trunc1( +; CHECK: ret i16 1 +; %y = add i32 %x, 1 %tx = trunc i32 %x to i16 %ty = trunc i32 %y to i16 %d = sub i16 %ty, %tx ret i16 %d -; CHECK: ret i16 1 } diff --git a/test/Transforms/InstSimplify/rem.ll b/test/Transforms/InstSimplify/rem.ll index f5ea45107e2a..df3f659b782e 100644 --- a/test/Transforms/InstSimplify/rem.ll +++ b/test/Transforms/InstSimplify/rem.ll @@ -1,25 +1,29 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s define i32 @select1(i32 %x, i1 %b) { ; CHECK-LABEL: @select1( +; CHECK: ret i32 0 +; %rhs = select i1 %b, i32 %x, i32 1 %rem = srem i32 %x, %rhs ret i32 %rem -; CHECK: ret i32 0 } define i32 @select2(i32 %x, i1 %b) { ; CHECK-LABEL: @select2( +; CHECK: ret i32 0 +; %rhs = select i1 %b, i32 %x, i32 1 %rem = urem i32 %x, %rhs ret i32 %rem -; CHECK: ret i32 0 } define i32 @rem1(i32 %x, i32 %n) { ; CHECK-LABEL: @rem1( -; CHECK-NEXT: %mod = srem i32 %x, %n -; CHECK-NEXT: ret i32 %mod +; CHECK: [[MOD:%.*]] = srem i32 %x, %n +; CHECK-NEXT: ret i32 [[MOD]] +; %mod = srem i32 %x, %n %mod1 = srem i32 %mod, %n ret i32 %mod1 @@ -27,8 +31,9 @@ define i32 @rem1(i32 %x, i32 %n) { define i32 @rem2(i32 %x, i32 %n) { ; CHECK-LABEL: @rem2( -; CHECK-NEXT: %mod = urem i32 %x, %n -; CHECK-NEXT: ret i32 %mod +; CHECK: [[MOD:%.*]] = urem i32 %x, %n +; CHECK-NEXT: ret i32 [[MOD]] +; %mod = urem i32 %x, %n %mod1 = urem i32 %mod, %n ret i32 %mod1 @@ -36,9 +41,10 @@ define i32 @rem2(i32 %x, i32 %n) { define i32 @rem3(i32 %x, i32 %n) { ; CHECK-LABEL: @rem3( -; CHECK-NEXT: %[[srem:.*]] = srem i32 %x, %n -; CHECK-NEXT: %[[urem:.*]] = urem i32 %[[srem]], %n -; CHECK-NEXT: ret i32 %[[urem]] +; CHECK: [[MOD:%.*]] = srem i32 %x, %n +; CHECK-NEXT: [[MOD1:%.*]] = urem i32 [[MOD]], %n +; CHECK-NEXT: ret i32 [[MOD1]] +; %mod = srem i32 %x, %n %mod1 = urem i32 %mod, %n ret i32 %mod1 diff --git a/test/Transforms/InstSimplify/returned.ll b/test/Transforms/InstSimplify/returned.ll new file mode 100644 index 000000000000..0e89e91085dc --- /dev/null +++ b/test/Transforms/InstSimplify/returned.ll @@ -0,0 +1,30 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +define i1 @bitcast() { +; CHECK-LABEL: @bitcast( + %a = alloca i32 + %b = alloca i64 + %x = bitcast i32* %a to i8* + %z = bitcast i64* %b to i8* + %y = call i8* @func1(i8* %z) + %cmp = icmp eq i8* %x, %y + ret i1 %cmp +; CHECK-NEXT: ret i1 false +} + +%gept = type { i32, i32 } + +define i1 @gep3() { +; CHECK-LABEL: @gep3( + %x = alloca %gept, align 8 + %a = getelementptr %gept, %gept* %x, i64 0, i32 0 + %y = call %gept* @func2(%gept* %x) + %b = getelementptr %gept, %gept* %y, i64 0, i32 1 + %equal = icmp eq i32* %a, %b + ret i1 %equal +; CHECK-NEXT: ret i1 false +} + +declare i8* @func1(i8* returned) nounwind readnone +declare %gept* @func2(%gept* returned) nounwind readnone + diff --git a/test/Transforms/InstSimplify/shift-128-kb.ll b/test/Transforms/InstSimplify/shift-128-kb.ll index 3f69ecccaf5b..76f1da57bbf9 100644 --- a/test/Transforms/InstSimplify/shift-128-kb.ll +++ b/test/Transforms/InstSimplify/shift-128-kb.ll @@ -1,9 +1,21 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt -S -instsimplify < %s | FileCheck %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" define zeroext i1 @_Z10isNegativemj(i64 %Val, i32 zeroext %IntegerBitWidth) { +; CHECK-LABEL: @_Z10isNegativemj( +; CHECK: [[CONV:%.*]] = zext i32 %IntegerBitWidth to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 128, [[CONV]] +; CHECK-NEXT: [[CONV1:%.*]] = trunc i64 [[SUB]] to i32 +; CHECK-NEXT: [[CONV2:%.*]] = zext i64 %Val to i128 +; CHECK-NEXT: [[SH_PROM:%.*]] = zext i32 [[CONV1]] to i128 +; CHECK-NEXT: [[SHL:%.*]] = shl i128 [[CONV2]], [[SH_PROM]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i128 [[SHL]], [[SH_PROM]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i128 [[SHR]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; entry: %conv = zext i32 %IntegerBitWidth to i64 %sub = sub i64 128, %conv @@ -16,7 +28,3 @@ entry: ret i1 %cmp } -; CHECK-LABEL: @_Z10isNegativemj -; CHECK-NOT: ret i1 false -; CHECK: ret i1 %cmp - diff --git a/test/Transforms/InstSimplify/shift-knownbits.ll b/test/Transforms/InstSimplify/shift-knownbits.ll new file mode 100644 index 000000000000..f50ea0582c6c --- /dev/null +++ b/test/Transforms/InstSimplify/shift-knownbits.ll @@ -0,0 +1,147 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instsimplify -S | FileCheck %s + +; If any bits of the shift amount are known to make it exceed or equal +; the number of bits in the type, the shift causes undefined behavior. + +define i32 @shl_amount_is_known_bogus(i32 %a, i32 %b) { +; CHECK-LABEL: @shl_amount_is_known_bogus( +; CHECK-NEXT: ret i32 undef +; + %or = or i32 %b, 32 + %shl = shl i32 %a, %or + ret i32 %shl +} + +; Check some weird types and the other shift ops. + +define i31 @lshr_amount_is_known_bogus(i31 %a, i31 %b) { +; CHECK-LABEL: @lshr_amount_is_known_bogus( +; CHECK-NEXT: ret i31 undef +; + %or = or i31 %b, 31 + %shr = lshr i31 %a, %or + ret i31 %shr +} + +define i33 @ashr_amount_is_known_bogus(i33 %a, i33 %b) { +; CHECK-LABEL: @ashr_amount_is_known_bogus( +; CHECK-NEXT: ret i33 undef +; + %or = or i33 %b, 33 + %shr = ashr i33 %a, %or + ret i33 %shr +} + + +; If all valid bits of the shift amount are known 0, there's no shift. +; It doesn't matter if high bits are set because that would be undefined. +; Therefore, the only possible valid result of these shifts is %a. + +define i16 @ashr_amount_is_zero(i16 %a, i16 %b) { +; CHECK-LABEL: @ashr_amount_is_zero( +; CHECK-NEXT: ret i16 %a +; + %and = and i16 %b, 65520 ; 0xfff0 + %shr = ashr i16 %a, %and + ret i16 %shr +} + +define i300 @lshr_amount_is_zero(i300 %a, i300 %b) { +; CHECK-LABEL: @lshr_amount_is_zero( +; CHECK-NEXT: ret i300 %a +; + %and = and i300 %b, 2048 + %shr = lshr i300 %a, %and + ret i300 %shr +} + +define i9 @shl_amount_is_zero(i9 %a, i9 %b) { +; CHECK-LABEL: @shl_amount_is_zero( +; CHECK-NEXT: ret i9 %a +; + %and = and i9 %b, 496 ; 0x1f0 + %shl = shl i9 %a, %and + ret i9 %shl +} + + +; Verify that we've calculated the log2 boundary of valid bits correctly for a weird type. + +define i9 @shl_amount_is_not_known_zero(i9 %a, i9 %b) { +; CHECK-LABEL: @shl_amount_is_not_known_zero( +; CHECK-NEXT: [[AND:%.*]] = and i9 %b, -8 +; CHECK-NEXT: [[SHL:%.*]] = shl i9 %a, [[AND]] +; CHECK-NEXT: ret i9 [[SHL]] +; + %and = and i9 %b, 504 ; 0x1f8 + %shl = shl i9 %a, %and + ret i9 %shl +} + + +; For vectors, we need all scalar elements to meet the requirements to optimize. + +define <2 x i32> @ashr_vector_bogus(<2 x i32> %a, <2 x i32> %b) { +; CHECK-LABEL: @ashr_vector_bogus( +; CHECK-NEXT: ret <2 x i32> undef +; + %or = or <2 x i32> %b, <i32 32, i32 32> + %shr = ashr <2 x i32> %a, %or + ret <2 x i32> %shr +} + +; FIXME: This is undef, but computeKnownBits doesn't handle the union. +define <2 x i32> @shl_vector_bogus(<2 x i32> %a, <2 x i32> %b) { +; CHECK-LABEL: @shl_vector_bogus( +; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> %b, <i32 32, i32 64> +; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i32> %a, [[OR]] +; CHECK-NEXT: ret <2 x i32> [[SHL]] +; + %or = or <2 x i32> %b, <i32 32, i32 64> + %shl = shl <2 x i32> %a, %or + ret <2 x i32> %shl +} + +define <2 x i32> @lshr_vector_zero(<2 x i32> %a, <2 x i32> %b) { +; CHECK-LABEL: @lshr_vector_zero( +; CHECK-NEXT: ret <2 x i32> %a +; + %and = and <2 x i32> %b, <i32 64, i32 256> + %shr = lshr <2 x i32> %a, %and + ret <2 x i32> %shr +} + +; Make sure that weird vector types work too. +define <2 x i15> @shl_vector_zero(<2 x i15> %a, <2 x i15> %b) { +; CHECK-LABEL: @shl_vector_zero( +; CHECK-NEXT: ret <2 x i15> %a +; + %and = and <2 x i15> %b, <i15 1024, i15 1024> + %shl = shl <2 x i15> %a, %and + ret <2 x i15> %shl +} + +define <2 x i32> @shl_vector_for_real(<2 x i32> %a, <2 x i32> %b) { +; CHECK-LABEL: @shl_vector_for_real( +; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> %b, <i32 3, i32 3> +; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i32> %a, [[AND]] +; CHECK-NEXT: ret <2 x i32> [[SHL]] +; + %and = and <2 x i32> %b, <i32 3, i32 3> ; a necessary mask op + %shl = shl <2 x i32> %a, %and + ret <2 x i32> %shl +} + + +; We calculate the valid bits of the shift using log2, and log2 of 1 (the type width) is 0. +; That should be ok. Either the shift amount is 0 or invalid (1), so we can always return %a. + +define i1 @shl_i1(i1 %a, i1 %b) { +; CHECK-LABEL: @shl_i1( +; CHECK-NEXT: ret i1 %a +; + %shl = shl i1 %a, %b + ret i1 %shl +} + diff --git a/test/Transforms/InstSimplify/shr-nop.ll b/test/Transforms/InstSimplify/shr-nop.ll index edabcc314ea6..9b0f4e9fe501 100644 --- a/test/Transforms/InstSimplify/shr-nop.ll +++ b/test/Transforms/InstSimplify/shr-nop.ll @@ -1,346 +1,431 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s -; CHECK-LABEL: @foo -; CHECK: %[[and:.*]] = and i32 %x, 1 -; CHECK-NEXT: %[[add:.*]] = add i32 %[[and]], -1 -; CHECK-NEXT: ret i32 %[[add]] define i32 @foo(i32 %x) { - %o = and i32 %x, 1 - %n = add i32 %o, -1 - %t = ashr i32 %n, 17 - ret i32 %t +; CHECK-LABEL: @foo( +; CHECK-NEXT: [[O:%.*]] = and i32 %x, 1 +; CHECK-NEXT: [[N:%.*]] = add i32 [[O]], -1 +; CHECK-NEXT: ret i32 [[N]] +; + %o = and i32 %x, 1 + %n = add i32 %o, -1 + %t = ashr i32 %n, 17 + ret i32 %t } -; CHECK-LABEL: @exact_lshr_eq_both_zero -; CHECK-NEXT: ret i1 true define i1 @exact_lshr_eq_both_zero(i8 %a) { - %shr = lshr exact i8 0, %a - %cmp = icmp eq i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @exact_lshr_eq_both_zero( +; CHECK-NEXT: ret i1 true +; + %shr = lshr exact i8 0, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_eq_both_zero -; CHECK-NEXT: ret i1 true define i1 @exact_ashr_eq_both_zero(i8 %a) { - %shr = ashr exact i8 0, %a - %cmp = icmp eq i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_eq_both_zero( +; CHECK-NEXT: ret i1 true +; + %shr = ashr exact i8 0, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_ashr_eq_both_zero -; CHECK-NEXT: ret i1 true define i1 @nonexact_ashr_eq_both_zero(i8 %a) { - %shr = ashr i8 0, %a - %cmp = icmp eq i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @nonexact_ashr_eq_both_zero( +; CHECK-NEXT: ret i1 true +; + %shr = ashr i8 0, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @exact_lshr_ne_both_zero -; CHECK-NEXT: ret i1 false define i1 @exact_lshr_ne_both_zero(i8 %a) { - %shr = lshr exact i8 0, %a - %cmp = icmp ne i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @exact_lshr_ne_both_zero( +; CHECK-NEXT: ret i1 false +; + %shr = lshr exact i8 0, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_ne_both_zero -; CHECK-NEXT: ret i1 false define i1 @exact_ashr_ne_both_zero(i8 %a) { - %shr = ashr exact i8 0, %a - %cmp = icmp ne i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_ne_both_zero( +; CHECK-NEXT: ret i1 false +; + %shr = ashr exact i8 0, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_lshr_ne_both_zero -; CHECK-NEXT: ret i1 false define i1 @nonexact_lshr_ne_both_zero(i8 %a) { - %shr = lshr i8 0, %a - %cmp = icmp ne i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @nonexact_lshr_ne_both_zero( +; CHECK-NEXT: ret i1 false +; + %shr = lshr i8 0, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_ashr_ne_both_zero -; CHECK-NEXT: ret i1 false define i1 @nonexact_ashr_ne_both_zero(i8 %a) { - %shr = ashr i8 0, %a - %cmp = icmp ne i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @nonexact_ashr_ne_both_zero( +; CHECK-NEXT: ret i1 false +; + %shr = ashr i8 0, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @exact_lshr_eq_last_zero -; CHECK-NEXT: ret i1 false define i1 @exact_lshr_eq_last_zero(i8 %a) { - %shr = lshr exact i8 128, %a - %cmp = icmp eq i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @exact_lshr_eq_last_zero( +; CHECK-NEXT: ret i1 false +; + %shr = lshr exact i8 128, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_eq_last_zero -; CHECK-NEXT: ret i1 false define i1 @exact_ashr_eq_last_zero(i8 %a) { - %shr = ashr exact i8 -128, %a - %cmp = icmp eq i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_eq_last_zero( +; CHECK-NEXT: ret i1 false +; + %shr = ashr exact i8 -128, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_lshr_eq_both_zero -; CHECK-NEXT: ret i1 true define i1 @nonexact_lshr_eq_both_zero(i8 %a) { - %shr = lshr i8 0, %a - %cmp = icmp eq i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @nonexact_lshr_eq_both_zero( +; CHECK-NEXT: ret i1 true +; + %shr = lshr i8 0, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @exact_lshr_ne_last_zero -; CHECK-NEXT: ret i1 true define i1 @exact_lshr_ne_last_zero(i8 %a) { - %shr = lshr exact i8 128, %a - %cmp = icmp ne i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @exact_lshr_ne_last_zero( +; CHECK-NEXT: ret i1 true +; + %shr = lshr exact i8 128, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_ne_last_zero -; CHECK-NEXT: ret i1 true define i1 @exact_ashr_ne_last_zero(i8 %a) { - %shr = ashr exact i8 -128, %a - %cmp = icmp ne i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_ne_last_zero( +; CHECK-NEXT: ret i1 true +; + %shr = ashr exact i8 -128, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_lshr_eq_last_zero -; CHECK-NEXT: ret i1 false define i1 @nonexact_lshr_eq_last_zero(i8 %a) { - %shr = lshr i8 128, %a - %cmp = icmp eq i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @nonexact_lshr_eq_last_zero( +; CHECK-NEXT: ret i1 false +; + %shr = lshr i8 128, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_ashr_eq_last_zero -; CHECK-NEXT: ret i1 false define i1 @nonexact_ashr_eq_last_zero(i8 %a) { - %shr = ashr i8 -128, %a - %cmp = icmp eq i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @nonexact_ashr_eq_last_zero( +; CHECK-NEXT: ret i1 false +; + %shr = ashr i8 -128, %a + %cmp = icmp eq i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_lshr_ne_last_zero -; CHECK-NEXT: ret i1 true define i1 @nonexact_lshr_ne_last_zero(i8 %a) { - %shr = lshr i8 128, %a - %cmp = icmp ne i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @nonexact_lshr_ne_last_zero( +; CHECK-NEXT: ret i1 true +; + %shr = lshr i8 128, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_ashr_ne_last_zero -; CHECK-NEXT: ret i1 true define i1 @nonexact_ashr_ne_last_zero(i8 %a) { - %shr = ashr i8 -128, %a - %cmp = icmp ne i8 %shr, 0 - ret i1 %cmp +; CHECK-LABEL: @nonexact_ashr_ne_last_zero( +; CHECK-NEXT: ret i1 true +; + %shr = ashr i8 -128, %a + %cmp = icmp ne i8 %shr, 0 + ret i1 %cmp } -; CHECK-LABEL: @lshr_eq_first_zero -; CHECK-NEXT: ret i1 false define i1 @lshr_eq_first_zero(i8 %a) { - %shr = lshr i8 0, %a - %cmp = icmp eq i8 %shr, 2 - ret i1 %cmp +; CHECK-LABEL: @lshr_eq_first_zero( +; CHECK-NEXT: ret i1 false +; + %shr = lshr i8 0, %a + %cmp = icmp eq i8 %shr, 2 + ret i1 %cmp } -; CHECK-LABEL: @ashr_eq_first_zero -; CHECK-NEXT: ret i1 false define i1 @ashr_eq_first_zero(i8 %a) { - %shr = ashr i8 0, %a - %cmp = icmp eq i8 %shr, 2 - ret i1 %cmp +; CHECK-LABEL: @ashr_eq_first_zero( +; CHECK-NEXT: ret i1 false +; + %shr = ashr i8 0, %a + %cmp = icmp eq i8 %shr, 2 + ret i1 %cmp } -; CHECK-LABEL: @lshr_ne_first_zero -; CHECK-NEXT: ret i1 true define i1 @lshr_ne_first_zero(i8 %a) { - %shr = lshr i8 0, %a - %cmp = icmp ne i8 %shr, 2 - ret i1 %cmp +; CHECK-LABEL: @lshr_ne_first_zero( +; CHECK-NEXT: ret i1 true +; + %shr = lshr i8 0, %a + %cmp = icmp ne i8 %shr, 2 + ret i1 %cmp } -; CHECK-LABEL: @ashr_ne_first_zero -; CHECK-NEXT: ret i1 true define i1 @ashr_ne_first_zero(i8 %a) { - %shr = ashr i8 0, %a - %cmp = icmp ne i8 %shr, 2 - ret i1 %cmp +; CHECK-LABEL: @ashr_ne_first_zero( +; CHECK-NEXT: ret i1 true +; + %shr = ashr i8 0, %a + %cmp = icmp ne i8 %shr, 2 + ret i1 %cmp } -; CHECK-LABEL: @ashr_eq_both_minus1 -; CHECK-NEXT: ret i1 true define i1 @ashr_eq_both_minus1(i8 %a) { - %shr = ashr i8 -1, %a - %cmp = icmp eq i8 %shr, -1 - ret i1 %cmp +; CHECK-LABEL: @ashr_eq_both_minus1( +; CHECK-NEXT: ret i1 true +; + %shr = ashr i8 -1, %a + %cmp = icmp eq i8 %shr, -1 + ret i1 %cmp } -; CHECK-LABEL: @ashr_ne_both_minus1 -; CHECK-NEXT: ret i1 false define i1 @ashr_ne_both_minus1(i8 %a) { - %shr = ashr i8 -1, %a - %cmp = icmp ne i8 %shr, -1 - ret i1 %cmp +; CHECK-LABEL: @ashr_ne_both_minus1( +; CHECK-NEXT: ret i1 false +; + %shr = ashr i8 -1, %a + %cmp = icmp ne i8 %shr, -1 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_eq_both_minus1 -; CHECK-NEXT: ret i1 true define i1 @exact_ashr_eq_both_minus1(i8 %a) { - %shr = ashr exact i8 -1, %a - %cmp = icmp eq i8 %shr, -1 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_eq_both_minus1( +; CHECK-NEXT: ret i1 true +; + %shr = ashr exact i8 -1, %a + %cmp = icmp eq i8 %shr, -1 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_ne_both_minus1 -; CHECK-NEXT: ret i1 false define i1 @exact_ashr_ne_both_minus1(i8 %a) { - %shr = ashr exact i8 -1, %a - %cmp = icmp ne i8 %shr, -1 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_ne_both_minus1( +; CHECK-NEXT: ret i1 false +; + %shr = ashr exact i8 -1, %a + %cmp = icmp ne i8 %shr, -1 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_eq_opposite_msb -; CHECK-NEXT: ret i1 false define i1 @exact_ashr_eq_opposite_msb(i8 %a) { - %shr = ashr exact i8 -128, %a - %cmp = icmp eq i8 %shr, 1 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_eq_opposite_msb( +; CHECK-NEXT: ret i1 false +; + %shr = ashr exact i8 -128, %a + %cmp = icmp eq i8 %shr, 1 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_eq_noexactlog -; CHECK-NEXT: ret i1 false define i1 @exact_ashr_eq_noexactlog(i8 %a) { - %shr = ashr exact i8 -90, %a - %cmp = icmp eq i8 %shr, -30 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_eq_noexactlog( +; CHECK-NEXT: ret i1 false +; + %shr = ashr exact i8 -90, %a + %cmp = icmp eq i8 %shr, -30 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_ne_opposite_msb -; CHECK-NEXT: ret i1 true define i1 @exact_ashr_ne_opposite_msb(i8 %a) { - %shr = ashr exact i8 -128, %a - %cmp = icmp ne i8 %shr, 1 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_ne_opposite_msb( +; CHECK-NEXT: ret i1 true +; + %shr = ashr exact i8 -128, %a + %cmp = icmp ne i8 %shr, 1 + ret i1 %cmp } -; CHECK-LABEL: @ashr_eq_opposite_msb -; CHECK-NEXT: ret i1 false define i1 @ashr_eq_opposite_msb(i8 %a) { - %shr = ashr i8 -128, %a - %cmp = icmp eq i8 %shr, 1 - ret i1 %cmp +; CHECK-LABEL: @ashr_eq_opposite_msb( +; CHECK-NEXT: ret i1 false +; + %shr = ashr i8 -128, %a + %cmp = icmp eq i8 %shr, 1 + ret i1 %cmp } -; CHECK-LABEL: @ashr_ne_opposite_msb -; CHECK-NEXT: ret i1 true define i1 @ashr_ne_opposite_msb(i8 %a) { - %shr = ashr i8 -128, %a - %cmp = icmp ne i8 %shr, 1 - ret i1 %cmp +; CHECK-LABEL: @ashr_ne_opposite_msb( +; CHECK-NEXT: ret i1 true +; + %shr = ashr i8 -128, %a + %cmp = icmp ne i8 %shr, 1 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_eq_shift_gt -; CHECK-NEXT: ret i1 false define i1 @exact_ashr_eq_shift_gt(i8 %a) { - %shr = ashr exact i8 -2, %a - %cmp = icmp eq i8 %shr, -8 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_eq_shift_gt( +; CHECK-NEXT: ret i1 false +; + %shr = ashr exact i8 -2, %a + %cmp = icmp eq i8 %shr, -8 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_ne_shift_gt -; CHECK-NEXT: ret i1 true define i1 @exact_ashr_ne_shift_gt(i8 %a) { - %shr = ashr exact i8 -2, %a - %cmp = icmp ne i8 %shr, -8 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_ne_shift_gt( +; CHECK-NEXT: ret i1 true +; + %shr = ashr exact i8 -2, %a + %cmp = icmp ne i8 %shr, -8 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_ashr_eq_shift_gt -; CHECK-NEXT: ret i1 false define i1 @nonexact_ashr_eq_shift_gt(i8 %a) { - %shr = ashr i8 -2, %a - %cmp = icmp eq i8 %shr, -8 - ret i1 %cmp +; CHECK-LABEL: @nonexact_ashr_eq_shift_gt( +; CHECK-NEXT: ret i1 false +; + %shr = ashr i8 -2, %a + %cmp = icmp eq i8 %shr, -8 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_ashr_ne_shift_gt -; CHECK-NEXT: ret i1 true define i1 @nonexact_ashr_ne_shift_gt(i8 %a) { - %shr = ashr i8 -2, %a - %cmp = icmp ne i8 %shr, -8 - ret i1 %cmp +; CHECK-LABEL: @nonexact_ashr_ne_shift_gt( +; CHECK-NEXT: ret i1 true +; + %shr = ashr i8 -2, %a + %cmp = icmp ne i8 %shr, -8 + ret i1 %cmp } -; CHECK-LABEL: @exact_lshr_eq_shift_gt -; CHECK-NEXT: ret i1 false define i1 @exact_lshr_eq_shift_gt(i8 %a) { - %shr = lshr exact i8 2, %a - %cmp = icmp eq i8 %shr, 8 - ret i1 %cmp +; CHECK-LABEL: @exact_lshr_eq_shift_gt( +; CHECK-NEXT: ret i1 false +; + %shr = lshr exact i8 2, %a + %cmp = icmp eq i8 %shr, 8 + ret i1 %cmp } -; CHECK-LABEL: @exact_lshr_ne_shift_gt -; CHECK-NEXT: ret i1 true define i1 @exact_lshr_ne_shift_gt(i8 %a) { - %shr = lshr exact i8 2, %a - %cmp = icmp ne i8 %shr, 8 - ret i1 %cmp +; CHECK-LABEL: @exact_lshr_ne_shift_gt( +; CHECK-NEXT: ret i1 true +; + %shr = lshr exact i8 2, %a + %cmp = icmp ne i8 %shr, 8 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_lshr_eq_shift_gt -; CHECK-NEXT: ret i1 false define i1 @nonexact_lshr_eq_shift_gt(i8 %a) { - %shr = lshr i8 2, %a - %cmp = icmp eq i8 %shr, 8 - ret i1 %cmp +; CHECK-LABEL: @nonexact_lshr_eq_shift_gt( +; CHECK-NEXT: ret i1 false +; + %shr = lshr i8 2, %a + %cmp = icmp eq i8 %shr, 8 + ret i1 %cmp } -; CHECK-LABEL: @nonexact_lshr_ne_shift_gt -; CHECK-NEXT: ret i1 true define i1 @nonexact_lshr_ne_shift_gt(i8 %a) { - %shr = ashr i8 2, %a - %cmp = icmp ne i8 %shr, 8 - ret i1 %cmp +; CHECK-LABEL: @nonexact_lshr_ne_shift_gt( +; CHECK-NEXT: ret i1 true +; + %shr = ashr i8 2, %a + %cmp = icmp ne i8 %shr, 8 + ret i1 %cmp } -; CHECK-LABEL: @exact_ashr_ne_noexactlog -; CHECK-NEXT: ret i1 true define i1 @exact_ashr_ne_noexactlog(i8 %a) { - %shr = ashr exact i8 -90, %a - %cmp = icmp ne i8 %shr, -30 - ret i1 %cmp +; CHECK-LABEL: @exact_ashr_ne_noexactlog( +; CHECK-NEXT: ret i1 true +; + %shr = ashr exact i8 -90, %a + %cmp = icmp ne i8 %shr, -30 + ret i1 %cmp } -; CHECK-LABEL: @exact_lshr_eq_noexactlog -; CHECK-NEXT: ret i1 false define i1 @exact_lshr_eq_noexactlog(i8 %a) { - %shr = lshr exact i8 90, %a - %cmp = icmp eq i8 %shr, 30 - ret i1 %cmp +; CHECK-LABEL: @exact_lshr_eq_noexactlog( +; CHECK-NEXT: ret i1 false +; + %shr = lshr exact i8 90, %a + %cmp = icmp eq i8 %shr, 30 + ret i1 %cmp } -; CHECK-LABEL: @exact_lshr_ne_noexactlog -; CHECK-NEXT: ret i1 true define i1 @exact_lshr_ne_noexactlog(i8 %a) { - %shr = lshr exact i8 90, %a - %cmp = icmp ne i8 %shr, 30 - ret i1 %cmp +; CHECK-LABEL: @exact_lshr_ne_noexactlog( +; CHECK-NEXT: ret i1 true +; + %shr = lshr exact i8 90, %a + %cmp = icmp ne i8 %shr, 30 + ret i1 %cmp } -; CHECK-LABEL: @exact_lshr_lowbit -; CHECK-NEXT: ret i32 7 define i32 @exact_lshr_lowbit(i32 %shiftval) { +; CHECK-LABEL: @exact_lshr_lowbit( +; CHECK-NEXT: ret i32 7 +; %shr = lshr exact i32 7, %shiftval ret i32 %shr } -; CHECK-LABEL: @exact_ashr_lowbit -; CHECK-NEXT: ret i32 7 define i32 @exact_ashr_lowbit(i32 %shiftval) { +; CHECK-LABEL: @exact_ashr_lowbit( +; CHECK-NEXT: ret i32 7 +; %shr = ashr exact i32 7, %shiftval ret i32 %shr } + +define i32 @ashr_zero(i32 %shiftval) { +; CHECK-LABEL: @ashr_zero( +; CHECK-NEXT: ret i32 0 +; + %shr = ashr i32 0, %shiftval + ret i32 %shr +} + +define i257 @ashr_minus1(i257 %shiftval) { +; CHECK-LABEL: @ashr_minus1( +; CHECK-NEXT: ret i257 -1 +; + %shr = ashr i257 -1, %shiftval + ret i257 %shr +} + +define <2 x i4097> @ashr_zero_vec(<2 x i4097> %shiftval) { +; CHECK-LABEL: @ashr_zero_vec( +; CHECK-NEXT: ret <2 x i4097> zeroinitializer +; + %shr = ashr <2 x i4097> zeroinitializer, %shiftval + ret <2 x i4097> %shr +} + +define <2 x i64> @ashr_minus1_vec(<2 x i64> %shiftval) { +; CHECK-LABEL: @ashr_minus1_vec( +; CHECK-NEXT: ret <2 x i64> <i64 -1, i64 -1> +; + %shr = ashr <2 x i64> <i64 -1, i64 -1>, %shiftval + ret <2 x i64> %shr +} + +define <2 x i4> @ashr_zero_minus1_vec(<2 x i4> %shiftval) { +; CHECK-LABEL: @ashr_zero_minus1_vec( +; CHECK-NEXT: ret <2 x i4> <i4 0, i4 -1> +; + %shr = ashr <2 x i4> <i4 0, i4 -1>, %shiftval + ret <2 x i4> %shr +} + diff --git a/test/Transforms/InstSimplify/undef.ll b/test/Transforms/InstSimplify/undef.ll index d75dc364243c..b92184bb6882 100644 --- a/test/Transforms/InstSimplify/undef.ll +++ b/test/Transforms/InstSimplify/undef.ll @@ -1,281 +1,347 @@ +; NOTE: Assertions have been autogenerated by update_test_checks.py ; RUN: opt -instsimplify -S < %s | FileCheck %s -; @test0 -; CHECK: ret i64 undef define i64 @test0() { +; CHECK-LABEL: @test0( +; CHECK: ret i64 undef +; %r = mul i64 undef, undef ret i64 %r } -; @test1 -; CHECK: ret i64 undef define i64 @test1() { +; CHECK-LABEL: @test1( +; CHECK: ret i64 undef +; %r = mul i64 3, undef ret i64 %r } -; @test2 -; CHECK: ret i64 undef define i64 @test2() { +; CHECK-LABEL: @test2( +; CHECK: ret i64 undef +; %r = mul i64 undef, 3 ret i64 %r } -; @test3 -; CHECK: ret i64 0 define i64 @test3() { +; CHECK-LABEL: @test3( +; CHECK: ret i64 0 +; %r = mul i64 undef, 6 ret i64 %r } -; @test4 -; CHECK: ret i64 0 define i64 @test4() { +; CHECK-LABEL: @test4( +; CHECK: ret i64 0 +; %r = mul i64 6, undef ret i64 %r } -; @test5 -; CHECK: ret i64 undef define i64 @test5() { +; CHECK-LABEL: @test5( +; CHECK: ret i64 undef +; %r = and i64 undef, undef ret i64 %r } -; @test6 -; CHECK: ret i64 undef define i64 @test6() { +; CHECK-LABEL: @test6( +; CHECK: ret i64 undef +; %r = or i64 undef, undef ret i64 %r } -; @test7 -; CHECK: ret i64 undef define i64 @test7() { +; CHECK-LABEL: @test7( +; CHECK: ret i64 undef +; %r = udiv i64 undef, 1 ret i64 %r } -; @test8 -; CHECK: ret i64 undef define i64 @test8() { +; CHECK-LABEL: @test8( +; CHECK: ret i64 undef +; %r = sdiv i64 undef, 1 ret i64 %r } -; @test9 -; CHECK: ret i64 0 define i64 @test9() { +; CHECK-LABEL: @test9( +; CHECK: ret i64 0 +; %r = urem i64 undef, 1 ret i64 %r } -; @test10 -; CHECK: ret i64 0 define i64 @test10() { +; CHECK-LABEL: @test10( +; CHECK: ret i64 0 +; %r = srem i64 undef, 1 ret i64 %r } -; @test11 -; CHECK: ret i64 undef define i64 @test11() { +; CHECK-LABEL: @test11( +; CHECK: ret i64 undef +; %r = shl i64 undef, undef ret i64 %r } -; @test11b -; CHECK: ret i64 undef define i64 @test11b(i64 %a) { +; CHECK-LABEL: @test11b( +; CHECK: ret i64 undef +; %r = shl i64 %a, undef ret i64 %r } -; @test12 -; CHECK: ret i64 undef define i64 @test12() { +; CHECK-LABEL: @test12( +; CHECK: ret i64 undef +; %r = ashr i64 undef, undef ret i64 %r } -; @test12b -; CHECK: ret i64 undef define i64 @test12b(i64 %a) { +; CHECK-LABEL: @test12b( +; CHECK: ret i64 undef +; %r = ashr i64 %a, undef ret i64 %r } -; @test13 -; CHECK: ret i64 undef define i64 @test13() { +; CHECK-LABEL: @test13( +; CHECK: ret i64 undef +; %r = lshr i64 undef, undef ret i64 %r } -; @test13b -; CHECK: ret i64 undef define i64 @test13b(i64 %a) { +; CHECK-LABEL: @test13b( +; CHECK: ret i64 undef +; %r = lshr i64 %a, undef ret i64 %r } -; @test14 -; CHECK: ret i1 undef define i1 @test14() { +; CHECK-LABEL: @test14( +; CHECK: ret i1 undef +; %r = icmp slt i64 undef, undef ret i1 %r } -; @test15 -; CHECK: ret i1 undef define i1 @test15() { +; CHECK-LABEL: @test15( +; CHECK: ret i1 undef +; %r = icmp ult i64 undef, undef ret i1 %r } -; @test16 -; CHECK: ret i64 undef define i64 @test16(i64 %a) { +; CHECK-LABEL: @test16( +; CHECK: ret i64 undef +; %r = select i1 undef, i64 %a, i64 undef ret i64 %r } -; @test17 -; CHECK: ret i64 undef define i64 @test17(i64 %a) { +; CHECK-LABEL: @test17( +; CHECK: ret i64 undef +; %r = select i1 undef, i64 undef, i64 %a ret i64 %r } -; @test18 -; CHECK: ret i64 undef define i64 @test18(i64 %a) { +; CHECK-LABEL: @test18( +; CHECK: [[R:%.*]] = call i64 undef(i64 %a) +; CHECK-NEXT: ret i64 undef +; %r = call i64 (i64) undef(i64 %a) ret i64 %r } -; CHECK-LABEL: @test19 -; CHECK: ret <4 x i8> undef define <4 x i8> @test19(<4 x i8> %a) { +; CHECK-LABEL: @test19( +; CHECK: ret <4 x i8> undef +; %b = shl <4 x i8> %a, <i8 8, i8 9, i8 undef, i8 -1> ret <4 x i8> %b } -; CHECK-LABEL: @test20 -; CHECK: ret i32 undef define i32 @test20(i32 %a) { +; CHECK-LABEL: @test20( +; CHECK: ret i32 undef +; %b = udiv i32 %a, 0 ret i32 %b } -; CHECK-LABEL: @test21 -; CHECK: ret i32 undef define i32 @test21(i32 %a) { +; CHECK-LABEL: @test21( +; CHECK: ret i32 undef +; %b = sdiv i32 %a, 0 ret i32 %b } -; CHECK-LABEL: @test22 -; CHECK: ret i32 undef define i32 @test22(i32 %a) { +; CHECK-LABEL: @test22( +; CHECK: ret i32 undef +; %b = ashr exact i32 undef, %a ret i32 %b } -; CHECK-LABEL: @test23 -; CHECK: ret i32 undef define i32 @test23(i32 %a) { +; CHECK-LABEL: @test23( +; CHECK: ret i32 undef +; %b = lshr exact i32 undef, %a ret i32 %b } -; CHECK-LABEL: @test24 -; CHECK: ret i32 undef define i32 @test24() { +; CHECK-LABEL: @test24( +; CHECK: ret i32 undef +; %b = udiv i32 undef, 0 ret i32 %b } -; CHECK-LABEL: @test25 -; CHECK: ret i32 undef define i32 @test25() { +; CHECK-LABEL: @test25( +; CHECK: ret i32 undef +; %b = lshr i32 0, undef ret i32 %b } -; CHECK-LABEL: @test26 -; CHECK: ret i32 undef define i32 @test26() { +; CHECK-LABEL: @test26( +; CHECK: ret i32 undef +; %b = ashr i32 0, undef ret i32 %b } -; CHECK-LABEL: @test27 -; CHECK: ret i32 undef define i32 @test27() { +; CHECK-LABEL: @test27( +; CHECK: ret i32 undef +; %b = shl i32 0, undef ret i32 %b } -; CHECK-LABEL: @test28 -; CHECK: ret i32 undef define i32 @test28(i32 %a) { +; CHECK-LABEL: @test28( +; CHECK: ret i32 undef +; %b = shl nsw i32 undef, %a ret i32 %b } -; CHECK-LABEL: @test29 -; CHECK: ret i32 undef define i32 @test29(i32 %a) { +; CHECK-LABEL: @test29( +; CHECK: ret i32 undef +; %b = shl nuw i32 undef, %a ret i32 %b } -; CHECK-LABEL: @test30 -; CHECK: ret i32 undef define i32 @test30(i32 %a) { +; CHECK-LABEL: @test30( +; CHECK: ret i32 undef +; %b = shl nsw nuw i32 undef, %a ret i32 %b } -; CHECK-LABEL: @test31 -; CHECK: ret i32 0 define i32 @test31(i32 %a) { +; CHECK-LABEL: @test31( +; CHECK: ret i32 0 +; %b = shl i32 undef, %a ret i32 %b } -; CHECK-LABEL: @test32 -; CHECK: ret i32 undef define i32 @test32(i32 %a) { +; CHECK-LABEL: @test32( +; CHECK: ret i32 undef +; %b = shl i32 undef, 0 ret i32 %b } -; CHECK-LABEL: @test33 -; CHECK: ret i32 undef define i32 @test33(i32 %a) { +; CHECK-LABEL: @test33( +; CHECK: ret i32 undef +; %b = ashr i32 undef, 0 ret i32 %b } -; CHECK-LABEL: @test34 -; CHECK: ret i32 undef define i32 @test34(i32 %a) { +; CHECK-LABEL: @test34( +; CHECK: ret i32 undef +; %b = lshr i32 undef, 0 ret i32 %b } -; CHECK-LABEL: @test35 -; CHECK: ret i32 undef define i32 @test35(<4 x i32> %V) { +; CHECK-LABEL: @test35( +; CHECK: ret i32 undef +; %b = extractelement <4 x i32> %V, i32 4 ret i32 %b } -; CHECK-LABEL: @test36 -; CHECK: ret i32 undef define i32 @test36(i32 %V) { +; CHECK-LABEL: @test36( +; CHECK: ret i32 undef +; %b = extractelement <4 x i32> undef, i32 %V ret i32 %b } + +define i32 @test37() { +; CHECK-LABEL: @test37( +; CHECK: ret i32 undef +; + %b = udiv i32 undef, undef + ret i32 %b +} + +define i32 @test38(i32 %a) { +; CHECK-LABEL: @test38( +; CHECK: ret i32 undef +; + %b = udiv i32 %a, undef + ret i32 %b +} + +define i32 @test39() { +; CHECK-LABEL: @test39( +; CHECK: ret i32 undef +; + %b = udiv i32 0, undef + ret i32 %b +} diff --git a/test/Transforms/InstSimplify/vec-cmp.ll b/test/Transforms/InstSimplify/vec-cmp.ll new file mode 100644 index 000000000000..ca6361a18ac4 --- /dev/null +++ b/test/Transforms/InstSimplify/vec-cmp.ll @@ -0,0 +1,65 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instsimplify -S | FileCheck %s + +define <2 x i1> @nonzero_vec_splat(<2 x i32> %x) { +; CHECK-LABEL: @nonzero_vec_splat( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %y = or <2 x i32> %x, <i32 1, i32 1> + %c = icmp eq <2 x i32> %y, zeroinitializer + ret <2 x i1> %c +} + +define <2 x i1> @nonzero_vec_nonsplat(<2 x i32> %x) { +; CHECK-LABEL: @nonzero_vec_nonsplat( +; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true> +; + %y = or <2 x i32> %x, <i32 2, i32 1> + %c = icmp ne <2 x i32> %y, zeroinitializer + ret <2 x i1> %c +} + +define <2 x i1> @nonzero_vec_undef_elt(<2 x i32> %x) { +; CHECK-LABEL: @nonzero_vec_undef_elt( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %y = or <2 x i32> %x, <i32 undef, i32 1> + %c = icmp eq <2 x i32> %y, zeroinitializer + ret <2 x i1> %c +} + +define <2 x i1> @may_be_zero_vec(<2 x i32> %x) { +; CHECK-LABEL: @may_be_zero_vec( +; CHECK-NEXT: [[Y:%.*]] = or <2 x i32> %x, <i32 0, i32 1> +; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[Y]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[C]] +; + %y = or <2 x i32> %x, <i32 0, i32 1> + %c = icmp ne <2 x i32> %y, zeroinitializer + ret <2 x i1> %c +} + +; Multiplies of non-zero numbers are non-zero if there is no unsigned overflow. +define <2 x i1> @nonzero_vec_mul_nuw(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @nonzero_vec_mul_nuw( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %xnz = or <2 x i32> %x, <i32 1, i32 2> + %ynz = or <2 x i32> %y, <i32 3, i32 undef> + %m = mul nuw <2 x i32> %xnz, %ynz + %c = icmp eq <2 x i32> %m, zeroinitializer + ret <2 x i1> %c +} + +; Multiplies of non-zero numbers are non-zero if there is no signed overflow. +define <2 x i1> @nonzero_vec_mul_nsw(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @nonzero_vec_mul_nsw( +; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true> +; + %xnz = or <2 x i32> %x, <i32 undef, i32 2> + %ynz = or <2 x i32> %y, <i32 3, i32 4> + %m = mul nsw <2 x i32> %xnz, %ynz + %c = icmp ne <2 x i32> %m, zeroinitializer + ret <2 x i1> %c +} + diff --git a/test/Transforms/InstSimplify/vector_gep.ll b/test/Transforms/InstSimplify/vector_gep.ll index 5c3062047c30..54887e99ee38 100644 --- a/test/Transforms/InstSimplify/vector_gep.ll +++ b/test/Transforms/InstSimplify/vector_gep.ll @@ -53,3 +53,12 @@ define <4 x i8*> @test5() { ; CHECK-LABEL: @test5 ; CHECK-NEXT: ret <4 x i8*> getelementptr (i8, <4 x i8*> <i8* inttoptr (i64 1 to i8*), i8* inttoptr (i64 2 to i8*), i8* inttoptr (i64 3 to i8*), i8* inttoptr (i64 4 to i8*)>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>) } + +@v = global [24 x [42 x [3 x i32]]] zeroinitializer, align 16 + +define <16 x i32*> @test6() { +; CHECK-LABEL: @test6 +; CHECK-NEXT: ret <16 x i32*> getelementptr ([24 x [42 x [3 x i32]]], [24 x [42 x [3 x i32]]]* @v, <16 x i64> zeroinitializer, <16 x i64> zeroinitializer, <16 x i64> <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15>, <16 x i64> zeroinitializer) + %VectorGep = getelementptr [24 x [42 x [3 x i32]]], [24 x [42 x [3 x i32]]]* @v, i64 0, i64 0, <16 x i64> <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15>, i64 0 + ret <16 x i32*> %VectorGep +}
\ No newline at end of file |