aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2008-02-25 04:08:09 +0000
committerOwen Anderson <resistor@mac.com>2008-02-25 04:08:09 +0000
commit90f4ff51d0cf4999e0b56bfcddd0d70a7c2c7a7a (patch)
treec33895312f9bf9d536b622e6fbbd35bd865b1d3d /lib/Transforms
parent1d18308a34941a06b1c42b4c9c4cf86b0fc179ca (diff)
downloadexternal_llvm-90f4ff51d0cf4999e0b56bfcddd0d70a7c2c7a7a.zip
external_llvm-90f4ff51d0cf4999e0b56bfcddd0d70a7c2c7a7a.tar.gz
external_llvm-90f4ff51d0cf4999e0b56bfcddd0d70a7c2c7a7a.tar.bz2
Fix an issue where GVN was performing the return slot optimization when it was
not safe. This is fixed by more aggressively checking that the return slot is not used elsewhere in the function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47544 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/Scalar/GVN.cpp34
1 files changed, 26 insertions, 8 deletions
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp
index 6506121..4b7e82c 100644
--- a/lib/Transforms/Scalar/GVN.cpp
+++ b/lib/Transforms/Scalar/GVN.cpp
@@ -752,6 +752,8 @@ namespace {
bool iterateOnFunction(Function &F);
Value* CollapsePhi(PHINode* p);
bool isSafeReplacement(PHINode* p, Instruction* inst);
+ bool valueHasOnlyOneUseAfter(Value* val, MemCpyInst* use,
+ Instruction* cutoff);
};
char GVN::ID = 0;
@@ -1055,22 +1057,32 @@ bool GVN::processLoad(LoadInst* L,
return deletedLoad;
}
-/// isReturnSlotOptznProfitable - Determine if performing a return slot
-/// fusion with the slot dest is profitable
-static bool isReturnSlotOptznProfitable(Value* dest, MemCpyInst* cpy) {
- // We currently consider it profitable if dest is otherwise dead.
- SmallVector<User*, 8> useList(dest->use_begin(), dest->use_end());
+/// valueHasOnlyOneUse - Returns true if a value has only one use after the
+/// cutoff that is in the current same block and is the same as the use
+/// parameter.
+bool GVN::valueHasOnlyOneUseAfter(Value* val, MemCpyInst* use,
+ Instruction* cutoff) {
+ DominatorTree& DT = getAnalysis<DominatorTree>();
+
+ SmallVector<User*, 8> useList(val->use_begin(), val->use_end());
while (!useList.empty()) {
User* UI = useList.back();
+
if (isa<GetElementPtrInst>(UI) || isa<BitCastInst>(UI)) {
useList.pop_back();
for (User::use_iterator I = UI->use_begin(), E = UI->use_end();
I != E; ++I)
useList.push_back(*I);
- } else if (UI == cpy)
+ } else if (UI == use) {
useList.pop_back();
- else
+ } else if (Instruction* inst = dyn_cast<Instruction>(UI)) {
+ if (inst->getParent() == use->getParent() &&
+ (inst == cutoff || !DT.dominates(cutoff, inst))) {
+ useList.pop_back();
+ } else
+ return false;
+ } else
return false;
}
@@ -1123,8 +1135,14 @@ bool GVN::performReturnSlotOptzn(MemCpyInst* cpy, CallInst* C,
if (TD.getTypeStoreSize(PT->getElementType()) != cpyLength->getZExtValue())
return false;
+ // For safety, we must ensure that the output parameter of the call only has
+ // a single use, the memcpy. Otherwise this can introduce an invalid
+ // transformation.
+ if (!valueHasOnlyOneUseAfter(CS.getArgument(0), cpy, C))
+ return false;
+
// We only perform the transformation if it will be profitable.
- if (!isReturnSlotOptznProfitable(cpyDest, cpy))
+ if (!valueHasOnlyOneUseAfter(cpyDest, cpy, C))
return false;
// In addition to knowing that the call does not access the return slot