1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4define i1 @and_consts(i32 %k, i32 %c1, i32 %c2) { 5; CHECK-LABEL: @and_consts( 6; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[K:%.*]], 12 7; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 12 8; CHECK-NEXT: ret i1 [[TMP2]] 9; 10 %t1 = and i32 4, %k 11 %t2 = icmp eq i32 %t1, 0 12 %t5 = and i32 8, %k 13 %t6 = icmp eq i32 %t5, 0 14 %or = or i1 %t2, %t6 15 ret i1 %or 16} 17 18define <2 x i1> @and_consts_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { 19; CHECK-LABEL: @and_consts_vector( 20; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[K:%.*]], <i32 12, i32 12> 21; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], <i32 12, i32 12> 22; CHECK-NEXT: ret <2 x i1> [[TMP2]] 23; 24 %t1 = and <2 x i32> <i32 4, i32 4>, %k 25 %t2 = icmp eq <2 x i32> %t1, zeroinitializer 26 %t5 = and <2 x i32> <i32 8, i32 8>, %k 27 %t6 = icmp eq <2 x i32> %t5, zeroinitializer 28 %or = or <2 x i1> %t2, %t6 29 ret <2 x i1> %or 30} 31 32define i1 @foo1_and(i32 %k, i32 %c1, i32 %c2) { 33; CHECK-LABEL: @foo1_and( 34; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] 35; CHECK-NEXT: [[T4:%.*]] = shl i32 1, [[C2:%.*]] 36; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T]], [[T4]] 37; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]] 38; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] 39; CHECK-NEXT: ret i1 [[TMP3]] 40; 41 %t = shl i32 1, %c1 42 %t4 = shl i32 1, %c2 43 %t1 = and i32 %t, %k 44 %t2 = icmp eq i32 %t1, 0 45 %t5 = and i32 %t4, %k 46 %t6 = icmp eq i32 %t5, 0 47 %or = or i1 %t2, %t6 48 ret i1 %or 49} 50 51define <2 x i1> @foo1_and_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { 52; CHECK-LABEL: @foo1_and_vector( 53; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C1:%.*]] 54; CHECK-NEXT: [[T4:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C2:%.*]] 55; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[T]], [[T4]] 56; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[K:%.*]] 57; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], [[TMP1]] 58; CHECK-NEXT: ret <2 x i1> [[TMP3]] 59; 60 %t = shl <2 x i32> <i32 1, i32 1>, %c1 61 %t4 = shl <2 x i32> <i32 1, i32 1>, %c2 62 %t1 = and <2 x i32> %t, %k 63 %t2 = icmp eq <2 x i32> %t1, zeroinitializer 64 %t5 = and <2 x i32> %t4, %k 65 %t6 = icmp eq <2 x i32> %t5, zeroinitializer 66 %or = or <2 x i1> %t2, %t6 67 ret <2 x i1> %or 68} 69 70; Same as above but with operands commuted one of the ands, but not the other. 71define i1 @foo1_and_commuted(i32 %k, i32 %c1, i32 %c2) { 72; CHECK-LABEL: @foo1_and_commuted( 73; CHECK-NEXT: [[K2:%.*]] = mul i32 [[K:%.*]], [[K]] 74; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] 75; CHECK-NEXT: [[T4:%.*]] = shl i32 1, [[C2:%.*]] 76; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T]], [[T4]] 77; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[K2]], [[TMP1]] 78; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] 79; CHECK-NEXT: ret i1 [[TMP3]] 80; 81 %k2 = mul i32 %k, %k ; to trick the complexity sorting 82 %t = shl i32 1, %c1 83 %t4 = shl i32 1, %c2 84 %t1 = and i32 %k2, %t 85 %t2 = icmp eq i32 %t1, 0 86 %t5 = and i32 %t4, %k2 87 %t6 = icmp eq i32 %t5, 0 88 %or = or i1 %t2, %t6 89 ret i1 %or 90} 91 92define <2 x i1> @foo1_and_commuted_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { 93; CHECK-LABEL: @foo1_and_commuted_vector( 94; CHECK-NEXT: [[K2:%.*]] = mul <2 x i32> [[K:%.*]], [[K]] 95; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C1:%.*]] 96; CHECK-NEXT: [[T4:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C2:%.*]] 97; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[T]], [[T4]] 98; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[K2]], [[TMP1]] 99; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], [[TMP1]] 100; CHECK-NEXT: ret <2 x i1> [[TMP3]] 101; 102 %k2 = mul <2 x i32> %k, %k ; to trick the complexity sorting 103 %t = shl <2 x i32> <i32 1, i32 1>, %c1 104 %t4 = shl <2 x i32> <i32 1, i32 1>, %c2 105 %t1 = and <2 x i32> %k2, %t 106 %t2 = icmp eq <2 x i32> %t1, zeroinitializer 107 %t5 = and <2 x i32> %t4, %k2 108 %t6 = icmp eq <2 x i32> %t5, zeroinitializer 109 %or = or <2 x i1> %t2, %t6 110 ret <2 x i1> %or 111} 112 113define i1 @or_consts(i32 %k, i32 %c1, i32 %c2) { 114; CHECK-LABEL: @or_consts( 115; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[K:%.*]], 12 116; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 12 117; CHECK-NEXT: ret i1 [[TMP2]] 118; 119 %t1 = and i32 4, %k 120 %t2 = icmp ne i32 %t1, 0 121 %t5 = and i32 8, %k 122 %t6 = icmp ne i32 %t5, 0 123 %or = and i1 %t2, %t6 124 ret i1 %or 125} 126 127define <2 x i1> @or_consts_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { 128; CHECK-LABEL: @or_consts_vector( 129; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[K:%.*]], <i32 12, i32 12> 130; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 12, i32 12> 131; CHECK-NEXT: ret <2 x i1> [[TMP2]] 132; 133 %t1 = and <2 x i32> <i32 4, i32 4>, %k 134 %t2 = icmp ne <2 x i32> %t1, zeroinitializer 135 %t5 = and <2 x i32> <i32 8, i32 8>, %k 136 %t6 = icmp ne <2 x i32> %t5, zeroinitializer 137 %or = and <2 x i1> %t2, %t6 138 ret <2 x i1> %or 139} 140 141define i1 @foo1_or(i32 %k, i32 %c1, i32 %c2) { 142; CHECK-LABEL: @foo1_or( 143; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] 144; CHECK-NEXT: [[T4:%.*]] = shl i32 1, [[C2:%.*]] 145; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T]], [[T4]] 146; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]] 147; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], [[TMP1]] 148; CHECK-NEXT: ret i1 [[TMP3]] 149; 150 %t = shl i32 1, %c1 151 %t4 = shl i32 1, %c2 152 %t1 = and i32 %t, %k 153 %t2 = icmp ne i32 %t1, 0 154 %t5 = and i32 %t4, %k 155 %t6 = icmp ne i32 %t5, 0 156 %or = and i1 %t2, %t6 157 ret i1 %or 158} 159 160define <2 x i1> @foo1_or_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { 161; CHECK-LABEL: @foo1_or_vector( 162; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C1:%.*]] 163; CHECK-NEXT: [[T4:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C2:%.*]] 164; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[T]], [[T4]] 165; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[K:%.*]] 166; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i32> [[TMP2]], [[TMP1]] 167; CHECK-NEXT: ret <2 x i1> [[TMP3]] 168; 169 %t = shl <2 x i32> <i32 1, i32 1>, %c1 170 %t4 = shl <2 x i32> <i32 1, i32 1>, %c2 171 %t1 = and <2 x i32> %t, %k 172 %t2 = icmp ne <2 x i32> %t1, zeroinitializer 173 %t5 = and <2 x i32> %t4, %k 174 %t6 = icmp ne <2 x i32> %t5, zeroinitializer 175 %or = and <2 x i1> %t2, %t6 176 ret <2 x i1> %or 177} 178 179; Same as above but with operands commuted one of the ors, but not the other. 180define i1 @foo1_or_commuted(i32 %k, i32 %c1, i32 %c2) { 181; CHECK-LABEL: @foo1_or_commuted( 182; CHECK-NEXT: [[K2:%.*]] = mul i32 [[K:%.*]], [[K]] 183; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] 184; CHECK-NEXT: [[T4:%.*]] = shl i32 1, [[C2:%.*]] 185; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T]], [[T4]] 186; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[K2]], [[TMP1]] 187; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], [[TMP1]] 188; CHECK-NEXT: ret i1 [[TMP3]] 189; 190 %k2 = mul i32 %k, %k ; to trick the complexity sorting 191 %t = shl i32 1, %c1 192 %t4 = shl i32 1, %c2 193 %t1 = and i32 %k2, %t 194 %t2 = icmp ne i32 %t1, 0 195 %t5 = and i32 %t4, %k2 196 %t6 = icmp ne i32 %t5, 0 197 %or = and i1 %t2, %t6 198 ret i1 %or 199} 200 201define <2 x i1> @foo1_or_commuted_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { 202; CHECK-LABEL: @foo1_or_commuted_vector( 203; CHECK-NEXT: [[K2:%.*]] = mul <2 x i32> [[K:%.*]], [[K]] 204; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C1:%.*]] 205; CHECK-NEXT: [[T4:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C2:%.*]] 206; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[T]], [[T4]] 207; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[K2]], [[TMP1]] 208; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i32> [[TMP2]], [[TMP1]] 209; CHECK-NEXT: ret <2 x i1> [[TMP3]] 210; 211 %k2 = mul <2 x i32> %k, %k ; to trick the complexity sorting 212 %t = shl <2 x i32> <i32 1, i32 1>, %c1 213 %t4 = shl <2 x i32> <i32 1, i32 1>, %c2 214 %t1 = and <2 x i32> %k2, %t 215 %t2 = icmp ne <2 x i32> %t1, zeroinitializer 216 %t5 = and <2 x i32> %t4, %k2 217 %t6 = icmp ne <2 x i32> %t5, zeroinitializer 218 %or = and <2 x i1> %t2, %t6 219 ret <2 x i1> %or 220} 221 222define i1 @foo1_and_signbit_lshr(i32 %k, i32 %c1, i32 %c2) { 223; CHECK-LABEL: @foo1_and_signbit_lshr( 224; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] 225; CHECK-NEXT: [[T4:%.*]] = lshr i32 -2147483648, [[C2:%.*]] 226; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T]], [[T4]] 227; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]] 228; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] 229; CHECK-NEXT: ret i1 [[TMP3]] 230; 231 %t = shl i32 1, %c1 232 %t4 = lshr i32 -2147483648, %c2 233 %t1 = and i32 %t, %k 234 %t2 = icmp eq i32 %t1, 0 235 %t5 = and i32 %t4, %k 236 %t6 = icmp eq i32 %t5, 0 237 %or = or i1 %t2, %t6 238 ret i1 %or 239} 240 241define <2 x i1> @foo1_and_signbit_lshr_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { 242; CHECK-LABEL: @foo1_and_signbit_lshr_vector( 243; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C1:%.*]] 244; CHECK-NEXT: [[T4:%.*]] = lshr <2 x i32> <i32 -2147483648, i32 -2147483648>, [[C2:%.*]] 245; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[T]], [[T4]] 246; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[K:%.*]] 247; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], [[TMP1]] 248; CHECK-NEXT: ret <2 x i1> [[TMP3]] 249; 250 %t = shl <2 x i32> <i32 1, i32 1>, %c1 251 %t4 = lshr <2 x i32> <i32 -2147483648, i32 -2147483648>, %c2 252 %t1 = and <2 x i32> %t, %k 253 %t2 = icmp eq <2 x i32> %t1, zeroinitializer 254 %t5 = and <2 x i32> %t4, %k 255 %t6 = icmp eq <2 x i32> %t5, zeroinitializer 256 %or = or <2 x i1> %t2, %t6 257 ret <2 x i1> %or 258} 259 260define i1 @foo1_or_signbit_lshr(i32 %k, i32 %c1, i32 %c2) { 261; CHECK-LABEL: @foo1_or_signbit_lshr( 262; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] 263; CHECK-NEXT: [[T4:%.*]] = lshr i32 -2147483648, [[C2:%.*]] 264; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T]], [[T4]] 265; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]] 266; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], [[TMP1]] 267; CHECK-NEXT: ret i1 [[TMP3]] 268; 269 %t = shl i32 1, %c1 270 %t4 = lshr i32 -2147483648, %c2 271 %t1 = and i32 %t, %k 272 %t2 = icmp ne i32 %t1, 0 273 %t5 = and i32 %t4, %k 274 %t6 = icmp ne i32 %t5, 0 275 %or = and i1 %t2, %t6 276 ret i1 %or 277} 278 279define <2 x i1> @foo1_or_signbit_lshr_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { 280; CHECK-LABEL: @foo1_or_signbit_lshr_vector( 281; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[C1:%.*]] 282; CHECK-NEXT: [[T4:%.*]] = lshr <2 x i32> <i32 -2147483648, i32 -2147483648>, [[C2:%.*]] 283; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[T]], [[T4]] 284; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[K:%.*]] 285; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i32> [[TMP2]], [[TMP1]] 286; CHECK-NEXT: ret <2 x i1> [[TMP3]] 287; 288 %t = shl <2 x i32> <i32 1, i32 1>, %c1 289 %t4 = lshr <2 x i32> <i32 -2147483648, i32 -2147483648>, %c2 290 %t1 = and <2 x i32> %t, %k 291 %t2 = icmp ne <2 x i32> %t1, zeroinitializer 292 %t5 = and <2 x i32> %t4, %k 293 %t6 = icmp ne <2 x i32> %t5, zeroinitializer 294 %or = and <2 x i1> %t2, %t6 295 ret <2 x i1> %or 296} 297 298; Same as last two, but shift-of-signbit replaced with 'icmp s*' 299define i1 @foo1_and_signbit_lshr_without_shifting_signbit(i32 %k, i32 %c1, i32 %c2) { 300; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit( 301; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 302; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[K:%.*]] 303; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 304; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] 305; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 306; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] 307; CHECK-NEXT: ret i1 [[OR]] 308; 309 %t0 = shl i32 1, %c1 310 %t1 = and i32 %t0, %k 311 %t2 = icmp eq i32 %t1, 0 312 %t3 = shl i32 %k, %c2 313 %t4 = icmp sgt i32 %t3, -1 314 %or = or i1 %t2, %t4 315 ret i1 %or 316} 317 318define i1 @foo1_or_signbit_lshr_without_shifting_signbit(i32 %k, i32 %c1, i32 %c2) { 319; CHECK-LABEL: @foo1_or_signbit_lshr_without_shifting_signbit( 320; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 321; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[K:%.*]] 322; CHECK-NEXT: [[T2:%.*]] = icmp ne i32 [[T1]], 0 323; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] 324; CHECK-NEXT: [[T4:%.*]] = icmp slt i32 [[T3]], 0 325; CHECK-NEXT: [[OR:%.*]] = and i1 [[T2]], [[T4]] 326; CHECK-NEXT: ret i1 [[OR]] 327; 328 %t0 = shl i32 1, %c1 329 %t1 = and i32 %t0, %k 330 %t2 = icmp ne i32 %t1, 0 331 %t3 = shl i32 %k, %c2 332 %t4 = icmp slt i32 %t3, 0 333 %or = and i1 %t2, %t4 334 ret i1 %or 335} 336 337; Shift-of-signbit replaced with 'icmp s*' for both sides 338define i1 @foo1_and_signbit_lshr_without_shifting_signbit_both_sides(i32 %k, i32 %c1, i32 %c2) { 339; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit_both_sides( 340; CHECK-NEXT: [[T0:%.*]] = shl i32 [[K:%.*]], [[C1:%.*]] 341; CHECK-NEXT: [[T2:%.*]] = shl i32 [[K]], [[C2:%.*]] 342; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[T0]], [[T2]] 343; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], -1 344; CHECK-NEXT: ret i1 [[TMP2]] 345; 346 %t0 = shl i32 %k, %c1 347 %t1 = icmp sgt i32 %t0, -1 348 %t2 = shl i32 %k, %c2 349 %t3 = icmp sgt i32 %t2, -1 350 %or = or i1 %t1, %t3 351 ret i1 %or 352} 353 354define i1 @foo1_or_signbit_lshr_without_shifting_signbit_both_sides(i32 %k, i32 %c1, i32 %c2) { 355; CHECK-LABEL: @foo1_or_signbit_lshr_without_shifting_signbit_both_sides( 356; CHECK-NEXT: [[T0:%.*]] = shl i32 [[K:%.*]], [[C1:%.*]] 357; CHECK-NEXT: [[T2:%.*]] = shl i32 [[K]], [[C2:%.*]] 358; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[T0]], [[T2]] 359; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0 360; CHECK-NEXT: ret i1 [[TMP2]] 361; 362 %t0 = shl i32 %k, %c1 363 %t1 = icmp slt i32 %t0, 0 364 %t2 = shl i32 %k, %c2 365 %t3 = icmp slt i32 %t2, 0 366 %or = and i1 %t1, %t3 367 ret i1 %or 368} 369 370; Extra use 371 372; Expect to fold 373define i1 @foo1_and_extra_use_shl(i32 %k, i32 %c1, i32 %c2, i32* %p) { 374; CHECK-LABEL: @foo1_and_extra_use_shl( 375; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 376; CHECK-NEXT: store i32 [[T0]], i32* [[P:%.*]], align 4 377; CHECK-NEXT: [[T1:%.*]] = shl i32 1, [[C2:%.*]] 378; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T0]], [[T1]] 379; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]] 380; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] 381; CHECK-NEXT: ret i1 [[TMP3]] 382; 383 %t0 = shl i32 1, %c1 384 store i32 %t0, i32* %p ; extra use of shl 385 %t1 = shl i32 1, %c2 386 %t2 = and i32 %t0, %k 387 %t3 = icmp eq i32 %t2, 0 388 %t4 = and i32 %t1, %k 389 %t5 = icmp eq i32 %t4, 0 390 %or = or i1 %t3, %t5 391 ret i1 %or 392} 393 394; Should not fold 395define i1 @foo1_and_extra_use_and(i32 %k, i32 %c1, i32 %c2, i32* %p) { 396; CHECK-LABEL: @foo1_and_extra_use_and( 397; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 398; CHECK-NEXT: [[T1:%.*]] = shl i32 1, [[C2:%.*]] 399; CHECK-NEXT: [[T2:%.*]] = and i32 [[T0]], [[K:%.*]] 400; CHECK-NEXT: store i32 [[T2]], i32* [[P:%.*]], align 4 401; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T0]], [[T1]] 402; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K]] 403; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] 404; CHECK-NEXT: ret i1 [[TMP3]] 405; 406 %t0 = shl i32 1, %c1 407 %t1 = shl i32 1, %c2 408 %t2 = and i32 %t0, %k 409 store i32 %t2, i32* %p ; extra use of and 410 %t3 = icmp eq i32 %t2, 0 411 %t4 = and i32 %t1, %k 412 %t5 = icmp eq i32 %t4, 0 413 %or = or i1 %t3, %t5 414 ret i1 %or 415} 416 417; Should not fold 418define i1 @foo1_and_extra_use_cmp(i32 %k, i32 %c1, i32 %c2, i1* %p) { 419; CHECK-LABEL: @foo1_and_extra_use_cmp( 420; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 421; CHECK-NEXT: [[T1:%.*]] = shl i32 1, [[C2:%.*]] 422; CHECK-NEXT: [[T2:%.*]] = and i32 [[T0]], [[K:%.*]] 423; CHECK-NEXT: [[T3:%.*]] = icmp eq i32 [[T2]], 0 424; CHECK-NEXT: store i1 [[T3]], i1* [[P:%.*]], align 1 425; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T0]], [[T1]] 426; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K]] 427; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] 428; CHECK-NEXT: ret i1 [[TMP3]] 429; 430 %t0 = shl i32 1, %c1 431 %t1 = shl i32 1, %c2 432 %t2 = and i32 %t0, %k 433 %t3 = icmp eq i32 %t2, 0 434 store i1 %t3, i1* %p ; extra use of cmp 435 %t4 = and i32 %t1, %k 436 %t5 = icmp eq i32 %t4, 0 437 %or = or i1 %t3, %t5 438 ret i1 %or 439} 440 441; Expect to fold 442define i1 @foo1_and_extra_use_shl2(i32 %k, i32 %c1, i32 %c2, i32* %p) { 443; CHECK-LABEL: @foo1_and_extra_use_shl2( 444; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 445; CHECK-NEXT: [[T1:%.*]] = shl i32 1, [[C2:%.*]] 446; CHECK-NEXT: store i32 [[T1]], i32* [[P:%.*]], align 4 447; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T0]], [[T1]] 448; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]] 449; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] 450; CHECK-NEXT: ret i1 [[TMP3]] 451; 452 %t0 = shl i32 1, %c1 453 %t1 = shl i32 1, %c2 454 store i32 %t1, i32* %p ; extra use of shl 455 %t2 = and i32 %t0, %k 456 %t3 = icmp eq i32 %t2, 0 457 %t4 = and i32 %t1, %k 458 %t5 = icmp eq i32 %t4, 0 459 %or = or i1 %t3, %t5 460 ret i1 %or 461} 462 463; Should not fold 464define i1 @foo1_and_extra_use_and2(i32 %k, i32 %c1, i32 %c2, i32* %p) { 465; CHECK-LABEL: @foo1_and_extra_use_and2( 466; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 467; CHECK-NEXT: [[T1:%.*]] = shl i32 1, [[C2:%.*]] 468; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[K:%.*]] 469; CHECK-NEXT: store i32 [[T4]], i32* [[P:%.*]], align 4 470; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T0]], [[T1]] 471; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K]] 472; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] 473; CHECK-NEXT: ret i1 [[TMP3]] 474; 475 %t0 = shl i32 1, %c1 476 %t1 = shl i32 1, %c2 477 %t2 = and i32 %t0, %k 478 %t3 = icmp eq i32 %t2, 0 479 %t4 = and i32 %t1, %k 480 store i32 %t4, i32* %p ; extra use of and 481 %t5 = icmp eq i32 %t4, 0 482 %or = or i1 %t3, %t5 483 ret i1 %or 484} 485 486; Should not fold 487define i1 @foo1_and_extra_use_cmp2(i32 %k, i32 %c1, i32 %c2, i1* %p) { 488; CHECK-LABEL: @foo1_and_extra_use_cmp2( 489; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 490; CHECK-NEXT: [[T1:%.*]] = shl i32 1, [[C2:%.*]] 491; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[K:%.*]] 492; CHECK-NEXT: [[T5:%.*]] = icmp eq i32 [[T4]], 0 493; CHECK-NEXT: store i1 [[T5]], i1* [[P:%.*]], align 1 494; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T0]], [[T1]] 495; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K]] 496; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] 497; CHECK-NEXT: ret i1 [[TMP3]] 498; 499 %t0 = shl i32 1, %c1 500 %t1 = shl i32 1, %c2 501 %t2 = and i32 %t0, %k 502 %t3 = icmp eq i32 %t2, 0 503 %t4 = and i32 %t1, %k 504 %t5 = icmp eq i32 %t4, 0 505 store i1 %t5, i1* %p ; extra use of cmp 506 %or = or i1 %t3, %t5 507 ret i1 %or 508} 509 510; Shift-of-signbit replaced with 'icmp s*' 511; Expect to fold 512define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_shl1(i32 %k, i32 %c1, i32 %c2, i32* %p) { 513; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_shl1( 514; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 515; CHECK-NEXT: store i32 [[T0]], i32* [[P:%.*]], align 4 516; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[K:%.*]] 517; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 518; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] 519; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 520; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] 521; CHECK-NEXT: ret i1 [[OR]] 522; 523 %t0 = shl i32 1, %c1 524 store i32 %t0, i32* %p ; extra use of shl 525 %t1 = and i32 %t0, %k 526 %t2 = icmp eq i32 %t1, 0 527 %t3 = shl i32 %k, %c2 528 %t4 = icmp sgt i32 %t3, -1 529 %or = or i1 %t2, %t4 530 ret i1 %or 531} 532 533; Not fold 534define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_and(i32 %k, i32 %c1, i32 %c2, i32* %p) { 535; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_and( 536; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 537; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[K:%.*]] 538; CHECK-NEXT: store i32 [[T1]], i32* [[P:%.*]], align 4 539; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 540; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] 541; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 542; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] 543; CHECK-NEXT: ret i1 [[OR]] 544; 545 %t0 = shl i32 1, %c1 546 %t1 = and i32 %t0, %k 547 store i32 %t1, i32* %p ; extra use of and 548 %t2 = icmp eq i32 %t1, 0 549 %t3 = shl i32 %k, %c2 550 %t4 = icmp sgt i32 %t3, -1 551 %or = or i1 %t2, %t4 552 ret i1 %or 553} 554 555; Not fold 556define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_cmp1(i32 %k, i32 %c1, i32 %c2, i1* %p) { 557; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_cmp1( 558; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 559; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[K:%.*]] 560; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 561; CHECK-NEXT: store i1 [[T2]], i1* [[P:%.*]], align 1 562; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] 563; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 564; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] 565; CHECK-NEXT: ret i1 [[OR]] 566; 567 %t0 = shl i32 1, %c1 568 %t1 = and i32 %t0, %k 569 %t2 = icmp eq i32 %t1, 0 570 store i1 %t2, i1* %p ; extra use of cmp 571 %t3 = shl i32 %k, %c2 572 %t4 = icmp sgt i32 %t3, -1 573 %or = or i1 %t2, %t4 574 ret i1 %or 575} 576 577; Not fold 578define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_shl2(i32 %k, i32 %c1, i32 %c2, i32* %p) { 579; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_shl2( 580; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 581; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[K:%.*]] 582; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 583; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] 584; CHECK-NEXT: store i32 [[T3]], i32* [[P:%.*]], align 4 585; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 586; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] 587; CHECK-NEXT: ret i1 [[OR]] 588; 589 %t0 = shl i32 1, %c1 590 %t1 = and i32 %t0, %k 591 %t2 = icmp eq i32 %t1, 0 592 %t3 = shl i32 %k, %c2 593 store i32 %t3, i32* %p ; extra use of shl 594 %t4 = icmp sgt i32 %t3, -1 595 %or = or i1 %t2, %t4 596 ret i1 %or 597} 598 599; Not fold 600define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_cmp2(i32 %k, i32 %c1, i32 %c2, i1* %p) { 601; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_cmp2( 602; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[C1:%.*]] 603; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[K:%.*]] 604; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 605; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] 606; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 607; CHECK-NEXT: store i1 [[T4]], i1* [[P:%.*]], align 1 608; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] 609; CHECK-NEXT: ret i1 [[OR]] 610; 611 %t0 = shl i32 1, %c1 612 %t1 = and i32 %t0, %k 613 %t2 = icmp eq i32 %t1, 0 614 %t3 = shl i32 %k, %c2 615 %t4 = icmp sgt i32 %t3, -1 616 store i1 %t4, i1* %p ; extra use of cmp 617 %or = or i1 %t2, %t4 618 ret i1 %or 619} 620 621; Negative tests 622 623; This test checks that we are not creating additional shift instruction when fold fails. 624define i1 @foo1_and_signbit_lshr_without_shifting_signbit_not_pwr2(i32 %k, i32 %c1, i32 %c2) { 625; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit_not_pwr2( 626; CHECK-NEXT: [[T0:%.*]] = shl i32 3, [[C1:%.*]] 627; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[K:%.*]] 628; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 629; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] 630; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 631; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] 632; CHECK-NEXT: ret i1 [[OR]] 633; 634 %t0 = shl i32 3, %c1 635 %t1 = and i32 %t0, %k 636 %t2 = icmp eq i32 %t1, 0 637 %t3 = shl i32 %k, %c2 638 %t4 = icmp sgt i32 %t3, -1 639 %or = or i1 %t2, %t4 640 ret i1 %or 641} 642