forked from OSchip/llvm-project
[Attributor][FIX] Restrict cross-SCC call deletion
If we know a call was not needed we might have ended up deleting it even if it was in a different SCC. This prevents us from doing so.
This commit is contained in:
parent
40b3067218
commit
137c99a6a5
|
@ -7481,6 +7481,10 @@ ChangeStatus Attributor::run() {
|
|||
LLVM_DEBUG(dbgs() << "Use " << *NewV << " in " << *U->getUser()
|
||||
<< " instead of " << *OldV << "\n");
|
||||
U->set(NewV);
|
||||
// Do not modify call instructions outside the SCC.
|
||||
if (auto *CB = dyn_cast<CallBase>(OldV))
|
||||
if (!Functions.count(CB->getCaller()))
|
||||
continue;
|
||||
if (Instruction *I = dyn_cast<Instruction>(OldV)) {
|
||||
CGModifiedFunctions.insert(I->getFunction());
|
||||
if (!isa<PHINode>(I) && !ToBeDeletedInsts.count(I) &&
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
|
||||
; RUN: opt -S -basicaa -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s --check-prefixes=CHECK
|
||||
; RUN: opt -S -basicaa -attributor-cgscc -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK
|
||||
; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s --check-prefixes=CHECK
|
||||
; RUN: opt -S -passes='attributor-cgscc' -aa-pipeline='basic-aa' -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK
|
||||
; RUN: opt -S -basicaa -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s --check-prefixes=CHECK,OLDPM,OLDPM_MODULE
|
||||
; RUN: opt -S -basicaa -attributor-cgscc -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK,OLDPM,OLDPM_CGSCC
|
||||
; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s --check-prefixes=CHECK,NEWPM,NEWPM_MODULE
|
||||
; RUN: opt -S -passes='attributor-cgscc' -aa-pipeline='basic-aa' -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK,NEWPM,NEWPM_CGSCC
|
||||
|
||||
; CHECK-NOT: @dead(
|
||||
; CHECK-NOT: @test(
|
||||
; CHECK-NOT: @caller(
|
||||
; OLDPM_MODULE-NOT: @dead
|
||||
; NEWPM_MODULE-NOT: @dead
|
||||
; OLDPM_CGSCC-NOT: @dead
|
||||
; NEWPM_CGSCC-NOT: @dead
|
||||
|
||||
define internal void @dead() {
|
||||
call i32 @test(i32* null, i32* null)
|
||||
|
@ -14,6 +15,24 @@ define internal void @dead() {
|
|||
}
|
||||
|
||||
define internal i32 @test(i32* %X, i32* %Y) {
|
||||
; OLDPM_CGSCC-LABEL: define {{[^@]+}}@test
|
||||
; OLDPM_CGSCC-SAME: (i32* noalias nocapture nofree writeonly align 4 [[X:%.*]])
|
||||
; OLDPM_CGSCC-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]]
|
||||
; OLDPM_CGSCC: live:
|
||||
; OLDPM_CGSCC-NEXT: store i32 0, i32* [[X]], align 4
|
||||
; OLDPM_CGSCC-NEXT: ret i32 undef
|
||||
; OLDPM_CGSCC: dead:
|
||||
; OLDPM_CGSCC-NEXT: unreachable
|
||||
;
|
||||
; NEWPM_CGSCC-LABEL: define {{[^@]+}}@test
|
||||
; NEWPM_CGSCC-SAME: (i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[X:%.*]])
|
||||
; NEWPM_CGSCC-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]]
|
||||
; NEWPM_CGSCC: live:
|
||||
; NEWPM_CGSCC-NEXT: store i32 0, i32* [[X]], align 4
|
||||
; NEWPM_CGSCC-NEXT: ret i32 undef
|
||||
; NEWPM_CGSCC: dead:
|
||||
; NEWPM_CGSCC-NEXT: unreachable
|
||||
;
|
||||
br i1 true, label %live, label %dead
|
||||
live:
|
||||
store i32 0, i32* %X
|
||||
|
@ -25,6 +44,18 @@ dead:
|
|||
}
|
||||
|
||||
define internal i32 @caller(i32* %B) {
|
||||
; OLDPM_CGSCC-LABEL: define {{[^@]+}}@caller()
|
||||
; OLDPM_CGSCC-NEXT: [[A:%.*]] = alloca i32
|
||||
; OLDPM_CGSCC-NEXT: store i32 1, i32* [[A]], align 4
|
||||
; OLDPM_CGSCC-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; OLDPM_CGSCC-NEXT: ret i32 0
|
||||
;
|
||||
; NEWPM_CGSCC-LABEL: define {{[^@]+}}@caller()
|
||||
; NEWPM_CGSCC-NEXT: [[A:%.*]] = alloca i32
|
||||
; NEWPM_CGSCC-NEXT: store i32 1, i32* [[A]], align 4
|
||||
; NEWPM_CGSCC-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; NEWPM_CGSCC-NEXT: ret i32 undef
|
||||
;
|
||||
%A = alloca i32
|
||||
store i32 1, i32* %A
|
||||
%C = call i32 @test(i32* %A, i32* %B)
|
||||
|
|
|
@ -722,6 +722,23 @@ define internal i32 @r1(i32) local_unnamed_addr {
|
|||
; 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_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-NEXT: br label [[F:%.*]]
|
||||
; CGSCC_NEW_PM: 3:
|
||||
; 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]]
|
||||
;
|
||||
br label %5
|
||||
|
||||
|
|
Loading…
Reference in New Issue