]> granicus.if.org Git - llvm/commitdiff
[Attributor][Fix] Do not remove instructions during manifestation
authorJohannes Doerfert <jdoerfert@anl.gov>
Mon, 5 Aug 2019 21:35:02 +0000 (21:35 +0000)
committerJohannes Doerfert <jdoerfert@anl.gov>
Mon, 5 Aug 2019 21:35:02 +0000 (21:35 +0000)
When we remove instructions cached references could still be live. This
patch avoids removing invoke instructions that are replaced by calls and
instead keeps them around but in a dead block.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@367933 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Transforms/Utils/Local.h
lib/Transforms/IPO/Attributor.cpp
lib/Transforms/Utils/Local.cpp
test/Transforms/FunctionAttrs/liveness.ll

index ee8df756d726388c38850c6ac9cd3f77664ecdd2..5c5e0aef34cdf4e1a2dcc8de48a61f8c6cd653d3 100644 (file)
@@ -271,6 +271,12 @@ inline unsigned getKnownAlignment(Value *V, const DataLayout &DL,
   return getOrEnforceKnownAlignment(V, 0, DL, CxtI, AC, DT);
 }
 
+/// Create a call that matches the invoke \p II in terms of arguments,
+/// attributes, debug information, etc. The call is not placed in a block and it
+/// will not have a name. The invoke instruction is not removed, nor are the
+/// uses replaced by the new call.
+CallInst *createCallMatchingInvoke(InvokeInst *II);
+
 /// This function converts the specified invoek into a normall call.
 void changeToCall(InvokeInst *II, DomTreeUpdater *DTU = nullptr);
 
index 1ae8ac77de09d23137b5c281b8b3e2a77a467dee..3ecad8b03ebabb545fd81825062b1df11f3c59ff 100644 (file)
@@ -1577,6 +1577,11 @@ struct AAIsDeadFunction : AAIsDead, BooleanState {
       Instruction *SplitPos = I->getNextNode();
 
       if (auto *II = dyn_cast<InvokeInst>(I)) {
+        // If we keep the invoke the split position is at the beginning of the
+        // normal desitination block (it invokes a noreturn function after all).
+        BasicBlock *NormalDestBB = II->getNormalDest();
+        SplitPos = &NormalDestBB->front();
+
         /// Invoke is replaced with a call and unreachable is placed after it if
         /// the callee is nounwind and noreturn. Otherwise, we keep the invoke
         /// and only place an unreachable in the normal successor.
@@ -1587,17 +1592,26 @@ struct AAIsDeadFunction : AAIsDead, BooleanState {
                 (AANoUnw && AANoUnw->isAssumedNoUnwind())) {
               LLVM_DEBUG(dbgs()
                          << "[AAIsDead] Replace invoke with call inst\n");
-              changeToCall(II);
-              changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
-              continue;
+              // We do not need an invoke (II) but instead want a call followed
+              // by an unreachable. However, we do not remove II as other
+              // abstract attributes might have it cached as part of their
+              // results. Given that we modify the CFG anyway, we simply keep II
+              // around but in a new dead block. To avoid II being live through
+              // a different edge we have to ensure the block we place it in is
+              // only reached from the current block of II and then not reached
+              // at all when we insert the unreachable.
+              SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c");
+              CallInst *CI = createCallMatchingInvoke(II);
+              CI->insertBefore(II);
+              CI->takeName(II);
+              II->replaceAllUsesWith(CI);
+              SplitPos = CI->getNextNode();
             }
           }
         }
-
-        BB = II->getNormalDest();
-        SplitPos = &BB->front();
       }
 
+      BB = SplitPos->getParent();
       SplitBlock(BB, SplitPos);
       changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
       HasChanged = ChangeStatus::CHANGED;
index 68443c15a7822fe540aead79c36984d0c531cc67..a1d1b3ec84f007ec4a458ce4413009e625be0a01 100644 (file)
@@ -1933,18 +1933,24 @@ unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap,
   return NumInstrsRemoved;
 }
 
-/// changeToCall - Convert the specified invoke into a normal call.
-void llvm::changeToCall(InvokeInst *II, DomTreeUpdater *DTU) {
-  SmallVector<Value*, 8> Args(II->arg_begin(), II->arg_end());
+CallInst *llvm::createCallMatchingInvoke(InvokeInst *II) {
+  SmallVector<Value *, 8> Args(II->arg_begin(), II->arg_end());
   SmallVector<OperandBundleDef, 1> OpBundles;
   II->getOperandBundlesAsDefs(OpBundles);
-  CallInst *NewCall = CallInst::Create(
-      II->getFunctionType(), II->getCalledValue(), Args, OpBundles, "", II);
-  NewCall->takeName(II);
+  CallInst *NewCall = CallInst::Create(II->getFunctionType(),
+                                       II->getCalledValue(), Args, OpBundles);
   NewCall->setCallingConv(II->getCallingConv());
   NewCall->setAttributes(II->getAttributes());
   NewCall->setDebugLoc(II->getDebugLoc());
   NewCall->copyMetadata(*II);
+  return NewCall;
+}
+
+/// changeToCall - Convert the specified invoke into a normal call.
+void llvm::changeToCall(InvokeInst *II, DomTreeUpdater *DTU) {
+  CallInst *NewCall = createCallMatchingInvoke(II);
+  NewCall->takeName(II);
+  NewCall->insertBefore(II);
   II->replaceAllUsesWith(NewCall);
 
   // Follow the call by a branch to the normal destination.
index cbf5631e6ebaef5f1739de3c4394e1cb9f44f341..166b15441e4af0152d05ac11eccfb6d3e7ee14e7 100644 (file)
@@ -184,9 +184,14 @@ cond.true:                                        ; preds = %entry
   call void @normal_call()
   %call = invoke i32 @foo_noreturn_nounwind() to label %continue
             unwind label %cleanup
-  ; CHECK:      call i32 @foo_noreturn_nounwind()
+  ; CHECK:      call void @normal_call()
+  ; CHECK-NEXT: call i32 @foo_noreturn_nounwind()
   ; CHECK-NEXT: unreachable
 
+  ; We keep the invoke around as other attributes might have references to it.
+  ; CHECK:       cond.true.split:                                  ; No predecessors!
+  ; CHECK-NEXT:      invoke i32 @foo_noreturn_nounwind()
+
 cond.false:                                       ; preds = %entry
   call void @normal_call()
   %call1 = call i32 @bar()