[llvm-commits] [llvm] r45218 - in /llvm/trunk: include/llvm/Instructions.h include/llvm/ParameterAttributes.h include/llvm/Support/CallSite.h lib/Transforms/IPO/PruneEH.cpp lib/Transforms/Scalar/InstructionCombining.cpp lib/Transforms/Utils/InlineFunction.cpp lib/VMCore/Function.cpp lib/VMCore/Instructions.cpp test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll

Duncan Sands baldrick at free.fr
Wed Dec 19 13:13:42 PST 2007


Author: baldrick
Date: Wed Dec 19 15:13:37 2007
New Revision: 45218

URL: http://llvm.org/viewvc/llvm-project?rev=45218&view=rev
Log:
When inlining through an 'nounwind' call, mark inlined
calls 'nounwind'.  It is important for correct C++
exception handling that nounwind markings do not get
lost, so this transformation is actually needed for
correctness.

Added:
    llvm/trunk/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll
Modified:
    llvm/trunk/include/llvm/Instructions.h
    llvm/trunk/include/llvm/ParameterAttributes.h
    llvm/trunk/include/llvm/Support/CallSite.h
    llvm/trunk/lib/Transforms/IPO/PruneEH.cpp
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
    llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
    llvm/trunk/lib/VMCore/Function.cpp
    llvm/trunk/lib/VMCore/Instructions.cpp

Modified: llvm/trunk/include/llvm/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instructions.h?rev=45218&r1=45217&r2=45218&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Instructions.h (original)
+++ llvm/trunk/include/llvm/Instructions.h Wed Dec 19 15:13:37 2007
@@ -948,6 +948,7 @@
   bool doesNotThrow() const {
     return paramHasAttr(0, ParamAttr::NoUnwind);
   }
+  void setDoesNotThrow(bool doesNotThrow = true);
 
   /// @brief Determine if the call returns a structure.
   bool isStructReturn() const {
@@ -1752,6 +1753,7 @@
   bool doesNotThrow() const {
     return paramHasAttr(0, ParamAttr::NoUnwind);
   }
+  void setDoesNotThrow(bool doesNotThrow = true);
 
   /// @brief Determine if the call returns a structure.
   bool isStructReturn() const {

Modified: llvm/trunk/include/llvm/ParameterAttributes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ParameterAttributes.h?rev=45218&r1=45217&r2=45218&view=diff

==============================================================================
--- llvm/trunk/include/llvm/ParameterAttributes.h (original)
+++ llvm/trunk/include/llvm/ParameterAttributes.h Wed Dec 19 15:13:37 2007
@@ -149,6 +149,14 @@
     static const ParamAttrsList *getModified(const ParamAttrsList *PAL,
                                              const ParamAttrsVector &modVec);
 
+    /// @brief Add the specified attributes to those in PAL at index idx.
+    static const ParamAttrsList *includeAttrs(const ParamAttrsList *PAL,
+                                              uint16_t idx, uint16_t attrs);
+
+    /// @brief Remove the specified attributes from those in PAL at index idx.
+    static const ParamAttrsList *excludeAttrs(const ParamAttrsList *PAL,
+                                              uint16_t idx, uint16_t attrs);
+
     /// Returns whether each of the specified lists of attributes can be safely
     /// replaced with the other in a function or a function call.
     /// @brief Whether one attribute list can safely replace the other.

Modified: llvm/trunk/include/llvm/Support/CallSite.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CallSite.h?rev=45218&r1=45217&r2=45218&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Support/CallSite.h (original)
+++ llvm/trunk/include/llvm/Support/CallSite.h Wed Dec 19 15:13:37 2007
@@ -75,6 +75,7 @@
 
   /// @brief Determine if the call cannot unwind.
   bool doesNotThrow() const;
+  void setDoesNotThrow(bool doesNotThrow = true);
 
   /// getType - Return the type of the instruction that generated this call site
   ///

Modified: llvm/trunk/lib/Transforms/IPO/PruneEH.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PruneEH.cpp?rev=45218&r1=45217&r2=45218&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/IPO/PruneEH.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/PruneEH.cpp Wed Dec 19 15:13:37 2007
@@ -122,17 +122,15 @@
   // If the SCC doesn't unwind or doesn't throw, note this fact.
   if (!SCCMightUnwind || !SCCMightReturn)
     for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
-      const ParamAttrsList *PAL = SCC[i]->getFunction()->getParamAttrs();
-      uint16_t RAttributes = PAL ? PAL->getParamAttrs(0) : 0;
+      uint16_t NewAttributes = ParamAttr::None;
 
       if (!SCCMightUnwind)
-        RAttributes |= ParamAttr::NoUnwind;
+        NewAttributes |= ParamAttr::NoUnwind;
       if (!SCCMightReturn)
-        RAttributes |= ParamAttr::NoReturn;
+        NewAttributes |= ParamAttr::NoReturn;
 
-      ParamAttrsVector modVec;
-      modVec.push_back(ParamAttrsWithIndex::get(0, RAttributes));
-      PAL = ParamAttrsList::getModified(PAL, modVec);
+      const ParamAttrsList *PAL = SCC[i]->getFunction()->getParamAttrs();
+      PAL = ParamAttrsList::includeAttrs(PAL, 0, NewAttributes);
       SCC[i]->getFunction()->setParamAttrs(PAL);
     }
 

Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=45218&r1=45217&r2=45218&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Wed Dec 19 15:13:37 2007
@@ -8026,16 +8026,9 @@
       }
   }
 
