1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=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]], splat (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_poison1(<4 x i32> %x, <4 x i32> %y) { 85; CHECK-LABEL: @vec_lshr_and_negC_eq_poison1( 86; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] 87; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], splat (i32 8) 88; CHECK-NEXT: ret <4 x i1> [[R]] 89; 90 %lshr = lshr <4 x i32> %x, %y 91 %and = and <4 x i32> %lshr, <i32 4294967288, i32 poison, i32 4294967288, i32 4294967288> ; ~7 92 %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 0> 93 ret <4 x i1> %r 94} 95 96define <4 x i1> @vec_lshr_and_negC_eq_poison2(<4 x i32> %x, <4 x i32> %y) { 97; CHECK-LABEL: @vec_lshr_and_negC_eq_poison2( 98; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] 99; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], splat (i32 8) 100; CHECK-NEXT: ret <4 x i1> [[R]] 101; 102 %lshr = lshr <4 x i32> %x, %y 103 %and = and <4 x i32> %lshr, <i32 4294967288, i32 4294967288, i32 4294967288, i32 4294967288> ; ~7 104 %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 poison> 105 ret <4 x i1> %r 106} 107 108define <4 x i1> @vec_lshr_and_negC_eq_poison3(<4 x i32> %x, <4 x i32> %y) { 109; CHECK-LABEL: @vec_lshr_and_negC_eq_poison3( 110; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] 111; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], splat (i32 8) 112; CHECK-NEXT: ret <4 x i1> [[R]] 113; 114 %lshr = lshr <4 x i32> %x, %y 115 %and = and <4 x i32> %lshr, <i32 4294967288, i32 4294967288, i32 poison, i32 4294967288> ; ~7 116 %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 poison> 117 ret <4 x i1> %r 118} 119 120; Extra use 121 122; Fold happened 123define i1 @scalar_lshr_and_negC_eq_extra_use_lshr(i32 %x, i32 %y, i32 %z, ptr %p) { 124; CHECK-LABEL: @scalar_lshr_and_negC_eq_extra_use_lshr( 125; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 126; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[LSHR]], [[Z:%.*]] 127; CHECK-NEXT: store i32 [[XOR]], ptr [[P:%.*]], align 4 128; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[LSHR]], 8 129; CHECK-NEXT: ret i1 [[R]] 130; 131 %lshr = lshr i32 %x, %y 132 %xor = xor i32 %lshr, %z ; extra use of lshr 133 store i32 %xor, ptr %p 134 %and = and i32 %lshr, 4294967288 ; ~7 135 %r = icmp eq i32 %and, 0 136 ret i1 %r 137} 138 139; Not fold 140define i1 @scalar_lshr_and_negC_eq_extra_use_and(i32 %x, i32 %y, i32 %z, ptr %p) { 141; CHECK-LABEL: @scalar_lshr_and_negC_eq_extra_use_and( 142; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 143; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], -8 144; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[AND]], [[Z:%.*]] 145; CHECK-NEXT: store i32 [[MUL]], ptr [[P:%.*]], align 4 146; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 147; CHECK-NEXT: ret i1 [[R]] 148; 149 %lshr = lshr i32 %x, %y 150 %and = and i32 %lshr, 4294967288 ; ~7 151 %mul = mul i32 %and, %z ; extra use of and 152 store i32 %mul, ptr %p 153 %r = icmp eq i32 %and, 0 154 ret i1 %r 155} 156 157; Not fold 158define i1 @scalar_lshr_and_negC_eq_extra_use_lshr_and(i32 %x, i32 %y, i32 %z, ptr %p, ptr %q) { 159; CHECK-LABEL: @scalar_lshr_and_negC_eq_extra_use_lshr_and( 160; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 161; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], -8 162; CHECK-NEXT: store i32 [[AND]], ptr [[P:%.*]], align 4 163; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LSHR]], [[Z:%.*]] 164; CHECK-NEXT: store i32 [[ADD]], ptr [[Q:%.*]], align 4 165; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 166; CHECK-NEXT: ret i1 [[R]] 167; 168 %lshr = lshr i32 %x, %y 169 %and = and i32 %lshr, 4294967288 ; ~7 170 store i32 %and, ptr %p ; extra use of and 171 %add = add i32 %lshr, %z ; extra use of lshr 172 store i32 %add, ptr %q 173 %r = icmp eq i32 %and, 0 174 ret i1 %r 175} 176 177define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant1(i32 %y) { 178; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant1( 179; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 12345, [[Y:%.*]] 180; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i32 [[LSHR]], 8 181; CHECK-NEXT: ret i1 [[R]] 182; 183 %lshr = lshr i32 12345, %y 184 %and = and i32 %lshr, 4294967288 ; ~7 185 %r = icmp eq i32 %and, 0 186 ret i1 %r 187} 188 189define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant2(i32 %y) { 190; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant2( 191; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[Y:%.*]], 25 192; CHECK-NEXT: ret i1 [[R]] 193; 194 %lshr = lshr i32 268435456, %y 195 %and = and i32 %lshr, 4294967288 ; ~7 196 %r = icmp eq i32 %and, 0 197 ret i1 %r 198} 199define i1 @scalar_i32_udiv_and_negC_eq_X_is_constant3(i32 %y) { 200; CHECK-LABEL: @scalar_i32_udiv_and_negC_eq_X_is_constant3( 201; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y:%.*]], 1544 202; CHECK-NEXT: ret i1 [[R]] 203; 204 %lshr = udiv i32 12345, %y 205 %and = and i32 %lshr, 16376 ; 0x3ff8 206 %r = icmp ne i32 %and, 0 207 ret i1 %r 208} 209 210; Negative test 211 212define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant_negative(i32 %y) { 213; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant_negative( 214; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 16384, [[Y:%.*]] 215; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], 16376 216; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 217; CHECK-NEXT: ret i1 [[R]] 218; 219 %lshr = lshr i32 16384, %y ; 0x4000 220 %and = and i32 %lshr, 16376 ; 0x3ff8 221 %r = icmp eq i32 %and, 0 222 ret i1 %r 223} 224; Check 'slt' predicate 225 226define i1 @scalar_i32_lshr_and_negC_slt(i32 %x, i32 %y) { 227; CHECK-LABEL: @scalar_i32_lshr_and_negC_slt( 228; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] 229; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[LSHR]], 0 230; CHECK-NEXT: ret i1 [[R]] 231; 232 %lshr = lshr i32 %x, %y 233 %and = and i32 %lshr, 4294967288 ; ~7 234 %r = icmp slt i32 %and, 0 235 ret i1 %r 236} 237 238; Compare with nonzero 239 240define i1 @scalar_i32_lshr_and_negC_eq_nonzero(i32 %x, i32 %y) { 241; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_nonzero( 242; CHECK-NEXT: ret i1 false 243; 244 %lshr = lshr i32 %x, %y 245 %and = and i32 %lshr, 4294967288 ; ~7 246 %r = icmp eq i32 %and, 1 ; should be comparing with 0 247 ret i1 %r 248} 249 250; Not NegatedPowerOf2 251 252define i1 @scalar_i8_lshr_and_negC_eq_not_negatedPowerOf2(i8 %x, i8 %y) { 253; CHECK-LABEL: @scalar_i8_lshr_and_negC_eq_not_negatedPowerOf2( 254; CHECK-NEXT: [[TMP1:%.*]] = shl i8 -3, [[Y:%.*]] 255; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]] 256; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP2]], 0 257; CHECK-NEXT: ret i1 [[R]] 258; 259 %lshr = lshr i8 %x, %y 260 %and = and i8 %lshr, 253 ; -3 261 %r = icmp eq i8 %and, 0 262 ret i1 %r 263} 264