1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -instcombine -S < %s | FileCheck %s 3 4; PR5438 5 6define i32 @test1(i32 %a, i32 %b) nounwind readnone { 7; CHECK-LABEL: @test1( 8; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], [[A:%.*]] 9; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], -1 10; CHECK-NEXT: [[DOTLOBIT_NOT:%.*]] = lshr i32 [[TMP2]], 31 11; CHECK-NEXT: ret i32 [[DOTLOBIT_NOT]] 12; 13 %t0 = icmp sgt i32 %a, -1 14 %t1 = icmp slt i32 %b, 0 15 %t2 = xor i1 %t1, %t0 16 %t3 = zext i1 %t2 to i32 17 ret i32 %t3 18} 19 20; TODO: This optimizes partially but not all the way. 21define i32 @test2(i32 %a, i32 %b) nounwind readnone { 22; CHECK-LABEL: @test2( 23; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 24; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 3 25; CHECK-NEXT: [[DOTLOBIT:%.*]] = and i32 [[TMP2]], 1 26; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[DOTLOBIT]], 1 27; CHECK-NEXT: ret i32 [[TMP3]] 28; 29 %t0 = and i32 %a, 8 30 %t1 = and i32 %b, 8 31 %t2 = icmp eq i32 %t0, %t1 32 %t3 = zext i1 %t2 to i32 33 ret i32 %t3 34} 35 36define i32 @test3(i32 %a, i32 %b) nounwind readnone { 37; CHECK-LABEL: @test3( 38; CHECK-NEXT: [[T2_UNSHIFTED:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 39; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[T2_UNSHIFTED]], -1 40; CHECK-NEXT: [[T2_UNSHIFTED_LOBIT_NOT:%.*]] = lshr i32 [[TMP1]], 31 41; CHECK-NEXT: ret i32 [[T2_UNSHIFTED_LOBIT_NOT]] 42; 43 %t0 = lshr i32 %a, 31 44 %t1 = lshr i32 %b, 31 45 %t2 = icmp eq i32 %t0, %t1 46 %t3 = zext i1 %t2 to i32 47 ret i32 %t3 48} 49 50; TODO this should optimize but doesn't due to missing vector support in InstCombiner::foldICmpEquality. 51define <2 x i32> @test3vec(<2 x i32> %a, <2 x i32> %b) nounwind readnone { 52; CHECK-LABEL: @test3vec( 53; CHECK-NEXT: [[T0:%.*]] = lshr <2 x i32> [[A:%.*]], <i32 31, i32 31> 54; CHECK-NEXT: [[T1:%.*]] = lshr <2 x i32> [[B:%.*]], <i32 31, i32 31> 55; CHECK-NEXT: [[T2:%.*]] = icmp eq <2 x i32> [[T0]], [[T1]] 56; CHECK-NEXT: [[T3:%.*]] = zext <2 x i1> [[T2]] to <2 x i32> 57; CHECK-NEXT: ret <2 x i32> [[T3]] 58; 59 %t0 = lshr <2 x i32> %a, <i32 31, i32 31> 60 %t1 = lshr <2 x i32> %b, <i32 31, i32 31> 61 %t2 = icmp eq <2 x i32> %t0, %t1 62 %t3 = zext <2 x i1> %t2 to <2 x i32> 63 ret <2 x i32> %t3 64} 65 66; Variation on @test3: checking the 2nd bit in a situation where the 5th bit 67; is one, not zero. 68define i32 @test3i(i32 %a, i32 %b) nounwind readnone { 69; CHECK-LABEL: @test3i( 70; CHECK-NEXT: [[T01:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 71; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[T01]], -1 72; CHECK-NEXT: [[T4:%.*]] = lshr i32 [[TMP1]], 31 73; CHECK-NEXT: ret i32 [[T4]] 74; 75 %t0 = lshr i32 %a, 29 76 %t1 = lshr i32 %b, 29 77 %t2 = or i32 %t0, 35 78 %t3 = or i32 %t1, 35 79 %t4 = icmp eq i32 %t2, %t3 80 %t5 = zext i1 %t4 to i32 81 ret i32 %t5 82} 83 84define i1 @test4a(i32 %a) { 85; CHECK-LABEL: @test4a( 86; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[A:%.*]], 1 87; CHECK-NEXT: ret i1 [[C]] 88; 89 %l = ashr i32 %a, 31 90 %na = sub i32 0, %a 91 %r = lshr i32 %na, 31 92 %signum = or i32 %l, %r 93 %c = icmp slt i32 %signum, 1 94 ret i1 %c 95} 96 97define <2 x i1> @test4a_vec(<2 x i32> %a) { 98; CHECK-LABEL: @test4a_vec( 99; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i32> [[A:%.*]], <i32 1, i32 1> 100; CHECK-NEXT: ret <2 x i1> [[C]] 101; 102 %l = ashr <2 x i32> %a, <i32 31, i32 31> 103 %na = sub <2 x i32> zeroinitializer, %a 104 %r = lshr <2 x i32> %na, <i32 31, i32 31> 105 %signum = or <2 x i32> %l, %r 106 %c = icmp slt <2 x i32> %signum, <i32 1, i32 1> 107 ret <2 x i1> %c 108} 109 110define i1 @test4b(i64 %a) { 111; CHECK-LABEL: @test4b( 112; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[A:%.*]], 1 113; CHECK-NEXT: ret i1 [[C]] 114; 115 %l = ashr i64 %a, 63 116 %na = sub i64 0, %a 117 %r = lshr i64 %na, 63 118 %signum = or i64 %l, %r 119 %c = icmp slt i64 %signum, 1 120 ret i1 %c 121} 122 123define i1 @test4c(i64 %a) { 124; CHECK-LABEL: @test4c( 125; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[A:%.*]], 1 126; CHECK-NEXT: ret i1 [[C]] 127; 128 %l = ashr i64 %a, 63 129 %na = sub i64 0, %a 130 %r = lshr i64 %na, 63 131 %signum = or i64 %l, %r 132 %signum.trunc = trunc i64 %signum to i32 133 %c = icmp slt i32 %signum.trunc, 1 134 ret i1 %c 135} 136 137define <2 x i1> @test4c_vec(<2 x i64> %a) { 138; CHECK-LABEL: @test4c_vec( 139; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i64> [[A:%.*]], <i64 1, i64 1> 140; CHECK-NEXT: ret <2 x i1> [[C]] 141; 142 %l = ashr <2 x i64> %a, <i64 63, i64 63> 143 %na = sub <2 x i64> zeroinitializer, %a 144 %r = lshr <2 x i64> %na, <i64 63, i64 63> 145 %signum = or <2 x i64> %l, %r 146 %signum.trunc = trunc <2 x i64> %signum to <2 x i32> 147 %c = icmp slt <2 x i32> %signum.trunc, <i32 1, i32 1> 148 ret <2 x i1> %c 149} 150 151