[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:
Johannes Doerfert 2020-02-14 20:06:34 -06:00
parent 40b3067218
commit 137c99a6a5
3 changed files with 59 additions and 7 deletions

View File

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

View File

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

View File

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