From: David Majnemer Date: Sat, 25 Jun 2016 00:04:10 +0000 (+0000) Subject: Reinstate r273711 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c1fd19fd0b89b4755207c62dfe8c2ef991cbb250;p=llvm Reinstate r273711 r273711 was reverted by r273743. The inliner needs to know about any call sites in the inlined function. These were obscured if we replaced a call to undef with an undef but kept the call around. This fixes PR28298. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273753 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/EarlyCSE.cpp b/lib/Transforms/Scalar/EarlyCSE.cpp index 0e93b0a37b0..9d0ef42e039 100644 --- a/lib/Transforms/Scalar/EarlyCSE.cpp +++ b/lib/Transforms/Scalar/EarlyCSE.cpp @@ -582,11 +582,18 @@ bool EarlyCSE::processNode(DomTreeNode *Node) { // its simpler value. if (Value *V = SimplifyInstruction(Inst, DL, &TLI, &DT, &AC)) { DEBUG(dbgs() << "EarlyCSE Simplify: " << *Inst << " to: " << *V << '\n'); - Inst->replaceAllUsesWith(V); - Inst->eraseFromParent(); - Changed = true; - ++NumSimplify; - continue; + if (!Inst->use_empty()) { + Inst->replaceAllUsesWith(V); + Changed = true; + } + if (isInstructionTriviallyDead(Inst, &TLI)) { + Inst->eraseFromParent(); + Changed = true; + } + if (Changed) { + ++NumSimplify; + continue; + } } // If this is a simple instruction that we can value number, process it. diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 944e06d4391..a963b2f50ed 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -2056,12 +2056,21 @@ bool GVN::processInstruction(Instruction *I) { // "%z = and i32 %x, %y" becomes "%z = and i32 %x, %x" which we now simplify. const DataLayout &DL = I->getModule()->getDataLayout(); if (Value *V = SimplifyInstruction(I, DL, TLI, DT, AC)) { - I->replaceAllUsesWith(V); - if (MD && V->getType()->getScalarType()->isPointerTy()) - MD->invalidateCachedPointerInfo(V); - markInstructionForDeletion(I); - ++NumGVNSimpl; - return true; + bool Changed = false; + if (!I->use_empty()) { + I->replaceAllUsesWith(V); + Changed = true; + } + if (isInstructionTriviallyDead(I, TLI)) { + markInstructionForDeletion(I); + Changed = true; + } + if (Changed) { + if (MD && V->getType()->getScalarType()->isPointerTy()) + MD->invalidateCachedPointerInfo(V); + ++NumGVNSimpl; + return true; + } } if (IntrinsicInst *IntrinsicI = dyn_cast(I)) diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index 1d8d2a5e469..e7957f9599a 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -1746,13 +1746,18 @@ bool JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred( // phi translation. if (Value *IV = SimplifyInstruction(New, BB->getModule()->getDataLayout())) { - delete New; ValueMapping[&*BI] = IV; + if (!New->mayHaveSideEffects()) { + delete New; + New = nullptr; + } } else { + ValueMapping[&*BI] = New; + } + if (New) { // Otherwise, insert the new instruction into the block. New->setName(BI->getName()); PredBB->getInstList().insert(OldPredBranch->getIterator(), New); - ValueMapping[&*BI] = New; } } diff --git a/lib/Transforms/Scalar/LoopRotation.cpp b/lib/Transforms/Scalar/LoopRotation.cpp index c6709d5334a..46db8f1210b 100644 --- a/lib/Transforms/Scalar/LoopRotation.cpp +++ b/lib/Transforms/Scalar/LoopRotation.cpp @@ -312,13 +312,18 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { if (V && LI->replacementPreservesLCSSAForm(C, V)) { // If so, then delete the temporary instruction and stick the folded value // in the map. - delete C; ValueMap[Inst] = V; + if (!C->mayHaveSideEffects()) { + delete C; + C = nullptr; + } } else { + ValueMap[Inst] = C; + } + if (C) { // Otherwise, stick the new instruction into the new block! C->setName(Inst->getName()); C->insertBefore(LoopEntryBranch); - ValueMap[Inst] = C; } } diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index 6ff05fe3e59..fcdb45b6611 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -296,9 +296,11 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB, if (Value *MappedV = VMap.lookup(V)) V = MappedV; - VMap[&*II] = V; - delete NewInst; - continue; + if (!NewInst->mayHaveSideEffects()) { + VMap[&*II] = V; + delete NewInst; + continue; + } } } diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 4f8935dd971..4d76aae2971 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -456,14 +456,23 @@ simplifyAndDCEInstruction(Instruction *I, if (Value *SimpleV = SimplifyInstruction(I, DL)) { // Add the users to the worklist. CAREFUL: an instruction can use itself, // in the case of a phi node. - for (User *U : I->users()) - if (U != I) + for (User *U : I->users()) { + if (U != I) { WorkList.insert(cast(U)); + } + } // Replace the instruction with its simplified value. - I->replaceAllUsesWith(SimpleV); - I->eraseFromParent(); - return true; + bool Changed = false; + if (!I->use_empty()) { + I->replaceAllUsesWith(SimpleV); + Changed = true; + } + if (isInstructionTriviallyDead(I, TLI)) { + I->eraseFromParent(); + Changed = true; + } + return Changed; } return false; } diff --git a/lib/Transforms/Utils/LoopUnroll.cpp b/lib/Transforms/Utils/LoopUnroll.cpp index f7e5c0c49f8..9e53b1c2647 100644 --- a/lib/Transforms/Utils/LoopUnroll.cpp +++ b/lib/Transforms/Utils/LoopUnroll.cpp @@ -623,18 +623,17 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool Force, // go. const DataLayout &DL = Header->getModule()->getDataLayout(); const std::vector &NewLoopBlocks = L->getBlocks(); - for (BasicBlock *BB : NewLoopBlocks) + for (BasicBlock *BB : NewLoopBlocks) { for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { Instruction *Inst = &*I++; + if (Value *V = SimplifyInstruction(Inst, DL)) + if (LI->replacementPreservesLCSSAForm(Inst, V)) + Inst->replaceAllUsesWith(V); if (isInstructionTriviallyDead(Inst)) BB->getInstList().erase(Inst); - else if (Value *V = SimplifyInstruction(Inst, DL)) - if (LI->replacementPreservesLCSSAForm(Inst, V)) { - Inst->replaceAllUsesWith(V); - BB->getInstList().erase(Inst); - } } + } NumCompletelyUnrolled += CompletelyUnroll; ++NumUnrolled; diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 6e1ac2c9a69..d22f5c63dee 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1885,14 +1885,19 @@ static bool FoldCondBranchOnPHI(BranchInst *BI, const DataLayout &DL) { // Check for trivial simplification. if (Value *V = SimplifyInstruction(N, DL)) { - TranslateMap[&*BBI] = V; - delete N; // Instruction folded away, don't need actual inst + if (!BBI->use_empty()) + TranslateMap[&*BBI] = V; + if (!N->mayHaveSideEffects()) { + delete N; // Instruction folded away, don't need actual inst + N = nullptr; + } } else { - // Insert the new instruction into its new home. - EdgeBB->getInstList().insert(InsertPt, N); if (!BBI->use_empty()) TranslateMap[&*BBI] = N; } + // Insert the new instruction into its new home. + if (N) + EdgeBB->getInstList().insert(InsertPt, N); } // Loop over all of the edges from PredBB to BB, changing them to branch diff --git a/test/Transforms/GVN/volatile.ll b/test/Transforms/GVN/volatile.ll index b31058db4ea..ccc5bbfa48e 100644 --- a/test/Transforms/GVN/volatile.ll +++ b/test/Transforms/GVN/volatile.ll @@ -152,6 +152,16 @@ exit: ret i32 %add } +define i32 @test9(i32* %V) { +entry: + %load = load volatile i32, i32* %V, !range !0 + ret i32 %load +} +; CHECK-LABEL: test9 +; CHECK: load volatile +; CHECK: ret i32 0 + declare void @use(i32) readonly declare void @clobber(i32* %p, i32* %q) +!0 = !{ i32 0, i32 1 } diff --git a/test/Transforms/Inline/pr28298.ll b/test/Transforms/Inline/pr28298.ll new file mode 100644 index 00000000000..0bb3f0a7115 --- /dev/null +++ b/test/Transforms/Inline/pr28298.ll @@ -0,0 +1,19 @@ +; RUN: opt -S -inline < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @test1() { +entry: + call void @test2() + ret void +} + +define internal void @test2() { +entry: + call void undef() + ret void +} + +; CHECK-LABEL: define void @test1( +; CHECK: call void undef( +; CHECK: ret void