From 3c1476d26c769cd97a631a129b30c62232ac96b6 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 25 Jul 2020 11:52:14 +0100 Subject: [PATCH] [IPSCCP] Drop argmemonly after replacing pointer argument. This patch updates IPSCCP to drop argmemonly and inaccessiblemem_or_argmemonly if it replaces a pointer argument. Fixes PR46717. Reviewers: efriedma, davide, nikic, jdoerfert Reviewed By: efriedma, jdoerfert Differential Revision: https://reviews.llvm.org/D84432 --- llvm/lib/Transforms/Scalar/SCCP.cpp | 30 ++++++++++++++++++---- llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll | 17 +++++------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp index 32dc14e..428f967 100644 --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -1911,15 +1911,35 @@ bool llvm::runIPSCCP( SmallVector BlocksToErase; - if (Solver.isBlockExecutable(&F.front())) - for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); AI != E; - ++AI) { - if (!AI->use_empty() && tryToReplaceWithConstant(Solver, &*AI)) { + if (Solver.isBlockExecutable(&F.front())) { + bool ReplacedPointerArg = false; + for (Argument &Arg : F.args()) { + if (!Arg.use_empty() && tryToReplaceWithConstant(Solver, &Arg)) { + ReplacedPointerArg |= Arg.getType()->isPointerTy(); ++IPNumArgsElimed; - continue; } } + // If we replaced an argument, the argmemonly and + // inaccessiblemem_or_argmemonly attributes do not hold any longer. Remove + // them from both the function and callsites. + if (ReplacedPointerArg) { + SmallVector AttributesToRemove = { + Attribute::ArgMemOnly, Attribute::InaccessibleMemOrArgMemOnly}; + for (auto Attr : AttributesToRemove) + F.removeFnAttr(Attr); + + for (User *U : F.users()) { + auto *CB = dyn_cast(U); + if (!CB || CB->getCalledFunction() != &F) + continue; + + for (auto Attr : AttributesToRemove) + CB->removeAttribute(AttributeList::FunctionIndex, Attr); + } + } + } + SmallPtrSet InsertedValues; for (BasicBlock &BB : F) { if (!Solver.isBlockExecutable(&BB)) { diff --git a/llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll b/llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll index a110476..2e3a357 100644 --- a/llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll +++ b/llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll @@ -11,7 +11,7 @@ ; Here the pointer argument %arg will be replaced by a constant. We need to ; drop argmemonly. define internal void @ptrarg.1(i32* %arg, i32 %val) argmemonly nounwind { -; CHECK: Function Attrs: argmemonly nounwind +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: @ptrarg.1( ; CHECK-NEXT: store i32 10, i32* @g, align 4 ; CHECK-NEXT: ret void @@ -59,7 +59,7 @@ define void @caller.2(i32* %ptr) { ; Here the pointer argument %arg will be replaced by a constant. We need to ; drop inaccessiblemem_or_argmemonly. define internal void @ptrarg.3(i32* %arg, i32 %val) inaccessiblemem_or_argmemonly nounwind { -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly nounwind +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: @ptrarg.3( ; CHECK-NEXT: store i32 10, i32* @g, align 4 ; CHECK-NEXT: ret void @@ -107,7 +107,7 @@ define void @caller.4(i32* %ptr) { ; Here the pointer argument %arg will be replaced by a constant. We need to ; drop inaccessiblemem_or_argmemonly. define internal void @ptrarg.5(i32* %arg, i32 %val) argmemonly inaccessiblemem_or_argmemonly nounwind { -; CHECK: Function Attrs: argmemonly inaccessiblemem_or_argmemonly nounwind +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: @ptrarg.5( ; CHECK-NEXT: store i32 10, i32* @g, align 4 ; CHECK-NEXT: ret void @@ -143,9 +143,9 @@ define internal void @ptrarg.6.cs.attributes(i32* %arg, i32 %val) { define i32 @caller.6.cs.attributes(i32 %n) { ; CHECK-LABEL: @caller.6.cs.attributes( ; CHECK-NEXT: store i32 1, i32* @g, align 4 -; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[ARGMEMONLY_INACCESSIBLEMEM_OR_ARGMEMONLY_NOUNWIND:#[0-9]+]] -; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[INACCESSIBLEMEM_OR_ARGMEMONLY_NOUNWIND:#[0-9]+]] -; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[ARGMEMONLY_NOUNWIND:#[0-9]+]] +; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[NOUNWIND:#[0-9]+]] +; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[NOUNWIND:#[0-9]+]] +; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[NOUNWIND:#[0-9]+]] ; CHECK-NEXT: tail call void @ptrarg.5(i32* @g, i32 10) [[NOUNWIND:#[0-9]+]] ; CHECK-NEXT: [[G_VAL:%.*]] = load i32, i32* @g, align 4 ; CHECK-NEXT: ret i32 [[G_VAL]] @@ -159,7 +159,4 @@ define i32 @caller.6.cs.attributes(i32 %n) { ret i32 %g.val } -; CHECK-DAG: [[ARGMEMONLY_INACCESSIBLEMEM_OR_ARGMEMONLY_NOUNWIND]] = { argmemonly inaccessiblemem_or_argmemonly nounwind } -; CHECK-DAG: [[INACCESSIBLEMEM_OR_ARGMEMONLY_NOUNWIND]] = { inaccessiblemem_or_argmemonly nounwind } -; CHECK-DAG: [[ARGMEMONLY_NOUNWIND]] = { argmemonly nounwind } -; CHECK-DAG: [[NOUNWIND]] = { nounwind } +; CHECK: [[NOUNWIND]] = { nounwind } -- 2.7.4