1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; For pattern ((X l>> Y) & ~C) ==/!= 0; when C+1 is power of 2 5; it may be optimal to fold into (X l>> Y) </>= C+1 6; rather than X & (~C << Y) ==/!= 0 7 8; Scalar tests 9 10define i1 @scalar_i8_lshr_and_negC_eq(i8 %x, i8 %y) { 11; CHECK-LABEL: @scalar_i8_lshr_and_negC_eq( 12; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 [[X:%.*]], [[Y:%.*]] 13; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[LSHR]], 4 14; CHECK-NEXT: ret i1 [[R]] 15; 16 %lshr = lshr i8 %x, %y 17 %and = and i8 %lshr, 252 ; ~3 18 %r = icmp eq i8 %and, 0 19 ret i1 %r 20} 21 22define i1 @scalar_i16_lshr_and_negC_eq(i16 %x, i16 %y) { 23; CHECK-LABEL: @scalar_i16_lshr_and_negC_eq( 24; CHECK-NEXT: [[LSHR:%.*]] = lshr i16 [[X:%.*]], [[Y:%.*]] 25; CHECK-NEXT: [[R:%.*]] = icmp ult i16 [[LSHR]], 128 26; CHECK-NEXT: ret i1 [[R]] 27; 28 %lshr = lshr i16 %x, %y 29 %and = and i16 %lshr, 65408 ; ~127 30 %r = icmp eq i16 %and, 0 31 ret i1 %r 32} 33 34define i1 @scalar_i32_lshr_and_negC_eq(i32 %x, i32 %y) { 35; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq( 36; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 37; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[LSHR]], 262144 38; CHECK-NEXT: ret i1 [[R]] 39; 40 %lshr = lshr i32 %x, %y 41 %and = and i32 %lshr, 4294705152 ; ~262143 42 %r = icmp eq i32 %and, 0 43 ret i1 %r 44} 45 46define i1 @scalar_i64_lshr_and_negC_eq(i64 %x, i64 %y) { 47; CHECK-LABEL: @scalar_i64_lshr_and_negC_eq( 48; CHECK-NEXT: [[LSHR:%.*]] = lshr i64 [[X:%.*]], [[Y:%.*]] 49; CHECK-NEXT: [[R:%.*]] = icmp ult i64 [[LSHR]], 8589934592 50; CHECK-NEXT: ret i1 [[R]] 51; 52 %lshr = lshr i64 %x, %y 53 %and = and i64 %lshr, 18446744065119617024 ; ~8589934591 54 %r = icmp eq i64 %and, 0 55 ret i1 %r 56} 57 58define i1 @scalar_i32_lshr_and_negC_ne(i32 %x, i32 %y) { 59; CHECK-LABEL: @scalar_i32_lshr_and_negC_ne( 60; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 61; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[LSHR]], 262143 62; CHECK-NEXT: ret i1 [[R]] 63; 64 %lshr = lshr i32 %x, %y 65 %and = and i32 %lshr, 4294705152 ; ~262143 66 %r = icmp ne i32 %and, 0 ; check 'ne' predicate 67 ret i1 %r 68} 69 70; Vector tests 71 72define <4 x i1> @vec_4xi32_lshr_and_negC_eq(<4 x i32> %x, <4 x i32> %y) { 73; CHECK-LABEL: @vec_4xi32_lshr_and_negC_eq( 74; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] 75; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], <i32 8, i32 8, i32 8, i32 8> 76; CHECK-NEXT: ret <4 x i1> [[R]] 77; 78 %lshr = lshr <4 x i32> %x, %y 79 %and = and <4 x i32> %lshr, <i32 4294967288, i32 4294967288, i32 4294967288, i32 4294967288> ; ~7 80 %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 0> 81 ret <4 x i1> %r 82} 83 84define <4 x i1> @vec_lshr_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) { 85; CHECK-LABEL: @vec_lshr_and_negC_eq_undef1( 86; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] 87; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], <i32 -8, i32 undef, i32 -8, i32 -8> 88; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer 89; CHECK-NEXT: ret <4 x i1> [[R]] 90; 91 %lshr = lshr <4 x i32> %x, %y 92 %and = and <4 x i32> %lshr, <i32 4294967288, i32 undef, i32 4294967288, i32 4294967288> ; ~7 93 %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 0> 94 ret <4 x i1> %r 95} 96 97define <4 x i1> @vec_lshr_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) { 98; CHECK-LABEL: @vec_lshr_and_negC_eq_undef2( 99; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] 100; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], <i32 -8, i32 -8, i32 -8, i32 -8> 101; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 0, i32 0, i32 0, i32 undef> 102; CHECK-NEXT: ret <4 x i1> [[R]] 103; 104 %lshr = lshr <4 x i32> %x, %y 105 %and = and <4 x i32> %lshr, <i32 4294967288, i32 4294967288, i32 4294967288, i32 4294967288> ; ~7 106 %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 undef> 107 ret <4 x i1> %r 108} 109 110define <4 x i1> @vec_lshr_and_negC_eq_undef3(<4 x i32> %x, <4 x i32> %y) { 111; CHECK-LABEL: @vec_lshr_and_negC_eq_undef3( 112; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] 113; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], <i32 -8, i32 -8, i32 undef, i32 -8> 114; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 0, i32 0, i32 0, i32 undef> 115; CHECK-NEXT: ret <4 x i1> [[R]] 116; 117 %lshr = lshr <4 x i32> %x, %y 118 %and = and <4 x i32> %lshr, <i32 4294967288, i32 4294967288, i32 undef, i32 4294967288> ; ~7 119 %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 undef> 120 ret <4 x i1> %r 121} 122 123; Extra use 124 125; Fold happened 126define i1 @scalar_lshr_and_negC_eq_extra_use_lshr(i32 %x, i32 %y, i32 %z, i32* %p) { 127; CHECK-LABEL: @scalar_lshr_and_negC_eq_extra_use_lshr( 128; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 129; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[LSHR]], [[Z:%.*]] 130; CHECK-NEXT: store i32 [[XOR]], i32* [[P:%.*]], align 4 131; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[LSHR]], 8 132; CHECK-NEXT: ret i1 [[R]] 133; 134 %lshr = lshr i32 %x, %y 135 %xor = xor i32 %lshr, %z ; extra use of lshr 136 store i32 %xor, i32* %p 137 %and = and i32 %lshr, 4294967288 ; ~7 138 %r = icmp eq i32 %and, 0 139 ret i1 %r 140} 141 142; Not fold 143define i1 @scalar_lshr_and_negC_eq_extra_use_and(i32 %x, i32 %y, i32 %z, i32* %p) { 144; CHECK-LABEL: @scalar_lshr_and_negC_eq_extra_use_and( 145; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 146; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], -8 147; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[AND]], [[Z:%.*]] 148; CHECK-NEXT: store i32 [[MUL]], i32* [[P:%.*]], align 4 149; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 150; CHECK-NEXT: ret i1 [[R]] 151; 152 %lshr = lshr i32 %x, %y 153 %and = and i32 %lshr, 4294967288 ; ~7 154 %mul = mul i32 %and, %z ; extra use of and 155 store i32 %mul, i32* %p 156 %r = icmp eq i32 %and, 0 157 ret i1 %r 158} 159 160; Not fold 161define i1 @scalar_lshr_and_negC_eq_extra_use_lshr_and(i32 %x, i32 %y, i32 %z, i32* %p, i32* %q) { 162; CHECK-LABEL: @scalar_lshr_and_negC_eq_extra_use_lshr_and( 163; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 164; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], -8 165; CHECK-NEXT: store i32 [[AND]], i32* [[P:%.*]], align 4 166; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LSHR]], [[Z:%.*]] 167; CHECK-NEXT: store i32 [[ADD]], i32* [[Q:%.*]], align 4 168; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 169; CHECK-NEXT: ret i1 [[R]] 170; 171 %lshr = lshr i32 %x, %y 172 %and = and i32 %lshr, 4294967288 ; ~7 173 store i32 %and, i32* %p ; extra use of and 174 %add = add i32 %lshr, %z ; extra use of lshr 175 store i32 %add, i32* %q 176 %r = icmp eq i32 %and, 0 177 ret i1 %r 178} 179 180; Negative tests 181 182; X is constant 183 184define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant1(i32 %y) { 185; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant1( 186; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 12345, [[Y:%.*]] 187; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[LSHR]], 8 188; CHECK-NEXT: ret i1 [[R]] 189; 190 %lshr = lshr i32 12345, %y 191 %and = and i32 %lshr, 4294967288 ; ~7 192 %r = icmp eq i32 %and, 0 193 ret i1 %r 194} 195 196define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant2(i32 %y) { 197; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant2( 198; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 268435456, [[Y:%.*]] 199; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[LSHR]], 8 200; CHECK-NEXT: ret i1 [[R]] 201; 202 %lshr = lshr i32 268435456, %y 203 %and = and i32 %lshr, 4294967288 ; ~7 204 %r = icmp eq i32 %and, 0 205 ret i1 %r 206} 207 208; Check 'slt' predicate 209 210define i1 @scalar_i32_lshr_and_negC_slt(i32 %x, i32 %y) { 211; CHECK-LABEL: @scalar_i32_lshr_and_negC_slt( 212; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 213; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[LSHR]], 0 214; CHECK-NEXT: ret i1 [[R]] 215; 216 %lshr = lshr i32 %x, %y 217 %and = and i32 %lshr, 4294967288 ; ~7 218 %r = icmp slt i32 %and, 0 219 ret i1 %r 220} 221 222; Compare with nonzero 223 224define i1 @scalar_i32_lshr_and_negC_eq_nonzero(i32 %x, i32 %y) { 225; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_nonzero( 226; CHECK-NEXT: ret i1 false 227; 228 %lshr = lshr i32 %x, %y 229 %and = and i32 %lshr, 4294967288 ; ~7 230 %r = icmp eq i32 %and, 1 ; should be comparing with 0 231 ret i1 %r 232} 233