forked from OSchip/llvm-project
[LICM][SCCP] Regenerate test checks (NFC)
This commit is contained in:
parent
f719dff043
commit
4294657bd5
|
@ -1,3 +1,4 @@
|
||||||
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||||
; RUN: opt < %s -licm -S | FileCheck %s
|
; RUN: opt < %s -licm -S | FileCheck %s
|
||||||
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
|
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
|
||||||
|
|
||||||
|
@ -5,6 +6,27 @@ target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
|
||||||
target triple = "i386-pc-windows-msvc18.0.0"
|
target triple = "i386-pc-windows-msvc18.0.0"
|
||||||
|
|
||||||
define void @test1(i32* %s, i1 %b) personality i32 (...)* @__CxxFrameHandler3 {
|
define void @test1(i32* %s, i1 %b) personality i32 (...)* @__CxxFrameHandler3 {
|
||||||
|
; CHECK-LABEL: @test1(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @pure_computation()
|
||||||
|
; CHECK-NEXT: br label [[WHILE_COND:%.*]]
|
||||||
|
; CHECK: while.cond:
|
||||||
|
; CHECK-NEXT: br i1 [[B:%.*]], label [[TRY_CONT_LOOPEXIT:%.*]], label [[WHILE_BODY:%.*]]
|
||||||
|
; CHECK: while.body:
|
||||||
|
; CHECK-NEXT: invoke void @may_throw()
|
||||||
|
; CHECK-NEXT: to label [[WHILE_COND]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||||
|
; CHECK: catch.dispatch:
|
||||||
|
; CHECK-NEXT: [[DOTLCSSA1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY]] ]
|
||||||
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %catch] unwind to caller
|
||||||
|
; CHECK: catch:
|
||||||
|
; CHECK-NEXT: [[CP:%.*]] = catchpad within [[CS]] [i8* null, i32 64, i8* null]
|
||||||
|
; CHECK-NEXT: store i32 [[DOTLCSSA1]], i32* [[S:%.*]], align 4
|
||||||
|
; CHECK-NEXT: catchret from [[CP]] to label [[TRY_CONT:%.*]]
|
||||||
|
; CHECK: try.cont.loopexit:
|
||||||
|
; CHECK-NEXT: br label [[TRY_CONT]]
|
||||||
|
; CHECK: try.cont:
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %while.cond
|
br label %while.cond
|
||||||
|
|
||||||
|
@ -29,11 +51,23 @@ try.cont: ; preds = %catch, %while.cond
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK-LABEL: define void @test1(
|
|
||||||
; CHECK: %[[CALL:.*]] = call i32 @pure_computation()
|
|
||||||
; CHECK: phi i32 [ %[[CALL]]
|
|
||||||
|
|
||||||
define void @test2(i32* %s, i1 %b) personality i32 (...)* @__CxxFrameHandler3 {
|
define void @test2(i32* %s, i1 %b) personality i32 (...)* @__CxxFrameHandler3 {
|
||||||
|
; CHECK-LABEL: @test2(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: br label [[WHILE_COND:%.*]]
|
||||||
|
; CHECK: while.cond:
|
||||||
|
; CHECK-NEXT: br i1 [[B:%.*]], label [[TRY_CONT:%.*]], label [[WHILE_BODY:%.*]]
|
||||||
|
; CHECK: while.body:
|
||||||
|
; CHECK-NEXT: invoke void @may_throw()
|
||||||
|
; CHECK-NEXT: to label [[WHILE_COND]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||||
|
; CHECK: catch.dispatch:
|
||||||
|
; CHECK-NEXT: [[CP:%.*]] = cleanuppad within none []
|
||||||
|
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @pure_computation() [ "funclet"(token [[CP]]) ]
|
||||||
|
; CHECK-NEXT: store i32 [[TMP0]], i32* [[S:%.*]], align 4
|
||||||
|
; CHECK-NEXT: cleanupret from [[CP]] unwind to caller
|
||||||
|
; CHECK: try.cont:
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %while.cond
|
br label %while.cond
|
||||||
|
|
||||||
|
@ -55,13 +89,38 @@ try.cont: ; preds = %catch, %while.cond
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK-LABEL: define void @test2(
|
|
||||||
; CHECK: %[[CP:.*]] = cleanuppad within none []
|
|
||||||
; CHECK-NEXT: %[[CALL:.*]] = call i32 @pure_computation() [ "funclet"(token %[[CP]]) ]
|
|
||||||
; CHECK-NEXT: store i32 %[[CALL]], i32* %s
|
|
||||||
; CHECK-NEXT: cleanupret from %[[CP]] unwind to caller
|
|
||||||
|
|
||||||
define void @test3(i1 %a, i1 %b, i1 %c) personality i32 (...)* @__CxxFrameHandler3 {
|
define void @test3(i1 %a, i1 %b, i1 %c) personality i32 (...)* @__CxxFrameHandler3 {
|
||||||
|
; CHECK-LABEL: @test3(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: [[DOTFRAME:%.*]] = alloca i8, align 4
|
||||||
|
; CHECK-NEXT: [[DOTFRAME2:%.*]] = alloca i8, align 4
|
||||||
|
; CHECK-NEXT: [[BC:%.*]] = bitcast i8* [[DOTFRAME]] to i32*
|
||||||
|
; CHECK-NEXT: [[BC2:%.*]] = bitcast i8* [[DOTFRAME2]] to i32*
|
||||||
|
; CHECK-NEXT: br i1 [[A:%.*]], label [[TRY_SUCCESS_OR_CAUGHT:%.*]], label [[FORBODY_PREHEADER:%.*]]
|
||||||
|
; CHECK: forbody.preheader:
|
||||||
|
; CHECK-NEXT: store i32 1, i32* [[BC]], align 4
|
||||||
|
; CHECK-NEXT: store i32 2, i32* [[BC2]], align 4
|
||||||
|
; CHECK-NEXT: br label [[FORBODY:%.*]]
|
||||||
|
; CHECK: catch.object.Throwable:
|
||||||
|
; CHECK-NEXT: [[CP:%.*]] = catchpad within [[CS:%.*]] [i8* null, i32 64, i8* null]
|
||||||
|
; CHECK-NEXT: unreachable
|
||||||
|
; CHECK: try.success.or.caught.loopexit:
|
||||||
|
; CHECK-NEXT: br label [[TRY_SUCCESS_OR_CAUGHT]]
|
||||||
|
; CHECK: try.success.or.caught:
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
; CHECK: postinvoke:
|
||||||
|
; CHECK-NEXT: br i1 [[B:%.*]], label [[ELSE:%.*]], label [[FORCOND_BACKEDGE:%.*]]
|
||||||
|
; CHECK: forcond.backedge:
|
||||||
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[TRY_SUCCESS_OR_CAUGHT_LOOPEXIT:%.*]], label [[FORBODY]]
|
||||||
|
; CHECK: catch.dispatch:
|
||||||
|
; CHECK-NEXT: [[CS]] = catchswitch within none [label %catch.object.Throwable] unwind to caller
|
||||||
|
; CHECK: forbody:
|
||||||
|
; CHECK-NEXT: invoke void @may_throw()
|
||||||
|
; CHECK-NEXT: to label [[POSTINVOKE:%.*]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||||
|
; CHECK: else:
|
||||||
|
; CHECK-NEXT: invoke void @may_throw()
|
||||||
|
; CHECK-NEXT: to label [[FORCOND_BACKEDGE]] unwind label [[CATCH_DISPATCH]]
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
%.frame = alloca i8, align 4
|
%.frame = alloca i8, align 4
|
||||||
%.frame2 = alloca i8, align 4
|
%.frame2 = alloca i8, align 4
|
||||||
|
@ -96,13 +155,6 @@ else: ; preds = %postinvoke
|
||||||
to label %forcond.backedge unwind label %catch.dispatch
|
to label %forcond.backedge unwind label %catch.dispatch
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK-LABEL: define void @test3(
|
|
||||||
; CHECK-LABEL: forbody.preheader:
|
|
||||||
; CHECK: store i32 1, i32* %bc, align 4
|
|
||||||
; CHECK: store i32 2, i32* %bc2, align 4
|
|
||||||
; CHECK: catchswitch within none
|
|
||||||
; CHECK-LABEL: forbody:
|
|
||||||
|
|
||||||
declare void @may_throw()
|
declare void @may_throw()
|
||||||
|
|
||||||
declare i32 @pure_computation() nounwind argmemonly readonly
|
declare i32 @pure_computation() nounwind argmemonly readonly
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||||
; RUN: opt < %s -basic-aa -licm -S | FileCheck %s
|
; RUN: opt < %s -basic-aa -licm -S | FileCheck %s
|
||||||
; RUN: opt < %s -debugify -basic-aa -licm -S | FileCheck %s -check-prefix=DEBUGIFY
|
; RUN: opt < %s -debugify -basic-aa -licm -S | FileCheck %s -check-prefix=DEBUGIFY
|
||||||
; RUN: opt < %s -basic-aa -licm -S -enable-mssa-loop-dependency=true -verify-memoryssa | FileCheck %s
|
; RUN: opt < %s -basic-aa -licm -S -enable-mssa-loop-dependency=true -verify-memoryssa | FileCheck %s
|
||||||
|
@ -9,6 +10,14 @@ declare void @foo()
|
||||||
|
|
||||||
; Sink readonly function.
|
; Sink readonly function.
|
||||||
define i32 @test1(i8* %P) {
|
define i32 @test1(i8* %P) {
|
||||||
|
; CHECK-LABEL: @test1(
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[OUT:%.*]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[A_LE:%.*]] = call i32 @strlen(i8* [[P:%.*]]) #[[ATTR3:[0-9]+]]
|
||||||
|
; CHECK-NEXT: ret i32 [[A_LE]]
|
||||||
|
;
|
||||||
br label %Loop
|
br label %Loop
|
||||||
|
|
||||||
Loop: ; preds = %Loop, %0
|
Loop: ; preds = %Loop, %0
|
||||||
|
@ -17,16 +26,21 @@ Loop: ; preds = %Loop, %0
|
||||||
|
|
||||||
Out: ; preds = %Loop
|
Out: ; preds = %Loop
|
||||||
ret i32 %A
|
ret i32 %A
|
||||||
; CHECK-LABEL: @test1(
|
|
||||||
; CHECK: Out:
|
|
||||||
; CHECK-NEXT: call i32 @strlen
|
|
||||||
; CHECK-NEXT: ret i32 %A
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare double @sin(double) readnone nounwind
|
declare double @sin(double) readnone nounwind
|
||||||
|
|
||||||
; Sink readnone function out of loop with unknown memory behavior.
|
; Sink readnone function out of loop with unknown memory behavior.
|
||||||
define double @test2(double %X) {
|
define double @test2(double %X) {
|
||||||
|
; CHECK-LABEL: @test2(
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: call void @foo()
|
||||||
|
; CHECK-NEXT: br i1 true, label [[LOOP]], label [[OUT:%.*]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[A_LE:%.*]] = call double @sin(double [[X:%.*]]) #[[ATTR4:[0-9]+]]
|
||||||
|
; CHECK-NEXT: ret double [[A_LE]]
|
||||||
|
;
|
||||||
br label %Loop
|
br label %Loop
|
||||||
|
|
||||||
Loop: ; preds = %Loop, %0
|
Loop: ; preds = %Loop, %0
|
||||||
|
@ -36,14 +50,19 @@ Loop: ; preds = %Loop, %0
|
||||||
|
|
||||||
Out: ; preds = %Loop
|
Out: ; preds = %Loop
|
||||||
ret double %A
|
ret double %A
|
||||||
; CHECK-LABEL: @test2(
|
|
||||||
; CHECK: Out:
|
|
||||||
; CHECK-NEXT: call double @sin
|
|
||||||
; CHECK-NEXT: ret double %A
|
|
||||||
}
|
}
|
||||||
|
|
||||||
; FIXME: Should be able to sink this case
|
; FIXME: Should be able to sink this case
|
||||||
define i32 @test2b(i32 %X) {
|
define i32 @test2b(i32 %X) {
|
||||||
|
; CHECK-LABEL: @test2b(
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: call void @foo()
|
||||||
|
; CHECK-NEXT: br i1 true, label [[LOOP]], label [[OUT:%.*]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[A_LE:%.*]] = sdiv i32 10, [[X:%.*]]
|
||||||
|
; CHECK-NEXT: ret i32 [[A_LE]]
|
||||||
|
;
|
||||||
br label %Loop
|
br label %Loop
|
||||||
|
|
||||||
Loop: ; preds = %Loop, %0
|
Loop: ; preds = %Loop, %0
|
||||||
|
@ -53,13 +72,18 @@ Loop: ; preds = %Loop, %0
|
||||||
|
|
||||||
Out: ; preds = %Loop
|
Out: ; preds = %Loop
|
||||||
ret i32 %A
|
ret i32 %A
|
||||||
; CHECK-LABEL: @test2b(
|
|
||||||
; CHECK: Out:
|
|
||||||
; CHECK-NEXT: sdiv
|
|
||||||
; CHECK-NEXT: ret i32 %A
|
|
||||||
}
|
}
|
||||||
|
|
||||||
define double @test2c(double* %P) {
|
define double @test2c(double* %P) {
|
||||||
|
; CHECK-LABEL: @test2c(
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: call void @foo()
|
||||||
|
; CHECK-NEXT: br i1 true, label [[LOOP]], label [[OUT:%.*]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[A_LE:%.*]] = load double, double* [[P:%.*]], align 8, !invariant.load !0
|
||||||
|
; CHECK-NEXT: ret double [[A_LE]]
|
||||||
|
;
|
||||||
br label %Loop
|
br label %Loop
|
||||||
|
|
||||||
Loop: ; preds = %Loop, %0
|
Loop: ; preds = %Loop, %0
|
||||||
|
@ -69,15 +93,25 @@ Loop: ; preds = %Loop, %0
|
||||||
|
|
||||||
Out: ; preds = %Loop
|
Out: ; preds = %Loop
|
||||||
ret double %A
|
ret double %A
|
||||||
; CHECK-LABEL: @test2c(
|
|
||||||
; CHECK: Out:
|
|
||||||
; CHECK-NEXT: load double
|
|
||||||
; CHECK-NEXT: ret double %A
|
|
||||||
}
|
}
|
||||||
|
|
||||||
; This testcase checks to make sure the sinker does not cause problems with
|
; This testcase checks to make sure the sinker does not cause problems with
|
||||||
; critical edges.
|
; critical edges.
|
||||||
define void @test3() {
|
define void @test3() {
|
||||||
|
; CHECK-LABEL: @test3(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
|
||||||
|
; CHECK: Loop.preheader:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
|
||||||
|
; CHECK: Exit.loopexit:
|
||||||
|
; CHECK-NEXT: [[X_LE:%.*]] = add i32 0, 1
|
||||||
|
; CHECK-NEXT: br label [[EXIT]]
|
||||||
|
; CHECK: Exit:
|
||||||
|
; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_LE]], [[EXIT_LOOPEXIT]] ]
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br i1 false, label %Loop, label %Exit
|
br i1 false, label %Loop, label %Exit
|
||||||
Loop:
|
Loop:
|
||||||
|
@ -87,10 +121,6 @@ Exit:
|
||||||
%Y = phi i32 [ 0, %Entry ], [ %X, %Loop ]
|
%Y = phi i32 [ 0, %Entry ], [ %X, %Loop ]
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
; CHECK-LABEL: @test3(
|
|
||||||
; CHECK: Exit.loopexit:
|
|
||||||
; CHECK-NEXT: %X.le = add i32 0, 1
|
|
||||||
; CHECK-NEXT: br label %Exit
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +129,20 @@ Exit:
|
||||||
; iteration of the loop.
|
; iteration of the loop.
|
||||||
;
|
;
|
||||||
define i32 @test4(i32 %N) {
|
define i32 @test4(i32 %N) {
|
||||||
|
; CHECK-LABEL: @test4(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN:%.*]] = phi i32 [ [[DEC:%.*]], [[LOOP]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[DEC]] = add i32 [[N_ADDR_0_PN]], -1
|
||||||
|
; CHECK-NEXT: [[TMP_1:%.*]] = icmp ne i32 [[N_ADDR_0_PN]], 1
|
||||||
|
; CHECK-NEXT: br i1 [[TMP_1]], label [[LOOP]], label [[OUT:%.*]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[LOOP]] ]
|
||||||
|
; CHECK-NEXT: [[TMP_6_LE:%.*]] = mul i32 [[N]], [[N_ADDR_0_PN_LCSSA]]
|
||||||
|
; CHECK-NEXT: [[TMP_7_LE:%.*]] = sub i32 [[TMP_6_LE]], [[N]]
|
||||||
|
; CHECK-NEXT: ret i32 [[TMP_7_LE]]
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop: ; preds = %Loop, %Entry
|
Loop: ; preds = %Loop, %Entry
|
||||||
|
@ -110,12 +154,6 @@ Loop: ; preds = %Loop, %Entry
|
||||||
br i1 %tmp.1, label %Loop, label %Out
|
br i1 %tmp.1, label %Loop, label %Out
|
||||||
Out: ; preds = %Loop
|
Out: ; preds = %Loop
|
||||||
ret i32 %tmp.7
|
ret i32 %tmp.7
|
||||||
; CHECK-LABEL: @test4(
|
|
||||||
; CHECK: Out:
|
|
||||||
; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %N_addr.0.pn
|
|
||||||
; CHECK-NEXT: mul i32 %N, %[[LCSSAPHI]]
|
|
||||||
; CHECK-NEXT: sub i32 %tmp.6.le, %N
|
|
||||||
; CHECK-NEXT: ret i32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
; To reduce register pressure, if a load is hoistable out of the loop, and the
|
; To reduce register pressure, if a load is hoistable out of the loop, and the
|
||||||
|
@ -125,6 +163,18 @@ Out: ; preds = %Loop
|
||||||
@X = global i32 5 ; <i32*> [#uses=1]
|
@X = global i32 5 ; <i32*> [#uses=1]
|
||||||
|
|
||||||
define i32 @test5(i32 %N) {
|
define i32 @test5(i32 %N) {
|
||||||
|
; CHECK-LABEL: @test5(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN:%.*]] = phi i32 [ [[DEC:%.*]], [[LOOP]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[DEC]] = add i32 [[N_ADDR_0_PN]], -1
|
||||||
|
; CHECK-NEXT: [[TMP_1:%.*]] = icmp ne i32 [[N_ADDR_0_PN]], 1
|
||||||
|
; CHECK-NEXT: br i1 [[TMP_1]], label [[LOOP]], label [[OUT:%.*]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[TMP_6_LE:%.*]] = load i32, i32* @X, align 4
|
||||||
|
; CHECK-NEXT: ret i32 [[TMP_6_LE]]
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop: ; preds = %Loop, %Entry
|
Loop: ; preds = %Loop, %Entry
|
||||||
|
@ -135,10 +185,6 @@ Loop: ; preds = %Loop, %Entry
|
||||||
br i1 %tmp.1, label %Loop, label %Out
|
br i1 %tmp.1, label %Loop, label %Out
|
||||||
Out: ; preds = %Loop
|
Out: ; preds = %Loop
|
||||||
ret i32 %tmp.6
|
ret i32 %tmp.6
|
||||||
; CHECK-LABEL: @test5(
|
|
||||||
; CHECK: Out:
|
|
||||||
; CHECK-NEXT: %tmp.6.le = load i32, i32* @X
|
|
||||||
; CHECK-NEXT: ret i32 %tmp.6.le
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,6 +198,15 @@ Out: ; preds = %Loop
|
||||||
@X2 = external global %Ty
|
@X2 = external global %Ty
|
||||||
|
|
||||||
define i32 @test6() {
|
define i32 @test6() {
|
||||||
|
; CHECK-LABEL: @test6(
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[OUT:%.*]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[DEAD_LE:%.*]] = getelementptr [[TY:%.*]], %Ty* @X2, i64 0, i32 0
|
||||||
|
; CHECK-NEXT: [[SUNK2_LE:%.*]] = load i32, i32* [[DEAD_LE]], align 4
|
||||||
|
; CHECK-NEXT: ret i32 [[SUNK2_LE]]
|
||||||
|
;
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop:
|
Loop:
|
||||||
%dead = getelementptr %Ty, %Ty* @X2, i64 0, i32 0
|
%dead = getelementptr %Ty, %Ty* @X2, i64 0, i32 0
|
||||||
|
@ -159,11 +214,6 @@ Loop:
|
||||||
br i1 false, label %Loop, label %Out
|
br i1 false, label %Loop, label %Out
|
||||||
Out: ; preds = %Loop
|
Out: ; preds = %Loop
|
||||||
ret i32 %sunk2
|
ret i32 %sunk2
|
||||||
; CHECK-LABEL: @test6(
|
|
||||||
; CHECK: Out:
|
|
||||||
; CHECK-NEXT: %dead.le = getelementptr %Ty, %Ty* @X2, i64 0, i32 0
|
|
||||||
; CHECK-NEXT: %sunk2.le = load i32, i32* %dead.le
|
|
||||||
; CHECK-NEXT: ret i32 %sunk2.le
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,6 +222,27 @@ Out: ; preds = %Loop
|
||||||
; multiple exits.
|
; multiple exits.
|
||||||
;
|
;
|
||||||
define i32 @test7(i32 %N, i1 %C) {
|
define i32 @test7(i32 %N, i1 %C) {
|
||||||
|
; CHECK-LABEL: @test7(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN:%.*]] = phi i32 [ [[DEC:%.*]], [[CONTLOOP:%.*]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[DEC]] = add i32 [[N_ADDR_0_PN]], -1
|
||||||
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[CONTLOOP]], label [[OUT1:%.*]]
|
||||||
|
; CHECK: ContLoop:
|
||||||
|
; CHECK-NEXT: [[TMP_1:%.*]] = icmp ne i32 [[N_ADDR_0_PN]], 1
|
||||||
|
; CHECK-NEXT: br i1 [[TMP_1]], label [[LOOP]], label [[OUT2:%.*]]
|
||||||
|
; CHECK: Out1:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[LOOP]] ]
|
||||||
|
; CHECK-NEXT: [[TMP_6_LE:%.*]] = mul i32 [[N]], [[N_ADDR_0_PN_LCSSA]]
|
||||||
|
; CHECK-NEXT: [[TMP_7_LE2:%.*]] = sub i32 [[TMP_6_LE]], [[N]]
|
||||||
|
; CHECK-NEXT: ret i32 [[TMP_7_LE2]]
|
||||||
|
; CHECK: Out2:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA5:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[CONTLOOP]] ]
|
||||||
|
; CHECK-NEXT: [[TMP_6_LE4:%.*]] = mul i32 [[N]], [[N_ADDR_0_PN_LCSSA5]]
|
||||||
|
; CHECK-NEXT: [[TMP_7_LE:%.*]] = sub i32 [[TMP_6_LE4]], [[N]]
|
||||||
|
; CHECK-NEXT: ret i32 [[TMP_7_LE]]
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop: ; preds = %ContLoop, %Entry
|
Loop: ; preds = %ContLoop, %Entry
|
||||||
|
@ -187,17 +258,6 @@ Out1: ; preds = %Loop
|
||||||
ret i32 %tmp.7
|
ret i32 %tmp.7
|
||||||
Out2: ; preds = %ContLoop
|
Out2: ; preds = %ContLoop
|
||||||
ret i32 %tmp.7
|
ret i32 %tmp.7
|
||||||
; CHECK-LABEL: @test7(
|
|
||||||
; CHECK: Out1:
|
|
||||||
; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %N_addr.0.pn
|
|
||||||
; CHECK-NEXT: mul i32 %N, %[[LCSSAPHI]]
|
|
||||||
; CHECK-NEXT: sub i32 %tmp.6.le, %N
|
|
||||||
; CHECK-NEXT: ret
|
|
||||||
; CHECK: Out2:
|
|
||||||
; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %N_addr.0.pn
|
|
||||||
; CHECK-NEXT: mul i32 %N, %[[LCSSAPHI]]
|
|
||||||
; CHECK-NEXT: sub i32 %tmp.6.le4, %N
|
|
||||||
; CHECK-NEXT: ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -205,6 +265,22 @@ Out2: ; preds = %ContLoop
|
||||||
; some exits out of the loop, and that we can do so without breaking dominator
|
; some exits out of the loop, and that we can do so without breaking dominator
|
||||||
; info.
|
; info.
|
||||||
define i32 @test8(i1 %C1, i1 %C2, i32* %P, i32* %Q) {
|
define i32 @test8(i1 %C1, i1 %C2, i32* %P, i32* %Q) {
|
||||||
|
; CHECK-LABEL: @test8(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: br i1 [[C1:%.*]], label [[CONT:%.*]], label [[EXIT1:%.*]]
|
||||||
|
; CHECK: Cont:
|
||||||
|
; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
|
||||||
|
; CHECK-NEXT: store i32 [[X]], i32* [[Q:%.*]], align 4
|
||||||
|
; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[EXIT2:%.*]]
|
||||||
|
; CHECK: exit1:
|
||||||
|
; CHECK-NEXT: ret i32 0
|
||||||
|
; CHECK: exit2:
|
||||||
|
; CHECK-NEXT: [[X_LCSSA:%.*]] = phi i32 [ [[X]], [[CONT]] ]
|
||||||
|
; CHECK-NEXT: [[V_LE:%.*]] = add i32 [[X_LCSSA]], 1
|
||||||
|
; CHECK-NEXT: ret i32 [[V_LE]]
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop: ; preds = %Cont, %Entry
|
Loop: ; preds = %Cont, %Entry
|
||||||
|
@ -218,17 +294,28 @@ exit1: ; preds = %Loop
|
||||||
ret i32 0
|
ret i32 0
|
||||||
exit2: ; preds = %Cont
|
exit2: ; preds = %Cont
|
||||||
ret i32 %V
|
ret i32 %V
|
||||||
; CHECK-LABEL: @test8(
|
|
||||||
; CHECK: exit1:
|
|
||||||
; CHECK-NEXT: ret i32 0
|
|
||||||
; CHECK: exit2:
|
|
||||||
; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %X
|
|
||||||
; CHECK-NEXT: %V.le = add i32 %[[LCSSAPHI]], 1
|
|
||||||
; CHECK-NEXT: ret i32 %V.le
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
define void @test9() {
|
define void @test9() {
|
||||||
|
; CHECK-LABEL: @test9(
|
||||||
|
; CHECK-NEXT: loopentry.2.i:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[NO_EXIT_1_I_PREHEADER:%.*]], label [[LOOPENTRY_3_I_PREHEADER:%.*]]
|
||||||
|
; CHECK: no_exit.1.i.preheader:
|
||||||
|
; CHECK-NEXT: br label [[NO_EXIT_1_I:%.*]]
|
||||||
|
; CHECK: no_exit.1.i:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[RETURN_I:%.*]], label [[ENDIF_8_I:%.*]]
|
||||||
|
; CHECK: endif.8.i:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[NO_EXIT_1_I]], label [[LOOPENTRY_3_I_PREHEADER_LOOPEXIT:%.*]]
|
||||||
|
; CHECK: loopentry.3.i.preheader.loopexit:
|
||||||
|
; CHECK-NEXT: [[INC_1_I_LE:%.*]] = add i32 0, 1
|
||||||
|
; CHECK-NEXT: br label [[LOOPENTRY_3_I_PREHEADER]]
|
||||||
|
; CHECK: loopentry.3.i.preheader:
|
||||||
|
; CHECK-NEXT: [[ARG_NUM_0_I_PH13000:%.*]] = phi i32 [ 0, [[LOOPENTRY_2_I:%.*]] ], [ [[INC_1_I_LE]], [[LOOPENTRY_3_I_PREHEADER_LOOPEXIT]] ]
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
; CHECK: return.i:
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
;
|
||||||
loopentry.2.i:
|
loopentry.2.i:
|
||||||
br i1 false, label %no_exit.1.i.preheader, label %loopentry.3.i.preheader
|
br i1 false, label %no_exit.1.i.preheader, label %loopentry.3.i.preheader
|
||||||
no_exit.1.i.preheader: ; preds = %loopentry.2.i
|
no_exit.1.i.preheader: ; preds = %loopentry.2.i
|
||||||
|
@ -246,16 +333,25 @@ loopentry.3.i.preheader: ; preds = %loopentry.3.i.preheader.loopexit, %loopentr
|
||||||
return.i: ; preds = %no_exit.1.i
|
return.i: ; preds = %no_exit.1.i
|
||||||
ret void
|
ret void
|
||||||
|
|
||||||
; CHECK-LABEL: @test9(
|
|
||||||
; CHECK: loopentry.3.i.preheader.loopexit:
|
|
||||||
; CHECK-NEXT: %inc.1.i.le = add i32 0, 1
|
|
||||||
; CHECK-NEXT: br label %loopentry.3.i.preheader
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
; Potentially trapping instructions may be sunk as long as they are guaranteed
|
; Potentially trapping instructions may be sunk as long as they are guaranteed
|
||||||
; to be executed.
|
; to be executed.
|
||||||
define i32 @test10(i32 %N) {
|
define i32 @test10(i32 %N) {
|
||||||
|
; CHECK-LABEL: @test10(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN:%.*]] = phi i32 [ [[DEC:%.*]], [[LOOP]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[DEC]] = add i32 [[N_ADDR_0_PN]], -1
|
||||||
|
; CHECK-NEXT: [[TMP_1:%.*]] = icmp ne i32 [[N_ADDR_0_PN]], 0
|
||||||
|
; CHECK-NEXT: br i1 [[TMP_1]], label [[LOOP]], label [[OUT:%.*]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[LOOP]] ]
|
||||||
|
; CHECK-NEXT: [[TMP_6_LE:%.*]] = sdiv i32 [[N]], [[N_ADDR_0_PN_LCSSA]]
|
||||||
|
; CHECK-NEXT: ret i32 [[TMP_6_LE]]
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop: ; preds = %Loop, %Entry
|
Loop: ; preds = %Loop, %Entry
|
||||||
|
@ -267,15 +363,17 @@ Loop: ; preds = %Loop, %Entry
|
||||||
Out: ; preds = %Loop
|
Out: ; preds = %Loop
|
||||||
ret i32 %tmp.6
|
ret i32 %tmp.6
|
||||||
|
|
||||||
; CHECK-LABEL: @test10(
|
|
||||||
; CHECK: Out:
|
|
||||||
; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %N_addr.0.pn
|
|
||||||
; CHECK-NEXT: %tmp.6.le = sdiv i32 %N, %[[LCSSAPHI]]
|
|
||||||
; CHECK-NEXT: ret i32 %tmp.6.le
|
|
||||||
}
|
}
|
||||||
|
|
||||||
; Should delete, not sink, dead instructions.
|
; Should delete, not sink, dead instructions.
|
||||||
define void @test11() {
|
define void @test11() {
|
||||||
|
; CHECK-LABEL: @test11(
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[OUT:%.*]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
;
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop:
|
Loop:
|
||||||
%dead1 = getelementptr %Ty, %Ty* @X2, i64 0, i32 0
|
%dead1 = getelementptr %Ty, %Ty* @X2, i64 0, i32 0
|
||||||
|
@ -283,15 +381,11 @@ Loop:
|
||||||
br i1 false, label %Loop, label %Out
|
br i1 false, label %Loop, label %Out
|
||||||
Out:
|
Out:
|
||||||
ret void
|
ret void
|
||||||
; CHECK-LABEL: @test11(
|
|
||||||
; CHECK: Out:
|
|
||||||
; CHECK-NEXT: ret void
|
|
||||||
|
|
||||||
; The GEP in dead1 is adding a zero offset, so the DIExpression can be kept as
|
; The GEP in dead1 is adding a zero offset, so the DIExpression can be kept as
|
||||||
; a "register location".
|
; a "register location".
|
||||||
; The GEP in dead2 is adding a 4 bytes to the pointer, so the DIExpression is
|
; The GEP in dead2 is adding a 4 bytes to the pointer, so the DIExpression is
|
||||||
; turned into an "implicit location" using DW_OP_stack_value.
|
; turned into an "implicit location" using DW_OP_stack_value.
|
||||||
;
|
|
||||||
; DEBUGIFY-LABEL: @test11(
|
; DEBUGIFY-LABEL: @test11(
|
||||||
; DEBUGIFY: call void @llvm.dbg.value(metadata %Ty* @X2, metadata {{.*}}, metadata !DIExpression())
|
; DEBUGIFY: call void @llvm.dbg.value(metadata %Ty* @X2, metadata {{.*}}, metadata !DIExpression())
|
||||||
; DEBUGIFY: call void @llvm.dbg.value(metadata %Ty* @X2, metadata {{.*}}, metadata !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value))
|
; DEBUGIFY: call void @llvm.dbg.value(metadata %Ty* @X2, metadata {{.*}}, metadata !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value))
|
||||||
|
@ -302,6 +396,46 @@ Out:
|
||||||
; Test a *many* way nested loop with multiple exit blocks both of which exit
|
; Test a *many* way nested loop with multiple exit blocks both of which exit
|
||||||
; multiple loop nests. This exercises LCSSA corner cases.
|
; multiple loop nests. This exercises LCSSA corner cases.
|
||||||
define i32 @PR18753(i1* %a, i1* %b, i1* %c, i1* %d) {
|
define i32 @PR18753(i1* %a, i1* %b, i1* %c, i1* %d) {
|
||||||
|
; CHECK-LABEL: @PR18753(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: br label [[L1_HEADER:%.*]]
|
||||||
|
; CHECK: l1.header:
|
||||||
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[L1_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds [1 x i32], [1 x i32]* @c, i64 0, i64 [[IV]]
|
||||||
|
; CHECK-NEXT: br label [[L2_HEADER:%.*]]
|
||||||
|
; CHECK: l2.header:
|
||||||
|
; CHECK-NEXT: [[X0:%.*]] = load i1, i1* [[C:%.*]], align 4
|
||||||
|
; CHECK-NEXT: br i1 [[X0]], label [[L1_LATCH]], label [[L3_PREHEADER:%.*]]
|
||||||
|
; CHECK: l3.preheader:
|
||||||
|
; CHECK-NEXT: br label [[L3_HEADER:%.*]]
|
||||||
|
; CHECK: l3.header:
|
||||||
|
; CHECK-NEXT: [[X1:%.*]] = load i1, i1* [[D:%.*]], align 4
|
||||||
|
; CHECK-NEXT: br i1 [[X1]], label [[L2_LATCH:%.*]], label [[L4_PREHEADER:%.*]]
|
||||||
|
; CHECK: l4.preheader:
|
||||||
|
; CHECK-NEXT: br label [[L4_HEADER:%.*]]
|
||||||
|
; CHECK: l4.header:
|
||||||
|
; CHECK-NEXT: [[X2:%.*]] = load i1, i1* [[A:%.*]], align 1
|
||||||
|
; CHECK-NEXT: br i1 [[X2]], label [[L3_LATCH:%.*]], label [[L4_BODY:%.*]]
|
||||||
|
; CHECK: l4.body:
|
||||||
|
; CHECK-NEXT: call void @f(i32* [[ARRAYIDX_I]])
|
||||||
|
; CHECK-NEXT: [[X3:%.*]] = load i1, i1* [[B:%.*]], align 1
|
||||||
|
; CHECK-NEXT: br i1 [[X3]], label [[L4_LATCH:%.*]], label [[EXIT:%.*]]
|
||||||
|
; CHECK: l4.latch:
|
||||||
|
; CHECK-NEXT: call void @g()
|
||||||
|
; CHECK-NEXT: [[X4:%.*]] = load i1, i1* [[B]], align 4
|
||||||
|
; CHECK-NEXT: br i1 [[X4]], label [[L4_HEADER]], label [[EXIT]]
|
||||||
|
; CHECK: l3.latch:
|
||||||
|
; CHECK-NEXT: br label [[L3_HEADER]]
|
||||||
|
; CHECK: l2.latch:
|
||||||
|
; CHECK-NEXT: br label [[L2_HEADER]]
|
||||||
|
; CHECK: l1.latch:
|
||||||
|
; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1
|
||||||
|
; CHECK-NEXT: br label [[L1_HEADER]]
|
||||||
|
; CHECK: exit:
|
||||||
|
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], [[L4_LATCH]] ], [ [[IV]], [[L4_BODY]] ]
|
||||||
|
; CHECK-NEXT: [[L_LE:%.*]] = trunc i64 [[IV_LCSSA]] to i32
|
||||||
|
; CHECK-NEXT: ret i32 [[L_LE]]
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %l1.header
|
br label %l1.header
|
||||||
|
|
||||||
|
@ -351,11 +485,6 @@ l1.latch:
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
%lcssa = phi i32 [ %l, %l4.latch ], [ %l, %l4.body ]
|
%lcssa = phi i32 [ %l, %l4.latch ], [ %l, %l4.body ]
|
||||||
; CHECK-LABEL: @PR18753(
|
|
||||||
; CHECK: exit:
|
|
||||||
; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i64 [ %iv, %l4.latch ], [ %iv, %l4.body ]
|
|
||||||
; CHECK-NEXT: %l.le = trunc i64 %[[LCSSAPHI]] to i32
|
|
||||||
; CHECK-NEXT: ret i32 %l.le
|
|
||||||
|
|
||||||
ret i32 %lcssa
|
ret i32 %lcssa
|
||||||
}
|
}
|
||||||
|
@ -366,7 +495,26 @@ exit:
|
||||||
; available (which is used for creating loads that may be used by the SSA
|
; available (which is used for creating loads that may be used by the SSA
|
||||||
; updater)
|
; updater)
|
||||||
define void @test13() {
|
define void @test13() {
|
||||||
; CHECK-LABEL: @test13
|
; CHECK-LABEL: @test13(
|
||||||
|
; CHECK-NEXT: br label [[LAB59:%.*]]
|
||||||
|
; CHECK: lab19:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[LAB20:%.*]], label [[LAB38_LOOPEXIT:%.*]]
|
||||||
|
; CHECK: lab20:
|
||||||
|
; CHECK-NEXT: br label [[LAB60:%.*]]
|
||||||
|
; CHECK: lab21:
|
||||||
|
; CHECK-NEXT: br i1 undef, label [[LAB22:%.*]], label [[LAB38:%.*]]
|
||||||
|
; CHECK: lab22:
|
||||||
|
; CHECK-NEXT: br label [[LAB38]]
|
||||||
|
; CHECK: lab38.loopexit:
|
||||||
|
; CHECK-NEXT: br label [[LAB38]]
|
||||||
|
; CHECK: lab38:
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
; CHECK: lab59:
|
||||||
|
; CHECK-NEXT: indirectbr i8* undef, [label [[LAB60]], label %lab38]
|
||||||
|
; CHECK: lab60:
|
||||||
|
; CHECK-NEXT: store i32 2145244101, i32* undef, align 4
|
||||||
|
; CHECK-NEXT: indirectbr i8* undef, [label [[LAB21:%.*]], label %lab19]
|
||||||
|
;
|
||||||
br label %lab59
|
br label %lab59
|
||||||
|
|
||||||
lab19:
|
lab19:
|
||||||
|
@ -388,35 +536,36 @@ lab59:
|
||||||
indirectbr i8* undef, [label %lab60, label %lab38]
|
indirectbr i8* undef, [label %lab60, label %lab38]
|
||||||
|
|
||||||
lab60:
|
lab60:
|
||||||
; CHECK: lab60:
|
|
||||||
; CHECK: store
|
|
||||||
; CHECK-NEXT: indirectbr
|
|
||||||
store i32 2145244101, i32* undef, align 4
|
store i32 2145244101, i32* undef, align 4
|
||||||
indirectbr i8* undef, [label %lab21, label %lab19]
|
indirectbr i8* undef, [label %lab21, label %lab19]
|
||||||
}
|
}
|
||||||
|
|
||||||
; Check if LICM can sink a sinkable instruction the exit blocks through
|
; Check if LICM can sink a sinkable instruction the exit blocks through
|
||||||
; a non-trivially replacable PHI node.
|
; a non-trivially replacable PHI node.
|
||||||
;
|
|
||||||
; CHECK-LABEL: @test14
|
|
||||||
; CHECK-LABEL: Loop:
|
|
||||||
; CHECK-NOT: mul
|
|
||||||
; CHECK-NOT: sub
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: Out12.split.loop.exit:
|
|
||||||
; CHECK: %[[LCSSAPHI:.*]] = phi i32 [ %N_addr.0.pn, %ContLoop ]
|
|
||||||
; CHECK: %[[MUL:.*]] = mul i32 %N, %[[LCSSAPHI]]
|
|
||||||
; CHECK: br label %Out12
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: Out12.split.loop.exit1:
|
|
||||||
; CHECK: %[[LCSSAPHI2:.*]] = phi i32 [ %N_addr.0.pn, %Loop ]
|
|
||||||
; CHECK: %[[MUL2:.*]] = mul i32 %N, %[[LCSSAPHI2]]
|
|
||||||
; CHECK: %[[SUB:.*]] = sub i32 %[[MUL2]], %N
|
|
||||||
; CHECK: br label %Out12
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: Out12:
|
|
||||||
; CHECK: phi i32 [ %[[MUL]], %Out12.split.loop.exit ], [ %[[SUB]], %Out12.split.loop.exit1 ]
|
|
||||||
define i32 @test14(i32 %N, i32 %N2, i1 %C) {
|
define i32 @test14(i32 %N, i32 %N2, i1 %C) {
|
||||||
|
; CHECK-LABEL: @test14(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN:%.*]] = phi i32 [ [[DEC:%.*]], [[CONTLOOP:%.*]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[DEC]] = add i32 [[N_ADDR_0_PN]], -1
|
||||||
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[CONTLOOP]], label [[OUT12_SPLIT_LOOP_EXIT1:%.*]]
|
||||||
|
; CHECK: ContLoop:
|
||||||
|
; CHECK-NEXT: [[TMP_1:%.*]] = icmp ne i32 [[N_ADDR_0_PN]], 1
|
||||||
|
; CHECK-NEXT: br i1 [[TMP_1]], label [[LOOP]], label [[OUT12_SPLIT_LOOP_EXIT:%.*]]
|
||||||
|
; CHECK: Out12.split.loop.exit:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA4:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[CONTLOOP]] ]
|
||||||
|
; CHECK-NEXT: [[SINK_MUL_LE3:%.*]] = mul i32 [[N]], [[N_ADDR_0_PN_LCSSA4]]
|
||||||
|
; CHECK-NEXT: br label [[OUT12:%.*]]
|
||||||
|
; CHECK: Out12.split.loop.exit1:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[LOOP]] ]
|
||||||
|
; CHECK-NEXT: [[SINK_MUL_LE:%.*]] = mul i32 [[N]], [[N_ADDR_0_PN_LCSSA]]
|
||||||
|
; CHECK-NEXT: [[SINK_SUB_LE:%.*]] = sub i32 [[SINK_MUL_LE]], [[N]]
|
||||||
|
; CHECK-NEXT: br label [[OUT12]]
|
||||||
|
; CHECK: Out12:
|
||||||
|
; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ [[SINK_MUL_LE3]], [[OUT12_SPLIT_LOOP_EXIT]] ], [ [[SINK_SUB_LE]], [[OUT12_SPLIT_LOOP_EXIT1]] ]
|
||||||
|
; CHECK-NEXT: ret i32 [[TMP]]
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop:
|
Loop:
|
||||||
|
@ -439,27 +588,31 @@ Out12:
|
||||||
; to the shared operations. As of now, we split predecessors of non-trivially
|
; to the shared operations. As of now, we split predecessors of non-trivially
|
||||||
; replicalbe PHIs by default in LICM because all incoming edges of a
|
; replicalbe PHIs by default in LICM because all incoming edges of a
|
||||||
; non-trivially replacable PHI in LCSSA is critical.
|
; non-trivially replacable PHI in LCSSA is critical.
|
||||||
;
|
|
||||||
; CHECK-LABEL: @test15
|
|
||||||
; CHECK-LABEL: Loop:
|
|
||||||
; CHECK-NOT: mul
|
|
||||||
; CHECK-NOT: sub
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: Out12.split.loop.exit:
|
|
||||||
; CHECK: %[[LCSSAPHI:.*]] = phi i32 [ %N_addr.0.pn, %ContLoop ]
|
|
||||||
; CHECK: %[[MUL:.*]] = mul i32 %N, %[[LCSSAPHI]]
|
|
||||||
; CHECK: %[[SUB:.*]] = sub i32 %[[MUL]], %N2
|
|
||||||
; CHECK: br label %Out12
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: Out12.split.loop.exit1:
|
|
||||||
; CHECK: %[[LCSSAPHI2:.*]] = phi i32 [ %N_addr.0.pn, %Loop ]
|
|
||||||
; CHECK: %[[MUL2:.*]] = mul i32 %N, %[[LCSSAPHI2]]
|
|
||||||
; CHECK: %[[SUB2:.*]] = sub i32 %[[MUL2]], %N
|
|
||||||
; CHECK: br label %Out12
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: Out12:
|
|
||||||
; CHECK: phi i32 [ %[[SUB]], %Out12.split.loop.exit ], [ %[[SUB2]], %Out12.split.loop.exit1 ]
|
|
||||||
define i32 @test15(i32 %N, i32 %N2, i1 %C) {
|
define i32 @test15(i32 %N, i32 %N2, i1 %C) {
|
||||||
|
; CHECK-LABEL: @test15(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN:%.*]] = phi i32 [ [[DEC:%.*]], [[CONTLOOP:%.*]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[DEC]] = add i32 [[N_ADDR_0_PN]], -1
|
||||||
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[CONTLOOP]], label [[OUT12_SPLIT_LOOP_EXIT1:%.*]]
|
||||||
|
; CHECK: ContLoop:
|
||||||
|
; CHECK-NEXT: [[TMP_1:%.*]] = icmp ne i32 [[N_ADDR_0_PN]], 1
|
||||||
|
; CHECK-NEXT: br i1 [[TMP_1]], label [[LOOP]], label [[OUT12_SPLIT_LOOP_EXIT:%.*]]
|
||||||
|
; CHECK: Out12.split.loop.exit:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA5:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[CONTLOOP]] ]
|
||||||
|
; CHECK-NEXT: [[SINK_MUL_LE4:%.*]] = mul i32 [[N]], [[N_ADDR_0_PN_LCSSA5]]
|
||||||
|
; CHECK-NEXT: [[SINK_SUB2_LE:%.*]] = sub i32 [[SINK_MUL_LE4]], [[N2:%.*]]
|
||||||
|
; CHECK-NEXT: br label [[OUT12:%.*]]
|
||||||
|
; CHECK: Out12.split.loop.exit1:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[LOOP]] ]
|
||||||
|
; CHECK-NEXT: [[SINK_MUL_LE:%.*]] = mul i32 [[N]], [[N_ADDR_0_PN_LCSSA]]
|
||||||
|
; CHECK-NEXT: [[SINK_SUB_LE:%.*]] = sub i32 [[SINK_MUL_LE]], [[N]]
|
||||||
|
; CHECK-NEXT: br label [[OUT12]]
|
||||||
|
; CHECK: Out12:
|
||||||
|
; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ [[SINK_SUB2_LE]], [[OUT12_SPLIT_LOOP_EXIT]] ], [ [[SINK_SUB_LE]], [[OUT12_SPLIT_LOOP_EXIT1]] ]
|
||||||
|
; CHECK-NEXT: ret i32 [[TMP]]
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop:
|
Loop:
|
||||||
|
@ -479,22 +632,37 @@ Out12:
|
||||||
|
|
||||||
; Sink through a non-trivially replacable PHI node which use the same sinkable
|
; Sink through a non-trivially replacable PHI node which use the same sinkable
|
||||||
; instruction multiple times.
|
; instruction multiple times.
|
||||||
;
|
|
||||||
; CHECK-LABEL: @test16
|
|
||||||
; CHECK-LABEL: Loop:
|
|
||||||
; CHECK-NOT: mul
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: Out.split.loop.exit:
|
|
||||||
; CHECK: %[[PHI:.*]] = phi i32 [ %l2, %ContLoop ]
|
|
||||||
; CHECK: br label %Out
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: Out.split.loop.exit1:
|
|
||||||
; CHECK: %[[SINKABLE:.*]] = mul i32 %l2.lcssa, %t.le
|
|
||||||
; CHECK: br label %Out
|
|
||||||
;
|
|
||||||
; CHECK-LABEL: Out:
|
|
||||||
; CHECK: %idx = phi i32 [ %[[PHI]], %Out.split.loop.exit ], [ %[[SINKABLE]], %Out.split.loop.exit1 ]
|
|
||||||
define i32 @test16(i1 %c, i8** %P, i32* %P2, i64 %V) {
|
define i32 @test16(i1 %c, i8** %P, i32* %P2, i64 %V) {
|
||||||
|
; CHECK-LABEL: @test16(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP_PH:%.*]]
|
||||||
|
; CHECK: loop.ph:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[LOOP_PH]] ], [ [[NEXT:%.*]], [[CONTLOOP:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[L2:%.*]] = call i32 @getv()
|
||||||
|
; CHECK-NEXT: switch i32 [[L2]], label [[CONTLOOP]] [
|
||||||
|
; CHECK-NEXT: i32 32, label [[OUT_SPLIT_LOOP_EXIT1:%.*]]
|
||||||
|
; CHECK-NEXT: i32 46, label [[OUT_SPLIT_LOOP_EXIT1]]
|
||||||
|
; CHECK-NEXT: i32 95, label [[OUT_SPLIT_LOOP_EXIT1]]
|
||||||
|
; CHECK-NEXT: ]
|
||||||
|
; CHECK: ContLoop:
|
||||||
|
; CHECK-NEXT: [[NEXT]] = add nuw i64 [[IV]], 1
|
||||||
|
; CHECK-NEXT: [[C1:%.*]] = call i1 @getc()
|
||||||
|
; CHECK-NEXT: br i1 [[C1]], label [[LOOP]], label [[OUT_SPLIT_LOOP_EXIT:%.*]]
|
||||||
|
; CHECK: Out.split.loop.exit:
|
||||||
|
; CHECK-NEXT: [[IDX_PH:%.*]] = phi i32 [ [[L2]], [[CONTLOOP]] ]
|
||||||
|
; CHECK-NEXT: br label [[OUT:%.*]]
|
||||||
|
; CHECK: Out.split.loop.exit1:
|
||||||
|
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[IV]], [[LOOP]] ], [ [[IV]], [[LOOP]] ], [ [[IV]], [[LOOP]] ]
|
||||||
|
; CHECK-NEXT: [[L2_LCSSA:%.*]] = phi i32 [ [[L2]], [[LOOP]] ], [ [[L2]], [[LOOP]] ], [ [[L2]], [[LOOP]] ]
|
||||||
|
; CHECK-NEXT: [[T_LE:%.*]] = trunc i64 [[IV_LCSSA]] to i32
|
||||||
|
; CHECK-NEXT: [[SINKABLE_LE:%.*]] = mul i32 [[L2_LCSSA]], [[T_LE]]
|
||||||
|
; CHECK-NEXT: br label [[OUT]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PH]], [[OUT_SPLIT_LOOP_EXIT]] ], [ [[SINKABLE_LE]], [[OUT_SPLIT_LOOP_EXIT1]] ]
|
||||||
|
; CHECK-NEXT: ret i32 [[IDX]]
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %loop.ph
|
br label %loop.ph
|
||||||
loop.ph:
|
loop.ph:
|
||||||
|
@ -520,27 +688,48 @@ Out:
|
||||||
|
|
||||||
; Sink a sinkable instruction through multiple non-trivially replacable PHIs in
|
; Sink a sinkable instruction through multiple non-trivially replacable PHIs in
|
||||||
; differect exit blocks.
|
; differect exit blocks.
|
||||||
;
|
|
||||||
; CHECK-LABEL: @test17
|
|
||||||
; CHECK-LABEL: Loop:
|
|
||||||
; CHECK-NOT: mul
|
|
||||||
;
|
|
||||||
; CHECK-LABEL:OutA.split.loop.exit{{.*}}:
|
|
||||||
; CHECK: %[[OP1:.*]] = phi i32 [ %N_addr.0.pn, %ContLoop1 ]
|
|
||||||
; CHECK: %[[SINKABLE:.*]] = mul i32 %N, %[[OP1]]
|
|
||||||
; CHECK: br label %OutA
|
|
||||||
;
|
|
||||||
; CHECK-LABEL:OutA:
|
|
||||||
; CHECK: phi i32{{.*}}[ %[[SINKABLE]], %OutA.split.loop.exit{{.*}} ]
|
|
||||||
;
|
|
||||||
; CHECK-LABEL:OutB.split.loop.exit{{.*}}:
|
|
||||||
; CHECK: %[[OP2:.*]] = phi i32 [ %N_addr.0.pn, %ContLoop2 ]
|
|
||||||
; CHECK: %[[SINKABLE2:.*]] = mul i32 %N, %[[OP2]]
|
|
||||||
; CHECK: br label %OutB
|
|
||||||
;
|
|
||||||
; CHECK-LABEL:OutB:
|
|
||||||
; CHECK: phi i32 {{.*}}[ %[[SINKABLE2]], %OutB.split.loop.exit{{.*}} ]
|
|
||||||
define i32 @test17(i32 %N, i32 %N2) {
|
define i32 @test17(i32 %N, i32 %N2) {
|
||||||
|
; CHECK-LABEL: @test17(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN:%.*]] = phi i32 [ [[DEC:%.*]], [[CONTLOOP3:%.*]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[C0:%.*]] = call i1 @getc()
|
||||||
|
; CHECK-NEXT: br i1 [[C0]], label [[CONTLOOP1:%.*]], label [[OUTA_SPLIT_LOOP_EXIT3:%.*]]
|
||||||
|
; CHECK: ContLoop1:
|
||||||
|
; CHECK-NEXT: [[C1:%.*]] = call i1 @getc()
|
||||||
|
; CHECK-NEXT: br i1 [[C1]], label [[CONTLOOP2:%.*]], label [[OUTA_SPLIT_LOOP_EXIT:%.*]]
|
||||||
|
; CHECK: ContLoop2:
|
||||||
|
; CHECK-NEXT: [[C2:%.*]] = call i1 @getc()
|
||||||
|
; CHECK-NEXT: br i1 [[C2]], label [[CONTLOOP3]], label [[OUTB_SPLIT_LOOP_EXIT1:%.*]]
|
||||||
|
; CHECK: ContLoop3:
|
||||||
|
; CHECK-NEXT: [[C3:%.*]] = call i1 @getc()
|
||||||
|
; CHECK-NEXT: [[DEC]] = add i32 [[N_ADDR_0_PN]], -1
|
||||||
|
; CHECK-NEXT: br i1 [[C3]], label [[LOOP]], label [[OUTB_SPLIT_LOOP_EXIT:%.*]]
|
||||||
|
; CHECK: OutA.split.loop.exit:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[CONTLOOP1]] ]
|
||||||
|
; CHECK-NEXT: [[SINK_MUL_LE:%.*]] = mul i32 [[N]], [[N_ADDR_0_PN_LCSSA]]
|
||||||
|
; CHECK-NEXT: br label [[OUTA:%.*]]
|
||||||
|
; CHECK: OutA.split.loop.exit3:
|
||||||
|
; CHECK-NEXT: [[TMP1_PH4:%.*]] = phi i32 [ [[N2:%.*]], [[LOOP]] ]
|
||||||
|
; CHECK-NEXT: br label [[OUTA]]
|
||||||
|
; CHECK: OutA:
|
||||||
|
; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[SINK_MUL_LE]], [[OUTA_SPLIT_LOOP_EXIT]] ], [ [[TMP1_PH4]], [[OUTA_SPLIT_LOOP_EXIT3]] ]
|
||||||
|
; CHECK-NEXT: br label [[OUT12:%.*]]
|
||||||
|
; CHECK: OutB.split.loop.exit:
|
||||||
|
; CHECK-NEXT: [[TMP2_PH:%.*]] = phi i32 [ [[DEC]], [[CONTLOOP3]] ]
|
||||||
|
; CHECK-NEXT: br label [[OUTB:%.*]]
|
||||||
|
; CHECK: OutB.split.loop.exit1:
|
||||||
|
; CHECK-NEXT: [[N_ADDR_0_PN_LCSSA6:%.*]] = phi i32 [ [[N_ADDR_0_PN]], [[CONTLOOP2]] ]
|
||||||
|
; CHECK-NEXT: [[SINK_MUL_LE5:%.*]] = mul i32 [[N]], [[N_ADDR_0_PN_LCSSA6]]
|
||||||
|
; CHECK-NEXT: br label [[OUTB]]
|
||||||
|
; CHECK: OutB:
|
||||||
|
; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP2_PH]], [[OUTB_SPLIT_LOOP_EXIT]] ], [ [[SINK_MUL_LE5]], [[OUTB_SPLIT_LOOP_EXIT1]] ]
|
||||||
|
; CHECK-NEXT: br label [[OUT12]]
|
||||||
|
; CHECK: Out12:
|
||||||
|
; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ [[TMP1]], [[OUTA]] ], [ [[TMP2]], [[OUTB]] ]
|
||||||
|
; CHECK-NEXT: ret i32 [[TMP]]
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop:
|
Loop:
|
||||||
|
@ -572,30 +761,35 @@ Out12:
|
||||||
|
|
||||||
|
|
||||||
; Sink a sinkable instruction through both trivially and non-trivially replacable PHIs.
|
; Sink a sinkable instruction through both trivially and non-trivially replacable PHIs.
|
||||||
;
|
|
||||||
; CHECK-LABEL: @test18
|
|
||||||
; CHECK-LABEL: Loop:
|
|
||||||
; CHECK-NOT: mul
|
|
||||||
; CHECK-NOT: sub
|
|
||||||
;
|
|
||||||
; CHECK-LABEL:Out12.split.loop.exit:
|
|
||||||
; CHECK: %[[OP:.*]] = phi i32 [ %iv, %ContLoop ]
|
|
||||||
; CHECK: %[[DEC:.*]] = phi i32 [ %dec, %ContLoop ]
|
|
||||||
; CHECK: %[[SINKMUL:.*]] = mul i32 %N, %[[OP]]
|
|
||||||
; CHECK: %[[SINKSUB:.*]] = sub i32 %[[SINKMUL]], %N2
|
|
||||||
; CHECK: br label %Out12
|
|
||||||
;
|
|
||||||
; CHECK-LABEL:Out12.split.loop.exit1:
|
|
||||||
; CHECK: %[[OP2:.*]] = phi i32 [ %iv, %Loop ]
|
|
||||||
; CHECK: %[[SINKMUL2:.*]] = mul i32 %N, %[[OP2]]
|
|
||||||
; CHECK: %[[SINKSUB2:.*]] = sub i32 %[[SINKMUL2]], %N2
|
|
||||||
; CHECK: br label %Out12
|
|
||||||
;
|
|
||||||
; CHECK-LABEL:Out12:
|
|
||||||
; CHECK: %tmp1 = phi i32 [ %[[SINKSUB]], %Out12.split.loop.exit ], [ %[[SINKSUB2]], %Out12.split.loop.exit1 ]
|
|
||||||
; CHECK: %tmp2 = phi i32 [ %[[DEC]], %Out12.split.loop.exit ], [ %[[SINKSUB2]], %Out12.split.loop.exit1 ]
|
|
||||||
; CHECK: %add = add i32 %tmp1, %tmp2
|
|
||||||
define i32 @test18(i32 %N, i32 %N2) {
|
define i32 @test18(i32 %N, i32 %N2) {
|
||||||
|
; CHECK-LABEL: @test18(
|
||||||
|
; CHECK-NEXT: Entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[DEC:%.*]], [[CONTLOOP:%.*]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
|
||||||
|
; CHECK-NEXT: [[C0:%.*]] = call i1 @getc()
|
||||||
|
; CHECK-NEXT: br i1 [[C0]], label [[CONTLOOP]], label [[OUT12_SPLIT_LOOP_EXIT1:%.*]]
|
||||||
|
; CHECK: ContLoop:
|
||||||
|
; CHECK-NEXT: [[DEC]] = add i32 [[IV]], -1
|
||||||
|
; CHECK-NEXT: [[C1:%.*]] = call i1 @getc()
|
||||||
|
; CHECK-NEXT: br i1 [[C1]], label [[LOOP]], label [[OUT12_SPLIT_LOOP_EXIT:%.*]]
|
||||||
|
; CHECK: Out12.split.loop.exit:
|
||||||
|
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[CONTLOOP]] ]
|
||||||
|
; CHECK-NEXT: [[TMP2_PH:%.*]] = phi i32 [ [[DEC]], [[CONTLOOP]] ]
|
||||||
|
; CHECK-NEXT: [[SINK_MUL_LE:%.*]] = mul i32 [[N]], [[IV_LCSSA]]
|
||||||
|
; CHECK-NEXT: [[SINK_SUB_LE4:%.*]] = sub i32 [[SINK_MUL_LE]], [[N2:%.*]]
|
||||||
|
; CHECK-NEXT: br label [[OUT12:%.*]]
|
||||||
|
; CHECK: Out12.split.loop.exit1:
|
||||||
|
; CHECK-NEXT: [[IV_LCSSA7:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
|
||||||
|
; CHECK-NEXT: [[SINK_MUL_LE6:%.*]] = mul i32 [[N]], [[IV_LCSSA7]]
|
||||||
|
; CHECK-NEXT: [[SINK_SUB_LE:%.*]] = sub i32 [[SINK_MUL_LE6]], [[N2]]
|
||||||
|
; CHECK-NEXT: br label [[OUT12]]
|
||||||
|
; CHECK: Out12:
|
||||||
|
; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[SINK_SUB_LE4]], [[OUT12_SPLIT_LOOP_EXIT]] ], [ [[SINK_SUB_LE]], [[OUT12_SPLIT_LOOP_EXIT1]] ]
|
||||||
|
; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP2_PH]], [[OUT12_SPLIT_LOOP_EXIT]] ], [ [[SINK_SUB_LE]], [[OUT12_SPLIT_LOOP_EXIT1]] ]
|
||||||
|
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP1]], [[TMP2]]
|
||||||
|
; CHECK-NEXT: ret i32 [[ADD]]
|
||||||
|
;
|
||||||
Entry:
|
Entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop:
|
Loop:
|
||||||
|
@ -618,12 +812,23 @@ Out12:
|
||||||
; Do not sink an instruction through a non-trivially replacable PHI, to avoid
|
; Do not sink an instruction through a non-trivially replacable PHI, to avoid
|
||||||
; assert while splitting predecessors, if the terminator of predecessor is an
|
; assert while splitting predecessors, if the terminator of predecessor is an
|
||||||
; indirectbr.
|
; indirectbr.
|
||||||
; CHECK-LABEL: @test19
|
|
||||||
; CHECK-LABEL: L0:
|
|
||||||
; CHECK: %sinkable = mul
|
|
||||||
; CHECK: %sinkable2 = add
|
|
||||||
|
|
||||||
define i32 @test19(i1 %cond, i1 %cond2, i8* %address, i32 %v1) nounwind {
|
define i32 @test19(i1 %cond, i1 %cond2, i8* %address, i32 %v1) nounwind {
|
||||||
|
; CHECK-LABEL: @test19(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: [[INDIRECT_GOTO_DEST:%.*]] = select i1 [[COND:%.*]], i8* blockaddress(@test19, [[EXIT:%.*]]), i8* [[ADDRESS:%.*]]
|
||||||
|
; CHECK-NEXT: [[INDIRECT_GOTO_DEST2:%.*]] = select i1 [[COND2:%.*]], i8* blockaddress(@test19, [[EXIT]]), i8* [[ADDRESS]]
|
||||||
|
; CHECK-NEXT: br label [[L0:%.*]]
|
||||||
|
; CHECK: L0:
|
||||||
|
; CHECK-NEXT: [[V2:%.*]] = call i32 @getv()
|
||||||
|
; CHECK-NEXT: [[SINKABLE:%.*]] = mul i32 [[V1:%.*]], [[V2]]
|
||||||
|
; CHECK-NEXT: [[SINKABLE2:%.*]] = add i32 [[V1]], [[V2]]
|
||||||
|
; CHECK-NEXT: indirectbr i8* [[INDIRECT_GOTO_DEST]], [label [[L1:%.*]], label %exit]
|
||||||
|
; CHECK: L1:
|
||||||
|
; CHECK-NEXT: indirectbr i8* [[INDIRECT_GOTO_DEST2]], [label [[L0]], label %exit]
|
||||||
|
; CHECK: exit:
|
||||||
|
; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[SINKABLE]], [[L0]] ], [ [[SINKABLE2]], [[L1]] ]
|
||||||
|
; CHECK-NEXT: ret i32 [[R]]
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %L0
|
br label %L0
|
||||||
L0:
|
L0:
|
||||||
|
@ -645,12 +850,29 @@ exit:
|
||||||
|
|
||||||
; Do not sink through a non-trivially replacable PHI if splitting predecessors
|
; Do not sink through a non-trivially replacable PHI if splitting predecessors
|
||||||
; not allowed in SplitBlockPredecessors().
|
; not allowed in SplitBlockPredecessors().
|
||||||
;
|
|
||||||
; CHECK-LABEL: @test20
|
|
||||||
; CHECK-LABEL: while.cond
|
|
||||||
; CHECK: %sinkable = mul
|
|
||||||
; CHECK: %sinkable2 = add
|
|
||||||
define void @test20(i32* %s, i1 %b, i32 %v1, i32 %v2) personality i32 (...)* @__CxxFrameHandler3 {
|
define void @test20(i32* %s, i1 %b, i32 %v1, i32 %v2) personality i32 (...)* @__CxxFrameHandler3 {
|
||||||
|
; CHECK-LABEL: @test20(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: br label [[WHILE_COND:%.*]]
|
||||||
|
; CHECK: while.cond:
|
||||||
|
; CHECK-NEXT: [[V:%.*]] = call i32 @getv()
|
||||||
|
; CHECK-NEXT: [[SINKABLE:%.*]] = mul i32 [[V]], [[V2:%.*]]
|
||||||
|
; CHECK-NEXT: [[SINKABLE2:%.*]] = add i32 [[V]], [[V2]]
|
||||||
|
; CHECK-NEXT: br i1 [[B:%.*]], label [[TRY_CONT:%.*]], label [[WHILE_BODY:%.*]]
|
||||||
|
; CHECK: while.body:
|
||||||
|
; CHECK-NEXT: invoke void @may_throw()
|
||||||
|
; CHECK-NEXT: to label [[WHILE_BODY2:%.*]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||||
|
; CHECK: while.body2:
|
||||||
|
; CHECK-NEXT: invoke void @may_throw2()
|
||||||
|
; CHECK-NEXT: to label [[WHILE_COND]] unwind label [[CATCH_DISPATCH]]
|
||||||
|
; CHECK: catch.dispatch:
|
||||||
|
; CHECK-NEXT: [[DOTLCSSA1:%.*]] = phi i32 [ [[SINKABLE]], [[WHILE_BODY]] ], [ [[SINKABLE2]], [[WHILE_BODY2]] ]
|
||||||
|
; CHECK-NEXT: [[CP:%.*]] = cleanuppad within none []
|
||||||
|
; CHECK-NEXT: store i32 [[DOTLCSSA1]], i32* [[S:%.*]], align 4
|
||||||
|
; CHECK-NEXT: cleanupret from [[CP]] unwind to caller
|
||||||
|
; CHECK: try.cont:
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %while.cond
|
br label %while.cond
|
||||||
while.cond:
|
while.cond:
|
||||||
|
@ -676,13 +898,26 @@ try.cont:
|
||||||
; The sinkable call should be sunk into an exit block split. After splitting
|
; The sinkable call should be sunk into an exit block split. After splitting
|
||||||
; the exit block, BlockColor for new blocks should be added properly so
|
; the exit block, BlockColor for new blocks should be added properly so
|
||||||
; that we should be able to access valid ColorVector.
|
; that we should be able to access valid ColorVector.
|
||||||
;
|
|
||||||
; CHECK-LABEL:@test21_pr36184
|
|
||||||
; CHECK-LABEL: Loop
|
|
||||||
; CHECK-NOT: %sinkableCall
|
|
||||||
; CHECK-LABEL:Out.split.loop.exit
|
|
||||||
; CHECK: %sinkableCall
|
|
||||||
define i32 @test21_pr36184(i8* %P) personality i32 (...)* @__CxxFrameHandler3 {
|
define i32 @test21_pr36184(i8* %P) personality i32 (...)* @__CxxFrameHandler3 {
|
||||||
|
; CHECK-LABEL: @test21_pr36184(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: br label [[LOOP_PH:%.*]]
|
||||||
|
; CHECK: loop.ph:
|
||||||
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||||
|
; CHECK: Loop:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[CONTLOOP:%.*]], label [[OUT_SPLIT_LOOP_EXIT1:%.*]]
|
||||||
|
; CHECK: ContLoop:
|
||||||
|
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[OUT_SPLIT_LOOP_EXIT:%.*]]
|
||||||
|
; CHECK: Out.split.loop.exit:
|
||||||
|
; CHECK-NEXT: [[IDX_PH:%.*]] = phi i32 [ 0, [[CONTLOOP]] ]
|
||||||
|
; CHECK-NEXT: br label [[OUT:%.*]]
|
||||||
|
; CHECK: Out.split.loop.exit1:
|
||||||
|
; CHECK-NEXT: [[SINKABLECALL_LE:%.*]] = call i32 @strlen(i8* [[P:%.*]]) #[[ATTR3]]
|
||||||
|
; CHECK-NEXT: br label [[OUT]]
|
||||||
|
; CHECK: Out:
|
||||||
|
; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PH]], [[OUT_SPLIT_LOOP_EXIT]] ], [ [[SINKABLECALL_LE]], [[OUT_SPLIT_LOOP_EXIT1]] ]
|
||||||
|
; CHECK-NEXT: ret i32 [[IDX]]
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %loop.ph
|
br label %loop.ph
|
||||||
|
|
||||||
|
@ -702,11 +937,30 @@ Out:
|
||||||
}
|
}
|
||||||
|
|
||||||
; We do not support splitting a landingpad block if BlockColors is not empty.
|
; We do not support splitting a landingpad block if BlockColors is not empty.
|
||||||
; CHECK-LABEL: @test22
|
|
||||||
; CHECK-LABEL: while.body2
|
|
||||||
; CHECK-LABEL: %mul
|
|
||||||
; CHECK-NOT: lpadBB.split{{.*}}
|
|
||||||
define void @test22(i1 %b, i32 %v1, i32 %v2) personality i32 (...)* @__CxxFrameHandler3 {
|
define void @test22(i1 %b, i32 %v1, i32 %v2) personality i32 (...)* @__CxxFrameHandler3 {
|
||||||
|
; CHECK-LABEL: @test22(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: br label [[WHILE_COND:%.*]]
|
||||||
|
; CHECK: while.cond:
|
||||||
|
; CHECK-NEXT: br i1 [[B:%.*]], label [[TRY_CONT:%.*]], label [[WHILE_BODY:%.*]]
|
||||||
|
; CHECK: while.body:
|
||||||
|
; CHECK-NEXT: invoke void @may_throw()
|
||||||
|
; CHECK-NEXT: to label [[WHILE_BODY2:%.*]] unwind label [[LPADBB:%.*]]
|
||||||
|
; CHECK: while.body2:
|
||||||
|
; CHECK-NEXT: [[V:%.*]] = call i32 @getv()
|
||||||
|
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[V]], [[V2:%.*]]
|
||||||
|
; CHECK-NEXT: invoke void @may_throw2()
|
||||||
|
; CHECK-NEXT: to label [[WHILE_COND]] unwind label [[LPADBB]]
|
||||||
|
; CHECK: lpadBB:
|
||||||
|
; CHECK-NEXT: [[DOTLCSSA1:%.*]] = phi i32 [ 0, [[WHILE_BODY]] ], [ [[MUL]], [[WHILE_BODY2]] ]
|
||||||
|
; CHECK-NEXT: [[TMP0:%.*]] = landingpad { i8*, i32 }
|
||||||
|
; CHECK-NEXT: catch i8* null
|
||||||
|
; CHECK-NEXT: br label [[LPADBBSUCC1:%.*]]
|
||||||
|
; CHECK: lpadBBSucc1:
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
; CHECK: try.cont:
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %while.cond
|
br label %while.cond
|
||||||
while.cond:
|
while.cond:
|
||||||
|
|
|
@ -1,23 +1,25 @@
|
||||||
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||||
; RUN: opt < %s -sccp -loop-deletion -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
; RUN: opt < %s -sccp -loop-deletion -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||||
|
|
||||||
declare double @sqrt(double) readnone nounwind
|
declare double @sqrt(double) readnone nounwind
|
||||||
%empty = type {}
|
%empty = type {}
|
||||||
declare %empty @has_side_effects()
|
declare %empty @has_side_effects()
|
||||||
|
|
||||||
define double @test_0(i32 %param) {
|
|
||||||
; CHECK-LABEL: @test_0(
|
|
||||||
; CHECK-NOT: br
|
|
||||||
entry:
|
|
||||||
; No matter how hard you try, sqrt(1.0) is always 1.0. This allows the
|
; No matter how hard you try, sqrt(1.0) is always 1.0. This allows the
|
||||||
; optimizer to delete this loop.
|
; optimizer to delete this loop.
|
||||||
|
define double @test_0(i32 %param) {
|
||||||
|
; CHECK-LABEL: @test_0(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: ret double 1.000000e+00
|
||||||
|
;
|
||||||
|
entry:
|
||||||
br label %Loop
|
br label %Loop
|
||||||
Loop: ; preds = %Loop, %entry
|
Loop: ; preds = %Loop, %entry
|
||||||
%I2 = phi i32 [ 0, %entry ], [ %I3, %Loop ] ; <i32> [#uses=1]
|
%I2 = phi i32 [ 0, %entry ], [ %I3, %Loop ]
|
||||||
%V = phi double [ 1.000000e+00, %entry ], [ %V2, %Loop ] ; <double> [#uses=2]
|
%V = phi double [ 1.000000e+00, %entry ], [ %V2, %Loop ]
|
||||||
%V2 = call double @sqrt( double %V ) ; <double> [#uses=1]
|
%V2 = call double @sqrt( double %V )
|
||||||
%I3 = add i32 %I2, 1 ; <i32> [#uses=2]
|
%I3 = add i32 %I2, 1
|
||||||
%tmp.7 = icmp ne i32 %I3, %param ; <i1> [#uses=1]
|
%tmp.7 = icmp ne i32 %I3, %param
|
||||||
br i1 %tmp.7, label %Loop, label %Exit
|
br i1 %tmp.7, label %Loop, label %Exit
|
||||||
Exit: ; preds = %Loop
|
Exit: ; preds = %Loop
|
||||||
ret double %V
|
ret double %V
|
||||||
|
@ -25,7 +27,9 @@ Exit: ; preds = %Loop
|
||||||
|
|
||||||
define i32 @test_1() {
|
define i32 @test_1() {
|
||||||
; CHECK-LABEL: @test_1(
|
; CHECK-LABEL: @test_1(
|
||||||
; CHECK: call %empty @has_side_effects()
|
; CHECK-NEXT: [[TMP1:%.*]] = call [[EMPTY:%.*]] @has_side_effects()
|
||||||
|
; CHECK-NEXT: ret i32 0
|
||||||
|
;
|
||||||
%1 = call %empty @has_side_effects()
|
%1 = call %empty @has_side_effects()
|
||||||
ret i32 0
|
ret i32 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
|
||||||
; RUN: opt < %s -ipsccp -S | FileCheck %s
|
; RUN: opt < %s -ipsccp -S | FileCheck %s
|
||||||
; PR36485
|
; PR36485
|
||||||
; musttail call result can\'t be replaced with a constant, unless the call
|
; musttail call result can\'t be replaced with a constant, unless the call
|
||||||
|
@ -6,11 +7,25 @@
|
||||||
declare i32 @external()
|
declare i32 @external()
|
||||||
|
|
||||||
define i8* @start(i8 %v) {
|
define i8* @start(i8 %v) {
|
||||||
|
; CHECK-LABEL: define {{[^@]+}}@start
|
||||||
|
; CHECK-SAME: (i8 [[V:%.*]]) {
|
||||||
|
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0
|
||||||
|
; CHECK-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||||||
|
; CHECK: true:
|
||||||
|
; CHECK-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 0)
|
||||||
|
; CHECK-NEXT: ret i8* [[CA]]
|
||||||
|
; CHECK: false:
|
||||||
|
; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1
|
||||||
|
; CHECK-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]]
|
||||||
|
; CHECK: c2_true:
|
||||||
|
; CHECK-NEXT: ret i8* null
|
||||||
|
; CHECK: c2_false:
|
||||||
|
; CHECK-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 [[V]])
|
||||||
|
; CHECK-NEXT: ret i8* [[CA2]]
|
||||||
|
;
|
||||||
%c1 = icmp eq i8 %v, 0
|
%c1 = icmp eq i8 %v, 0
|
||||||
br i1 %c1, label %true, label %false
|
br i1 %c1, label %true, label %false
|
||||||
true:
|
true:
|
||||||
; CHECK: %ca = musttail call i8* @side_effects(i8 0)
|
|
||||||
; CHECK: ret i8* %ca
|
|
||||||
%ca = musttail call i8* @side_effects(i8 %v)
|
%ca = musttail call i8* @side_effects(i8 %v)
|
||||||
ret i8* %ca
|
ret i8* %ca
|
||||||
false:
|
false:
|
||||||
|
@ -18,41 +33,48 @@ false:
|
||||||
br i1 %c2, label %c2_true, label %c2_false
|
br i1 %c2, label %c2_true, label %c2_false
|
||||||
c2_true:
|
c2_true:
|
||||||
%ca1 = musttail call i8* @no_side_effects(i8 %v)
|
%ca1 = musttail call i8* @no_side_effects(i8 %v)
|
||||||
; CHECK: ret i8* null
|
|
||||||
ret i8* %ca1
|
ret i8* %ca1
|
||||||
c2_false:
|
c2_false:
|
||||||
; CHECK: %ca2 = musttail call i8* @dont_zap_me(i8 %v)
|
|
||||||
; CHECK: ret i8* %ca2
|
|
||||||
%ca2 = musttail call i8* @dont_zap_me(i8 %v)
|
%ca2 = musttail call i8* @dont_zap_me(i8 %v)
|
||||||
ret i8* %ca2
|
ret i8* %ca2
|
||||||
}
|
}
|
||||||
|
|
||||||
define internal i8* @side_effects(i8 %v) {
|
define internal i8* @side_effects(i8 %v) {
|
||||||
|
; CHECK-LABEL: define {{[^@]+}}@side_effects
|
||||||
|
; CHECK-SAME: (i8 [[V:%.*]]) {
|
||||||
|
; CHECK-NEXT: [[I1:%.*]] = call i32 @external()
|
||||||
|
; CHECK-NEXT: [[CA:%.*]] = musttail call i8* @start(i8 0)
|
||||||
|
; CHECK-NEXT: ret i8* [[CA]]
|
||||||
|
;
|
||||||
%i1 = call i32 @external()
|
%i1 = call i32 @external()
|
||||||
|
|
||||||
; since this goes back to `start` the SCPP should be see that the return value
|
; since this goes back to `start` the SCPP should be see that the return value
|
||||||
; is always `null`.
|
; is always `null`.
|
||||||
; The call can't be removed due to `external` call above, though.
|
; The call can't be removed due to `external` call above, though.
|
||||||
|
|
||||||
; CHECK: %ca = musttail call i8* @start(i8 0)
|
|
||||||
%ca = musttail call i8* @start(i8 %v)
|
%ca = musttail call i8* @start(i8 %v)
|
||||||
|
|
||||||
; Thus the result must be returned anyway
|
; Thus the result must be returned anyway
|
||||||
; CHECK: ret i8* %ca
|
|
||||||
ret i8* %ca
|
ret i8* %ca
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; The call to this function is removed, so the return value must be zapped
|
||||||
define internal i8* @no_side_effects(i8 %v) readonly nounwind {
|
define internal i8* @no_side_effects(i8 %v) readonly nounwind {
|
||||||
; The call to this function is removed, so the return value must be zapped
|
; CHECK-LABEL: define {{[^@]+}}@no_side_effects
|
||||||
; CHECK: ret i8* undef
|
; CHECK-SAME: (i8 [[V:%.*]]) #[[ATTR0:[0-9]+]] {
|
||||||
|
; CHECK-NEXT: ret i8* undef
|
||||||
|
;
|
||||||
ret i8* null
|
ret i8* null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; The call to this function cannot be removed due to side effects. Thus the
|
||||||
|
; return value should stay as it is, and should not be zapped.
|
||||||
define internal i8* @dont_zap_me(i8 %v) {
|
define internal i8* @dont_zap_me(i8 %v) {
|
||||||
|
; CHECK-LABEL: define {{[^@]+}}@dont_zap_me
|
||||||
|
; CHECK-SAME: (i8 [[V:%.*]]) {
|
||||||
|
; CHECK-NEXT: [[I1:%.*]] = call i32 @external()
|
||||||
|
; CHECK-NEXT: ret i8* null
|
||||||
|
;
|
||||||
%i1 = call i32 @external()
|
%i1 = call i32 @external()
|
||||||
|
|
||||||
; The call to this function cannot be removed due to side effects. Thus the
|
|
||||||
; return value should stay as it is, and should not be zapped.
|
|
||||||
; CHECK: ret i8* null
|
|
||||||
ret i8* null
|
ret i8* null
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,27 @@
|
||||||
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||||
; RUN: opt < %s -S -ipsccp | FileCheck %s
|
; RUN: opt < %s -S -ipsccp | FileCheck %s
|
||||||
; PR5596
|
; PR5596
|
||||||
|
|
||||||
; IPSCCP should propagate the 0 argument, eliminate the switch, and propagate
|
; IPSCCP should propagate the 0 argument, eliminate the switch, and propagate
|
||||||
; the result.
|
; the result.
|
||||||
|
|
||||||
; CHECK: define i32 @main() #0 {
|
|
||||||
; CHECK-NEXT: entry:
|
|
||||||
; CHECK-NOT: call
|
|
||||||
; CHECK-NEXT: ret i32 123
|
|
||||||
|
|
||||||
define i32 @main() noreturn nounwind {
|
define i32 @main() noreturn nounwind {
|
||||||
|
; CHECK-LABEL: @main(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: ret i32 123
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
%call2 = tail call i32 @wwrite(i64 0) nounwind
|
%call2 = tail call i32 @wwrite(i64 0) nounwind
|
||||||
ret i32 %call2
|
ret i32 %call2
|
||||||
}
|
}
|
||||||
|
|
||||||
define internal i32 @wwrite(i64 %i) nounwind readnone {
|
define internal i32 @wwrite(i64 %i) nounwind readnone {
|
||||||
|
; CHECK-LABEL: @wwrite(
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: br label [[SW_DEFAULT:%.*]]
|
||||||
|
; CHECK: sw.default:
|
||||||
|
; CHECK-NEXT: ret i32 undef
|
||||||
|
;
|
||||||
entry:
|
entry:
|
||||||
switch i64 %i, label %sw.default [
|
switch i64 %i, label %sw.default [
|
||||||
i64 3, label %return
|
i64 3, label %return
|
||||||
|
|
Loading…
Reference in New Issue