summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2016-08-03 17:12:47 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2016-08-03 17:12:47 +0000
commitfad04908692228a1853e93e9adbbd398756629ff (patch)
tree7991ea2a27bb24855e5e54d6a97d6a751c03f5c3
parent57dc4cf0e1dc149f05569aee7c5dd8fec04f81b4 (diff)
downloadbcm5719-llvm-fad04908692228a1853e93e9adbbd398756629ff.tar.gz
bcm5719-llvm-fad04908692228a1853e93e9adbbd398756629ff.zip
[CloneFunction] Don't remove side effecting calls
We were able to figure out that the result of a call is some constant. While propagating that fact, we added the constant to the value map. This is problematic because it results in us losing the call site when processing the value map. This fixes PR28802. llvm-svn: 277611
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp6
-rw-r--r--llvm/lib/Transforms/Utils/CloneFunction.cpp35
-rw-r--r--llvm/test/Transforms/Inline/inline_constprop.ll22
3 files changed, 59 insertions, 4 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 5b723e59742..ac03fdc86e6 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4356,7 +4356,8 @@ static bool replaceAndRecursivelySimplifyImpl(Instruction *I, Value *SimpleV,
// Gracefully handle edge cases where the instruction is not wired into any
// parent block.
- if (I->getParent())
+ if (I->getParent() && !I->isEHPad() && !isa<TerminatorInst>(I) &&
+ !I->mayHaveSideEffects())
I->eraseFromParent();
} else {
Worklist.insert(I);
@@ -4384,7 +4385,8 @@ static bool replaceAndRecursivelySimplifyImpl(Instruction *I, Value *SimpleV,
// Gracefully handle edge cases where the instruction is not wired into any
// parent block.
- if (I->getParent())
+ if (I->getParent() && !I->isEHPad() && !isa<TerminatorInst>(I) &&
+ !I->mayHaveSideEffects())
I->eraseFromParent();
}
return Simplified;
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index c5ca56360fc..e6aa85c2aaa 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
@@ -552,9 +553,39 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
// two PHINodes, the iteration over the old PHIs remains valid, and the
// mapping will just map us to the new node (which may not even be a PHI
// node).
+ const DataLayout &DL = NewFunc->getParent()->getDataLayout();
+ SmallSetVector<const Value *, 8> Worklist;
for (unsigned Idx = 0, Size = PHIToResolve.size(); Idx != Size; ++Idx)
- if (PHINode *PN = dyn_cast<PHINode>(VMap[PHIToResolve[Idx]]))
- recursivelySimplifyInstruction(PN);
+ if (isa<PHINode>(VMap[PHIToResolve[Idx]]))
+ Worklist.insert(PHIToResolve[Idx]);
+
+ // Note that we must test the size on each iteration, the worklist can grow.
+ for (unsigned Idx = 0; Idx != Worklist.size(); ++Idx) {
+ const Value *OrigV = Worklist[Idx];
+ auto *I = cast<Instruction>(VMap.lookup(OrigV));
+ if (!I)
+ continue;
+
+ // See if this instruction simplifies.
+ Value *SimpleV = SimplifyInstruction(I, DL);
+ if (!SimpleV)
+ continue;
+
+ // Stash away all the uses of the old instruction so we can check them for
+ // recursive simplifications after a RAUW. This is cheaper than checking all
+ // uses of To on the recursive step in most cases.
+ for (const User *U : OrigV->users())
+ Worklist.insert(cast<Instruction>(U));
+
+ // Replace the instruction with its simplified value.
+ I->replaceAllUsesWith(SimpleV);
+
+ // If the original instruction had no side effects, remove it.
+ if (isInstructionTriviallyDead(I))
+ I->eraseFromParent();
+ else
+ VMap[OrigV] = I;
+ }
// Now that the inlined function body has been fully constructed, go through
// and zap unconditional fall-through branches. This happens all the time when
diff --git a/llvm/test/Transforms/Inline/inline_constprop.ll b/llvm/test/Transforms/Inline/inline_constprop.ll
index de23b6157a7..813a71cc24e 100644
--- a/llvm/test/Transforms/Inline/inline_constprop.ll
+++ b/llvm/test/Transforms/Inline/inline_constprop.ll
@@ -279,3 +279,25 @@ return:
%retval.0 = phi i32* [ %b, %if.end3 ], [ %a, %if.then ]
ret i32* %retval.0
}
+
+declare i32 @PR28802.external(i32 returned %p1)
+
+define internal i32 @PR28802.callee() {
+entry:
+ br label %cont
+
+cont:
+ %0 = phi i32 [ 0, %entry ]
+ %call = call i32 @PR28802.external(i32 %0)
+ ret i32 %call
+}
+
+define i32 @PR28802() {
+entry:
+ %call = call i32 @PR28802.callee()
+ ret i32 %call
+}
+
+; CHECK-LABEL: define i32 @PR28802(
+; CHECK: call i32 @PR28802.external(i32 0)
+; CHECK: ret i32 0
OpenPOWER on IntegriCloud