-  if (isa<InlineAsm>(Callee) && !CS.paramHasAttr(0, ParamAttr::NoUnwind)) {
+  if (isa<InlineAsm>(Callee) && !CS.doesNotThrow()) {
     // Inline asm calls cannot throw - mark them 'nounwind'.
-    const ParamAttrsList *PAL = CS.getParamAttrs();
-    uint16_t RAttributes = PAL ? PAL->getParamAttrs(0) : 0;
-    RAttributes |= ParamAttr::NoUnwind;
-
-    ParamAttrsVector modVec;
-    modVec.push_back(ParamAttrsWithIndex::get(0, RAttributes));
-    PAL = ParamAttrsList::getModified(PAL, modVec);
-    CS.setParamAttrs(PAL);
+    CS.setDoesNotThrow();
     Changed = true;
   }
 

Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=45218&r1=45217&r2=45218&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Wed Dec 19 15:13:37 2007
@@ -194,6 +194,10 @@
   bool MustClearTailCallFlags =
     isa<CallInst>(TheCall) && !cast<CallInst>(TheCall)->isTailCall();
 
+  // If the call to the callee cannot throw, set the 'nounwind' flag on any
+  // calls that we inline.
+  bool MarkNoUnwind = CS.doesNotThrow();
+
   BasicBlock *OrigBB = TheCall->getParent();
   Function *Caller = OrigBB->getParent();
 
@@ -207,7 +211,7 @@
   std::vector<ReturnInst*> Returns;
   ClonedCodeInfo InlinedFunctionInfo;
   Function::iterator FirstNewBlock;
-  
+
   { // Scope to destroy ValueMap after cloning.
     DenseMap<const Value*, Value*> ValueMap;
 
@@ -323,15 +327,33 @@
 
   // If we are inlining tail call instruction through a call site that isn't 
   // marked 'tail', we must remove the tail marker for any calls in the inlined
-  // code.
-  if (MustClearTailCallFlags && InlinedFunctionInfo.ContainsCalls) {
+  // code.  Also, calls inlined through a 'nounwind' call site should be marked
+  // 'nounwind'.
+  if (InlinedFunctionInfo.ContainsCalls &&
+      (MustClearTailCallFlags || MarkNoUnwind)) {
     for (Function::iterator BB = FirstNewBlock, E = Caller->end();
          BB != E; ++BB)
       for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
-        if (CallInst *CI = dyn_cast<CallInst>(I))
-          CI->setTailCall(false);
+        if (CallInst *CI = dyn_cast<CallInst>(I)) {
+          if (MustClearTailCallFlags)
+            CI->setTailCall(false);
+          if (MarkNoUnwind)
+            CI->setDoesNotThrow();
+        }
   }
 
+  // If we are inlining through a 'nounwind' call site then any inlined 'unwind'
+  // instructions are unreachable.
+  if (InlinedFunctionInfo.ContainsUnwinds && MarkNoUnwind)
+    for (Function::iterator BB = FirstNewBlock, E = Caller->end();
+         BB != E; ++BB) {
+      TerminatorInst *Term = BB->getTerminator();
+      if (isa<UnwindInst>(Term)) {
+        new UnreachableInst(Term);
+        BB->getInstList().erase(Term);
+      }
+    }
+
   // If we are inlining for an invoke instruction, we must make sure to rewrite
   // any inlined 'unwind' instructions into branches to the invoke exception
   // destination, and call instructions into invoke instructions.

Modified: llvm/trunk/lib/VMCore/Function.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Function.cpp?rev=45218&r1=45217&r2=45218&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Function.cpp (original)
+++ llvm/trunk/lib/VMCore/Function.cpp Wed Dec 19 15:13:37 2007
@@ -261,6 +261,32 @@
   return get(newVec);
 }
 
+const ParamAttrsList *
+ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
+                             uint16_t idx, uint16_t attrs) {
+  uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
+  uint16_t NewAttrs = OldAttrs | attrs;
+  if (NewAttrs == OldAttrs)
+    return PAL;
+
+  ParamAttrsVector modVec;
+  modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
+  return getModified(PAL, modVec);
+}
+
+const ParamAttrsList *
+ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
+                             uint16_t idx, uint16_t attrs) {
+  uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
+  uint16_t NewAttrs = OldAttrs & ~attrs;
+  if (NewAttrs == OldAttrs)
+    return PAL;
+
+  ParamAttrsVector modVec;
+  modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
+  return getModified(PAL, modVec);
+}
+
 ParamAttrsList::~ParamAttrsList() {
   ParamAttrsLists->RemoveNode(this);
 }

