diff --git a/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll b/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll new file mode 100644 index 00000000000000..4f2f66f26402e2 --- /dev/null +++ b/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll @@ -0,0 +1,272 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -ipsccp -S | FileCheck %s + +declare void @use(i1) + +; We can simplify the conditions in the true block, because the condition +; allows us to replace all uses of %a in the block with a constant. +define void @val_undef_eq() { +; CHECK-LABEL: @val_undef_eq( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = add i32 undef, 0 +; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 [[A]], 10 +; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + %a = add i32 undef, 0 + %bc.1 = icmp eq i32 %a, 10 + br i1 %bc.1, label %true, label %false + +true: + %f.1 = icmp ne i32 %a, 10 + call void @use(i1 %f.1) + %f.2 = icmp eq i32 %a, 10 + call void @use(i1 %f.2) + ret void + +false: + ret void +} + +declare void @use.i32(i32) + +; It is not allowed to use the range information from the condition to remove +; %a.127 = and ... in the true block, as %a could be undef. +define void @val_undef_range() { +; CHECK-LABEL: @val_undef_range( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = add i32 undef, 0 +; CHECK-NEXT: [[BC_1:%.*]] = icmp ult i32 [[A]], 127 +; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 128 +; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127 +; CHECK-NEXT: call void @use.i32(i32 [[A_127]]) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + %a = add i32 undef, 0 + %bc.1 = icmp ult i32 %a, 127 + br i1 %bc.1, label %true, label %false + +true: + %f.1 = icmp eq i32 %a, 128 + call void @use(i1 %f.1) + + %a.127 = and i32 %a, 127 + call void @use.i32(i32 %a.127) + ret void + +false: + ret void +} + +; All uses of %p can be replaced by a constant (10). +define void @val_singlecrfromundef_range(i1 %cond) { +; CHECK-LABEL: @val_singlecrfromundef_range( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[COND:%.*]], label [[INC1:%.*]], label [[INC2:%.*]] +; CHECK: inc1: +; CHECK-NEXT: br label [[IF:%.*]] +; CHECK: inc2: +; CHECK-NEXT: br label [[IF]] +; CHECK: if: +; CHECK-NEXT: br label [[TRUE:%.*]] +; CHECK: true: +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use.i32(i32 10) +; CHECK-NEXT: ret void +; +entry: + + br i1 %cond, label %inc1, label %inc2 + +inc1: + br label %if + +inc2: + br label %if + +if: + %p = phi i32 [ 10, %inc1 ], [ undef, %inc2 ] + %bc.1 = icmp ult i32 %p, 127 + br i1 %bc.1, label %true, label %false + +true: + %f.1 = icmp eq i32 %p, 128 + call void @use(i1 %f.1) + + %p.127 = and i32 %p, 127 + call void @use.i32(i32 %p.127) + ret void + +false: + ret void +} + + +; It is not allowed to use the information from the condition ([0, 128)) +; to remove a.127.2 = and i32 %p, 127, as %p might be undef. +define void @val_undef_to_cr_to_overdef_range(i32 %a, i1 %cond) { +; CHECK-LABEL: @val_undef_to_cr_to_overdef_range( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A:%.*]], 127 +; CHECK-NEXT: br i1 [[COND:%.*]], label [[INC1:%.*]], label [[INC2:%.*]] +; CHECK: inc1: +; CHECK-NEXT: br label [[IF:%.*]] +; CHECK: inc2: +; CHECK-NEXT: br label [[IF]] +; CHECK: if: +; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[A_127]], [[INC1]] ], [ undef, [[INC2]] ] +; CHECK-NEXT: [[BC_1:%.*]] = icmp ult i32 [[P]], 100 +; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[P]], 128 +; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: [[P_127:%.*]] = and i32 [[P]], 127 +; CHECK-NEXT: call void @use.i32(i32 [[P_127]]) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + %a.127 = and i32 %a, 127 + br i1 %cond, label %inc1, label %inc2 + +inc1: + br label %if + +inc2: + br label %if + +if: + %p = phi i32 [ %a.127, %inc1 ], [ undef, %inc2 ] + %bc.1 = icmp ult i32 %p, 100 + br i1 %bc.1, label %true, label %false + +true: + %f.1 = icmp eq i32 %p, 128 + call void @use(i1 %f.1) + + %p.127 = and i32 %p, 127 + call void @use.i32(i32 %p.127) + ret void + +false: + ret void +} + +; All uses of %p can be replaced by a constant (10), we are allowed to use it +; as a bound too. +define void @bound_singlecrfromundef(i32 %a, i1 %cond) { +; CHECK-LABEL: @bound_singlecrfromundef( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[PRED:%.*]] +; CHECK: bb2: +; CHECK-NEXT: br label [[PRED]] +; CHECK: pred: +; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[A:%.*]], 10 +; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 5 +; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: [[T_1:%.*]] = icmp ne i32 [[A]], 5 +; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127 +; CHECK-NEXT: call void @use.i32(i32 [[A_127]]) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + br i1 %cond, label %bb1, label %bb2 + +bb1: + br label %pred + +bb2: + br label %pred + +pred: + %p = phi i32 [ undef, %bb1 ], [ 10, %bb2 ] + %bc.1 = icmp ugt i32 %a, %p + br i1 %bc.1, label %true, label %false + +true: + %f.1 = icmp eq i32 %a, 5 + call void @use(i1 %f.1) + + %t.1 = icmp ne i32 %a, 5 + call void @use(i1 %t.1) + + %a.127 = and i32 %a, 127 + call void @use.i32(i32 %a.127) + + ret void + +false: + ret void +} + +; It is not allowed to use the information from %p as a bound, because an +; incoming value is undef. +define void @bound_range_and_undef(i32 %a, i1 %cond) { +; CHECK-LABEL: @bound_range_and_undef( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A_10:%.*]] = and i32 [[A:%.*]], 127 +; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[PRED:%.*]] +; CHECK: bb2: +; CHECK-NEXT: br label [[PRED]] +; CHECK: pred: +; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[A_10]], [[BB1]] ], [ undef, [[BB2]] ] +; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[A]], [[P]] +; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 300 +; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: [[A_127_2:%.*]] = and i32 [[P]], 127 +; CHECK-NEXT: call void @use.i32(i32 [[A_127_2]]) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + %a.10 = and i32 %a, 127 + br i1 %cond, label %bb1, label %bb2 + +bb1: + br label %pred + +bb2: + br label %pred + +pred: + %p = phi i32 [ %a.10, %bb1 ], [ undef, %bb2 ] + %bc.1 = icmp ugt i32 %a, %p + br i1 %bc.1, label %true, label %false + +true: + %f.1 = icmp eq i32 %a, 300 + call void @use(i1 %f.1) + + %a.127.2 = and i32 %p, 127 + call void @use.i32(i32 %a.127.2) + + ret void + +false: + ret void +} diff --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll index 345e521d35c769..b722854abeb53f 100644 --- a/llvm/test/Transforms/SCCP/conditions-ranges.ll +++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll @@ -232,136 +232,6 @@ false: ret void } -define void @loop.1() { -entry: - br label %for.cond - -for.cond: ; preds = %for.cond.cleanup13, %if.then - %i.0 = phi i32 [ 0, %entry ], [ %inc27, %for.cond.cleanup13 ] - %cmp9 = icmp sle i32 %i.0, 3 - br i1 %cmp9, label %for.body, label %for.cond.cleanup - -for.cond.cleanup: ; preds = %for.cond - ret void - -for.body: ; preds = %for.cond - br label %for.cond11 - -for.cond11: ; preds = %arrayctor.cont21, %for.body - br label %for.cond.cleanup13 - -for.cond.cleanup13: ; preds = %for.cond11 - %inc27 = add nsw i32 %i.0, 1 - br label %for.cond -} - - -define void @loop() { -; CHECK-LABEL: @loop( -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[FOR_COND:%.*]] -; CHECK: for.cond: -; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC27:%.*]], [[FOR_COND_CLEANUP13:%.*]] ] -; CHECK-NEXT: [[CMP9:%.*]] = icmp sle i32 [[I_0]], 3 -; CHECK-NEXT: br i1 [[CMP9]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] -; CHECK: for.cond.cleanup: -; CHECK-NEXT: ret void -; CHECK: for.body: -; CHECK-NEXT: br label [[FOR_COND11:%.*]] -; CHECK: for.cond11: -; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[FOR_BODY]] ], [ [[INC:%.*]], [[FOR_BODY14:%.*]] ] -; CHECK-NEXT: [[CMP12:%.*]] = icmp slt i32 [[J_0]], 2 -; CHECK-NEXT: br i1 [[CMP12]], label [[FOR_BODY14]], label [[FOR_COND_CLEANUP13]] -; CHECK: for.cond.cleanup13: -; CHECK-NEXT: [[INC27]] = add nsw i32 [[I_0]], 1 -; CHECK-NEXT: br label [[FOR_COND]] -; CHECK: for.body14: -; CHECK-NEXT: [[INC]] = add nsw i32 [[J_0]], 1 -; CHECK-NEXT: br label [[FOR_COND11]] -; -entry: - br label %for.cond - -for.cond: ; preds = %for.cond.cleanup13, %if.then - %i.0 = phi i32 [ 0, %entry ], [ %inc27, %for.cond.cleanup13 ] - %cmp9 = icmp sle i32 %i.0, 3 - br i1 %cmp9, label %for.body, label %for.cond.cleanup - -for.cond.cleanup: ; preds = %for.cond - ret void - -for.body: ; preds = %for.cond - br label %for.cond11 - -for.cond11: ; preds = %arrayctor.cont21, %for.body - %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.body14 ] - %cmp12 = icmp slt i32 %j.0, 2 - br i1 %cmp12, label %for.body14, label %for.cond.cleanup13 - -for.cond.cleanup13: ; preds = %for.cond11 - %inc27 = add nsw i32 %i.0, 1 - br label %for.cond - -for.body14: - %inc = add nsw i32 %j.0, 1 - br label %for.cond11 -} - -define i32 @udiv_1(i64 %sz) { -; CHECK-LABEL: @udiv_1( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 4088, [[SZ:%.*]] -; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] -; CHECK: cond.true: -; CHECK-NEXT: [[DIV:%.*]] = udiv i64 4088, [[SZ]] -; CHECK-NEXT: br label [[COND_END]] -; CHECK: cond.end: -; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32 -; CHECK-NEXT: ret i32 [[CONV]] -; -entry: - %cmp = icmp ugt i64 4088, %sz - br i1 %cmp, label %cond.true, label %cond.end - -cond.true: ; preds = %entry - %div = udiv i64 4088, %sz - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %div, %cond.true ], [ 1, %entry ] - %conv = trunc i64 %cond to i32 - ret i32 %conv -} - -; Same as @udiv_1, but with the condition switched. -define i32 @udiv_2(i64 %sz) { -; CHECK-LABEL: @udiv_2( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SZ:%.*]], 4088 -; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] -; CHECK: cond.true: -; CHECK-NEXT: [[DIV:%.*]] = udiv i64 4088, [[SZ]] -; CHECK-NEXT: br label [[COND_END]] -; CHECK: cond.end: -; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32 -; CHECK-NEXT: ret i32 [[CONV]] -; -entry: - %cmp = icmp ugt i64 %sz, 4088 - br i1 %cmp, label %cond.true, label %cond.end - -cond.true: ; preds = %entry - %div = udiv i64 4088, %sz - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %div, %cond.true ], [ 1, %entry ] - %conv = trunc i64 %cond to i32 - ret i32 %conv -} - ; Test with 2 unrelated nested conditions. define void @f7_nested_conds(i32* %a, i32 %b) { ; CHECK-LABEL: @f7_nested_conds( @@ -710,3 +580,273 @@ true: ; %b in [0, 256) false: ret void } + +define void @f11_contradiction(i32 %a, i32 %b) { +; CHECK-LABEL: @f11_contradiction( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 [[B:%.*]], 10 +; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: br label [[FALSE]] +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + %bc.1 = icmp eq i32 %b, 10 + br i1 %bc.1, label %true, label %false + +true: ; %b in [10, 11) + %bc.2 = icmp eq i32 %b, 20 + br i1 %bc.2, label %true.2, label %false + +true.2: + %f.1 = icmp eq i32 %b, 256 + call void @use(i1 %f.1) + %f.2 = icmp ne i32 %b, 300 + call void @use(i1 %f.2) + ret void + +false: + ret void +} + +define void @f12_float(float %b) { +; CHECK-LABEL: @f12_float( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[BC_1:%.*]] = fcmp olt float 1.000000e+00, [[B:%.*]] +; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + %a = fadd float 0.0, 1.0 + %bc.1 = fcmp olt float %a, %b + br i1 %bc.1, label %true, label %false + +true: ; %b in [10, 11) + %f.1 = fcmp one float %a, 1.0 + call void @use(i1 %f.1) + + %t.1 = fcmp oeq float %a, 1.0 + call void @use(i1 %t.1) + ret void + +false: + ret void +} + + +@A = global i32 17 +@B = global i32 17 + +define void @f13_constexpr1() { +; CHECK-LABEL: @f13_constexpr1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 add (i32 ptrtoint (i32* @A to i32), i32 10), 55 +; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 add (i32 ptrtoint (i32* @A to i32), i32 10), 10 +; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 add (i32 ptrtoint (i32* @A to i32), i32 10), 55 +; CHECK-NEXT: call void @use(i1 [[F_2]]) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + %a = add i32 ptrtoint (i32* @A to i32), 10 + %bc.1 = icmp eq i32 %a, 55 + br i1 %bc.1, label %true, label %false + +true: ; %b in [10, 11) + %f.1 = icmp eq i32 %a, 10 + call void @use(i1 %f.1) + %f.2 = icmp eq i32 %a, 55 + call void @use(i1 %f.2) + + ret void + +false: + ret void +} + +; TODO: can we fold the compares in the true block? +define void @f14_constexpr2() { +; CHECK-LABEL: @f14_constexpr2( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 icmp eq (i32 ptrtoint (i32* @A to i32), i32 ptrtoint (i32* @B to i32)), label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: call void @use(i1 icmp ne (i32 ptrtoint (i32* @A to i32), i32 ptrtoint (i32* @B to i32))) +; CHECK-NEXT: call void @use(i1 icmp eq (i32 ptrtoint (i32* @A to i32), i32 ptrtoint (i32* @B to i32))) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + %a = add i32 ptrtoint (i32* @A to i32), 0 + %b = add i32 ptrtoint (i32* @B to i32), 0 + %bc.1 = icmp eq i32 %a, %b + br i1 %bc.1, label %true, label %false + +true: ; %b in [10, 11) + %f.1 = icmp ne i32 %a, %b + call void @use(i1 %f.1) + %f.2 = icmp eq i32 %a, %b + call void @use(i1 %f.2) + + ret void + +false: + ret void +} + +define void @loop_1() { +; CHECK-LABEL: @loop_1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC27:%.*]], [[FOR_COND_CLEANUP13:%.*]] ] +; CHECK-NEXT: [[CMP9:%.*]] = icmp sle i32 [[I_0]], 3 +; CHECK-NEXT: br i1 [[CMP9]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: ret void +; CHECK: for.body: +; CHECK-NEXT: br label [[FOR_COND11:%.*]] +; CHECK: for.cond11: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP13]] +; CHECK: for.cond.cleanup13: +; CHECK-NEXT: [[INC27]] = add nsw i32 [[I_0]], 1 +; CHECK-NEXT: br label [[FOR_COND]] +; +entry: + br label %for.cond + +for.cond: ; preds = %for.cond.cleanup13, %if.then + %i.0 = phi i32 [ 0, %entry ], [ %inc27, %for.cond.cleanup13 ] + %cmp9 = icmp sle i32 %i.0, 3 + br i1 %cmp9, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + ret void + +for.body: ; preds = %for.cond + br label %for.cond11 + +for.cond11: ; preds = %arrayctor.cont21, %for.body + br label %for.cond.cleanup13 + +for.cond.cleanup13: ; preds = %for.cond11 + %inc27 = add nsw i32 %i.0, 1 + br label %for.cond +} + + +define void @loop() { +; CHECK-LABEL: @loop( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC27:%.*]], [[FOR_COND_CLEANUP13:%.*]] ] +; CHECK-NEXT: [[CMP9:%.*]] = icmp sle i32 [[I_0]], 3 +; CHECK-NEXT: br i1 [[CMP9]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: ret void +; CHECK: for.body: +; CHECK-NEXT: br label [[FOR_COND11:%.*]] +; CHECK: for.cond11: +; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[FOR_BODY]] ], [ [[INC:%.*]], [[FOR_BODY14:%.*]] ] +; CHECK-NEXT: [[CMP12:%.*]] = icmp slt i32 [[J_0]], 2 +; CHECK-NEXT: br i1 [[CMP12]], label [[FOR_BODY14]], label [[FOR_COND_CLEANUP13]] +; CHECK: for.cond.cleanup13: +; CHECK-NEXT: [[INC27]] = add nsw i32 [[I_0]], 1 +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: for.body14: +; CHECK-NEXT: [[INC]] = add nsw i32 [[J_0]], 1 +; CHECK-NEXT: br label [[FOR_COND11]] +; +entry: + br label %for.cond + +for.cond: ; preds = %for.cond.cleanup13, %if.then + %i.0 = phi i32 [ 0, %entry ], [ %inc27, %for.cond.cleanup13 ] + %cmp9 = icmp sle i32 %i.0, 3 + br i1 %cmp9, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + ret void + +for.body: ; preds = %for.cond + br label %for.cond11 + +for.cond11: ; preds = %arrayctor.cont21, %for.body + %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.body14 ] + %cmp12 = icmp slt i32 %j.0, 2 + br i1 %cmp12, label %for.body14, label %for.cond.cleanup13 + +for.cond.cleanup13: ; preds = %for.cond11 + %inc27 = add nsw i32 %i.0, 1 + br label %for.cond + +for.body14: + %inc = add nsw i32 %j.0, 1 + br label %for.cond11 +} + +define i32 @udiv_1(i64 %sz) { +; CHECK-LABEL: @udiv_1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 4088, [[SZ:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] +; CHECK: cond.true: +; CHECK-NEXT: [[DIV:%.*]] = udiv i64 4088, [[SZ]] +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32 +; CHECK-NEXT: ret i32 [[CONV]] +; +entry: + %cmp = icmp ugt i64 4088, %sz + br i1 %cmp, label %cond.true, label %cond.end + +cond.true: ; preds = %entry + %div = udiv i64 4088, %sz + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %div, %cond.true ], [ 1, %entry ] + %conv = trunc i64 %cond to i32 + ret i32 %conv +} + +; Same as @udiv_1, but with the condition switched. +define i32 @udiv_2(i64 %sz) { +; CHECK-LABEL: @udiv_2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SZ:%.*]], 4088 +; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] +; CHECK: cond.true: +; CHECK-NEXT: [[DIV:%.*]] = udiv i64 4088, [[SZ]] +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32 +; CHECK-NEXT: ret i32 [[CONV]] +; +entry: + %cmp = icmp ugt i64 %sz, 4088 + br i1 %cmp, label %cond.true, label %cond.end + +cond.true: ; preds = %entry + %div = udiv i64 4088, %sz + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %div, %cond.true ], [ 1, %entry ] + %conv = trunc i64 %cond to i32 + ret i32 %conv +}