1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare i64 @llvm.cttz.i64(i64, i1) 5 6declare i64 @llvm.ctlz.i64(i64, i1) 7 8declare <8 x i64> @llvm.cttz.v8i64(<8 x i64>, i1) 9 10define i32 @test0(i64 %x) { 11; CHECK-LABEL: @test0( 12; CHECK-NEXT: start: 13; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[X:%.*]], 0 14; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]] 15; CHECK: non_zero: 16; CHECK-NEXT: [[CTZ:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X]], i1 true) 17; CHECK-NEXT: [[CTZ32:%.*]] = trunc nuw nsw i64 [[CTZ]] to i32 18; CHECK-NEXT: br label [[EXIT]] 19; CHECK: exit: 20; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[CTZ32]], [[NON_ZERO]] ], [ 0, [[START:%.*]] ] 21; CHECK-NEXT: ret i32 [[RES]] 22; 23start: 24 %c = icmp eq i64 %x, 0 25 br i1 %c, label %exit, label %non_zero 26 27non_zero: 28 %ctz = call i64 @llvm.cttz.i64(i64 %x, i1 false) 29 %ctz32 = trunc i64 %ctz to i32 30 br label %exit 31 32exit: 33 %res = phi i32 [ %ctz32, %non_zero ], [ 0, %start ] 34 ret i32 %res 35} 36 37define i32 @test1(i64 %x) { 38; CHECK-LABEL: @test1( 39; CHECK-NEXT: start: 40; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[X:%.*]], 0 41; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]] 42; CHECK: non_zero: 43; CHECK-NEXT: [[CTZ:%.*]] = call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X]], i1 true) 44; CHECK-NEXT: [[CTZ32:%.*]] = trunc nuw nsw i64 [[CTZ]] to i32 45; CHECK-NEXT: br label [[EXIT]] 46; CHECK: exit: 47; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[CTZ32]], [[NON_ZERO]] ], [ 0, [[START:%.*]] ] 48; CHECK-NEXT: ret i32 [[RES]] 49; 50start: 51 %c = icmp eq i64 %x, 0 52 br i1 %c, label %exit, label %non_zero 53 54non_zero: 55 %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 56 %ctz32 = trunc i64 %ctz to i32 57 br label %exit 58 59exit: 60 %res = phi i32 [ %ctz32, %non_zero ], [ 0, %start ] 61 ret i32 %res 62} 63 64define <8 x i64> @test2(<8 x i64> %x) { 65; CHECK-LABEL: @test2( 66; CHECK-NEXT: start: 67; CHECK-NEXT: [[A:%.*]] = icmp eq <8 x i64> [[X:%.*]], zeroinitializer 68; CHECK-NEXT: [[B:%.*]] = bitcast <8 x i1> [[A]] to i8 69; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[B]], 0 70; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]] 71; CHECK: non_zero: 72; CHECK-NEXT: [[CTZ:%.*]] = call range(i64 0, 65) <8 x i64> @llvm.cttz.v8i64(<8 x i64> [[X]], i1 false) 73; CHECK-NEXT: br label [[EXIT]] 74; CHECK: exit: 75; CHECK-NEXT: [[RES:%.*]] = phi <8 x i64> [ [[CTZ]], [[NON_ZERO]] ], [ zeroinitializer, [[START:%.*]] ] 76; CHECK-NEXT: ret <8 x i64> [[RES]] 77; 78start: 79 %a = icmp eq <8 x i64> %x, zeroinitializer 80 %b = bitcast <8 x i1> %a to i8 81 %c = icmp eq i8 %b, 0 82 br i1 %c, label %exit, label %non_zero 83 84non_zero: 85 ; NB: We cannot determine that vectors are known to be zero based 86 ; on the dominating condition 87 %ctz = call <8 x i64> @llvm.cttz.v8i64(<8 x i64> %x, i1 false) 88 br label %exit 89 90exit: 91 %res = phi <8 x i64> [ %ctz, %non_zero ], [ zeroinitializer, %start ] 92 ret <8 x i64> %res 93} 94 95; Test that exposed a bug in the PHI handling after D60846. 96; Check that folding happens correctly. 97define void @D60846_miscompile(ptr %p) { 98; CHECK-LABEL: @D60846_miscompile( 99; CHECK-NEXT: entry: 100; CHECK-NEXT: br label [[LOOP:%.*]] 101; CHECK: loop: 102; CHECK-NEXT: [[I:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[COMMON:%.*]] ] 103; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i16 [[I]], 0 104; CHECK-NEXT: br i1 [[IS_ZERO]], label [[COMMON]], label [[NON_ZERO:%.*]] 105; CHECK: non_zero: 106; CHECK-NEXT: store i1 true, ptr [[P:%.*]], align 1 107; CHECK-NEXT: br label [[COMMON]] 108; CHECK: common: 109; CHECK-NEXT: [[I_INC]] = add nuw nsw i16 [[I]], 1 110; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i16 [[I]], 0 111; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 112; CHECK: exit: 113; CHECK-NEXT: ret void 114; 115entry: 116 br label %loop 117 118loop: ; preds = %common, %entry 119 %i = phi i16 [ 0, %entry ], [ %i.inc, %common ] 120 %is_zero = icmp eq i16 %i, 0 121 br i1 %is_zero, label %common, label %non_zero 122 123non_zero: ; preds = %loop 124 %is_one = icmp eq i16 %i, 1 125 store i1 %is_one, ptr %p 126 br label %common 127 128common: ; preds = %non_zero, %loop 129 %i.inc = add i16 %i, 1 130 %loop_cond = icmp ult i16 %i.inc, 2 131 br i1 %loop_cond, label %loop, label %exit 132 133exit: ; preds = %common 134 ret void 135} 136 137define i64 @test_sgt_zero(i64 %x) { 138; CHECK-LABEL: @test_sgt_zero( 139; CHECK-NEXT: start: 140; CHECK-NEXT: [[C:%.*]] = icmp sgt i64 [[X:%.*]], 0 141; CHECK-NEXT: br i1 [[C]], label [[NON_ZERO:%.*]], label [[EXIT:%.*]] 142; CHECK: non_zero: 143; CHECK-NEXT: [[CTZ:%.*]] = call range(i64 1, 65) i64 @llvm.ctlz.i64(i64 [[X]], i1 true) 144; CHECK-NEXT: ret i64 [[CTZ]] 145; CHECK: exit: 146; CHECK-NEXT: ret i64 -1 147; 148start: 149 %c = icmp sgt i64 %x, 0 150 br i1 %c, label %non_zero, label %exit 151 152non_zero: 153 %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 154 ret i64 %ctz 155 156exit: 157 ret i64 -1 158} 159 160define i64 @test_slt_neg_ten(i64 %x) { 161; CHECK-LABEL: @test_slt_neg_ten( 162; CHECK-NEXT: start: 163; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[X:%.*]], -10 164; CHECK-NEXT: br i1 [[C]], label [[NON_ZERO:%.*]], label [[EXIT:%.*]] 165; CHECK: non_zero: 166; CHECK-NEXT: ret i64 0 167; CHECK: exit: 168; CHECK-NEXT: ret i64 -1 169; 170start: 171 %c = icmp slt i64 %x, -10 172 br i1 %c, label %non_zero, label %exit 173 174non_zero: 175 %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 176 ret i64 %ctz 177 178exit: 179 ret i64 -1 180} 181 182define i64 @test_slt_ten(i64 %x) { 183; CHECK-LABEL: @test_slt_ten( 184; CHECK-NEXT: start: 185; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[X:%.*]], 10 186; CHECK-NEXT: br i1 [[C]], label [[MAYBE_ZERO:%.*]], label [[EXIT:%.*]] 187; CHECK: maybe_zero: 188; CHECK-NEXT: [[CTZ:%.*]] = call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X]], i1 false) 189; CHECK-NEXT: ret i64 [[CTZ]] 190; CHECK: exit: 191; CHECK-NEXT: ret i64 -1 192; 193start: 194 %c = icmp slt i64 %x, 10 195 br i1 %c, label %maybe_zero, label %exit 196 197maybe_zero: 198 %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 199 ret i64 %ctz 200 201exit: 202 ret i64 -1 203} 204 205define i64 @test_ugt_unknown(i64 %x, i64 %y) { 206; CHECK-LABEL: @test_ugt_unknown( 207; CHECK-NEXT: start: 208; CHECK-NEXT: [[C:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]] 209; CHECK-NEXT: br i1 [[C]], label [[NON_ZERO:%.*]], label [[EXIT:%.*]] 210; CHECK: non_zero: 211; CHECK-NEXT: [[CTZ:%.*]] = call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X]], i1 true) 212; CHECK-NEXT: ret i64 [[CTZ]] 213; CHECK: exit: 214; CHECK-NEXT: ret i64 -1 215; 216start: 217 %c = icmp ugt i64 %x, %y 218 br i1 %c, label %non_zero, label %exit 219 220non_zero: 221 %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 222 ret i64 %ctz 223 224exit: 225 ret i64 -1 226} 227 228define i64 @test_sle_zero(i64 %x) { 229; CHECK-LABEL: @test_sle_zero( 230; CHECK-NEXT: start: 231; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[X:%.*]], 1 232; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]] 233; CHECK: non_zero: 234; CHECK-NEXT: [[CTZ:%.*]] = call range(i64 1, 65) i64 @llvm.ctlz.i64(i64 [[X]], i1 true) 235; CHECK-NEXT: ret i64 [[CTZ]] 236; CHECK: exit: 237; CHECK-NEXT: ret i64 -1 238; 239start: 240 %c = icmp sle i64 %x, 0 241 br i1 %c, label %exit, label %non_zero 242 243non_zero: 244 %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 245 ret i64 %ctz 246 247exit: 248 ret i64 -1 249} 250 251define i64 @test_sge_neg_ten(i64 %x) { 252; CHECK-LABEL: @test_sge_neg_ten( 253; CHECK-NEXT: start: 254; CHECK-NEXT: [[C:%.*]] = icmp sgt i64 [[X:%.*]], -11 255; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]] 256; CHECK: non_zero: 257; CHECK-NEXT: ret i64 0 258; CHECK: exit: 259; CHECK-NEXT: ret i64 -1 260; 261start: 262 %c = icmp sge i64 %x, -10 263 br i1 %c, label %exit, label %non_zero 264 265non_zero: 266 %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 267 ret i64 %ctz 268 269exit: 270 ret i64 -1 271} 272 273define i64 @test_sge_ten(i64 %x) { 274; CHECK-LABEL: @test_sge_ten( 275; CHECK-NEXT: start: 276; CHECK-NEXT: [[C:%.*]] = icmp sgt i64 [[X:%.*]], 9 277; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[MAYBE_ZERO:%.*]] 278; CHECK: maybe_zero: 279; CHECK-NEXT: [[CTZ:%.*]] = call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X]], i1 false) 280; CHECK-NEXT: ret i64 [[CTZ]] 281; CHECK: exit: 282; CHECK-NEXT: ret i64 -1 283; 284start: 285 %c = icmp sge i64 %x, 10 286 br i1 %c, label %exit, label %maybe_zero 287 288maybe_zero: 289 %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 290 ret i64 %ctz 291 292exit: 293 ret i64 -1 294} 295 296define i64 @test_ule_unknown(i64 %x, i64 %y) { 297; CHECK-LABEL: @test_ule_unknown( 298; CHECK-NEXT: start: 299; CHECK-NEXT: [[C_NOT:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]] 300; CHECK-NEXT: br i1 [[C_NOT]], label [[NON_ZERO:%.*]], label [[EXIT:%.*]] 301; CHECK: non_zero: 302; CHECK-NEXT: [[CTZ:%.*]] = call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X]], i1 true) 303; CHECK-NEXT: ret i64 [[CTZ]] 304; CHECK: exit: 305; CHECK-NEXT: ret i64 -1 306; 307start: 308 %c = icmp ule i64 %x, %y 309 br i1 %c, label %exit, label %non_zero 310 311non_zero: 312 %ctz = call i64 @llvm.ctlz.i64(i64 %x, i1 false) 313 ret i64 %ctz 314 315exit: 316 ret i64 -1 317} 318