1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[Attributor] Add initial AAIsDead for arguments

We usually will ask for liveness of an argument anyway so we ended up
lazily creating the attribute anyway. However, that is not always the
case and even if it is we should go the eager route here. Various tests
show how this can improve the outcome. One test exposed a problem with
type mismatches between argument and call site argument, a fix is
included. For liveness various more tests were added as well.
This commit is contained in:
Johannes Doerfert 2020-02-16 16:42:47 -06:00
parent 57e72ad661
commit fb9c302f30
4 changed files with 204 additions and 61 deletions

View File

@ -7331,6 +7331,24 @@ bool Attributor::checkForAllCallSites(
return false;
}
// Make sure the arguments that can be matched between the call site and the
// callee argee on their type. It is unlikely they do not and it doesn't
// make sense for all attributes to know/care about this.
assert(&Fn == ACS.getCalledFunction() && "Expected known callee");
unsigned MinArgsParams =
std::min(size_t(ACS.getNumArgOperands()), Fn.arg_size());
for (unsigned u = 0; u < MinArgsParams; ++u) {
Value *CSArgOp = ACS.getCallArgOperand(u);
if (CSArgOp && Fn.getArg(u)->getType() != CSArgOp->getType()) {
LLVM_DEBUG(
dbgs() << "[Attributor] Call site / callee argument type mismatch ["
<< u << "@" << Fn.getName() << ": "
<< *Fn.getArg(u)->getType() << " vs. "
<< *ACS.getCallArgOperand(u)->getType() << "\n");
return false;
}
}
if (Pred(ACS))
continue;
@ -8231,6 +8249,9 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
// Every argument might be simplified.
getOrCreateAAFor<AAValueSimplify>(ArgPos);
// Every argument might be dead.
getOrCreateAAFor<AAIsDead>(ArgPos);
if (Arg.getType()->isPointerTy()) {
// Every argument with pointer type might be marked nonnull.
getOrCreateAAFor<AANonNull>(ArgPos);

View File

@ -33,7 +33,7 @@
define dso_local i16 @foo(i16 %a) {
; CHECK-LABEL: define {{[^@]+}}@foo
; CHECK-SAME: (i16 [[A:%.*]])
; CHECK-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16)*)(i16 [[A]])
; CHECK-NEXT: [[CALL:%.*]] = call i16 @bar()
; CHECK-NEXT: ret i16 [[CALL]]
;
%call = call i16 bitcast (i16 (i16, i16) * @bar to i16 (i16) *)(i16 %a)
@ -41,13 +41,33 @@ define dso_local i16 @foo(i16 %a) {
}
define internal i16 @bar(i16 %p1, i16 %p2) {
; CHECK-LABEL: define {{[^@]+}}@bar
; CHECK-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]])
; CHECK-LABEL: define {{[^@]+}}@bar()
; CHECK-NEXT: ret i16 0
;
ret i16 0
}
define dso_local i16 @foo2(i16 %a) {
; CHECK-LABEL: define {{[^@]+}}@foo2
; CHECK-SAME: (i16 [[A:%.*]])
; CHECK-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar2 to i16 (i16)*)(i16 [[A]])
; CHECK-NEXT: ret i16 [[CALL]]
;
%call = call i16 bitcast (i16 (i16, i16) * @bar2 to i16 (i16) *)(i16 %a)
ret i16 %call
}
define internal i16 @bar2(i16 %p1, i16 %p2) {
; CHECK-LABEL: define {{[^@]+}}@bar2
; CHECK-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]])
; CHECK-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]]
; CHECK-NEXT: ret i16 [[A]]
;
%a = add i16 %p1, %p2
ret i16 %a
}
;-------------------------------------------------------------------------------
; Additional tests to verify that we still optimize when having a mismatch
; in argument count due to varargs (as long as all non-variadic arguments have

View File

@ -1,11 +1,14 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,MODULE,ALL_BUT_OLD_CGSCCC
; RUN: opt -attributor-cgscc --attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,MODULE,ALL_BUT_OLD_CGSCCC
; RUN: opt -passes='attributor-cgscc' --attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC,ALL_BUT_OLD_CGSCCC
; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,MODULE,MODULE_OLD
; RUN: opt -attributor-cgscc --attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC,CGSCC_OLD
; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,MODULE,MODULE_NEW
; RUN: opt -passes='attributor-cgscc' --attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC,CGSCC_NEW
; UTC_ARGS: --disable
; ALL_BUT_OLD_CGSCCC: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)]
; MODULE_OLD: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)]
; MODULE_NEW: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)]
; CGSCC_OLD: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, %lab0), i8* blockaddress(@dead_with_blockaddress_users, %end)]
; CGSCC_NEW: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)]
@dead_with_blockaddress_users.l = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, %lab0), i8* blockaddress(@dead_with_blockaddress_users, %end)]
declare void @no_return_call() nofree noreturn nounwind nosync
@ -58,7 +61,7 @@ define internal i32 @internal_load(i32*) norecurse nounwind uwtable {
; CHECK: Function Attrs: nofree noreturn nosync nounwind
; MODULE-NEXT: define i32 @first_block_no_return(i32 %a, i32* nocapture nofree nonnull readnone %ptr1, i32* nocapture nofree readnone %ptr2)
; CGSCC-NEXT: define i32 @first_block_no_return(i32 %a, i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) %ptr1, i32* nocapture nofree readnone %ptr2)
; CGSCC-NEXT: define i32 @first_block_no_return(i32 %a, i32* nocapture nofree nonnull readnone %ptr1, i32* nocapture nofree readnone %ptr2)
define i32 @first_block_no_return(i32 %a, i32* nonnull %ptr1, i32* %ptr2) #0 {
entry:
call i32 @internal_load(i32* %ptr1)
@ -1051,18 +1054,15 @@ live_with_dead_entry:
ret void
}
; MODULE: define internal void @useless_arg_sink()
; CGSCC: define internal void @useless_arg_sink(i32*{{.*}} %a)
; CHECK: define internal void @useless_arg_sink()
define internal void @useless_arg_sink(i32* %a) {
call void @sink()
ret void
}
; MODULE: define internal void @useless_arg_almost_sink()
; CGSCC: define internal void @useless_arg_almost_sink(i32*{{.*}} %a)
; CHECK: define internal void @useless_arg_almost_sink()
define internal void @useless_arg_almost_sink(i32* %a) {
; MODULE: call void @useless_arg_sink()
; CGSCC: call void @useless_arg_sink(i32* noalias nocapture nofree readnone %a)
; CHECK: call void @useless_arg_sink()
call void @useless_arg_sink(i32* %a)
ret void
}
@ -1070,8 +1070,7 @@ define internal void @useless_arg_almost_sink(i32* %a) {
; Check we do not annotate the function interface of this weak function.
; CHECK: define weak_odr void @useless_arg_ext(i32* %a)
define weak_odr void @useless_arg_ext(i32* %a) {
; MODULE: call void @useless_arg_almost_sink()
; CGSCC: call void @useless_arg_almost_sink(i32* noalias nofree readnone %a)
; CHECK: call void @useless_arg_almost_sink()
call void @useless_arg_almost_sink(i32* %a)
ret void
}
@ -1106,8 +1105,7 @@ define internal i32 @switch_default(i64 %i) nounwind {
; MODULE: return:
; MODULE-NEXT: unreachable
;
; CGSCC-LABEL: define {{[^@]+}}@switch_default
; CGSCC-SAME: (i64 [[I:%.*]])
; CGSCC-LABEL: define {{[^@]+}}@switch_default()
; CGSCC-NEXT: entry:
; CGSCC-NEXT: switch i64 0, label [[SW_DEFAULT:%.*]] [
; CGSCC-NEXT: i64 3, label [[RETURN:%.*]]
@ -1134,19 +1132,26 @@ return:
}
define i32 @switch_default_caller() {
; MODULE-LABEL: define {{[^@]+}}@switch_default_caller()
; MODULE-NEXT: [[CALL2:%.*]] = tail call i32 @switch_default()
; MODULE-NEXT: ret i32 123
;
; CGSCC-LABEL: define {{[^@]+}}@switch_default_caller()
; CGSCC-NEXT: [[CALL2:%.*]] = tail call i32 @switch_default(i64 0)
; CGSCC-NEXT: ret i32 123
; CHECK-LABEL: define {{[^@]+}}@switch_default_caller()
; CHECK-NEXT: [[CALL2:%.*]] = tail call i32 @switch_default()
; CHECK-NEXT: ret i32 123
;
%call2 = tail call i32 @switch_default(i64 0)
ret i32 %call2
}
define internal i32 @switch_default_dead(i64 %i) nounwind {
; CGSCC-LABEL: define {{[^@]+}}@switch_default_dead()
; CGSCC-NEXT: entry:
; CGSCC-NEXT: switch i64 0, label [[SW_DEFAULT:%.*]] [
; CGSCC-NEXT: i64 3, label [[RETURN:%.*]]
; CGSCC-NEXT: i64 10, label [[RETURN]]
; CGSCC-NEXT: ]
; CGSCC: sw.default:
; CGSCC-NEXT: ret i32 123
; CGSCC: return:
; CGSCC-NEXT: unreachable
;
entry:
switch i64 %i, label %sw.default [
i64 3, label %return
@ -1168,10 +1173,115 @@ define i32 @switch_default_dead_caller() {
ret i32 %call2
}
define void @call_via_pointer_with_dead_args(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
; CHECK-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args
; CHECK-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree nonnull [[FP:%.*]])
; CHECK-NEXT: call void [[FP]](i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
; CHECK-NEXT: ret void
;
call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
ret void
}
; FIXME: We have to prevent the propagation of %fp in the new pm CGSCC pass until the CallGraphUpdater can handle the new call edge.
define internal void @call_via_pointer_with_dead_args_internal_a(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
; MODULE-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
; MODULE-SAME: (i32* [[A:%.*]], i32* nonnull align 128 dereferenceable(4) [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree nonnull [[FP:%.*]])
; MODULE-NEXT: call void @called_via_pointer(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; MODULE-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
; CGSCC-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree nonnull [[FP:%.*]])
; CGSCC-NEXT: call void @called_via_pointer(i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
; CGSCC-NEXT: ret void
;
call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
ret void
}
define internal void @call_via_pointer_with_dead_args_internal_b(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
; MODULE-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
; MODULE-SAME: (i32* [[A:%.*]], i32* nonnull align 128 dereferenceable(4) [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree nonnull [[FP:%.*]])
; MODULE-NEXT: call void @called_via_pointer_internal_2(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; MODULE-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
; CGSCC-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree nonnull [[FP:%.*]])
; CGSCC-NEXT: call void @called_via_pointer_internal_2(i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** noalias null)
; CGSCC-NEXT: ret void
;
call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
ret void
}
define void @call_via_pointer_with_dead_args_caller(i32* %a, i32* %b) {
; CHECK-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_caller
; CHECK-SAME: (i32* [[A:%.*]], i32* [[B:%.*]])
; CHECK-NEXT: [[PTR1:%.*]] = alloca i32, align 128
; CHECK-NEXT: [[PTR2:%.*]] = alloca i32, align 128
; CHECK-NEXT: [[PTR3:%.*]] = alloca i32, align 128
; CHECK-NEXT: [[PTR4:%.*]] = alloca i32, align 128
; CHECK-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer)
; CHECK-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer_internal_1)
; CHECK-NEXT: call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR3]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer)
; CHECK-NEXT: call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR4]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer_internal_2)
; CHECK-NEXT: ret void
;
%ptr1 = alloca i32, align 128
%ptr2 = alloca i32, align 128
%ptr3 = alloca i32, align 128
%ptr4 = alloca i32, align 128
call void @call_via_pointer_with_dead_args(i32* %a, i32* %ptr1, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer)
call void @call_via_pointer_with_dead_args(i32* %a, i32* %ptr2, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer_internal_1)
call void @call_via_pointer_with_dead_args_internal_a(i32* %b, i32* %ptr3, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer)
call void @call_via_pointer_with_dead_args_internal_b(i32* %b, i32* %ptr4, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer_internal_2)
ret void
}
define void @called_via_pointer(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
; CHECK-LABEL: define {{[^@]+}}@called_via_pointer
; CHECK-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT: tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT: ret void
;
entry:
tail call void @use_i32p(i32* %a)
tail call void @use_i32p(i32* %a)
ret void
}
define internal void @called_via_pointer_internal_1(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
; CHECK-LABEL: define {{[^@]+}}@called_via_pointer_internal_1
; CHECK-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT: tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT: ret void
;
entry:
tail call void @use_i32p(i32* %a)
tail call void @use_i32p(i32* %a)
ret void
}
; FIXME: Figure out why the MODULE has the unused arguments still
define internal void @called_via_pointer_internal_2(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
; CHECK-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
; CHECK-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT: tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT: ret void
;
entry:
tail call void @use_i32p(i32* %a)
tail call void @use_i32p(i32* %a)
ret void
}
declare void @use_i32p(i32*)
; UTC_ARGS: --disable
; Allow blockaddress users
; ALL_BUT_OLD_CGSCCC-NOT @dead_with_blockaddress_users
; MODULE-NOT: @dead_with_blockaddress_users
; CGSCC_NEW-NOT: @dead_with_blockaddress_users
; CGSCC_OLD: @dead_with_blockaddress_users
define internal void @dead_with_blockaddress_users(i32* nocapture %pc) nounwind readonly {
entry:
br label %indirectgoto

View File

@ -705,40 +705,38 @@ define internal i32 @r1(i32) local_unnamed_addr {
; OLD_PM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100
; OLD_PM-NEXT: br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]]
;
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@r1
; CGSCC_OLD_PM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr
; CGSCC_OLD_PM-NEXT: br label [[TMP5:%.*]]
; CGSCC_OLD_PM: 2:
; CGSCC_OLD_PM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP8:%.*]], 10000
; CGSCC_OLD_PM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[F:%.*]]
; CGSCC_OLD_PM: 4:
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@r1() local_unnamed_addr
; CGSCC_OLD_PM-NEXT: br label [[TMP4:%.*]]
; CGSCC_OLD_PM: 1:
; CGSCC_OLD_PM-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000
; CGSCC_OLD_PM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]]
; CGSCC_OLD_PM: 3:
; CGSCC_OLD_PM-NEXT: ret i32 20
; CGSCC_OLD_PM: f:
; CGSCC_OLD_PM-NEXT: ret i32 10
; CGSCC_OLD_PM: 5:
; CGSCC_OLD_PM-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP5]] ]
; CGSCC_OLD_PM-NEXT: [[TMP7:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP5]] ]
; CGSCC_OLD_PM-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP6]], [[TMP7]]
; CGSCC_OLD_PM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1
; CGSCC_OLD_PM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP9]], 100
; CGSCC_OLD_PM-NEXT: br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP5]]
; CGSCC_OLD_PM: 4:
; CGSCC_OLD_PM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ]
; CGSCC_OLD_PM-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ]
; CGSCC_OLD_PM-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]]
; CGSCC_OLD_PM-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1
; CGSCC_OLD_PM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100
; CGSCC_OLD_PM-NEXT: br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]]
;
; CGSCC_NEW_PM-LABEL: define {{[^@]+}}@r1
; CGSCC_NEW_PM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr
; CGSCC_NEW_PM-NEXT: br label [[TMP4:%.*]]
; CGSCC_NEW_PM: 2:
; CGSCC_NEW_PM-LABEL: define {{[^@]+}}@r1() local_unnamed_addr
; CGSCC_NEW_PM-NEXT: br label [[TMP3:%.*]]
; CGSCC_NEW_PM: 1:
; CGSCC_NEW_PM-NEXT: br label [[F:%.*]]
; CGSCC_NEW_PM: 3:
; CGSCC_NEW_PM: 2:
; CGSCC_NEW_PM-NEXT: unreachable
; CGSCC_NEW_PM: f:
; CGSCC_NEW_PM-NEXT: ret i32 10
; CGSCC_NEW_PM: 4:
; CGSCC_NEW_PM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ]
; CGSCC_NEW_PM-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP7:%.*]], [[TMP4]] ]
; CGSCC_NEW_PM-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]]
; CGSCC_NEW_PM-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1
; CGSCC_NEW_PM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100
; CGSCC_NEW_PM-NEXT: br i1 [[TMP9]], label [[TMP2:%.*]], label [[TMP4]]
; CGSCC_NEW_PM: 3:
; CGSCC_NEW_PM-NEXT: [[TMP4:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP7:%.*]], [[TMP3]] ]
; CGSCC_NEW_PM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP6:%.*]], [[TMP3]] ]
; CGSCC_NEW_PM-NEXT: [[TMP6]] = add nuw nsw i32 [[TMP4]], [[TMP5]]
; CGSCC_NEW_PM-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP4]], 1
; CGSCC_NEW_PM-NEXT: [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 100
; CGSCC_NEW_PM-NEXT: br i1 [[TMP8]], label [[TMP1:%.*]], label [[TMP3]]
;
br label %5
@ -780,7 +778,7 @@ define void @f1(i32){
;
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@f1
; CGSCC_OLD_PM-SAME: (i32 [[TMP0:%.*]])
; CGSCC_OLD_PM-NEXT: [[TMP2:%.*]] = tail call i32 @r1(i32 [[TMP0]])
; CGSCC_OLD_PM-NEXT: [[TMP2:%.*]] = tail call i32 @r1()
; CGSCC_OLD_PM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 15
; CGSCC_OLD_PM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
; CGSCC_OLD_PM: 4:
@ -1122,13 +1120,7 @@ define dso_local i64 @select_int2ptr_bitcast_ptr2int(i32 %a) local_unnamed_addr
; CHECK-LABEL: define {{[^@]+}}@select_int2ptr_bitcast_ptr2int
; CHECK-SAME: (i32 [[A:%.*]]) local_unnamed_addr
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 5
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[CMP]], i32 1, i32 2
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A]], 10
; CHECK-NEXT: [[Y_0_V:%.*]] = select i1 [[CMP1]], i32 1, i32 2
; CHECK-NEXT: [[Y_0:%.*]] = add nuw nsw i32 [[DOT]], [[Y_0_V]]
; CHECK-NEXT: [[CMP6:%.*]] = icmp eq i32 [[Y_0]], 5
; CHECK-NEXT: [[I2P:%.*]] = inttoptr i1 [[CMP6]] to i1*
; CHECK-NEXT: [[I2P:%.*]] = inttoptr i1 false to i1*
; CHECK-NEXT: [[BC:%.*]] = bitcast i1* [[I2P]] to i32*
; CHECK-NEXT: [[P2I:%.*]] = ptrtoint i32* [[BC]] to i64
; CHECK-NEXT: ret i64 [[P2I]]