Modified: llvm/trunk/lib/VMCore/Instructions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=45218&r1=45217&r2=45218&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Instructions.cpp (original)
+++ llvm/trunk/lib/VMCore/Instructions.cpp Wed Dec 19 15:13:37 2007
@@ -71,6 +71,12 @@
   else
     return cast<InvokeInst>(I)->doesNotThrow();
 }
+void CallSite::setDoesNotThrow(bool doesNotThrow) {
+  if (CallInst *CI = dyn_cast<CallInst>(I))
+    CI->setDoesNotThrow(doesNotThrow);
+  else
+    cast<InvokeInst>(I)->setDoesNotThrow(doesNotThrow);
+}
 
 //===----------------------------------------------------------------------===//
 //                            TerminatorInst Class
@@ -405,6 +411,15 @@
   return false;
 }
 
+void CallInst::setDoesNotThrow(bool doesNotThrow) {
+  const ParamAttrsList *PAL = getParamAttrs();
+  if (doesNotThrow)
+    PAL = ParamAttrsList::includeAttrs(PAL, 0, ParamAttr::NoUnwind);
+  else
+    PAL = ParamAttrsList::excludeAttrs(PAL, 0, ParamAttr::NoUnwind);
+  setParamAttrs(PAL);
+}
+
 
 //===----------------------------------------------------------------------===//
 //                        InvokeInst Implementation
@@ -483,6 +498,15 @@
   return false;
 }
 
+void InvokeInst::setDoesNotThrow(bool doesNotThrow) {
+  const ParamAttrsList *PAL = getParamAttrs();
+  if (doesNotThrow)
+    PAL = ParamAttrsList::includeAttrs(PAL, 0, ParamAttr::NoUnwind);
+  else
+    PAL = ParamAttrsList::excludeAttrs(PAL, 0, ParamAttr::NoUnwind);
+  setParamAttrs(PAL);
+}
+
 
 //===----------------------------------------------------------------------===//
 //                        ReturnInst Implementation

Added: llvm/trunk/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll?rev=45218&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll Wed Dec 19 15:13:37 2007
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s -o - | opt -inline | llvm-dis | grep nounwind
+; RUN: llvm-as < %s -o - | opt -inline | llvm-dis | grep unreachable
+
+declare i1 @extern()
+
+define internal i32 @test() {
+entry:
+	%n = call i1 @extern( )
+	br i1 %n, label %r, label %u
+r:
+	ret i32 0;
+u:
+	unwind
+}
+
+define i32 @caller() {
+	%X = call i32 @test( ) nounwind
+	ret i32 %X
+}





More information about the llvm-commits mailing list