From 137c99a6a5cd419086824035c1498baddbd46962 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Fri, 14 Feb 2020 20:06:34 -0600 Subject: [PATCH] [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. --- llvm/lib/Transforms/IPO/Attributor.cpp | 4 ++ .../live_called_from_dead.ll | 45 ++++++++++++++++--- llvm/test/Transforms/Attributor/range.ll | 17 +++++++ 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index e7b8927fe7eb..0ca65eb55566 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -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(OldV)) + if (!Functions.count(CB->getCaller())) + continue; if (Instruction *I = dyn_cast(OldV)) { CGModifiedFunctions.insert(I->getFunction()); if (!isa(I) && !ToBeDeletedInsts.count(I) && diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll index 23715ae2da7c..c69842119ec6 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll @@ -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) diff --git a/llvm/test/Transforms/Attributor/range.ll b/llvm/test/Transforms/Attributor/range.ll index 4f2c941f4f42..f943f650a02c 100644 --- a/llvm/test/Transforms/Attributor/range.ll +++ b/llvm/test/Transforms/Attributor/range.ll @@ -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