1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; The pattern: 5; icmp eq/ne (and (X shift Y), Z), 0 6; is equivalent to pattern 7; icmp eq/ne (and (Z oppositeshift Y), X), 0 8; We should canonicalize to one of them. 9; Let's go with 'lshr'. 10; Exception: unless it's a shift of constant, then don't touch it. 11 12;------------------------------------------------------------------------------; 13; Basic scalar test 14;------------------------------------------------------------------------------; 15 16define i1 @t0(i32 %x, i32 %y, i32 %z) { 17; CHECK-LABEL: @t0( 18; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 19; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]] 20; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 21; CHECK-NEXT: ret i1 [[T2]] 22; 23 %t0 = shl i32 %x, %y 24 %t1 = and i32 %t0, %z 25 %t2 = icmp eq i32 %t1, 0 26 ret i1 %t2 27} 28 29define i1 @t1_ne(i32 %x, i32 %y, i32 %z) { 30; CHECK-LABEL: @t1_ne( 31; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 32; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]] 33; CHECK-NEXT: [[T2:%.*]] = icmp ne i32 [[T1]], 0 34; CHECK-NEXT: ret i1 [[T2]] 35; 36 %t0 = shl i32 %x, %y 37 %t1 = and i32 %t0, %z 38 %t2 = icmp ne i32 %t1, 0 39 ret i1 %t2 40} 41 42;------------------------------------------------------------------------------; 43; Basic vector test 44;------------------------------------------------------------------------------; 45 46define <4 x i1> @t2_vec_splat(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { 47; CHECK-LABEL: @t2_vec_splat( 48; CHECK-NEXT: [[T0:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] 49; CHECK-NEXT: [[T1:%.*]] = and <4 x i32> [[T0]], [[Z:%.*]] 50; CHECK-NEXT: [[T2:%.*]] = icmp eq <4 x i32> [[T1]], zeroinitializer 51; CHECK-NEXT: ret <4 x i1> [[T2]] 52; 53 %t0 = shl <4 x i32> %x, %y 54 %t1 = and <4 x i32> %t0, %z 55 %t2 = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 0, i32 0> 56 ret <4 x i1> %t2 57} 58 59define <4 x i1> @t3_vec_splat_undef(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { 60; CHECK-LABEL: @t3_vec_splat_undef( 61; CHECK-NEXT: [[T0:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] 62; CHECK-NEXT: [[T1:%.*]] = and <4 x i32> [[T0]], [[Z:%.*]] 63; CHECK-NEXT: [[T2:%.*]] = icmp eq <4 x i32> [[T1]], <i32 0, i32 0, i32 undef, i32 0> 64; CHECK-NEXT: ret <4 x i1> [[T2]] 65; 66 %t0 = shl <4 x i32> %x, %y 67 %t1 = and <4 x i32> %t0, %z 68 %t2 = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 undef, i32 0> 69 ret <4 x i1> %t2 70} 71 72;------------------------------------------------------------------------------; 73; Commutativity 74;------------------------------------------------------------------------------; 75 76declare i32 @gen32() 77 78define i1 @t4_commutative(i32 %x, i32 %y) { 79; CHECK-LABEL: @t4_commutative( 80; CHECK-NEXT: [[Z:%.*]] = call i32 @gen32() 81; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 82; CHECK-NEXT: [[T1:%.*]] = and i32 [[Z]], [[T0]] 83; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 84; CHECK-NEXT: ret i1 [[T2]] 85; 86 %z = call i32 @gen32() 87 %t0 = shl i32 %x, %y 88 %t1 = and i32 %z, %t0 ; swapped 89 %t2 = icmp eq i32 %t1, 0 90 ret i1 %t2 91} 92 93;------------------------------------------------------------------------------; 94; Shifts in both hands of 'and' 95;------------------------------------------------------------------------------; 96 97define i1 @t5_twoshifts0(i32 %a, i32 %b, i32 %c, i32 %d) { 98; CHECK-LABEL: @t5_twoshifts0( 99; CHECK-NEXT: [[T0:%.*]] = shl i32 [[A:%.*]], [[B:%.*]] 100; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[C:%.*]] 101; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[D:%.*]] 102; CHECK-NEXT: [[T3:%.*]] = icmp eq i32 [[T2]], 0 103; CHECK-NEXT: ret i1 [[T3]] 104; 105 %t0 = shl i32 %a, %b 106 %t1 = shl i32 %t0, %c 107 %t2 = and i32 %t1, %d 108 %t3 = icmp eq i32 %t2, 0 109 ret i1 %t3 110} 111 112define i1 @t6_twoshifts1(i32 %a, i32 %b, i32 %c, i32 %d) { 113; CHECK-LABEL: @t6_twoshifts1( 114; CHECK-NEXT: [[T0:%.*]] = shl i32 [[A:%.*]], [[B:%.*]] 115; CHECK-NEXT: [[T1:%.*]] = shl i32 [[C:%.*]], [[D:%.*]] 116; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 117; CHECK-NEXT: [[T3:%.*]] = icmp eq i32 [[T2]], 0 118; CHECK-NEXT: ret i1 [[T3]] 119; 120 %t0 = shl i32 %a, %b 121 %t1 = shl i32 %c, %d 122 %t2 = and i32 %t1, %t0 123 %t3 = icmp eq i32 %t2, 0 124 ret i1 %t3 125} 126 127define i1 @t7_twoshifts2(i32 %a, i32 %b, i32 %c, i32 %d) { 128; CHECK-LABEL: @t7_twoshifts2( 129; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[B:%.*]] 130; CHECK-NEXT: [[T1:%.*]] = shl i32 [[C:%.*]], [[D:%.*]] 131; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 132; CHECK-NEXT: [[T3:%.*]] = icmp eq i32 [[T2]], 0 133; CHECK-NEXT: ret i1 [[T3]] 134; 135 %t0 = shl i32 1, %b 136 %t1 = shl i32 %c, %d 137 %t2 = and i32 %t1, %t0 138 %t3 = icmp eq i32 %t2, 0 139 ret i1 %t3 140} 141 142define i1 @t8_twoshifts3(i32 %a, i32 %b, i32 %c, i32 %d) { 143; CHECK-LABEL: @t8_twoshifts3( 144; CHECK-NEXT: [[T0:%.*]] = shl i32 [[A:%.*]], [[B:%.*]] 145; CHECK-NEXT: [[T1:%.*]] = shl i32 1, [[D:%.*]] 146; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]] 147; CHECK-NEXT: [[T3:%.*]] = icmp eq i32 [[T2]], 0 148; CHECK-NEXT: ret i1 [[T3]] 149; 150 %t0 = shl i32 %a, %b 151 %t1 = shl i32 1, %d 152 %t2 = and i32 %t1, %t0 153 %t3 = icmp eq i32 %t2, 0 154 ret i1 %t3 155} 156 157;------------------------------------------------------------------------------; 158; Extra uses 159;------------------------------------------------------------------------------; 160 161declare void @use32(i32) 162 163define i1 @t9_extrause0(i32 %x, i32 %y, i32 %z) { 164; CHECK-LABEL: @t9_extrause0( 165; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 166; CHECK-NEXT: call void @use32(i32 [[T0]]) 167; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]] 168; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 169; CHECK-NEXT: ret i1 [[T2]] 170; 171 %t0 = shl i32 %x, %y 172 call void @use32(i32 %t0) 173 %t1 = and i32 %t0, %z 174 %t2 = icmp eq i32 %t1, 0 175 ret i1 %t2 176} 177 178define i1 @t10_extrause1(i32 %x, i32 %y, i32 %z) { 179; CHECK-LABEL: @t10_extrause1( 180; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 181; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]] 182; CHECK-NEXT: call void @use32(i32 [[T1]]) 183; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 184; CHECK-NEXT: ret i1 [[T2]] 185; 186 %t0 = shl i32 %x, %y 187 %t1 = and i32 %t0, %z 188 call void @use32(i32 %t1) 189 %t2 = icmp eq i32 %t1, 0 190 ret i1 %t2 191} 192 193define i1 @t11_extrause2(i32 %x, i32 %y, i32 %z) { 194; CHECK-LABEL: @t11_extrause2( 195; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 196; CHECK-NEXT: call void @use32(i32 [[T0]]) 197; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]] 198; CHECK-NEXT: call void @use32(i32 [[T1]]) 199; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 200; CHECK-NEXT: ret i1 [[T2]] 201; 202 %t0 = shl i32 %x, %y 203 call void @use32(i32 %t0) 204 %t1 = and i32 %t0, %z 205 call void @use32(i32 %t1) 206 %t2 = icmp eq i32 %t1, 0 207 ret i1 %t2 208} 209 210;------------------------------------------------------------------------------; 211; Constants 212;------------------------------------------------------------------------------; 213 214define i1 @t12_shift_of_const0(i32 %x, i32 %y, i32 %z) { 215; CHECK-LABEL: @t12_shift_of_const0( 216; CHECK-NEXT: [[T0:%.*]] = shl i32 1, [[Y:%.*]] 217; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]] 218; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 219; CHECK-NEXT: ret i1 [[T2]] 220; 221 %t0 = shl i32 1, %y 222 %t1 = and i32 %t0, %z 223 %t2 = icmp eq i32 %t1, 0 224 ret i1 %t2 225} 226define i1 @t13_shift_of_const1(i32 %x, i32 %y, i32 %z) { 227; CHECK-LABEL: @t13_shift_of_const1( 228; CHECK-NEXT: [[T0:%.*]] = lshr i32 1, [[Y:%.*]] 229; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]] 230; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 231; CHECK-NEXT: ret i1 [[T2]] 232; 233 %t0 = lshr i32 1, %y 234 %t1 = and i32 %t0, %z 235 %t2 = icmp eq i32 %t1, 0 236 ret i1 %t2 237} 238 239define i1 @t14_and_with_const0(i32 %x, i32 %y, i32 %z) { 240; CHECK-LABEL: @t14_and_with_const0( 241; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 1, [[Y:%.*]] 242; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]] 243; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[TMP2]], 0 244; CHECK-NEXT: ret i1 [[T2]] 245; 246 %t0 = shl i32 %x, %y 247 %t1 = and i32 %t0, 1 248 %t2 = icmp eq i32 %t1, 0 249 ret i1 %t2 250} 251define i1 @t15_and_with_const1(i32 %x, i32 %y, i32 %z) { 252; CHECK-LABEL: @t15_and_with_const1( 253; CHECK-NEXT: [[TMP1:%.*]] = shl i32 1, [[Y:%.*]] 254; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]] 255; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[TMP2]], 0 256; CHECK-NEXT: ret i1 [[T2]] 257; 258 %t0 = lshr i32 %x, %y 259 %t1 = and i32 %t0, 1 260 %t2 = icmp eq i32 %t1, 0 261 ret i1 %t2 262} 263 264;------------------------------------------------------------------------------; 265; Negative test 266;------------------------------------------------------------------------------; 267 268define i1 @n16(i32 %x, i32 %y, i32 %z) { 269; CHECK-LABEL: @n16( 270; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] 271; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]] 272; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 1 273; CHECK-NEXT: ret i1 [[T2]] 274; 275 %t0 = shl i32 %x, %y 276 %t1 = and i32 %t0, %z 277 %t2 = icmp eq i32 %t1, 1 ; not with '0' 278 ret i1 %t2 279} 280