| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -passes=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, ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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]], ptr @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, ptr @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() |