1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00
llvm-mirror/test/Transforms/LoopUnroll/unroll-cost-symbolic-execute.ll
Philip Reames 88bae72814 [unroll] Use value domain for symbolic execution based cost model
The current full unroll cost model does a symbolic evaluation of the loop up to a fixed limit. That symbolic evaluation currently simplifies to constants, but we can generalize to arbitrary Values using the InstructionSimplify infrastructure at very low cost.

By itself, this enables some simplifications, but it's mainly useful when combined with the branch simplification over in D102928.

Differential Revision: https://reviews.llvm.org/D102934
2021-05-26 08:41:25 -07:00

657 lines
28 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -loop-unroll -S -unroll-threshold=120 -unroll-max-iteration-count-to-analyze=100 < %s | FileCheck %s
; TODO: None of the if.false blocks are reachable, it would be nice if
; the output of unrolling made this obvious and didn't rely on other
; passes to cleanup code the cost model already knew was dead.
@G = global i32 0
; Symbolic simplification can prove the value of %zext on first
; iteration, and can prove that it's loop invariant on the second
define i32 @test_symbolic_simplify(i32 %limit) {
; CHECK-LABEL: @test_symbolic_simplify(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: store i32 -1, i32* @G, align 4
; CHECK-NEXT: [[CMP_1:%.*]] = icmp eq i32 0, [[LIMIT:%.*]]
; CHECK-NEXT: [[ZEXT_1:%.*]] = sext i1 [[CMP_1]] to i32
; CHECK-NEXT: store i32 [[ZEXT_1]], i32* @G, align 4
; CHECK-NEXT: [[CMP_2:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_2:%.*]] = sext i1 [[CMP_2]] to i32
; CHECK-NEXT: store i32 [[ZEXT_2]], i32* @G, align 4
; CHECK-NEXT: [[CMP_3:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_3:%.*]] = sext i1 [[CMP_3]] to i32
; CHECK-NEXT: store i32 [[ZEXT_3]], i32* @G, align 4
; CHECK-NEXT: [[CMP_4:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_4:%.*]] = sext i1 [[CMP_4]] to i32
; CHECK-NEXT: store i32 [[ZEXT_4]], i32* @G, align 4
; CHECK-NEXT: [[CMP_5:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_5:%.*]] = sext i1 [[CMP_5]] to i32
; CHECK-NEXT: store i32 [[ZEXT_5]], i32* @G, align 4
; CHECK-NEXT: [[CMP_6:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_6:%.*]] = sext i1 [[CMP_6]] to i32
; CHECK-NEXT: store i32 [[ZEXT_6]], i32* @G, align 4
; CHECK-NEXT: [[CMP_7:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_7:%.*]] = sext i1 [[CMP_7]] to i32
; CHECK-NEXT: store i32 [[ZEXT_7]], i32* @G, align 4
; CHECK-NEXT: [[CMP_8:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_8:%.*]] = sext i1 [[CMP_8]] to i32
; CHECK-NEXT: store i32 [[ZEXT_8]], i32* @G, align 4
; CHECK-NEXT: [[CMP_9:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_9:%.*]] = sext i1 [[CMP_9]] to i32
; CHECK-NEXT: store i32 [[ZEXT_9]], i32* @G, align 4
; CHECK-NEXT: [[CMP_10:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_10:%.*]] = sext i1 [[CMP_10]] to i32
; CHECK-NEXT: store i32 [[ZEXT_10]], i32* @G, align 4
; CHECK-NEXT: [[CMP_11:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_11:%.*]] = sext i1 [[CMP_11]] to i32
; CHECK-NEXT: store i32 [[ZEXT_11]], i32* @G, align 4
; CHECK-NEXT: [[CMP_12:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_12:%.*]] = sext i1 [[CMP_12]] to i32
; CHECK-NEXT: store i32 [[ZEXT_12]], i32* @G, align 4
; CHECK-NEXT: [[CMP_13:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_13:%.*]] = sext i1 [[CMP_13]] to i32
; CHECK-NEXT: store i32 [[ZEXT_13]], i32* @G, align 4
; CHECK-NEXT: [[CMP_14:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_14:%.*]] = sext i1 [[CMP_14]] to i32
; CHECK-NEXT: store i32 [[ZEXT_14]], i32* @G, align 4
; CHECK-NEXT: [[CMP_15:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_15:%.*]] = sext i1 [[CMP_15]] to i32
; CHECK-NEXT: store i32 [[ZEXT_15]], i32* @G, align 4
; CHECK-NEXT: [[CMP_16:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_16:%.*]] = sext i1 [[CMP_16]] to i32
; CHECK-NEXT: store i32 [[ZEXT_16]], i32* @G, align 4
; CHECK-NEXT: [[CMP_17:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_17:%.*]] = sext i1 [[CMP_17]] to i32
; CHECK-NEXT: store i32 [[ZEXT_17]], i32* @G, align 4
; CHECK-NEXT: [[CMP_18:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_18:%.*]] = sext i1 [[CMP_18]] to i32
; CHECK-NEXT: store i32 [[ZEXT_18]], i32* @G, align 4
; CHECK-NEXT: [[CMP_19:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_19:%.*]] = sext i1 [[CMP_19]] to i32
; CHECK-NEXT: store i32 [[ZEXT_19]], i32* @G, align 4
; CHECK-NEXT: [[CMP_20:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_20:%.*]] = sext i1 [[CMP_20]] to i32
; CHECK-NEXT: store i32 [[ZEXT_20]], i32* @G, align 4
; CHECK-NEXT: [[CMP_21:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_21:%.*]] = sext i1 [[CMP_21]] to i32
; CHECK-NEXT: store i32 [[ZEXT_21]], i32* @G, align 4
; CHECK-NEXT: [[CMP_22:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_22:%.*]] = sext i1 [[CMP_22]] to i32
; CHECK-NEXT: store i32 [[ZEXT_22]], i32* @G, align 4
; CHECK-NEXT: [[CMP_23:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_23:%.*]] = sext i1 [[CMP_23]] to i32
; CHECK-NEXT: store i32 [[ZEXT_23]], i32* @G, align 4
; CHECK-NEXT: [[CMP_24:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_24:%.*]] = sext i1 [[CMP_24]] to i32
; CHECK-NEXT: store i32 [[ZEXT_24]], i32* @G, align 4
; CHECK-NEXT: [[CMP_25:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_25:%.*]] = sext i1 [[CMP_25]] to i32
; CHECK-NEXT: store i32 [[ZEXT_25]], i32* @G, align 4
; CHECK-NEXT: [[CMP_26:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_26:%.*]] = sext i1 [[CMP_26]] to i32
; CHECK-NEXT: store i32 [[ZEXT_26]], i32* @G, align 4
; CHECK-NEXT: [[CMP_27:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_27:%.*]] = sext i1 [[CMP_27]] to i32
; CHECK-NEXT: store i32 [[ZEXT_27]], i32* @G, align 4
; CHECK-NEXT: [[CMP_28:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_28:%.*]] = sext i1 [[CMP_28]] to i32
; CHECK-NEXT: store i32 [[ZEXT_28]], i32* @G, align 4
; CHECK-NEXT: [[CMP_29:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_29:%.*]] = sext i1 [[CMP_29]] to i32
; CHECK-NEXT: store i32 [[ZEXT_29]], i32* @G, align 4
; CHECK-NEXT: [[CMP_30:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_30:%.*]] = sext i1 [[CMP_30]] to i32
; CHECK-NEXT: store i32 [[ZEXT_30]], i32* @G, align 4
; CHECK-NEXT: [[CMP_31:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_31:%.*]] = sext i1 [[CMP_31]] to i32
; CHECK-NEXT: store i32 [[ZEXT_31]], i32* @G, align 4
; CHECK-NEXT: [[CMP_32:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_32:%.*]] = sext i1 [[CMP_32]] to i32
; CHECK-NEXT: store i32 [[ZEXT_32]], i32* @G, align 4
; CHECK-NEXT: [[CMP_33:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_33:%.*]] = sext i1 [[CMP_33]] to i32
; CHECK-NEXT: store i32 [[ZEXT_33]], i32* @G, align 4
; CHECK-NEXT: [[CMP_34:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_34:%.*]] = sext i1 [[CMP_34]] to i32
; CHECK-NEXT: store i32 [[ZEXT_34]], i32* @G, align 4
; CHECK-NEXT: [[CMP_35:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_35:%.*]] = sext i1 [[CMP_35]] to i32
; CHECK-NEXT: store i32 [[ZEXT_35]], i32* @G, align 4
; CHECK-NEXT: [[CMP_36:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_36:%.*]] = sext i1 [[CMP_36]] to i32
; CHECK-NEXT: store i32 [[ZEXT_36]], i32* @G, align 4
; CHECK-NEXT: [[CMP_37:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_37:%.*]] = sext i1 [[CMP_37]] to i32
; CHECK-NEXT: store i32 [[ZEXT_37]], i32* @G, align 4
; CHECK-NEXT: [[CMP_38:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_38:%.*]] = sext i1 [[CMP_38]] to i32
; CHECK-NEXT: store i32 [[ZEXT_38]], i32* @G, align 4
; CHECK-NEXT: [[CMP_39:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_39:%.*]] = sext i1 [[CMP_39]] to i32
; CHECK-NEXT: store i32 [[ZEXT_39]], i32* @G, align 4
; CHECK-NEXT: [[CMP_40:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_40:%.*]] = sext i1 [[CMP_40]] to i32
; CHECK-NEXT: store i32 [[ZEXT_40]], i32* @G, align 4
; CHECK-NEXT: [[CMP_41:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_41:%.*]] = sext i1 [[CMP_41]] to i32
; CHECK-NEXT: store i32 [[ZEXT_41]], i32* @G, align 4
; CHECK-NEXT: [[CMP_42:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_42:%.*]] = sext i1 [[CMP_42]] to i32
; CHECK-NEXT: store i32 [[ZEXT_42]], i32* @G, align 4
; CHECK-NEXT: [[CMP_43:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_43:%.*]] = sext i1 [[CMP_43]] to i32
; CHECK-NEXT: store i32 [[ZEXT_43]], i32* @G, align 4
; CHECK-NEXT: [[CMP_44:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_44:%.*]] = sext i1 [[CMP_44]] to i32
; CHECK-NEXT: store i32 [[ZEXT_44]], i32* @G, align 4
; CHECK-NEXT: [[CMP_45:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_45:%.*]] = sext i1 [[CMP_45]] to i32
; CHECK-NEXT: store i32 [[ZEXT_45]], i32* @G, align 4
; CHECK-NEXT: [[CMP_46:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_46:%.*]] = sext i1 [[CMP_46]] to i32
; CHECK-NEXT: store i32 [[ZEXT_46]], i32* @G, align 4
; CHECK-NEXT: [[CMP_47:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_47:%.*]] = sext i1 [[CMP_47]] to i32
; CHECK-NEXT: store i32 [[ZEXT_47]], i32* @G, align 4
; CHECK-NEXT: [[CMP_48:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_48:%.*]] = sext i1 [[CMP_48]] to i32
; CHECK-NEXT: store i32 [[ZEXT_48]], i32* @G, align 4
; CHECK-NEXT: [[CMP_49:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_49:%.*]] = sext i1 [[CMP_49]] to i32
; CHECK-NEXT: store i32 [[ZEXT_49]], i32* @G, align 4
; CHECK-NEXT: [[CMP_50:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_50:%.*]] = sext i1 [[CMP_50]] to i32
; CHECK-NEXT: store i32 [[ZEXT_50]], i32* @G, align 4
; CHECK-NEXT: [[CMP_51:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_51:%.*]] = sext i1 [[CMP_51]] to i32
; CHECK-NEXT: store i32 [[ZEXT_51]], i32* @G, align 4
; CHECK-NEXT: [[CMP_52:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_52:%.*]] = sext i1 [[CMP_52]] to i32
; CHECK-NEXT: store i32 [[ZEXT_52]], i32* @G, align 4
; CHECK-NEXT: [[CMP_53:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_53:%.*]] = sext i1 [[CMP_53]] to i32
; CHECK-NEXT: store i32 [[ZEXT_53]], i32* @G, align 4
; CHECK-NEXT: [[CMP_54:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_54:%.*]] = sext i1 [[CMP_54]] to i32
; CHECK-NEXT: store i32 [[ZEXT_54]], i32* @G, align 4
; CHECK-NEXT: [[CMP_55:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_55:%.*]] = sext i1 [[CMP_55]] to i32
; CHECK-NEXT: store i32 [[ZEXT_55]], i32* @G, align 4
; CHECK-NEXT: [[CMP_56:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_56:%.*]] = sext i1 [[CMP_56]] to i32
; CHECK-NEXT: store i32 [[ZEXT_56]], i32* @G, align 4
; CHECK-NEXT: [[CMP_57:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_57:%.*]] = sext i1 [[CMP_57]] to i32
; CHECK-NEXT: store i32 [[ZEXT_57]], i32* @G, align 4
; CHECK-NEXT: [[CMP_58:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_58:%.*]] = sext i1 [[CMP_58]] to i32
; CHECK-NEXT: store i32 [[ZEXT_58]], i32* @G, align 4
; CHECK-NEXT: [[CMP_59:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_59:%.*]] = sext i1 [[CMP_59]] to i32
; CHECK-NEXT: store i32 [[ZEXT_59]], i32* @G, align 4
; CHECK-NEXT: [[CMP_60:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_60:%.*]] = sext i1 [[CMP_60]] to i32
; CHECK-NEXT: store i32 [[ZEXT_60]], i32* @G, align 4
; CHECK-NEXT: [[CMP_61:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_61:%.*]] = sext i1 [[CMP_61]] to i32
; CHECK-NEXT: store i32 [[ZEXT_61]], i32* @G, align 4
; CHECK-NEXT: [[CMP_62:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_62:%.*]] = sext i1 [[CMP_62]] to i32
; CHECK-NEXT: store i32 [[ZEXT_62]], i32* @G, align 4
; CHECK-NEXT: [[CMP_63:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_63:%.*]] = sext i1 [[CMP_63]] to i32
; CHECK-NEXT: store i32 [[ZEXT_63]], i32* @G, align 4
; CHECK-NEXT: [[CMP_64:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_64:%.*]] = sext i1 [[CMP_64]] to i32
; CHECK-NEXT: store i32 [[ZEXT_64]], i32* @G, align 4
; CHECK-NEXT: [[CMP_65:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_65:%.*]] = sext i1 [[CMP_65]] to i32
; CHECK-NEXT: store i32 [[ZEXT_65]], i32* @G, align 4
; CHECK-NEXT: [[CMP_66:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_66:%.*]] = sext i1 [[CMP_66]] to i32
; CHECK-NEXT: store i32 [[ZEXT_66]], i32* @G, align 4
; CHECK-NEXT: [[CMP_67:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_67:%.*]] = sext i1 [[CMP_67]] to i32
; CHECK-NEXT: store i32 [[ZEXT_67]], i32* @G, align 4
; CHECK-NEXT: [[CMP_68:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_68:%.*]] = sext i1 [[CMP_68]] to i32
; CHECK-NEXT: store i32 [[ZEXT_68]], i32* @G, align 4
; CHECK-NEXT: [[CMP_69:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_69:%.*]] = sext i1 [[CMP_69]] to i32
; CHECK-NEXT: store i32 [[ZEXT_69]], i32* @G, align 4
; CHECK-NEXT: [[CMP_70:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_70:%.*]] = sext i1 [[CMP_70]] to i32
; CHECK-NEXT: store i32 [[ZEXT_70]], i32* @G, align 4
; CHECK-NEXT: [[CMP_71:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_71:%.*]] = sext i1 [[CMP_71]] to i32
; CHECK-NEXT: store i32 [[ZEXT_71]], i32* @G, align 4
; CHECK-NEXT: [[CMP_72:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_72:%.*]] = sext i1 [[CMP_72]] to i32
; CHECK-NEXT: store i32 [[ZEXT_72]], i32* @G, align 4
; CHECK-NEXT: [[CMP_73:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_73:%.*]] = sext i1 [[CMP_73]] to i32
; CHECK-NEXT: store i32 [[ZEXT_73]], i32* @G, align 4
; CHECK-NEXT: [[CMP_74:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_74:%.*]] = sext i1 [[CMP_74]] to i32
; CHECK-NEXT: store i32 [[ZEXT_74]], i32* @G, align 4
; CHECK-NEXT: [[CMP_75:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_75:%.*]] = sext i1 [[CMP_75]] to i32
; CHECK-NEXT: store i32 [[ZEXT_75]], i32* @G, align 4
; CHECK-NEXT: [[CMP_76:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_76:%.*]] = sext i1 [[CMP_76]] to i32
; CHECK-NEXT: store i32 [[ZEXT_76]], i32* @G, align 4
; CHECK-NEXT: [[CMP_77:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_77:%.*]] = sext i1 [[CMP_77]] to i32
; CHECK-NEXT: store i32 [[ZEXT_77]], i32* @G, align 4
; CHECK-NEXT: [[CMP_78:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_78:%.*]] = sext i1 [[CMP_78]] to i32
; CHECK-NEXT: store i32 [[ZEXT_78]], i32* @G, align 4
; CHECK-NEXT: [[CMP_79:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_79:%.*]] = sext i1 [[CMP_79]] to i32
; CHECK-NEXT: store i32 [[ZEXT_79]], i32* @G, align 4
; CHECK-NEXT: [[CMP_80:%.*]] = icmp eq i32 0, [[LIMIT]]
; CHECK-NEXT: [[ZEXT_80:%.*]] = sext i1 [[CMP_80]] to i32
; CHECK-NEXT: store i32 [[ZEXT_80]], i32* @G, align 4
; CHECK-NEXT: ret i32 [[ZEXT_80]]
;
entry:
br label %loop
loop: ; preds = %backedge, %entry
%phi = phi i32 [ 0, %entry ], [ %limit, %loop ]
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
%sub = sub i32 %limit, %phi
%cmp = icmp eq i32 %sub, %limit
%zext = sext i1 %cmp to i32
store i32 %zext, i32* @G
%iv.next = add i32 %iv, 1
%loop.cond = icmp ne i32 %iv, 80
br i1 %loop.cond, label %loop, label %done
done: ; preds = %backedge
ret i32 %zext
}
; Use symbolic value facts to prune unreachable (expensive) paths
; through the loop.
define i32 @test_symbolic_path(i32 %limit) {
; CHECK-LABEL: @test_symbolic_path(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 true, label [[BACKEDGE:%.*]], label [[IF_FALSE:%.*]]
; CHECK: if.false:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: br i1 true, label [[BACKEDGE_1:%.*]], label [[IF_FALSE_1:%.*]]
; CHECK: if.false.1:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE_1]]
; CHECK: backedge.1:
; CHECK-NEXT: br i1 true, label [[BACKEDGE_2:%.*]], label [[IF_FALSE_2:%.*]]
; CHECK: if.false.2:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE_2]]
; CHECK: backedge.2:
; CHECK-NEXT: br i1 true, label [[BACKEDGE_3:%.*]], label [[IF_FALSE_3:%.*]]
; CHECK: if.false.3:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE_3]]
; CHECK: backedge.3:
; CHECK-NEXT: br i1 true, label [[BACKEDGE_4:%.*]], label [[IF_FALSE_4:%.*]]
; CHECK: if.false.4:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE_4]]
; CHECK: backedge.4:
; CHECK-NEXT: br i1 true, label [[BACKEDGE_5:%.*]], label [[IF_FALSE_5:%.*]]
; CHECK: if.false.5:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE_5]]
; CHECK: backedge.5:
; CHECK-NEXT: br i1 true, label [[BACKEDGE_6:%.*]], label [[IF_FALSE_6:%.*]]
; CHECK: if.false.6:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE_6]]
; CHECK: backedge.6:
; CHECK-NEXT: br i1 true, label [[BACKEDGE_7:%.*]], label [[IF_FALSE_7:%.*]]
; CHECK: if.false.7:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE_7]]
; CHECK: backedge.7:
; CHECK-NEXT: br i1 true, label [[BACKEDGE_8:%.*]], label [[IF_FALSE_8:%.*]]
; CHECK: if.false.8:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE_8]]
; CHECK: backedge.8:
; CHECK-NEXT: ret i32 0
;
entry:
br label %loop
loop: ; preds = %backedge, %entry
%sum = phi i32 [ 0, %entry ], [ %sum.next, %backedge ]
%iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
%sub = sub i32 %limit, %sum
%is.positive = icmp eq i32 %sub, %limit
br i1 %is.positive, label %backedge, label %if.false
if.false: ; preds = %loop
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
br label %backedge
backedge: ; preds = %if.false, %loop
%hidden_zero = sub i32 %limit, %sub
%sum.next = add i32 %sum, %hidden_zero
%iv.next = add i32 %iv, 1
%loop.cond = icmp ne i32 %iv, 8
br i1 %loop.cond, label %loop, label %done
done: ; preds = %backedge
%sum.next.lcssa = phi i32 [ %sum.next, %backedge ]
ret i32 %sum.next.lcssa
}
; A test to show the ability to simplify branches (even without general
; symbolic execution of the loop beyond constants) is still useful.
define i32 @test_dom_condition(i32 %limit) {
; CHECK-LABEL: @test_dom_condition(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOOP_GUARD:%.*]] = icmp sge i32 [[LIMIT:%.*]], 0
; CHECK-NEXT: br i1 [[LOOP_GUARD]], label [[LOOP_PREHEADER:%.*]], label [[FAILURE:%.*]]
; CHECK: loop.preheader:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[SUM]]
; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sle i32 [[SUB]], [[LIMIT]]
; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE]], label [[IF_FALSE:%.*]]
; CHECK: if.false:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[SUB]]
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[IV]], 8
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]]
; CHECK: done:
; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]
; CHECK: failure:
; CHECK-NEXT: unreachable
;
entry:
%loop_guard = icmp sge i32 %limit, 0
br i1 %loop_guard, label %loop, label %failure
loop: ; preds = %backedge, %entry
%sum = phi i32 [ 0, %entry ], [ %sum.next, %backedge ]
%iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
%sub = sub i32 0, %sum
%is.positive = icmp sle i32 %sub, %limit
br i1 %is.positive, label %backedge, label %if.false
if.false: ; preds = %loop
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
br label %backedge
backedge: ; preds = %if.false, %loop
%sum.next = add i32 %sum, %sub
%iv.next = add i32 %iv, 1
%loop.cond = icmp ne i32 %iv, 8
br i1 %loop.cond, label %loop, label %done
done: ; preds = %backedge
%sum.next.lcssa = phi i32 [ %sum.next, %backedge ]
ret i32 %sum.next.lcssa
failure:
unreachable
}
; We can symbolically evaluate %sub to %limit on first iteration, and
; to zero on all future iterations.
define i32 @test_both(i32 %limit) {
; CHECK-LABEL: @test_both(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOOP_GUARD:%.*]] = icmp sge i32 [[LIMIT:%.*]], 0
; CHECK-NEXT: br i1 [[LOOP_GUARD]], label [[LOOP_PREHEADER:%.*]], label [[FAILURE:%.*]]
; CHECK: loop.preheader:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[LIMIT]], [[SUM]]
; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sge i32 [[SUB]], 0
; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE]], label [[IF_FALSE:%.*]]
; CHECK: if.false:
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[SUB]]
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[IV]], 8
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]]
; CHECK: done:
; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]
; CHECK: failure:
; CHECK-NEXT: unreachable
;
entry:
%loop_guard = icmp sge i32 %limit, 0
br i1 %loop_guard, label %loop, label %failure
loop: ; preds = %backedge, %entry
%sum = phi i32 [ 0, %entry ], [ %sum.next, %backedge ]
%iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
%sub = sub i32 %limit, %sum
%is.positive = icmp sge i32 %sub, 0
br i1 %is.positive, label %backedge, label %if.false
if.false: ; preds = %loop
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
call void @foo()
br label %backedge
backedge: ; preds = %if.false, %loop
%sum.next = add i32 %sum, %sub
%iv.next = add i32 %iv, 1
%loop.cond = icmp ne i32 %iv, 8
br i1 %loop.cond, label %loop, label %done
done: ; preds = %backedge
%sum.next.lcssa = phi i32 [ %sum.next, %backedge ]
ret i32 %sum.next.lcssa
failure:
unreachable
}
declare void @foo()