1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -instcombine -S < %s | FileCheck %s 3 4declare i3 @llvm.cttz.i3(i3, i1) 5declare i32 @llvm.cttz.i32(i32, i1 immarg) 6declare i32 @llvm.ctlz.i32(i32, i1 immarg) 7declare i64 @llvm.cttz.i64(i64, i1 immarg) 8declare i64 @llvm.ctlz.i64(i64, i1 immarg) 9 10declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1) 11declare <2 x i32> @llvm.cttz.v2i32(<2 x i32>, i1) 12 13 14declare void @use(i32) 15declare void @use2(i1) 16 17define i32 @select_clz_to_ctz(i32 %a) { 18; CHECK-LABEL: @select_clz_to_ctz( 19; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A:%.*]], i1 true), !range !0 20; CHECK-NEXT: ret i32 [[COND]] 21; 22 %sub = sub i32 0, %a 23 %and = and i32 %sub, %a 24 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) 25 %tobool = icmp eq i32 %a, 0 26 %sub1 = xor i32 %lz, 31 27 %cond = select i1 %tobool, i32 %lz, i32 %sub1 28 ret i32 %cond 29} 30 31define i32 @select_clz_to_ctz_preserve_flag(i32 %a) { 32; CHECK-LABEL: @select_clz_to_ctz_preserve_flag( 33; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A:%.*]], i1 false), !range !0 34; CHECK-NEXT: ret i32 [[COND]] 35; 36 %sub = sub i32 0, %a 37 %and = and i32 %sub, %a 38 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 false) 39 %tobool = icmp eq i32 %a, 0 40 %sub1 = xor i32 %lz, 31 41 %cond = select i1 %tobool, i32 %lz, i32 %sub1 42 ret i32 %cond 43} 44 45define <2 x i32> @select_clz_to_ctz_vec(<2 x i32> %a) { 46; CHECK-LABEL: @select_clz_to_ctz_vec( 47; CHECK-NEXT: [[COND:%.*]] = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[A:%.*]], i1 true) 48; CHECK-NEXT: ret <2 x i32> [[COND]] 49; 50 %sub = sub <2 x i32> zeroinitializer, %a 51 %and = and <2 x i32> %sub, %a 52 %lz = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %and, i1 true) 53 %tobool = icmp eq <2 x i32> %a, zeroinitializer 54 %sub1 = xor <2 x i32> %lz, <i32 31, i32 31> 55 %cond = select <2 x i1> %tobool, <2 x i32> %lz, <2 x i32> %sub1 56 ret <2 x i32> %cond 57} 58 59define i32 @select_clz_to_ctz_extra_use(i32 %a) { 60; CHECK-LABEL: @select_clz_to_ctz_extra_use( 61; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] 62; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]] 63; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 true), !range !0 64; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31 65; CHECK-NEXT: call void @use(i32 [[SUB1]]) 66; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A]], i1 true), !range !0 67; CHECK-NEXT: ret i32 [[COND]] 68; 69 %sub = sub i32 0, %a 70 %and = and i32 %sub, %a 71 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) 72 %tobool = icmp eq i32 %a, 0 73 %sub1 = xor i32 %lz, 31 74 call void @use(i32 %sub1) 75 %cond = select i1 %tobool, i32 %lz, i32 %sub1 76 ret i32 %cond 77} 78 79define i32 @select_clz_to_ctz_and_commuted(i32 %a) { 80; CHECK-LABEL: @select_clz_to_ctz_and_commuted( 81; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A:%.*]], i1 true), !range !0 82; CHECK-NEXT: ret i32 [[COND]] 83; 84 %sub = sub i32 0, %a 85 %and = and i32 %a, %sub 86 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) 87 %tobool = icmp eq i32 %a, 0 88 %sub1 = xor i32 %lz, 31 89 %cond = select i1 %tobool, i32 %lz, i32 %sub1 90 ret i32 %cond 91} 92 93define i32 @select_clz_to_ctz_icmp_ne(i32 %a) { 94; CHECK-LABEL: @select_clz_to_ctz_icmp_ne( 95; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[A:%.*]], 0 96; CHECK-NEXT: call void @use2(i1 [[TOBOOL]]) 97; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A]], i1 true), !range !0 98; CHECK-NEXT: ret i32 [[COND]] 99; 100 %sub = sub i32 0, %a 101 %and = and i32 %sub, %a 102 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) 103 %tobool = icmp ne i32 %a, 0 104 call void @use2(i1 %tobool) 105 %sub1 = xor i32 %lz, 31 106 %cond = select i1 %tobool, i32 %sub1, i32 %lz 107 ret i32 %cond 108} 109 110define i64 @select_clz_to_ctz_i64(i64 %a) { 111; CHECK-LABEL: @select_clz_to_ctz_i64( 112; CHECK-NEXT: [[COND:%.*]] = call i64 @llvm.cttz.i64(i64 [[A:%.*]], i1 true), !range !1 113; CHECK-NEXT: ret i64 [[COND]] 114; 115 %sub = sub i64 0, %a 116 %and = and i64 %sub, %a 117 %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true) 118 %tobool = icmp eq i64 %a, 0 119 %sub1 = xor i64 %lz, 63 120 %cond = select i1 %tobool, i64 %lz, i64 %sub1 121 ret i64 %cond 122} 123 124; Negative tests 125 126define i32 @select_clz_to_ctz_wrong_sub(i32 %a) { 127; CHECK-LABEL: @select_clz_to_ctz_wrong_sub( 128; CHECK-NEXT: [[SUB:%.*]] = sub i32 1, [[A:%.*]] 129; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]] 130; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 true), !range !0 131; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0 132; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31 133; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[LZ]], i32 [[SUB1]] 134; CHECK-NEXT: ret i32 [[COND]] 135; 136 %sub = sub i32 1, %a 137 %and = and i32 %sub, %a 138 %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) 139 %tobool = icmp eq i32 %a, 0 140 %sub1 = xor i32 %lz, 31 141 %cond = select i1 %tobool, i32 %lz, i32 %sub1 142 ret i32 %cond 143} 144 145define i64 @select_clz_to_ctz_i64_wrong_xor(i64 %a) { 146; CHECK-LABEL: @select_clz_to_ctz_i64_wrong_xor( 147; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]] 148; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]] 149; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1 150; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A]], 0 151; CHECK-NEXT: [[SUB11:%.*]] = or i64 [[LZ]], 64 152; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB11]] 153; CHECK-NEXT: ret i64 [[COND]] 154; 155 %sub = sub i64 0, %a 156 %and = and i64 %sub, %a 157 %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true) 158 %tobool = icmp eq i64 %a, 0 159 %sub1 = xor i64 %lz, 64 160 %cond = select i1 %tobool, i64 %lz, i64 %sub1 161 ret i64 %cond 162} 163 164define i64 @select_clz_to_ctz_i64_wrong_icmp_cst(i64 %a) { 165; CHECK-LABEL: @select_clz_to_ctz_i64_wrong_icmp_cst( 166; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]] 167; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]] 168; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1 169; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A]], 1 170; CHECK-NEXT: [[SUB1:%.*]] = xor i64 [[LZ]], 63 171; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB1]] 172; CHECK-NEXT: ret i64 [[COND]] 173; 174 %sub = sub i64 0, %a 175 %and = and i64 %sub, %a 176 %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true) 177 %tobool = icmp eq i64 %a, 1 178 %sub1 = xor i64 %lz, 63 179 %cond = select i1 %tobool, i64 %lz, i64 %sub1 180 ret i64 %cond 181} 182 183define i64 @select_clz_to_ctz_i64_wrong_icmp_pred(i64 %a) { 184; CHECK-LABEL: @select_clz_to_ctz_i64_wrong_icmp_pred( 185; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]] 186; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]] 187; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1 188; CHECK-NEXT: [[TOBOOL:%.*]] = icmp slt i64 [[A]], 0 189; CHECK-NEXT: [[SUB1:%.*]] = xor i64 [[LZ]], 63 190; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB1]] 191; CHECK-NEXT: ret i64 [[COND]] 192; 193 %sub = sub i64 0, %a 194 %and = and i64 %sub, %a 195 %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true) 196 %tobool = icmp slt i64 %a, 0 197 %sub1 = xor i64 %lz, 63 198 %cond = select i1 %tobool, i64 %lz, i64 %sub1 199 ret i64 %cond 200} 201 202define <2 x i32> @select_clz_to_ctz_vec_with_undef(<2 x i32> %a) { 203; CHECK-LABEL: @select_clz_to_ctz_vec_with_undef( 204; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> zeroinitializer, [[A:%.*]] 205; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[SUB]], [[A]] 206; CHECK-NEXT: [[LZ:%.*]] = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[AND]], i1 true) 207; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq <2 x i32> [[A]], zeroinitializer 208; CHECK-NEXT: [[SUB1:%.*]] = xor <2 x i32> [[LZ]], <i32 31, i32 undef> 209; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TOBOOL]], <2 x i32> [[LZ]], <2 x i32> [[SUB1]] 210; CHECK-NEXT: ret <2 x i32> [[COND]] 211; 212 %sub = sub <2 x i32> zeroinitializer, %a 213 %and = and <2 x i32> %sub, %a 214 %lz = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %and, i1 true) 215 %tobool = icmp eq <2 x i32> %a, zeroinitializer 216 %sub1 = xor <2 x i32> %lz, <i32 31, i32 undef> 217 %cond = select <2 x i1> %tobool, <2 x i32> %lz, <2 x i32> %sub1 218 ret <2 x i32> %cond 219} 220 221define i4 @PR45762(i3 %x4) { 222; CHECK-LABEL: @PR45762( 223; CHECK-NEXT: [[T4:%.*]] = call i3 @llvm.cttz.i3(i3 [[X4:%.*]], i1 false), !range !2 224; CHECK-NEXT: [[T7:%.*]] = zext i3 [[T4]] to i4 225; CHECK-NEXT: [[ONE_HOT_16:%.*]] = shl i4 1, [[T7]] 226; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i3 [[X4]], 0 227; CHECK-NEXT: [[UMUL_23:%.*]] = select i1 [[TMP1]], i4 0, i4 [[T7]] 228; CHECK-NEXT: [[SEL_71:%.*]] = shl i4 [[ONE_HOT_16]], [[UMUL_23]] 229; CHECK-NEXT: ret i4 [[SEL_71]] 230; 231 %t4 = call i3 @llvm.cttz.i3(i3 %x4, i1 false) 232 %t5 = icmp eq i3 %x4, 0 233 %t6 = select i1 %t5, i3 3, i3 %t4 234 %t7 = zext i3 %t6 to i4 235 %one_hot_16 = shl i4 1, %t7 236 %t8 = lshr i4 %one_hot_16, 0 237 %bit_slice_61 = trunc i4 %t8 to i1 238 %t9 = lshr i4 %one_hot_16, 1 239 %bit_slice_62 = trunc i4 %t9 to i1 240 %t10 = lshr i4 %one_hot_16, 2 241 %bit_slice_64 = trunc i4 %t10 to i1 242 %t11 = or i1 %bit_slice_61, %bit_slice_62 243 %or_69 = or i1 %t11, %bit_slice_64 244 %umul_23 = mul i4 %one_hot_16, %one_hot_16 245 %t12 = icmp eq i1 %or_69, false 246 %sel_71 = select i1 %t12, i4 %one_hot_16, i4 %umul_23 247 ret i4 %sel_71 248} 249