[llvm] 081efa7 - [SCCP] Add a few constantexpr,undef tests for cond propagation

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 25 14:29:54 PDT 2020


Author: Florian Hahn
Date: 2020-03-25T21:28:35Z
New Revision: 081efa7dd0846c64c8359ba34cdf6a0a5aad8c80

URL: https://github.com/llvm/llvm-project/commit/081efa7dd0846c64c8359ba34cdf6a0a5aad8c80
DIFF: https://github.com/llvm/llvm-project/commit/081efa7dd0846c64c8359ba34cdf6a0a5aad8c80.diff

LOG: [SCCP] Add a few constantexpr,undef tests for cond propagation

Added: 
    llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll

Modified: 
    llvm/test/Transforms/SCCP/conditions-ranges.ll

Removed: 
    


################################################################################
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 000000000000..4f2f66f26402
--- /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 345e521d35c7..b722854abeb5 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
+}
+
+
+ at A = global i32 17
+ at 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
+}


        


More information about the llvm-commits mailing list