1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; Given pattern: 5; icmp eq/ne (and ((x shift Q), (y oppositeshift K))), 0 6; we should move shifts to the same hand of 'and', i.e. e.g. rewrite as 7; icmp eq/ne (and (((x shift Q) shift K), y)), 0 8; We are only interested in opposite logical shifts here. 9 10; Basic scalar test with constants 11 12define i1 @t0_const_lshr_shl_ne(i32 %x, i32 %y) { 13; CHECK-LABEL: @t0_const_lshr_shl_ne( 14; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 15; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] 16; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 17; CHECK-NEXT: ret i1 [[TMP3]] 18; 19 %t0 = lshr i32 %x, 1 20 %t1 = shl i32 %y, 1 21 %t2 = and i32 %t1, %t0 22 %t3 = icmp ne i32 %t2, 0 23 ret i1 %t3 24} 25define i1 @t1_const_shl_lshr_ne(i32 %x, i32 %y) { 26; CHECK-LABEL: @t1_const_shl_lshr_ne( 27; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 2 28; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]] 29; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 30; CHECK-NEXT: ret i1 [[TMP3]] 31; 32 %t0 = shl i32 %x, 1 33 %t1 = lshr i32 %y, 1 34 %t2 = and i32 %t1, %t0 35 %t3 = icmp ne i32 %t2, 0 36 ret i1 %t3 37} 38 39; We are ok with 'eq' predicate too. 40define i1 @t2_const_lshr_shl_eq(i32 %x, i32 %y) { 41; CHECK-LABEL: @t2_const_lshr_shl_eq( 42; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 43; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] 44; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 45; CHECK-NEXT: ret i1 [[TMP3]] 46; 47 %t0 = lshr i32 %x, 1 48 %t1 = shl i32 %y, 1 49 %t2 = and i32 %t1, %t0 50 %t3 = icmp eq i32 %t2, 0 51 ret i1 %t3 52} 53 54; Basic scalar test with constants after folding 55 56define i1 @t3_const_after_fold_lshr_shl_ne(i32 %x, i32 %y, i32 %len) { 57; CHECK-LABEL: @t3_const_after_fold_lshr_shl_ne( 58; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 31 59; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] 60; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 61; CHECK-NEXT: ret i1 [[TMP3]] 62; 63 %t0 = sub i32 32, %len 64 %t1 = lshr i32 %x, %t0 65 %t2 = add i32 %len, -1 66 %t3 = shl i32 %y, %t2 67 %t4 = and i32 %t1, %t3 68 %t5 = icmp ne i32 %t4, 0 69 ret i1 %t5 70} 71define i1 @t4_const_after_fold_lshr_shl_ne(i32 %x, i32 %y, i32 %len) { 72; CHECK-LABEL: @t4_const_after_fold_lshr_shl_ne( 73; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 31 74; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]] 75; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 76; CHECK-NEXT: ret i1 [[TMP3]] 77; 78 %t0 = sub i32 32, %len 79 %t1 = shl i32 %x, %t0 80 %t2 = add i32 %len, -1 81 %t3 = lshr i32 %y, %t2 82 %t4 = and i32 %t1, %t3 83 %t5 = icmp ne i32 %t4, 0 84 ret i1 %t5 85} 86 87; Completely variable shift amounts 88 89define i1 @t5_const_lshr_shl_ne(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { 90; CHECK-LABEL: @t5_const_lshr_shl_ne( 91; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] 92; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] 93; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 94; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 95; CHECK-NEXT: ret i1 [[T3]] 96; 97 %t0 = lshr i32 %x, %shamt0 98 %t1 = shl i32 %y, %shamt1 99 %t2 = and i32 %t1, %t0 100 %t3 = icmp ne i32 %t2, 0 101 ret i1 %t3 102} 103define i1 @t6_const_shl_lshr_ne(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { 104; CHECK-LABEL: @t6_const_shl_lshr_ne( 105; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[SHAMT0:%.*]] 106; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[Y:%.*]], [[SHAMT1:%.*]] 107; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 108; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 109; CHECK-NEXT: ret i1 [[T3]] 110; 111 %t0 = shl i32 %x, %shamt0 112 %t1 = lshr i32 %y, %shamt1 113 %t2 = and i32 %t1, %t0 114 %t3 = icmp ne i32 %t2, 0 115 ret i1 %t3 116} 117 118; Very basic vector tests 119 120define <2 x i1> @t7_const_lshr_shl_ne_vec_splat(<2 x i32> %x, <2 x i32> %y) { 121; CHECK-LABEL: @t7_const_lshr_shl_ne_vec_splat( 122; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 2, i32 2> 123; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y:%.*]] 124; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer 125; CHECK-NEXT: ret <2 x i1> [[TMP3]] 126; 127 %t0 = lshr <2 x i32> %x, <i32 1, i32 1> 128 %t1 = shl <2 x i32> %y, <i32 1, i32 1> 129 %t2 = and <2 x i32> %t1, %t0 130 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0> 131 ret <2 x i1> %t3 132} 133define <2 x i1> @t8_const_lshr_shl_ne_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) { 134; CHECK-LABEL: @t8_const_lshr_shl_ne_vec_nonsplat( 135; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 4, i32 6> 136; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y:%.*]] 137; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer 138; CHECK-NEXT: ret <2 x i1> [[TMP3]] 139; 140 %t0 = lshr <2 x i32> %x, <i32 1, i32 2> 141 %t1 = shl <2 x i32> %y, <i32 3, i32 4> 142 %t2 = and <2 x i32> %t1, %t0 143 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0> 144 ret <2 x i1> %t3 145} 146define <3 x i1> @t9_const_lshr_shl_ne_vec_undef0(<3 x i32> %x, <3 x i32> %y) { 147; CHECK-LABEL: @t9_const_lshr_shl_ne_vec_undef0( 148; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> 149; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] 150; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer 151; CHECK-NEXT: ret <3 x i1> [[TMP3]] 152; 153 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1> 154 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1> 155 %t2 = and <3 x i32> %t1, %t0 156 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0> 157 ret <3 x i1> %t3 158} 159define <3 x i1> @t10_const_lshr_shl_ne_vec_undef1(<3 x i32> %x, <3 x i32> %y) { 160; CHECK-LABEL: @t10_const_lshr_shl_ne_vec_undef1( 161; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> 162; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] 163; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer 164; CHECK-NEXT: ret <3 x i1> [[TMP3]] 165; 166 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1> 167 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1> 168 %t2 = and <3 x i32> %t1, %t0 169 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0> 170 ret <3 x i1> %t3 171} 172define <3 x i1> @t11_const_lshr_shl_ne_vec_undef2(<3 x i32> %x, <3 x i32> %y) { 173; CHECK-LABEL: @t11_const_lshr_shl_ne_vec_undef2( 174; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 2, i32 2> 175; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] 176; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer 177; CHECK-NEXT: ret <3 x i1> [[TMP3]] 178; 179 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1> 180 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1> 181 %t2 = and <3 x i32> %t1, %t0 182 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0> 183 ret <3 x i1> %t3 184} 185define <3 x i1> @t12_const_lshr_shl_ne_vec_undef3(<3 x i32> %x, <3 x i32> %y) { 186; CHECK-LABEL: @t12_const_lshr_shl_ne_vec_undef3( 187; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> 188; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] 189; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer 190; CHECK-NEXT: ret <3 x i1> [[TMP3]] 191; 192 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1> 193 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1> 194 %t2 = and <3 x i32> %t1, %t0 195 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0> 196 ret <3 x i1> %t3 197} 198define <3 x i1> @t13_const_lshr_shl_ne_vec_undef4(<3 x i32> %x, <3 x i32> %y) { 199; CHECK-LABEL: @t13_const_lshr_shl_ne_vec_undef4( 200; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> 201; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] 202; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer 203; CHECK-NEXT: ret <3 x i1> [[TMP3]] 204; 205 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1> 206 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1> 207 %t2 = and <3 x i32> %t1, %t0 208 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0> 209 ret <3 x i1> %t3 210} 211define <3 x i1> @t14_const_lshr_shl_ne_vec_undef5(<3 x i32> %x, <3 x i32> %y) { 212; CHECK-LABEL: @t14_const_lshr_shl_ne_vec_undef5( 213; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> 214; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] 215; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer 216; CHECK-NEXT: ret <3 x i1> [[TMP3]] 217; 218 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1> 219 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1> 220 %t2 = and <3 x i32> %t1, %t0 221 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0> 222 ret <3 x i1> %t3 223} 224define <3 x i1> @t15_const_lshr_shl_ne_vec_undef6(<3 x i32> %x, <3 x i32> %y) { 225; CHECK-LABEL: @t15_const_lshr_shl_ne_vec_undef6( 226; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2> 227; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]] 228; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer 229; CHECK-NEXT: ret <3 x i1> [[TMP3]] 230; 231 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1> 232 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1> 233 %t2 = and <3 x i32> %t1, %t0 234 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0> 235 ret <3 x i1> %t3 236} 237 238; Commutativity tests 239 240declare i32 @gen32() 241 242define i1 @t16_commutativity0(i32 %x) { 243; CHECK-LABEL: @t16_commutativity0( 244; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32() 245; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 246; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] 247; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 248; CHECK-NEXT: ret i1 [[TMP3]] 249; 250 %y = call i32 @gen32() 251 %t0 = lshr i32 %x, 1 252 %t1 = shl i32 %y, 1 253 %t2 = and i32 %t1, %t0 254 %t3 = icmp ne i32 %t2, 0 255 ret i1 %t3 256} 257 258define i1 @t17_commutativity1(i32 %y) { 259; CHECK-LABEL: @t17_commutativity1( 260; CHECK-NEXT: [[X:%.*]] = call i32 @gen32() 261; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 262; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] 263; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 264; CHECK-NEXT: ret i1 [[TMP3]] 265; 266 %x = call i32 @gen32() 267 %t0 = lshr i32 %x, 1 268 %t1 = shl i32 %y, 1 269 %t2 = and i32 %t0, %t1 ; "swapped" 270 %t3 = icmp ne i32 %t2, 0 271 ret i1 %t3 272} 273 274; One-use tests 275 276declare void @use32(i32) 277 278define i1 @t18_const_oneuse0(i32 %x, i32 %y) { 279; CHECK-LABEL: @t18_const_oneuse0( 280; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 281; CHECK-NEXT: call void @use32(i32 [[T0]]) 282; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 283; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] 284; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 285; CHECK-NEXT: ret i1 [[TMP3]] 286; 287 %t0 = lshr i32 %x, 1 288 call void @use32(i32 %t0) 289 %t1 = shl i32 %y, 1 290 %t2 = and i32 %t1, %t0 291 %t3 = icmp ne i32 %t2, 0 292 ret i1 %t3 293} 294define i1 @t19_const_oneuse1(i32 %x, i32 %y) { 295; CHECK-LABEL: @t19_const_oneuse1( 296; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 297; CHECK-NEXT: call void @use32(i32 [[T1]]) 298; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 299; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] 300; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 301; CHECK-NEXT: ret i1 [[TMP3]] 302; 303 %t0 = lshr i32 %x, 1 304 %t1 = shl i32 %y, 1 305 call void @use32(i32 %t1) 306 %t2 = and i32 %t1, %t0 307 %t3 = icmp ne i32 %t2, 0 308 ret i1 %t3 309} 310define i1 @t20_const_oneuse2(i32 %x, i32 %y) { 311; CHECK-LABEL: @t20_const_oneuse2( 312; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 313; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 314; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 315; CHECK-NEXT: call void @use32(i32 [[T2]]) 316; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 317; CHECK-NEXT: ret i1 [[T3]] 318; 319 %t0 = lshr i32 %x, 1 320 %t1 = shl i32 %y, 1 321 %t2 = and i32 %t1, %t0 322 call void @use32(i32 %t2) 323 %t3 = icmp ne i32 %t2, 0 324 ret i1 %t3 325} 326define i1 @t21_const_oneuse3(i32 %x, i32 %y) { 327; CHECK-LABEL: @t21_const_oneuse3( 328; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 329; CHECK-NEXT: call void @use32(i32 [[T0]]) 330; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 331; CHECK-NEXT: call void @use32(i32 [[T1]]) 332; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 333; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 334; CHECK-NEXT: ret i1 [[T3]] 335; 336 %t0 = lshr i32 %x, 1 337 call void @use32(i32 %t0) 338 %t1 = shl i32 %y, 1 339 call void @use32(i32 %t1) 340 %t2 = and i32 %t1, %t0 341 %t3 = icmp ne i32 %t2, 0 342 ret i1 %t3 343} 344define i1 @t22_const_oneuse4(i32 %x, i32 %y) { 345; CHECK-LABEL: @t22_const_oneuse4( 346; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 347; CHECK-NEXT: call void @use32(i32 [[T0]]) 348; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 349; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 350; CHECK-NEXT: call void @use32(i32 [[T2]]) 351; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 352; CHECK-NEXT: ret i1 [[T3]] 353; 354 %t0 = lshr i32 %x, 1 355 call void @use32(i32 %t0) 356 %t1 = shl i32 %y, 1 357 %t2 = and i32 %t1, %t0 358 call void @use32(i32 %t2) 359 %t3 = icmp ne i32 %t2, 0 360 ret i1 %t3 361} 362define i1 @t23_const_oneuse5(i32 %x, i32 %y) { 363; CHECK-LABEL: @t23_const_oneuse5( 364; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 365; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 366; CHECK-NEXT: call void @use32(i32 [[T1]]) 367; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 368; CHECK-NEXT: call void @use32(i32 [[T2]]) 369; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 370; CHECK-NEXT: ret i1 [[T3]] 371; 372 %t0 = lshr i32 %x, 1 373 %t1 = shl i32 %y, 1 374 call void @use32(i32 %t1) 375 %t2 = and i32 %t1, %t0 376 call void @use32(i32 %t2) 377 %t3 = icmp ne i32 %t2, 0 378 ret i1 %t3 379} 380define i1 @t24_const_oneuse6(i32 %x, i32 %y) { 381; CHECK-LABEL: @t24_const_oneuse6( 382; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 383; CHECK-NEXT: call void @use32(i32 [[T0]]) 384; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 385; CHECK-NEXT: call void @use32(i32 [[T1]]) 386; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 387; CHECK-NEXT: call void @use32(i32 [[T2]]) 388; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 389; CHECK-NEXT: ret i1 [[T3]] 390; 391 %t0 = lshr i32 %x, 1 392 call void @use32(i32 %t0) 393 %t1 = shl i32 %y, 1 394 call void @use32(i32 %t1) 395 %t2 = and i32 %t1, %t0 396 call void @use32(i32 %t2) 397 %t3 = icmp ne i32 %t2, 0 398 ret i1 %t3 399} 400 401define i1 @t25_var_oneuse0(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { 402; CHECK-LABEL: @t25_var_oneuse0( 403; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] 404; CHECK-NEXT: call void @use32(i32 [[T0]]) 405; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] 406; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 407; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 408; CHECK-NEXT: ret i1 [[T3]] 409; 410 %t0 = lshr i32 %x, %shamt0 411 call void @use32(i32 %t0) 412 %t1 = shl i32 %y, %shamt1 413 %t2 = and i32 %t1, %t0 414 %t3 = icmp ne i32 %t2, 0 415 ret i1 %t3 416} 417define i1 @t26_var_oneuse1(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { 418; CHECK-LABEL: @t26_var_oneuse1( 419; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] 420; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] 421; CHECK-NEXT: call void @use32(i32 [[T1]]) 422; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 423; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 424; CHECK-NEXT: ret i1 [[T3]] 425; 426 %t0 = lshr i32 %x, %shamt0 427 %t1 = shl i32 %y, %shamt1 428 call void @use32(i32 %t1) 429 %t2 = and i32 %t1, %t0 430 %t3 = icmp ne i32 %t2, 0 431 ret i1 %t3 432} 433define i1 @t27_var_oneuse2(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { 434; CHECK-LABEL: @t27_var_oneuse2( 435; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] 436; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] 437; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 438; CHECK-NEXT: call void @use32(i32 [[T2]]) 439; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 440; CHECK-NEXT: ret i1 [[T3]] 441; 442 %t0 = lshr i32 %x, %shamt0 443 %t1 = shl i32 %y, %shamt1 444 %t2 = and i32 %t1, %t0 445 call void @use32(i32 %t2) 446 %t3 = icmp ne i32 %t2, 0 447 ret i1 %t3 448} 449define i1 @t28_var_oneuse3(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { 450; CHECK-LABEL: @t28_var_oneuse3( 451; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] 452; CHECK-NEXT: call void @use32(i32 [[T0]]) 453; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] 454; CHECK-NEXT: call void @use32(i32 [[T1]]) 455; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 456; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 457; CHECK-NEXT: ret i1 [[T3]] 458; 459 %t0 = lshr i32 %x, %shamt0 460 call void @use32(i32 %t0) 461 %t1 = shl i32 %y, %shamt1 462 call void @use32(i32 %t1) 463 %t2 = and i32 %t1, %t0 464 %t3 = icmp ne i32 %t2, 0 465 ret i1 %t3 466} 467define i1 @t29_var_oneuse4(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { 468; CHECK-LABEL: @t29_var_oneuse4( 469; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] 470; CHECK-NEXT: call void @use32(i32 [[T0]]) 471; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] 472; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 473; CHECK-NEXT: call void @use32(i32 [[T2]]) 474; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 475; CHECK-NEXT: ret i1 [[T3]] 476; 477 %t0 = lshr i32 %x, %shamt0 478 call void @use32(i32 %t0) 479 %t1 = shl i32 %y, %shamt1 480 %t2 = and i32 %t1, %t0 481 call void @use32(i32 %t2) 482 %t3 = icmp ne i32 %t2, 0 483 ret i1 %t3 484} 485define i1 @t30_var_oneuse5(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { 486; CHECK-LABEL: @t30_var_oneuse5( 487; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] 488; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] 489; CHECK-NEXT: call void @use32(i32 [[T1]]) 490; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 491; CHECK-NEXT: call void @use32(i32 [[T2]]) 492; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 493; CHECK-NEXT: ret i1 [[T3]] 494; 495 %t0 = lshr i32 %x, %shamt0 496 %t1 = shl i32 %y, %shamt1 497 call void @use32(i32 %t1) 498 %t2 = and i32 %t1, %t0 499 call void @use32(i32 %t2) 500 %t3 = icmp ne i32 %t2, 0 501 ret i1 %t3 502} 503define i1 @t31_var_oneuse6(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { 504; CHECK-LABEL: @t31_var_oneuse6( 505; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]] 506; CHECK-NEXT: call void @use32(i32 [[T0]]) 507; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]] 508; CHECK-NEXT: call void @use32(i32 [[T1]]) 509; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 510; CHECK-NEXT: call void @use32(i32 [[T2]]) 511; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0 512; CHECK-NEXT: ret i1 [[T3]] 513; 514 %t0 = lshr i32 %x, %shamt0 515 call void @use32(i32 %t0) 516 %t1 = shl i32 %y, %shamt1 517 call void @use32(i32 %t1) 518 %t2 = and i32 %t1, %t0 519 call void @use32(i32 %t2) 520 %t3 = icmp ne i32 %t2, 0 521 ret i1 %t3 522} 523 524; Shift-of-const 525 526; Ok, non-truncated shift is of constant; 527define i1 @t32_shift_of_const_oneuse0(i32 %x, i32 %y, i32 %len) { 528; CHECK-LABEL: @t32_shift_of_const_oneuse0( 529; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]] 530; CHECK-NEXT: call void @use32(i32 [[T0]]) 531; CHECK-NEXT: [[T1:%.*]] = lshr i32 -52543054, [[T0]] 532; CHECK-NEXT: call void @use32(i32 [[T1]]) 533; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1 534; CHECK-NEXT: call void @use32(i32 [[T2]]) 535; CHECK-NEXT: [[T3:%.*]] = shl i32 [[Y:%.*]], [[T2]] 536; CHECK-NEXT: call void @use32(i32 [[T3]]) 537; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y]], 1 538; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0 539; CHECK-NEXT: ret i1 [[TMP2]] 540; 541 %t0 = sub i32 32, %len 542 call void @use32(i32 %t0) 543 %t1 = lshr i32 4242424242, %t0 ; shift-of-constant 544 call void @use32(i32 %t1) 545 %t2 = add i32 %len, -1 546 call void @use32(i32 %t2) 547 %t3 = shl i32 %y, %t2 548 call void @use32(i32 %t3) 549 %t4 = and i32 %t1, %t3 ; no extra uses 550 %t5 = icmp ne i32 %t4, 0 551 ret i1 %t5 552} 553; Ok, truncated shift is of constant; 554define i1 @t33_shift_of_const_oneuse1(i32 %x, i32 %y, i32 %len) { 555; CHECK-LABEL: @t33_shift_of_const_oneuse1( 556; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]] 557; CHECK-NEXT: call void @use32(i32 [[T0]]) 558; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]] 559; CHECK-NEXT: call void @use32(i32 [[T1]]) 560; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1 561; CHECK-NEXT: call void @use32(i32 [[T2]]) 562; CHECK-NEXT: [[T3:%.*]] = shl i32 -52543054, [[T2]] 563; CHECK-NEXT: call void @use32(i32 [[T3]]) 564; CHECK-NEXT: ret i1 false 565; 566 %t0 = sub i32 32, %len 567 call void @use32(i32 %t0) 568 %t1 = lshr i32 %x, %t0 ; shift-of-constant 569 call void @use32(i32 %t1) 570 %t2 = add i32 %len, -1 571 call void @use32(i32 %t2) 572 %t3 = shl i32 4242424242, %t2 573 call void @use32(i32 %t3) 574 %t4 = and i32 %t1, %t3 ; no extra uses 575 %t5 = icmp ne i32 %t4, 0 576 ret i1 %t5 577} 578 579; Commutativity with extra uses 580 581define i1 @t34_commutativity0_oneuse0(i32 %x) { 582; CHECK-LABEL: @t34_commutativity0_oneuse0( 583; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32() 584; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 585; CHECK-NEXT: call void @use32(i32 [[T0]]) 586; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 587; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] 588; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 589; CHECK-NEXT: ret i1 [[TMP3]] 590; 591 %y = call i32 @gen32() 592 %t0 = lshr i32 %x, 1 593 call void @use32(i32 %t0) 594 %t1 = shl i32 %y, 1 595 %t2 = and i32 %t1, %t0 596 %t3 = icmp ne i32 %t2, 0 597 ret i1 %t3 598} 599define i1 @t35_commutativity0_oneuse1(i32 %x) { 600; CHECK-LABEL: @t35_commutativity0_oneuse1( 601; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32() 602; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y]], 1 603; CHECK-NEXT: call void @use32(i32 [[T1]]) 604; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2 605; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] 606; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 607; CHECK-NEXT: ret i1 [[TMP3]] 608; 609 %y = call i32 @gen32() 610 %t0 = lshr i32 %x, 1 611 %t1 = shl i32 %y, 1 612 call void @use32(i32 %t1) 613 %t2 = and i32 %t1, %t0 614 %t3 = icmp ne i32 %t2, 0 615 ret i1 %t3 616} 617 618define i1 @t36_commutativity1_oneuse0(i32 %y) { 619; CHECK-LABEL: @t36_commutativity1_oneuse0( 620; CHECK-NEXT: [[X:%.*]] = call i32 @gen32() 621; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X]], 1 622; CHECK-NEXT: call void @use32(i32 [[T0]]) 623; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 624; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] 625; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 626; CHECK-NEXT: ret i1 [[TMP3]] 627; 628 %x = call i32 @gen32() 629 %t0 = lshr i32 %x, 1 630 call void @use32(i32 %t0) 631 %t1 = shl i32 %y, 1 632 %t2 = and i32 %t0, %t1 ; "swapped" 633 %t3 = icmp ne i32 %t2, 0 634 ret i1 %t3 635} 636define i1 @t37_commutativity1_oneuse1(i32 %y) { 637; CHECK-LABEL: @t37_commutativity1_oneuse1( 638; CHECK-NEXT: [[X:%.*]] = call i32 @gen32() 639; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 640; CHECK-NEXT: call void @use32(i32 [[T1]]) 641; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 642; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] 643; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 644; CHECK-NEXT: ret i1 [[TMP3]] 645; 646 %x = call i32 @gen32() 647 %t0 = lshr i32 %x, 1 648 %t1 = shl i32 %y, 1 649 call void @use32(i32 %t1) 650 %t2 = and i32 %t0, %t1 ; "swapped" 651 %t3 = icmp ne i32 %t2, 0 652 ret i1 %t3 653} 654 655; Negative tests 656define <2 x i1> @n38_overshift(<2 x i32> %x, <2 x i32> %y) { 657; CHECK-LABEL: @n38_overshift( 658; CHECK-NEXT: [[T0:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 15, i32 1> 659; CHECK-NEXT: [[T1:%.*]] = shl <2 x i32> [[Y:%.*]], <i32 17, i32 1> 660; CHECK-NEXT: [[T2:%.*]] = and <2 x i32> [[T1]], [[T0]] 661; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[T2]], zeroinitializer 662; CHECK-NEXT: ret <2 x i1> [[T3]] 663; 664 %t0 = lshr <2 x i32> %x, <i32 15, i32 1> 665 %t1 = shl <2 x i32> %y, <i32 17, i32 1> 666 %t2 = and <2 x i32> %t1, %t0 667 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0> 668 ret <2 x i1> %t3 669} 670 671; As usual, don't crash given constantexpr's :/ 672@f.a = internal global i16 0 673define i1 @constantexpr() { 674; CHECK-LABEL: @constantexpr( 675; CHECK-NEXT: entry: 676; CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @f.a, align 2 677; CHECK-NEXT: [[TMP1:%.*]] = lshr i16 [[TMP0]], 1 678; CHECK-NEXT: [[TMP2:%.*]] = and i16 [[TMP1]], shl (i16 1, i16 zext (i1 icmp ne (i16 ptrtoint (i16* @f.a to i16), i16 1) to i16)) 679; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i16 [[TMP2]], 0 680; CHECK-NEXT: ret i1 [[TOBOOL]] 681; 682entry: 683 %0 = load i16, i16* @f.a 684 %shr = ashr i16 %0, 1 685 %shr1 = ashr i16 %shr, zext (i1 icmp ne (i16 ptrtoint (i16* @f.a to i16), i16 1) to i16) 686 %and = and i16 %shr1, 1 687 %tobool = icmp ne i16 %and, 0 688 ret i1 %tobool 689} 690 691; See https://bugs.llvm.org/show_bug.cgi?id=44802 692define i1 @pr44802(i3 %a, i3 %x, i3 %y) { 693; CHECK-LABEL: @pr44802( 694; CHECK-NEXT: [[T0:%.*]] = icmp ne i3 [[A:%.*]], 0 695; CHECK-NEXT: [[T1:%.*]] = zext i1 [[T0]] to i3 696; CHECK-NEXT: [[T2:%.*]] = lshr i3 [[X:%.*]], [[T1]] 697; CHECK-NEXT: [[T3:%.*]] = shl i3 [[Y:%.*]], [[T1]] 698; CHECK-NEXT: [[T4:%.*]] = and i3 [[T2]], [[T3]] 699; CHECK-NEXT: [[T5:%.*]] = icmp ne i3 [[T4]], 0 700; CHECK-NEXT: ret i1 [[T5]] 701; 702 %t0 = icmp ne i3 %a, 0 703 %t1 = zext i1 %t0 to i3 704 %t2 = lshr i3 %x, %t1 705 %t3 = shl i3 %y, %t1 706 %t4 = and i3 %t2, %t3 707 %t5 = icmp ne i3 %t4, 0 708 ret i1 %t5 709} 710