[NFC][SimplifyCFG] Autogenerate check lines in many test files

These are potentially being affected by an upcoming patch.
This commit is contained in:
Roman Lebedev 2021-04-27 21:28:53 +03:00
parent 8de7d8b2c2
commit e4c61d5f83
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
23 changed files with 1110 additions and 533 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ]

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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
}

View File

@ -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
}

View File

@ -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}

View File

@ -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:

View File

@ -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]]

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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