forked from OSchip/llvm-project
[NFC][SimplifyCFG] Autogenerate check lines in many test files
These are potentially being affected by an upcoming patch.
This commit is contained in:
parent
8de7d8b2c2
commit
e4c61d5f83
|
@ -1,4 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by update_test_checks.py
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
|
||||
; Test normal folding
|
||||
|
@ -71,9 +71,9 @@ TheDest:
|
|||
define i32 @test4(i32 %C) {
|
||||
; CHECK-LABEL: @test4(
|
||||
; CHECK-NEXT: L1:
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 %C, 0
|
||||
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[COND]], i32 1, i32 0
|
||||
; CHECK-NEXT: ret i32 [[DOT]]
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[C:%.*]], 0
|
||||
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[COND]], i32 1, i32 0
|
||||
; CHECK-NEXT: ret i32 [[SPEC_SELECT]]
|
||||
;
|
||||
switch i32 %C, label %L1 [
|
||||
i32 0, label %L2
|
||||
|
@ -88,9 +88,9 @@ L2:
|
|||
define i32 @test5(i32 %C) {
|
||||
; CHECK-LABEL: @test5(
|
||||
; CHECK-NEXT: L1:
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 %C, 0
|
||||
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[COND]], i32 1, i32 0
|
||||
; CHECK-NEXT: ret i32 [[DOT]]
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[C:%.*]], 0
|
||||
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[COND]], i32 1, i32 0
|
||||
; CHECK-NEXT: ret i32 [[SPEC_SELECT]]
|
||||
;
|
||||
switch i32 %C, label %L1 [
|
||||
i32 0, label %L2
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
define void @foo(i1 %C, i32* %P) {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: store i32 7, i32* [[P:%.*]]
|
||||
; CHECK-NEXT: store i32 7, i32* [[P:%.*]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
br i1 %C, label %T, label %F
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck -enable-var-scope %s
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
|
||||
target datalayout = "E-m:e-i64:64-n32:64"
|
||||
target triple = "powerpc64-unknown-linux-gnu"
|
||||
|
||||
define i64 @test1(i64 %A) {
|
||||
; CHECK-LABEL: @test1(
|
||||
; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
|
||||
; CHECK-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
|
||||
; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTLZ]]
|
||||
; CHECK-NEXT: ret i64 [[SEL]]
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A:%.*]], 0
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[A]], i1 true)
|
||||
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i64 64, i64 [[TMP0]]
|
||||
; CHECK-NEXT: ret i64 [[SPEC_SELECT]]
|
||||
;
|
||||
entry:
|
||||
%tobool = icmp eq i64 %A, 0
|
||||
br i1 %tobool, label %cond.end, label %cond.true
|
||||
|
@ -23,10 +26,12 @@ cond.end: ; preds = %entry, %cond.true
|
|||
|
||||
define i64 @test1b(i64 %A) {
|
||||
; CHECK-LABEL: @test1b(
|
||||
; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
|
||||
; CHECK-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
|
||||
; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTTZ]]
|
||||
; CHECK-NEXT: ret i64 [[SEL]]
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A:%.*]], 0
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.cttz.i64(i64 [[A]], i1 true)
|
||||
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL]], i64 64, i64 [[TMP0]]
|
||||
; CHECK-NEXT: ret i64 [[SPEC_SELECT]]
|
||||
;
|
||||
entry:
|
||||
%tobool = icmp eq i64 %A, 0
|
||||
br i1 %tobool, label %cond.end, label %cond.true
|
||||
|
|
|
@ -51,7 +51,7 @@ define i32 @bar(i32 %c) {
|
|||
; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
|
||||
; CHECK: switch.lookup:
|
||||
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.bar, i32 0, i32 [[SWITCH_TABLEIDX]]
|
||||
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]]
|
||||
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4
|
||||
; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
|
||||
; CHECK: return:
|
||||
; CHECK-NEXT: ret i32 15
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S -hoist-common-insts=true | FileCheck %s
|
||||
|
||||
; ModuleID = 'cppeh-simplify.cpp'
|
||||
|
@ -16,14 +17,12 @@ target triple = "x86_64-pc-windows-msvc18.0.0"
|
|||
; In this case, both cleanup pads can be eliminated and the invoke can be
|
||||
; converted to a call.
|
||||
;
|
||||
; CHECK: define void @f1()
|
||||
; CHECK: entry:
|
||||
; CHECK: call void @g()
|
||||
; CHECK: ret void
|
||||
; CHECK-NOT: cleanuppad
|
||||
; CHECK: }
|
||||
;
|
||||
define void @f1() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
; CHECK-LABEL: @f1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: call void @g()
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
invoke void @g() to label %invoke.cont unwind label %ehcleanup
|
||||
|
||||
|
@ -56,22 +55,24 @@ ehcleanup.1: ; preds = %ehcleanup
|
|||
; should unwind to the caller (that is, exception handling continues with the
|
||||
; parent frame of the caller).
|
||||
;
|
||||
; CHECK: define void @f2()
|
||||
; CHECK: entry:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK: ehcleanup:
|
||||
; CHECK: cleanuppad within none
|
||||
; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %b)
|
||||
; CHECK: cleanupret from %0 unwind label %catch.dispatch
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK: catchswitch within none [label %catch] unwind to caller
|
||||
; CHECK: catch:
|
||||
; CHECK: catchpad
|
||||
; CHECK: catchret
|
||||
; CHECK-NOT: cleanuppad
|
||||
; CHECK: }
|
||||
;
|
||||
define void @f2() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
; CHECK-LABEL: @f2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[B:%.*]] = alloca [[STRUCT_S2:%.*]], align 1
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[TRY_CONT:%.*]] unwind label [[EHCLEANUP:%.*]]
|
||||
; CHECK: ehcleanup:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = cleanuppad within none []
|
||||
; CHECK-NEXT: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* [[B]])
|
||||
; CHECK-NEXT: cleanupret from [[TMP0]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind to caller
|
||||
; CHECK: catch:
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = catchpad within [[CS1]] [i8* null, i32 64, i8* null]
|
||||
; CHECK-NEXT: catchret from [[TMP1]] to label [[TRY_CONT]]
|
||||
; CHECK: try.cont:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%b = alloca %struct.S2, align 1
|
||||
invoke void @g() to label %invoke.cont unwind label %ehcleanup
|
||||
|
@ -117,23 +118,25 @@ ehcleanup.1:
|
|||
;
|
||||
; In this case the inner cleanup pad should be eliminated and the invoke of g()
|
||||
; should unwind directly to the catchpad.
|
||||
;
|
||||
; CHECK-LABEL: define void @f3()
|
||||
; CHECK: entry:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK: to label %try.cont unwind label %catch.dispatch
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: catchswitch within none [label %catch] unwind label %ehcleanup.1
|
||||
; CHECK: catch:
|
||||
; CHECK: catchpad within %cs1 [i8* null, i32 64, i8* null]
|
||||
; CHECK: catchret
|
||||
; CHECK: ehcleanup.1:
|
||||
; CHECK: cleanuppad
|
||||
; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a)
|
||||
; CHECK: cleanupret from %cp3 unwind to caller
|
||||
; CHECK: }
|
||||
;
|
||||
|
||||
define void @f3() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
; CHECK-LABEL: @f3(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_S2:%.*]], align 1
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[TRY_CONT:%.*]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind label [[EHCLEANUP_1:%.*]]
|
||||
; CHECK: catch:
|
||||
; CHECK-NEXT: [[CP2:%.*]] = catchpad within [[CS1]] [i8* null, i32 64, i8* null]
|
||||
; CHECK-NEXT: catchret from [[CP2]] to label [[TRY_CONT]]
|
||||
; CHECK: try.cont:
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: ehcleanup.1:
|
||||
; CHECK-NEXT: [[CP3:%.*]] = cleanuppad within none []
|
||||
; CHECK-NEXT: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* [[A]])
|
||||
; CHECK-NEXT: cleanupret from [[CP3]] unwind to caller
|
||||
;
|
||||
entry:
|
||||
%a = alloca %struct.S2, align 1
|
||||
invoke void @g() to label %invoke.cont unwind label %ehcleanup
|
||||
|
@ -180,29 +183,30 @@ ehcleanup.1:
|
|||
; catch block should be converted to a call (that is, that is, exception
|
||||
; handling continues with the parent frame of the caller).)
|
||||
;
|
||||
; CHECK-LABEL: define void @f4()
|
||||
; CHECK: entry:
|
||||
; CHECK: call void @g
|
||||
; Note: The cleanuppad simplification will insert an unconditional branch here
|
||||
; but it will be eliminated, placing the following invoke in the entry BB.
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK: to label %try.cont unwind label %catch.dispatch
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK: catchswitch within none [label %catch] unwind to caller
|
||||
; CHECK: catch:
|
||||
; CHECK: catchpad
|
||||
; CHECK: catchret
|
||||
; CHECK-NOT: cleanuppad
|
||||
; CHECK: }
|
||||
;
|
||||
define void @f4() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
; CHECK-LABEL: @f4(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: call void @g()
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[TRY_CONT:%.*]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind to caller
|
||||
; CHECK: catch:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS1]] [i8* null, i32 64, i8* null]
|
||||
; CHECK-NEXT: catchret from [[TMP0]] to label [[TRY_CONT]]
|
||||
; CHECK: try.cont:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
invoke void @g()
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
|
||||
invoke.cont: ; preds = %entry
|
||||
invoke void @g()
|
||||
to label %try.cont unwind label %catch.dispatch
|
||||
to label %try.cont unwind label %catch.dispatch
|
||||
|
||||
catch.dispatch: ; preds = %invoke.cont
|
||||
%cs1 = catchswitch within none [label %catch] unwind label %ehcleanup
|
||||
|
@ -238,24 +242,31 @@ ehcleanup:
|
|||
; In this case, the cleanup pad should be eliminated and the PHI node in the
|
||||
; cleanup pad should be sunk into the catch dispatch block.
|
||||
;
|
||||
; CHECK-LABEL: define i32 @f6()
|
||||
; CHECK: entry:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK-NOT: ehcleanup:
|
||||
; CHECK-NOT: cleanuppad
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK: %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
|
||||
; CHECK: }
|
||||
define i32 @f6() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
; CHECK-LABEL: @f6(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[RETURN:%.*]] unwind label [[CATCH_DISPATCH]]
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: [[STATE_0:%.*]] = phi i32 [ 2, [[INVOKE_CONT]] ], [ 1, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind to caller
|
||||
; CHECK: catch:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS1]] [i8* null, i32 64, i8* null]
|
||||
; CHECK-NEXT: catchret from [[TMP0]] to label [[RETURN]]
|
||||
; CHECK: return:
|
||||
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[STATE_0]], [[CATCH:%.*]] ], [ 0, [[INVOKE_CONT]] ]
|
||||
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
||||
;
|
||||
entry:
|
||||
invoke void @g()
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
|
||||
invoke.cont: ; preds = %entry
|
||||
invoke void @g()
|
||||
to label %return unwind label %ehcleanup
|
||||
to label %return unwind label %ehcleanup
|
||||
|
||||
ehcleanup: ; preds = %invoke.cont, %entry
|
||||
%state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
|
||||
|
@ -295,30 +306,38 @@ return: ; preds = %invoke.cont, %catch
|
|||
; In this case, the cleanup pad should be eliminated and the PHI node in the
|
||||
; cleanup pad should be merged with the PHI node in the catch dispatch block.
|
||||
;
|
||||
; CHECK-LABEL: define i32 @f7()
|
||||
; CHECK: entry:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK: invoke.cont.1:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK-NOT: ehcleanup:
|
||||
; CHECK-NOT: cleanuppad
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK: %state.1 = phi i32 [ 1, %entry ], [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ]
|
||||
; CHECK: }
|
||||
define i32 @f7() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
; CHECK-LABEL: @f7(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT_1:%.*]] unwind label [[CATCH_DISPATCH]]
|
||||
; CHECK: invoke.cont.1:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[RETURN:%.*]] unwind label [[CATCH_DISPATCH]]
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: [[STATE_1:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 3, [[INVOKE_CONT_1]] ], [ 2, [[INVOKE_CONT]] ]
|
||||
; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind to caller
|
||||
; CHECK: catch:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS1]] [i8* null, i32 64, i8* null]
|
||||
; CHECK-NEXT: catchret from [[TMP0]] to label [[RETURN]]
|
||||
; CHECK: return:
|
||||
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[STATE_1]], [[CATCH:%.*]] ], [ 0, [[INVOKE_CONT_1]] ]
|
||||
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
||||
;
|
||||
entry:
|
||||
invoke void @g()
|
||||
to label %invoke.cont unwind label %catch.dispatch
|
||||
to label %invoke.cont unwind label %catch.dispatch
|
||||
|
||||
invoke.cont: ; preds = %entry
|
||||
invoke void @g()
|
||||
to label %invoke.cont.1 unwind label %ehcleanup
|
||||
to label %invoke.cont.1 unwind label %ehcleanup
|
||||
|
||||
invoke.cont.1: ; preds = %invoke.cont
|
||||
invoke void @g()
|
||||
to label %return unwind label %ehcleanup
|
||||
to label %return unwind label %ehcleanup
|
||||
|
||||
ehcleanup: ; preds = %invoke.cont.1, %invoke.cont
|
||||
%state.0 = phi i32 [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ]
|
||||
|
@ -365,24 +384,34 @@ return: ; preds = %invoke.cont.1, %cat
|
|||
; should have an incoming value entry for path from 'foo' that references the
|
||||
; PHI node itself.
|
||||
;
|
||||
; CHECK-LABEL: define void @f8()
|
||||
; CHECK: entry:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK-NOT: ehcleanup:
|
||||
; CHECK-NOT: cleanuppad
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK: %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ], [ %x, %catch.cont ]
|
||||
; CHECK: }
|
||||
define void @f8() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
; CHECK-LABEL: @f8(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[RETURN:%.*]] unwind label [[CATCH_DISPATCH]]
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: [[X:%.*]] = phi i32 [ 2, [[INVOKE_CONT]] ], [ 1, [[ENTRY:%.*]] ], [ [[X]], [[CATCH_CONT:%.*]] ]
|
||||
; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind to caller
|
||||
; CHECK: catch:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS1]] [i8* null, i32 64, i8* null]
|
||||
; CHECK-NEXT: call void @use_x(i32 [[X]])
|
||||
; CHECK-NEXT: catchret from [[TMP0]] to label [[CATCH_CONT]]
|
||||
; CHECK: catch.cont:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[RETURN]] unwind label [[CATCH_DISPATCH]]
|
||||
; CHECK: return:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
invoke void @g()
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
|
||||
invoke.cont: ; preds = %entry
|
||||
invoke void @g()
|
||||
to label %return unwind label %ehcleanup
|
||||
to label %return unwind label %ehcleanup
|
||||
|
||||
ehcleanup: ; preds = %invoke.cont, %entry
|
||||
%x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
|
||||
|
@ -399,24 +428,33 @@ catch: ; preds = %catch.dispatch
|
|||
|
||||
catch.cont: ; preds = %catch
|
||||
invoke void @g()
|
||||
to label %return unwind label %catch.dispatch
|
||||
to label %return unwind label %catch.dispatch
|
||||
|
||||
return: ; preds = %invoke.cont, %catch.cont
|
||||
ret void
|
||||
}
|
||||
; CHECK-LABEL: define i32 @f9()
|
||||
; CHECK: entry:
|
||||
; CHECK: invoke void @"\01??1S2@@QEAA@XZ"(
|
||||
; CHECK-NOT: cleanuppad
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK: }
|
||||
define i32 @f9() personality i32 (...)* @__CxxFrameHandler3 {
|
||||
; CHECK-LABEL: @f9(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[S:%.*]] = alloca i8, align 1
|
||||
; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[S]])
|
||||
; CHECK-NEXT: [[BC:%.*]] = bitcast i8* [[S]] to %struct.S2*
|
||||
; CHECK-NEXT: invoke void @"\01??1S2@@QEAA@XZ"(%struct.S2* [[BC]])
|
||||
; CHECK-NEXT: to label [[TRY_CONT:%.*]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: [[CATCH_SWITCH:%.*]] = catchswitch within none [label %catch] unwind to caller
|
||||
; CHECK: catch:
|
||||
; CHECK-NEXT: [[CATCH_PAD:%.*]] = catchpad within [[CATCH_SWITCH]] [i8* null, i32 0, i8* null]
|
||||
; CHECK-NEXT: catchret from [[CATCH_PAD]] to label [[TRY_CONT]]
|
||||
; CHECK: try.cont:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
entry:
|
||||
%s = alloca i8, align 1
|
||||
call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %s)
|
||||
%bc = bitcast i8* %s to %struct.S2*
|
||||
invoke void @"\01??1S2@@QEAA@XZ"(%struct.S2* %bc)
|
||||
to label %try.cont unwind label %ehcleanup
|
||||
to label %try.cont unwind label %ehcleanup
|
||||
|
||||
ehcleanup:
|
||||
%cleanup.pad = cleanuppad within none []
|
||||
|
@ -434,13 +472,15 @@ try.cont:
|
|||
ret i32 0
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define void @f10(
|
||||
define void @f10(i32 %V) personality i32 (...)* @__CxxFrameHandler3 {
|
||||
; CHECK-LABEL: @f10(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: call void @g()
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
entry:
|
||||
invoke void @g()
|
||||
to label %unreachable unwind label %cleanup
|
||||
; CHECK: call void @g()
|
||||
; CHECK-NEXT: unreachable
|
||||
to label %unreachable unwind label %cleanup
|
||||
|
||||
unreachable:
|
||||
unreachable
|
||||
|
@ -448,7 +488,7 @@ unreachable:
|
|||
cleanup:
|
||||
%cp = cleanuppad within none []
|
||||
switch i32 %V, label %cleanupret1 [
|
||||
i32 0, label %cleanupret2
|
||||
i32 0, label %cleanupret2
|
||||
]
|
||||
|
||||
cleanupret1:
|
||||
|
@ -458,37 +498,39 @@ cleanupret2:
|
|||
cleanupret from %cp unwind to caller
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define void @f11(
|
||||
; This case tests the handling of an empty cleanup pad that
|
||||
; contains a lifetime_end intrinsic and does not dominate its
|
||||
; successor.
|
||||
; CHECK: entry:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK: invoke.cont2:
|
||||
; CHECK: invoke void @g()
|
||||
; CHECK-NOT: ehcleanup:
|
||||
; CHECK-NOT: phi
|
||||
; CHECK-NOT: cleanuppad
|
||||
; CHECK-NOT: lifetime.end
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK: catchswitch
|
||||
; CHECK: catch:
|
||||
; CHECK: catchret
|
||||
; CHECK: }
|
||||
define void @f11() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
|
||||
; CHECK-LABEL: @f11(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[CATCH_DISPATCH:%.*]]
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[CATCH_DISPATCH]]
|
||||
; CHECK: invoke.cont2:
|
||||
; CHECK-NEXT: invoke void @g()
|
||||
; CHECK-NEXT: to label [[RETURN:%.*]] unwind label [[CATCH_DISPATCH]]
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind to caller
|
||||
; CHECK: catch:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS1]] [i8* null, i32 64, i8* null]
|
||||
; CHECK-NEXT: catchret from [[TMP0]] to label [[RETURN]]
|
||||
; CHECK: return:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
invoke void @g()
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
|
||||
invoke.cont: ; preds = %entry
|
||||
invoke void @g()
|
||||
to label %invoke.cont2 unwind label %ehcleanup
|
||||
to label %invoke.cont2 unwind label %ehcleanup
|
||||
|
||||
invoke.cont2: ; preds = %invoke.cont
|
||||
invoke void @g()
|
||||
to label %return unwind label %catch.dispatch
|
||||
to label %return unwind label %catch.dispatch
|
||||
|
||||
ehcleanup: ; preds = %invoke.cont, %entry
|
||||
%x = phi i8* [ undef, %invoke.cont ], [ undef, %entry ]
|
||||
|
|
|
@ -8,14 +8,14 @@ define void @test_costly(i32* %p, i32 %a, i32 %b, i32 %c, i32 %d) {
|
|||
; CHECK-NEXT: br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
|
||||
; CHECK: yes1:
|
||||
; CHECK-NEXT: [[VAL0:%.*]] = sdiv i32 [[D:%.*]], [[C:%.*]]
|
||||
; CHECK-NEXT: store i32 [[VAL0]], i32* [[P:%.*]]
|
||||
; CHECK-NEXT: store i32 [[VAL0]], i32* [[P:%.*]], align 4
|
||||
; CHECK-NEXT: br label [[FALLTHROUGH]]
|
||||
; CHECK: fallthrough:
|
||||
; CHECK-NEXT: [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0
|
||||
; CHECK-NEXT: br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
|
||||
; CHECK: yes2:
|
||||
; CHECK-NEXT: [[VAL1:%.*]] = sdiv i32 [[C]], [[D]]
|
||||
; CHECK-NEXT: store i32 [[VAL1]], i32* [[P]]
|
||||
; CHECK-NEXT: store i32 [[VAL1]], i32* [[P]], align 4
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: ret void
|
||||
|
|
|
@ -1,39 +1,46 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; Test CFG simplify removal of branch instructions.
|
||||
;
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
; RUN: opt < %s -passes=simplify-cfg -S | FileCheck %s
|
||||
|
||||
define void @test1() {
|
||||
br label %1
|
||||
ret void
|
||||
; CHECK-LABEL: @test1(
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
br label %1
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test2() {
|
||||
ret void
|
||||
ret void
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
ret void
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test3(i1 %T) {
|
||||
br i1 %T, label %1, label %1
|
||||
ret void
|
||||
; CHECK-LABEL: @test3(
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
br i1 %T, label %1, label %1
|
||||
ret void
|
||||
}
|
||||
|
||||
; Folding branch to a common destination.
|
||||
; CHECK-LABEL: @test4_fold
|
||||
; CHECK: %cmp1 = icmp eq i32 %a, %b
|
||||
; CHECK: %cmp2 = icmp ugt i32 %a, 0
|
||||
; CHECK: %or.cond = and i1 %cmp1, %cmp2
|
||||
; CHECK: br i1 %or.cond, label %else, label %untaken
|
||||
; CHECK-NOT: taken:
|
||||
; CHECK: ret void
|
||||
define void @test4_fold(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: @test4_fold(
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[A]], 0
|
||||
; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: br i1 [[OR_COND]], label [[ELSE:%.*]], label [[UNTAKEN:%.*]]
|
||||
; CHECK: else:
|
||||
; CHECK-NEXT: call void @foo()
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: untaken:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%cmp1 = icmp eq i32 %a, %b
|
||||
br i1 %cmp1, label %taken, label %untaken
|
||||
|
||||
|
@ -51,12 +58,12 @@ untaken:
|
|||
|
||||
; Prefer a simplification based on a dominating condition rather than folding a
|
||||
; branch to a common destination.
|
||||
; CHECK-LABEL: @test4
|
||||
; CHECK-NOT: br
|
||||
; CHECK-NOT: br
|
||||
; CHECK-NOT: call
|
||||
; CHECK: ret void
|
||||
define void @test4_no_fold(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: @test4_no_fold(
|
||||
; CHECK-NEXT: untaken:
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%cmp1 = icmp eq i32 %a, %b
|
||||
br i1 %cmp1, label %taken, label %untaken
|
||||
|
||||
|
@ -76,9 +83,12 @@ declare void @foo()
|
|||
|
||||
; PR5795
|
||||
define void @test5(i32 %A) {
|
||||
; CHECK-LABEL: @test5(
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
switch i32 %A, label %return [
|
||||
i32 2, label %1
|
||||
i32 10, label %2
|
||||
i32 2, label %1
|
||||
i32 10, label %2
|
||||
]
|
||||
|
||||
ret void
|
||||
|
@ -87,18 +97,22 @@ define void @test5(i32 %A) {
|
|||
|
||||
return: ; preds = %entry
|
||||
ret void
|
||||
; CHECK-LABEL: @test5(
|
||||
; CHECK-NEXT: ret void
|
||||
}
|
||||
|
||||
|
||||
; PR14893
|
||||
define i8 @test6f() {
|
||||
; CHECK-LABEL: @test6f
|
||||
; CHECK: alloca i8, align 1
|
||||
; CHECK-NEXT: call i8 @test6g
|
||||
; CHECK-NEXT: icmp eq i8 %tmp, 0
|
||||
; CHECK-NEXT: load i8, i8* %r, align 1{{$}}
|
||||
; CHECK-LABEL: @test6f(
|
||||
; CHECK-NEXT: bb0:
|
||||
; CHECK-NEXT: [[R:%.*]] = alloca i8, align 1
|
||||
; CHECK-NEXT: [[TMP:%.*]] = call i8 @test6g(i8* [[R]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[TMP]], 0
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = load i8, i8* [[R]], align 1
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i8 [[TMP3]], 1
|
||||
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP1]], i1 true, i1 [[TMP4]]
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[OR_COND]], i8 0, i8 1
|
||||
; CHECK-NEXT: ret i8 [[TMP6]]
|
||||
;
|
||||
|
||||
bb0:
|
||||
%r = alloca i8, align 1
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
|
||||
|
||||
; We could hoist the div/rem in these tests because it's safe to do so.
|
||||
|
@ -7,14 +8,14 @@
|
|||
define i32 @hoist_sdiv(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: @hoist_sdiv(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[REM:%.*]] = srem i32 %a, %b
|
||||
; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 42
|
||||
; CHECK-NEXT: br i1 [[CMP]], label %if, label %end
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
|
||||
; CHECK: if:
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %a, %b
|
||||
; CHECK-NEXT: br label %end
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A]], [[B]]
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ 3, %entry ]
|
||||
; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
entry:
|
||||
|
@ -34,14 +35,14 @@ end:
|
|||
define i64 @hoist_udiv(i64 %a, i64 %b) {
|
||||
; CHECK-LABEL: @hoist_udiv(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[REM:%.*]] = urem i64 %a, %b
|
||||
; CHECK-NEXT: [[REM:%.*]] = urem i64 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[REM]], 42
|
||||
; CHECK-NEXT: br i1 [[CMP]], label %if, label %end
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
|
||||
; CHECK: if:
|
||||
; CHECK-NEXT: [[DIV:%.*]] = udiv i64 %a, %b
|
||||
; CHECK-NEXT: br label %end
|
||||
; CHECK-NEXT: [[DIV:%.*]] = udiv i64 [[A]], [[B]]
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[RET:%.*]] = phi i64 [ [[DIV]], %if ], [ 3, %entry ]
|
||||
; CHECK-NEXT: [[RET:%.*]] = phi i64 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: ret i64 [[RET]]
|
||||
;
|
||||
entry:
|
||||
|
@ -61,14 +62,14 @@ end:
|
|||
define i16 @hoist_srem(i16 %a, i16 %b) {
|
||||
; CHECK-LABEL: @hoist_srem(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 %a, %b
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[DIV]], 42
|
||||
; CHECK-NEXT: br i1 [[CMP]], label %if, label %end
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
|
||||
; CHECK: if:
|
||||
; CHECK-NEXT: [[REM:%.*]] = srem i16 %a, %b
|
||||
; CHECK-NEXT: br label %end
|
||||
; CHECK-NEXT: [[REM:%.*]] = srem i16 [[A]], [[B]]
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[RET:%.*]] = phi i16 [ [[REM]], %if ], [ 3, %entry ]
|
||||
; CHECK-NEXT: [[RET:%.*]] = phi i16 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: ret i16 [[RET]]
|
||||
;
|
||||
entry:
|
||||
|
@ -88,14 +89,14 @@ end:
|
|||
define i8 @hoist_urem(i8 %a, i8 %b) {
|
||||
; CHECK-LABEL: @hoist_urem(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 %a, %b
|
||||
; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[DIV]], 42
|
||||
; CHECK-NEXT: br i1 [[CMP]], label %if, label %end
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
|
||||
; CHECK: if:
|
||||
; CHECK-NEXT: [[REM:%.*]] = urem i8 %a, %b
|
||||
; CHECK-NEXT: br label %end
|
||||
; CHECK-NEXT: [[REM:%.*]] = urem i8 [[A]], [[B]]
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[RET:%.*]] = phi i8 [ [[REM]], %if ], [ 3, %entry ]
|
||||
; CHECK-NEXT: [[RET:%.*]] = phi i8 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: ret i8 [[RET]]
|
||||
;
|
||||
entry:
|
||||
|
|
|
@ -64,15 +64,15 @@ merge_block:
|
|||
define i32 @f_3(i1* %c, i32* %buf) {
|
||||
; CHECK-LABEL: @f_3(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[C0:%.*]] = load volatile i1, i1* [[C:%.*]]
|
||||
; CHECK-NEXT: [[C0:%.*]] = load volatile i1, i1* [[C:%.*]], align 1
|
||||
; CHECK-NEXT: br i1 [[C0]], label [[GUARD_BLOCK:%.*]], label [[MERGE_BLOCK:%.*]]
|
||||
; CHECK: guard_block:
|
||||
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK: merge_block:
|
||||
; CHECK-NEXT: [[C1:%.*]] = load volatile i1, i1* [[C]]
|
||||
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[C1]], i32 50, i32 100
|
||||
; CHECK-NEXT: ret i32 [[DOT]]
|
||||
; CHECK-NEXT: [[C1:%.*]] = load volatile i1, i1* [[C]], align 1
|
||||
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C1]], i32 50, i32 100
|
||||
; CHECK-NEXT: ret i32 [[SPEC_SELECT]]
|
||||
;
|
||||
entry:
|
||||
%c0 = load volatile i1, i1* %c
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt %s -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 | FileCheck %s
|
||||
; Check for when one branch implies the value of a successors conditional and
|
||||
; it's not simply the same conditional repeated.
|
||||
|
||||
define void @test(i32 %length.i, i32 %i) {
|
||||
; CHECK-LABEL: @test
|
||||
; CHECK-LABEL: @test(
|
||||
; CHECK-NEXT: [[IPLUS1:%.*]] = add nsw i32 [[I:%.*]], 1
|
||||
; CHECK-NEXT: [[VAR29:%.*]] = icmp slt i32 [[IPLUS1]], [[LENGTH_I:%.*]]
|
||||
; CHECK-NEXT: br i1 [[VAR29]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS:%.*]]
|
||||
; CHECK: in_bounds:
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: out_of_bounds:
|
||||
; CHECK-NEXT: call void @foo(i64 0)
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
%iplus1 = add nsw i32 %i, 1
|
||||
%var29 = icmp slt i32 %iplus1, %length.i
|
||||
; CHECK: br i1 %var29, label %in_bounds, label %out_of_bounds
|
||||
br i1 %var29, label %next, label %out_of_bounds
|
||||
|
||||
next:
|
||||
; CHECK-LABEL: in_bounds:
|
||||
; CHECK-NEXT: ret void
|
||||
%var30 = icmp slt i32 %i, %length.i
|
||||
br i1 %var30, label %in_bounds, label %out_of_bounds2
|
||||
|
||||
|
@ -30,15 +37,28 @@ out_of_bounds2:
|
|||
; If the add is not nsw, it's not safe to use the fact about i+1 to imply the
|
||||
; i condition since it could have overflowed.
|
||||
define void @test_neg(i32 %length.i, i32 %i) {
|
||||
; CHECK-LABEL: @test_neg
|
||||
; CHECK-LABEL: @test_neg(
|
||||
; CHECK-NEXT: [[IPLUS1:%.*]] = add i32 [[I:%.*]], 1
|
||||
; CHECK-NEXT: [[VAR29:%.*]] = icmp slt i32 [[IPLUS1]], [[LENGTH_I:%.*]]
|
||||
; CHECK-NEXT: br i1 [[VAR29]], label [[NEXT:%.*]], label [[OUT_OF_BOUNDS:%.*]]
|
||||
; CHECK: next:
|
||||
; CHECK-NEXT: [[VAR30:%.*]] = icmp slt i32 [[I]], [[LENGTH_I]]
|
||||
; CHECK-NEXT: br i1 [[VAR30]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS2:%.*]]
|
||||
; CHECK: in_bounds:
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: out_of_bounds:
|
||||
; CHECK-NEXT: call void @foo(i64 0)
|
||||
; CHECK-NEXT: unreachable
|
||||
; CHECK: out_of_bounds2:
|
||||
; CHECK-NEXT: call void @foo(i64 1)
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
%iplus1 = add i32 %i, 1
|
||||
%var29 = icmp slt i32 %iplus1, %length.i
|
||||
; CHECK: br i1 %var29, label %next, label %out_of_bounds
|
||||
br i1 %var29, label %next, label %out_of_bounds
|
||||
|
||||
next:
|
||||
%var30 = icmp slt i32 %i, %length.i
|
||||
; CHECK: br i1 %var30, label %in_bounds, label %out_of_bounds2
|
||||
br i1 %var30, label %in_bounds, label %out_of_bounds2
|
||||
|
||||
in_bounds:
|
||||
|
@ -55,10 +75,18 @@ out_of_bounds2:
|
|||
|
||||
|
||||
define void @test2(i32 %length.i, i32 %i) {
|
||||
; CHECK-LABEL: @test2
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK-NEXT: [[IPLUS100:%.*]] = add nsw i32 [[I:%.*]], 100
|
||||
; CHECK-NEXT: [[VAR29:%.*]] = icmp slt i32 [[IPLUS100]], [[LENGTH_I:%.*]]
|
||||
; CHECK-NEXT: br i1 [[VAR29]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS:%.*]]
|
||||
; CHECK: in_bounds:
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: out_of_bounds:
|
||||
; CHECK-NEXT: call void @foo(i64 0)
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
%iplus100 = add nsw i32 %i, 100
|
||||
%var29 = icmp slt i32 %iplus100, %length.i
|
||||
; CHECK: br i1 %var29, label %in_bounds, label %out_of_bounds
|
||||
br i1 %var29, label %next, label %out_of_bounds
|
||||
|
||||
next:
|
||||
|
|
|
@ -1,29 +1,37 @@
|
|||
; RUN: opt < %s -mem2reg -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck -enable-var-scope %s
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -mem2reg -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
|
||||
define i32 @test(i32 %x) {
|
||||
; CHECK-LABEL: @test
|
||||
; CHECK-LABEL: @test(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
|
||||
; CHECK: if.then:
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call i32 asm "mov $0, #1", "=r"() #[[ATTR0:[0-9]+]]
|
||||
; CHECK-NEXT: br label [[IF_END:%.*]]
|
||||
; CHECK: if.else:
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call i32 asm "mov $0, #2", "=r"() #[[ATTR0]]
|
||||
; CHECK-NEXT: br label [[IF_END]]
|
||||
; CHECK: if.end:
|
||||
; CHECK-NEXT: [[Y_0:%.*]] = phi i32 [ [[TMP1]], [[IF_THEN]] ], [ [[TMP2]], [[IF_ELSE]] ]
|
||||
; CHECK-NEXT: ret i32 [[Y_0]]
|
||||
;
|
||||
entry:
|
||||
%y = alloca i32, align 4
|
||||
%tobool = icmp ne i32 %x, 0
|
||||
br i1 %tobool, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
; CHECK: if.then:
|
||||
; CHECK: [[ASM1:%.*]] = call i32 asm "mov $0, #1", "=r"()
|
||||
%tmp1 = call i32 asm "mov $0, #1", "=r"() nounwind readnone
|
||||
store i32 %tmp1, i32* %y, align 4
|
||||
br label %if.end
|
||||
|
||||
if.else:
|
||||
; CHECK: if.else:
|
||||
; CHECK: [[ASM2:%.*]] = call i32 asm "mov $0, #2", "=r"()
|
||||
%tmp2 = call i32 asm "mov $0, #2", "=r"() nounwind readnone
|
||||
store i32 %tmp2, i32* %y, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
; CHECK: if.end:
|
||||
; CHECK: {{%.*}} = phi i32 [ [[ASM1]], %if.then ], [ [[ASM2]], %if.else ]
|
||||
%tmp3 = load i32, i32* %y, align 4
|
||||
ret i32 %tmp3
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||
|
||||
|
@ -9,153 +10,187 @@ declare i32 @nounwind_fn() nounwind
|
|||
declare i32 @fn()
|
||||
|
||||
|
||||
; CHECK-LABEL: @f1(
|
||||
define i8* @f1() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||
; CHECK-LABEL: @f1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: call void @llvm.trap()
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
entry:
|
||||
; CHECK: call void @llvm.trap()
|
||||
; CHECK: unreachable
|
||||
%call = invoke noalias i8* undef()
|
||||
to label %invoke.cont unwind label %lpad
|
||||
to label %invoke.cont unwind label %lpad
|
||||
|
||||
invoke.cont:
|
||||
ret i8* %call
|
||||
|
||||
lpad:
|
||||
%0 = landingpad { i8*, i32 }
|
||||
filter [0 x i8*] zeroinitializer
|
||||
filter [0 x i8*] zeroinitializer
|
||||
%1 = extractvalue { i8*, i32 } %0, 0
|
||||
tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
|
||||
unreachable
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @f2(
|
||||
define i8* @f2() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||
; CHECK-LABEL: @f2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: call void @llvm.trap()
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
entry:
|
||||
; CHECK: call void @llvm.trap()
|
||||
; CHECK: unreachable
|
||||
%call = invoke noalias i8* null()
|
||||
to label %invoke.cont unwind label %lpad
|
||||
to label %invoke.cont unwind label %lpad
|
||||
|
||||
invoke.cont:
|
||||
ret i8* %call
|
||||
|
||||
lpad:
|
||||
%0 = landingpad { i8*, i32 }
|
||||
filter [0 x i8*] zeroinitializer
|
||||
filter [0 x i8*] zeroinitializer
|
||||
%1 = extractvalue { i8*, i32 } %0, 0
|
||||
tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
|
||||
unreachable
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @f2_no_null_opt(
|
||||
define i8* @f2_no_null_opt() nounwind uwtable ssp #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||
; CHECK-LABEL: @f2_no_null_opt(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[CALL:%.*]] = invoke noalias i8* null()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK-NEXT: ret i8* [[CALL]]
|
||||
; CHECK: lpad:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = landingpad { i8*, i32 }
|
||||
; CHECK-NEXT: filter [0 x i8*] zeroinitializer
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i8*, i32 } [[TMP0]], 0
|
||||
; CHECK-NEXT: tail call void @__cxa_call_unexpected(i8* [[TMP1]]) #[[ATTR6:[0-9]+]]
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
entry:
|
||||
; CHECK: invoke noalias i8* null()
|
||||
%call = invoke noalias i8* null()
|
||||
to label %invoke.cont unwind label %lpad
|
||||
to label %invoke.cont unwind label %lpad
|
||||
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK: ret i8* %call
|
||||
invoke.cont:
|
||||
ret i8* %call
|
||||
|
||||
lpad:
|
||||
%0 = landingpad { i8*, i32 }
|
||||
filter [0 x i8*] zeroinitializer
|
||||
filter [0 x i8*] zeroinitializer
|
||||
%1 = extractvalue { i8*, i32 } %0, 0
|
||||
tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
|
||||
; CHECK: unreachable
|
||||
unreachable
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @f3(
|
||||
define i32 @f3() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||
; CHECK-NEXT: entry
|
||||
; CHECK-LABEL: @f3(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: ret i32 3
|
||||
;
|
||||
entry:
|
||||
; CHECK-NEXT: ret i32 3
|
||||
%call = invoke i32 @read_only()
|
||||
to label %invoke.cont unwind label %lpad
|
||||
to label %invoke.cont unwind label %lpad
|
||||
|
||||
invoke.cont:
|
||||
ret i32 3
|
||||
|
||||
lpad:
|
||||
%0 = landingpad { i8*, i32 }
|
||||
filter [0 x i8*] zeroinitializer
|
||||
filter [0 x i8*] zeroinitializer
|
||||
%1 = extractvalue { i8*, i32 } %0, 0
|
||||
tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
|
||||
unreachable
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @f4(
|
||||
define i32 @f4() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||
; CHECK-NEXT: entry
|
||||
; CHECK-LABEL: @f4(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[CALL:%.*]] = call i32 @read_only()
|
||||
; CHECK-NEXT: ret i32 [[CALL]]
|
||||
;
|
||||
entry:
|
||||
; CHECK-NEXT: call i32 @read_only()
|
||||
%call = invoke i32 @read_only()
|
||||
to label %invoke.cont unwind label %lpad
|
||||
to label %invoke.cont unwind label %lpad
|
||||
|
||||
invoke.cont:
|
||||
; CHECK-NEXT: ret i32 %call
|
||||
ret i32 %call
|
||||
|
||||
lpad:
|
||||
%0 = landingpad { i8*, i32 }
|
||||
filter [0 x i8*] zeroinitializer
|
||||
filter [0 x i8*] zeroinitializer
|
||||
%1 = extractvalue { i8*, i32 } %0, 0
|
||||
tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
|
||||
unreachable
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @f5(
|
||||
define i32 @f5(i1 %cond, i8* %a, i8* %b) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||
; CHECK-LABEL: @f5(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[X:%.*]], label [[Y:%.*]]
|
||||
; CHECK: x:
|
||||
; CHECK-NEXT: [[CALL:%.*]] = invoke i32 @fn()
|
||||
; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: y:
|
||||
; CHECK-NEXT: [[CALL2:%.*]] = call i32 @nounwind_fn()
|
||||
; CHECK-NEXT: br label [[CONT]]
|
||||
; CHECK: cont:
|
||||
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[CALL]], [[X]] ], [ [[CALL2]], [[Y]] ]
|
||||
; CHECK-NEXT: ret i32 [[PHI]]
|
||||
; CHECK: lpad:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = landingpad { i8*, i32 }
|
||||
; CHECK-NEXT: filter [0 x i8*] zeroinitializer
|
||||
; CHECK-NEXT: tail call void @__cxa_call_unexpected(i8* [[A:%.*]]) #[[ATTR6]]
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
entry:
|
||||
br i1 %cond, label %x, label %y
|
||||
|
||||
x:
|
||||
; CHECK: invoke i32 @fn()
|
||||
%call = invoke i32 @fn()
|
||||
to label %cont unwind label %lpad
|
||||
to label %cont unwind label %lpad
|
||||
|
||||
y:
|
||||
; CHECK: call i32 @nounwind_fn()
|
||||
%call2 = invoke i32 @nounwind_fn()
|
||||
to label %cont unwind label %lpad
|
||||
to label %cont unwind label %lpad
|
||||
|
||||
cont:
|
||||
; CHECK: phi i32
|
||||
; CHECK: ret i32 %phi
|
||||
%phi = phi i32 [%call, %x], [%call2, %y]
|
||||
ret i32 %phi
|
||||
|
||||
lpad:
|
||||
; CHECK-NOT: phi
|
||||
%phi2 = phi i8* [%a, %x], [%b, %y]
|
||||
%0 = landingpad { i8*, i32 }
|
||||
filter [0 x i8*] zeroinitializer
|
||||
; CHECK: __cxa_call_unexpected(i8* %a)
|
||||
filter [0 x i8*] zeroinitializer
|
||||
tail call void @__cxa_call_unexpected(i8* %phi2) noreturn nounwind
|
||||
unreachable
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @f6(
|
||||
define void @f6() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
||||
; CHECK-LABEL: @f6(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[FOO:%.*]] = invoke i32 @fn()
|
||||
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD:%.*]]
|
||||
; CHECK: invoke.cont2:
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: lpad:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = landingpad { i8*, i32 }
|
||||
; CHECK-NEXT: cleanup
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
invoke void @purefn()
|
||||
to label %invoke.cont1 unwind label %lpad
|
||||
to label %invoke.cont1 unwind label %lpad
|
||||
|
||||
invoke.cont1:
|
||||
%foo = invoke i32 @fn()
|
||||
to label %invoke.cont2 unwind label %lpad
|
||||
to label %invoke.cont2 unwind label %lpad
|
||||
|
||||
invoke.cont2:
|
||||
ret void
|
||||
|
||||
lpad:
|
||||
; CHECK-NOT: phi
|
||||
%tmp = phi i8* [ null, %invoke.cont1 ], [ null, %entry ]
|
||||
landingpad { i8*, i32 }
|
||||
cleanup
|
||||
cleanup
|
||||
ret void
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
|
||||
declare void @bar()
|
||||
|
@ -6,30 +7,32 @@ declare void @bar()
|
|||
; instructions to call instructions if the handler just rethrows the exception.
|
||||
define i32 @test1() personality i32 (...)* @__gxx_personality_v0 {
|
||||
; CHECK-LABEL: @test1(
|
||||
; CHECK-NEXT: call void @bar(), !prof ![[PROF:[0-9]+]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
invoke void @bar( )
|
||||
to label %1 unwind label %Rethrow, !prof !0
|
||||
ret i32 0
|
||||
; CHECK-NEXT: call void @bar(), !prof !0
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
invoke void @bar( )
|
||||
to label %1 unwind label %Rethrow, !prof !0
|
||||
ret i32 0
|
||||
Rethrow:
|
||||
%exn = landingpad {i8*, i32}
|
||||
catch i8* null
|
||||
resume { i8*, i32 } %exn
|
||||
%exn = landingpad {i8*, i32}
|
||||
catch i8* null
|
||||
resume { i8*, i32 } %exn
|
||||
}
|
||||
|
||||
!0 = !{!"branch_weights", i32 369, i32 2}
|
||||
|
||||
define i32 @test2() personality i32 (...)* @__gxx_personality_v0 {
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK-NEXT: call void @bar() [ "foo"(i32 100) ]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
invoke void @bar( ) [ "foo"(i32 100) ]
|
||||
to label %1 unwind label %Rethrow
|
||||
ret i32 0
|
||||
; CHECK-NEXT: call void @bar() [ "foo"(i32 100) ]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
invoke void @bar( ) [ "foo"(i32 100) ]
|
||||
to label %1 unwind label %Rethrow
|
||||
ret i32 0
|
||||
Rethrow:
|
||||
%exn = landingpad {i8*, i32}
|
||||
catch i8* null
|
||||
resume { i8*, i32 } %exn
|
||||
%exn = landingpad {i8*, i32}
|
||||
catch i8* null
|
||||
resume { i8*, i32 } %exn
|
||||
}
|
||||
|
||||
declare i64 @dummy1()
|
||||
|
@ -39,20 +42,29 @@ declare i64 @dummy2()
|
|||
; instructions to call instructions if they share a common trivial unwind
|
||||
; block.
|
||||
define i64 @test3(i1 %cond) personality i32 (...)* @__gxx_personality_v0 {
|
||||
entry:
|
||||
; CHECK-LABEL: @test3(
|
||||
; CHECK: %call1 = call i64 @dummy1()
|
||||
; CHECK: %call2 = call i64 @dummy2()
|
||||
; CHECK-NOT: resume { i8*, i32 } %lp
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BR1:%.*]], label [[BR2:%.*]]
|
||||
; CHECK: br1:
|
||||
; CHECK-NEXT: [[CALL1:%.*]] = call i64 @dummy1()
|
||||
; CHECK-NEXT: br label [[INVOKE_CONT:%.*]]
|
||||
; CHECK: br2:
|
||||
; CHECK-NEXT: [[CALL2:%.*]] = call i64 @dummy2()
|
||||
; CHECK-NEXT: br label [[INVOKE_CONT]]
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK-NEXT: [[C:%.*]] = phi i64 [ [[CALL1]], [[BR1]] ], [ [[CALL2]], [[BR2]] ]
|
||||
; CHECK-NEXT: ret i64 [[C]]
|
||||
;
|
||||
entry:
|
||||
br i1 %cond, label %br1, label %br2
|
||||
|
||||
br1:
|
||||
%call1 = invoke i64 @dummy1()
|
||||
to label %invoke.cont unwind label %lpad1
|
||||
to label %invoke.cont unwind label %lpad1
|
||||
|
||||
br2:
|
||||
%call2 = invoke i64 @dummy2()
|
||||
to label %invoke.cont unwind label %lpad2
|
||||
to label %invoke.cont unwind label %lpad2
|
||||
|
||||
invoke.cont:
|
||||
%c = phi i64 [%call1, %br1], [%call2, %br2]
|
||||
|
@ -61,7 +73,7 @@ invoke.cont:
|
|||
|
||||
lpad1:
|
||||
%0 = landingpad { i8*, i32 }
|
||||
cleanup
|
||||
cleanup
|
||||
br label %rethrow
|
||||
|
||||
rethrow:
|
||||
|
@ -70,10 +82,8 @@ rethrow:
|
|||
|
||||
lpad2:
|
||||
%1 = landingpad { i8*, i32 }
|
||||
cleanup
|
||||
cleanup
|
||||
br label %rethrow
|
||||
}
|
||||
|
||||
declare i32 @__gxx_personality_v0(...)
|
||||
|
||||
; CHECK: ![[PROF]] = !{!"branch_weights", i32 371}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
@ -8,27 +9,27 @@ declare void @f()
|
|||
|
||||
define void @foo(i32 %Kind) {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT:entry:
|
||||
; CHECK-NEXT: switch i32 %Kind, label %sw.epilog [
|
||||
; CHECK-NEXT: i32 15, label %sw.bb2
|
||||
; CHECK-NEXT: i32 2, label %sw.bb
|
||||
; CHECK-NEXT: ]
|
||||
; CHECK: sw.bb:
|
||||
; CHECK-NEXT: call void @g()
|
||||
; CHECK-NEXT: call void @g()
|
||||
; CHECK-NEXT: br label %sw.epilog
|
||||
; CHECK: sw.bb2:
|
||||
; CHECK-NEXT: call void @f()
|
||||
; CHECK-NEXT: br label %sw.epilog
|
||||
; CHECK: sw.epilog:
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK-NEXT:}
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: switch i32 [[KIND:%.*]], label [[SW_EPILOG:%.*]] [
|
||||
; CHECK-NEXT: i32 15, label [[SW_BB2:%.*]]
|
||||
; CHECK-NEXT: i32 2, label [[SW_BB:%.*]]
|
||||
; CHECK-NEXT: ]
|
||||
; CHECK: sw.bb:
|
||||
; CHECK-NEXT: call void @g()
|
||||
; CHECK-NEXT: call void @g()
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw.bb2:
|
||||
; CHECK-NEXT: call void @f()
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw.epilog:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
||||
entry:
|
||||
switch i32 %Kind, label %sw.epilog [
|
||||
i32 1, label %sw.epilog
|
||||
i32 2, label %sw.bb
|
||||
i32 15, label %sw.bb2
|
||||
i32 1, label %sw.epilog
|
||||
i32 2, label %sw.bb
|
||||
i32 15, label %sw.bb2
|
||||
]
|
||||
|
||||
sw.bb:
|
||||
|
|
|
@ -11,8 +11,8 @@ define i32 @upper_bound(i32* %r, i32 %high, i32 %k) nounwind {
|
|||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[WHILE_COND:%.*]]
|
||||
; CHECK: while.cond:
|
||||
; CHECK-NEXT: [[HIGH_ADDR_0:%.*]] = phi i32 [ [[HIGH:%.*]], [[ENTRY:%.*]] ], [ [[DIV_HIGH_ADDR_0:%.*]], [[WHILE_BODY:%.*]] ]
|
||||
; CHECK-NEXT: [[LOW_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[LOW_0_ADD2:%.*]], [[WHILE_BODY]] ]
|
||||
; CHECK-NEXT: [[HIGH_ADDR_0:%.*]] = phi i32 [ [[HIGH:%.*]], [[ENTRY:%.*]] ], [ [[SPEC_SELECT:%.*]], [[WHILE_BODY:%.*]] ]
|
||||
; CHECK-NEXT: [[LOW_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SPEC_SELECT1:%.*]], [[WHILE_BODY]] ]
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[LOW_0]], [[HIGH_ADDR_0]]
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY]], label [[WHILE_END:%.*]]
|
||||
; CHECK: while.body:
|
||||
|
@ -20,11 +20,11 @@ define i32 @upper_bound(i32* %r, i32 %high, i32 %k) nounwind {
|
|||
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[ADD]], 2
|
||||
; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[DIV]] to i64
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[R:%.*]], i64 [[IDXPROM]]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[K:%.*]], [[TMP0]]
|
||||
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[DIV]], 1
|
||||
; CHECK-NEXT: [[DIV_HIGH_ADDR_0]] = select i1 [[CMP1]], i32 [[DIV]], i32 [[HIGH_ADDR_0]]
|
||||
; CHECK-NEXT: [[LOW_0_ADD2]] = select i1 [[CMP1]], i32 [[LOW_0]], i32 [[ADD2]]
|
||||
; CHECK-NEXT: [[SPEC_SELECT]] = select i1 [[CMP1]], i32 [[DIV]], i32 [[HIGH_ADDR_0]]
|
||||
; CHECK-NEXT: [[SPEC_SELECT1]] = select i1 [[CMP1]], i32 [[LOW_0]], i32 [[ADD2]]
|
||||
; CHECK-NEXT: br label [[WHILE_COND]]
|
||||
; CHECK: while.end:
|
||||
; CHECK-NEXT: ret i32 [[LOW_0]]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
; PR1796
|
||||
|
||||
|
@ -6,7 +7,7 @@ declare void @Finisher(i32) noreturn
|
|||
; Make sure we optimize a sequence of two calls (second unreachable);
|
||||
define void @double_call(i32) {
|
||||
; CHECK-LABEL: @double_call(
|
||||
; CHECK-NEXT: tail call void @Finisher(i32 %0) #0
|
||||
; CHECK-NEXT: tail call void @Finisher(i32 [[TMP0:%.*]]) #[[ATTR0:[0-9]+]]
|
||||
; CHECK-NEXT: unreachable
|
||||
;
|
||||
tail call void @Finisher(i32 %0) noreturn
|
||||
|
@ -18,7 +19,7 @@ define void @double_call(i32) {
|
|||
; is that it must be followed by [optional bitcast then] ret).
|
||||
define void @must_tail(i32) {
|
||||
; CHECK-LABEL: @must_tail(
|
||||
; CHECK-NEXT: musttail call void @Finisher(i32 %0) #0
|
||||
; CHECK-NEXT: musttail call void @Finisher(i32 [[TMP0:%.*]]) #[[ATTR0]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
musttail call void @Finisher(i32 %0) #0
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S -o - < %s | FileCheck %s
|
||||
|
||||
declare void @func2(i32)
|
||||
|
@ -8,12 +9,27 @@ declare void @func8(i32)
|
|||
;; test1 - create a switch with case 2 and case 4 from two branches: N == 2
|
||||
;; and N == 4.
|
||||
define void @test1(i32 %N) nounwind uwtable {
|
||||
; CHECK-LABEL: @test1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: switch i32 [[N:%.*]], label [[IF_ELSE8:%.*]] [
|
||||
; CHECK-NEXT: i32 2, label [[IF_THEN:%.*]]
|
||||
; CHECK-NEXT: i32 4, label [[IF_THEN7:%.*]]
|
||||
; CHECK-NEXT: ], !prof !0
|
||||
; CHECK: if.then:
|
||||
; CHECK-NEXT: call void @func2(i32 [[N]]) #[[ATTR1:[0-9]+]]
|
||||
; CHECK-NEXT: br label [[IF_END9:%.*]]
|
||||
; CHECK: if.then7:
|
||||
; CHECK-NEXT: call void @func4(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[IF_END9]]
|
||||
; CHECK: if.else8:
|
||||
; CHECK-NEXT: call void @func8(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[IF_END9]]
|
||||
; CHECK: if.end9:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%cmp = icmp eq i32 %N, 2
|
||||
br i1 %cmp, label %if.then, label %if.else, !prof !0
|
||||
; CHECK: test1
|
||||
; CHECK: switch i32 %N
|
||||
; CHECK: ], !prof !0
|
||||
|
||||
if.then:
|
||||
call void @func2(i32 %N) nounwind
|
||||
|
@ -40,21 +56,45 @@ if.end9:
|
|||
|
||||
;; test2 - Merge two switches where PredDefault == BB.
|
||||
define void @test2(i32 %M, i32 %N) nounwind uwtable {
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[M:%.*]], 2
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[SW1:%.*]], label [[SW2:%.*]]
|
||||
; CHECK: sw1:
|
||||
; CHECK-NEXT: switch i32 [[N:%.*]], label [[SW_EPILOG:%.*]] [
|
||||
; CHECK-NEXT: i32 2, label [[SW_BB:%.*]]
|
||||
; CHECK-NEXT: i32 3, label [[SW_BB1:%.*]]
|
||||
; CHECK-NEXT: i32 4, label [[SW_BB5:%.*]]
|
||||
; CHECK-NEXT: ], !prof !1
|
||||
; CHECK: sw.bb:
|
||||
; CHECK-NEXT: call void @func2(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw.bb1:
|
||||
; CHECK-NEXT: call void @func4(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw2:
|
||||
; CHECK-NEXT: switch i32 [[N]], label [[SW_EPILOG]] [
|
||||
; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]]
|
||||
; CHECK-NEXT: i32 4, label [[SW_BB5]]
|
||||
; CHECK-NEXT: ], !prof !2
|
||||
; CHECK: sw.bb4:
|
||||
; CHECK-NEXT: call void @func6(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw.bb5:
|
||||
; CHECK-NEXT: call void @func8(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw.epilog:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %M, 2
|
||||
br i1 %cmp, label %sw1, label %sw2
|
||||
|
||||
sw1:
|
||||
switch i32 %N, label %sw2 [
|
||||
i32 2, label %sw.bb
|
||||
i32 3, label %sw.bb1
|
||||
i32 2, label %sw.bb
|
||||
i32 3, label %sw.bb1
|
||||
], !prof !2
|
||||
; CHECK: test2
|
||||
; CHECK: switch i32 %N, label %sw.epilog
|
||||
; CHECK: i32 2, label %sw.bb
|
||||
; CHECK: i32 3, label %sw.bb1
|
||||
; CHECK: i32 4, label %sw.bb5
|
||||
; CHECK: ], !prof !1
|
||||
|
||||
sw.bb:
|
||||
call void @func2(i32 %N) nounwind
|
||||
|
@ -68,8 +108,8 @@ sw2:
|
|||
;; Here "case 2" is invalidated if control is transferred through default case
|
||||
;; of the first switch.
|
||||
switch i32 %N, label %sw.epilog [
|
||||
i32 2, label %sw.bb4
|
||||
i32 4, label %sw.bb5
|
||||
i32 2, label %sw.bb4
|
||||
i32 4, label %sw.bb5
|
||||
], !prof !3
|
||||
|
||||
sw.bb4:
|
||||
|
@ -86,22 +126,46 @@ sw.epilog:
|
|||
|
||||
;; test3 - Merge two switches where PredDefault != BB.
|
||||
define void @test3(i32 %M, i32 %N) nounwind uwtable {
|
||||
; CHECK-LABEL: @test3(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[M:%.*]], 2
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[SW1:%.*]], label [[SW2:%.*]]
|
||||
; CHECK: sw1:
|
||||
; CHECK-NEXT: switch i32 [[N:%.*]], label [[SW_BB:%.*]] [
|
||||
; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]]
|
||||
; CHECK-NEXT: i32 3, label [[SW_BB4:%.*]]
|
||||
; CHECK-NEXT: i32 2, label [[SW_EPILOG:%.*]]
|
||||
; CHECK-NEXT: ], !prof !3
|
||||
; CHECK: sw.bb:
|
||||
; CHECK-NEXT: call void @func2(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw.bb1:
|
||||
; CHECK-NEXT: call void @func4(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw2:
|
||||
; CHECK-NEXT: switch i32 [[N]], label [[SW_EPILOG]] [
|
||||
; CHECK-NEXT: i32 3, label [[SW_BB4]]
|
||||
; CHECK-NEXT: i32 4, label [[SW_BB5:%.*]]
|
||||
; CHECK-NEXT: ], !prof !4
|
||||
; CHECK: sw.bb4:
|
||||
; CHECK-NEXT: call void @func6(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw.bb5:
|
||||
; CHECK-NEXT: call void @func8(i32 [[N]]) #[[ATTR1]]
|
||||
; CHECK-NEXT: br label [[SW_EPILOG]]
|
||||
; CHECK: sw.epilog:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %M, 2
|
||||
br i1 %cmp, label %sw1, label %sw2
|
||||
|
||||
sw1:
|
||||
switch i32 %N, label %sw.bb [
|
||||
i32 2, label %sw2
|
||||
i32 3, label %sw2
|
||||
i32 1, label %sw.bb1
|
||||
i32 2, label %sw2
|
||||
i32 3, label %sw2
|
||||
i32 1, label %sw.bb1
|
||||
], !prof !4
|
||||
; CHECK: test3
|
||||
; CHECK: switch i32 %N, label %sw.bb
|
||||
; CHECK: i32 1, label %sw.bb1
|
||||
; CHECK: i32 3, label %sw.bb4
|
||||
; CHECK: i32 2, label %sw.epilog
|
||||
; CHECK: ], !prof !3
|
||||
|
||||
sw.bb:
|
||||
call void @func2(i32 %N) nounwind
|
||||
|
@ -113,8 +177,8 @@ sw.bb1:
|
|||
|
||||
sw2:
|
||||
switch i32 %N, label %sw.epilog [
|
||||
i32 3, label %sw.bb4
|
||||
i32 4, label %sw.bb5
|
||||
i32 3, label %sw.bb4
|
||||
i32 4, label %sw.bb5
|
||||
], !prof !5
|
||||
|
||||
sw.bb4:
|
||||
|
|
|
@ -541,8 +541,8 @@ define i32 @HoistThenElseCodeToIf(i32 %n) {
|
|||
; CHECK-LABEL: @HoistThenElseCodeToIf(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[N:%.*]], 0
|
||||
; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TOBOOL]], i32 1, i32 234, !prof !12
|
||||
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
||||
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[TOBOOL]], i32 1, i32 234, !prof !12
|
||||
; CHECK-NEXT: ret i32 [[DOT]]
|
||||
;
|
||||
entry:
|
||||
%tobool = icmp eq i32 %n, 0
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
|
||||
|
||||
; We're sign extending an 8-bit value.
|
||||
|
@ -8,13 +9,19 @@
|
|||
|
||||
define i1 @repeated_signbits(i8 %condition) {
|
||||
; CHECK-LABEL: @repeated_signbits(
|
||||
; CHECK: switch i32
|
||||
; CHECK-DAG: i32 -128, label %a
|
||||
; CHECK-DAG: i32 -1, label %a
|
||||
; CHECK-DAG: i32 0, label %a
|
||||
; CHECK-DAG: i32 127, label %a
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[SEXT:%.*]] = sext i8 [[CONDITION:%.*]] to i32
|
||||
; CHECK-NEXT: switch i32 [[SEXT]], label [[DEFAULT:%.*]] [
|
||||
; CHECK-NEXT: i32 0, label [[A:%.*]]
|
||||
; CHECK-NEXT: i32 127, label [[A]]
|
||||
; CHECK-NEXT: i32 -128, label [[A]]
|
||||
; CHECK-NEXT: i32 -1, label [[A]]
|
||||
; CHECK-NEXT: ]
|
||||
; CHECK-NOT: , !prof
|
||||
; CHECK: a:
|
||||
; CHECK-NEXT: [[MERGE:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ false, [[DEFAULT]] ]
|
||||
; CHECK-NEXT: ret i1 [[MERGE]]
|
||||
; CHECK: default:
|
||||
; CHECK-NEXT: br label [[A]]
|
||||
;
|
||||
entry:
|
||||
%sext = sext i8 %condition to i32
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck -enable-var-scope %s
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
|
||||
; Test basic folding to a conditional branch.
|
||||
define i32 @foo(i64 %x, i64 %y) nounwind {
|
||||
|
@ -11,11 +11,11 @@ define i32 @foo(i64 %x, i64 %y) nounwind {
|
|||
; CHECK-NEXT: [[LT:%.*]] = icmp slt i64 [[X]], [[Y]]
|
||||
; CHECK-NEXT: br i1 [[LT]], label [[A:%.*]], label [[B]]
|
||||
; CHECK: a:
|
||||
; CHECK-NEXT: tail call void @bees.a() #0
|
||||
; CHECK-NEXT: tail call void @bees.a() #[[ATTR0:[0-9]+]]
|
||||
; CHECK-NEXT: ret i32 1
|
||||
; CHECK: b:
|
||||
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 0, [[SWITCH]] ], [ 2, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: tail call void @bees.b() #0
|
||||
; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
|
||||
; CHECK-NEXT: ret i32 [[RETVAL]]
|
||||
;
|
||||
entry:
|
||||
|
@ -45,7 +45,7 @@ bees:
|
|||
define i32 @bar(i64 %x, i64 %y) nounwind {
|
||||
; CHECK-LABEL: @bar(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: tail call void @bees.a() #0
|
||||
; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
entry:
|
||||
|
@ -72,7 +72,7 @@ bees:
|
|||
define void @bazz(i64 %x, i64 %y) nounwind {
|
||||
; CHECK-LABEL: @bazz(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: tail call void @bees.b() #0
|
||||
; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
@ -98,7 +98,7 @@ bees:
|
|||
define void @quux(i64 %x, i64 %y) nounwind {
|
||||
; CHECK-LABEL: @quux(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: tail call void @bees.a() #0
|
||||
; CHECK-NEXT: tail call void @bees.a() #[[ATTR0]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
|
||||
; a, b;
|
||||
|
@ -20,16 +21,16 @@ define i32 @fn1() {
|
|||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @b, align 4
|
||||
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
|
||||
; CHECK-NEXT: br i1 [[TOBOOL]], label %return, label %if.then
|
||||
; CHECK-NEXT: br i1 [[TOBOOL]], label [[RETURN:%.*]], label [[IF_THEN:%.*]]
|
||||
; CHECK: if.then:
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
|
||||
; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[TMP1]], 0
|
||||
; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP:%.*]], i32 0, i32 0
|
||||
; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i32 0, i32 0
|
||||
; CHECK-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 [[TMP1]], 5
|
||||
; CHECK-NEXT: [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i32 5, i32 [[SWITCH_SELECT]]
|
||||
; CHECK-NEXT: br label %return
|
||||
; CHECK-NEXT: br label [[RETURN]]
|
||||
; CHECK: return:
|
||||
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[SWITCH_SELECT2]], %if.then ], [ 0, %entry ]
|
||||
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[SWITCH_SELECT2]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
||||
;
|
||||
entry:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
;
|
||||
; rdar:13349374
|
||||
|
@ -6,16 +7,31 @@
|
|||
; Essentially, volatile needs to be backdoor that tells the optimizer
|
||||
; it can no longer use language standard as an excuse. The compiler
|
||||
; needs to expose the volatile access to the platform.
|
||||
;
|
||||
; CHECK-LABEL: @test(
|
||||
; CHECK: entry:
|
||||
; CHECK: @Trace
|
||||
; CHECK: while.body:
|
||||
; CHECK: store volatile
|
||||
; CHECK: end:
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||
|
||||
define void @test(i8** nocapture %PeiServices) #0 {
|
||||
; CHECK-LABEL: @test(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[CALL:%.*]] = tail call i32 (...) @Trace() #[[ATTR2:[0-9]+]]
|
||||
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[CALL]], 0
|
||||
; CHECK-NEXT: br i1 [[TOBOOL]], label [[WHILE_BODY:%.*]], label [[IF_THEN:%.*]]
|
||||
; CHECK: if.then:
|
||||
; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 (...) @Trace() #[[ATTR2]]
|
||||
; CHECK-NEXT: br label [[WHILE_BODY]]
|
||||
; CHECK: while.body:
|
||||
; CHECK-NEXT: [[ADDR_017:%.*]] = phi i8* [ [[INCDEC_PTR:%.*]], [[WHILE_BODY]] ], [ null, [[IF_THEN]] ], [ null, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[X_016:%.*]] = phi i8 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[IF_THEN]] ], [ 0, [[ENTRY]] ]
|
||||
; CHECK-NEXT: [[INC]] = add i8 [[X_016]], 1
|
||||
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[ADDR_017]], i64 1
|
||||
; CHECK-NEXT: store volatile i8 [[X_016]], i8* [[ADDR_017]], align 1
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint i8* [[INCDEC_PTR]] to i64
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], 4096
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY]], label [[END:%.*]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%call = tail call i32 (...) @Trace() #2
|
||||
%tobool = icmp eq i32 %call, 0
|
||||
|
|
Loading…
Reference in New Issue