[llvm-commits] [llvm] r71071 - in /llvm/trunk: docs/LangRef.html include/llvm/Instruction.h lib/Transforms/Scalar/ADCE.cpp lib/Transforms/Scalar/GVN.cpp lib/Transforms/Scalar/InstructionCombining.cpp lib/Transforms/Scalar/LoopDeletion.cpp lib/Transforms/Scalar/LoopIndexSplit.cpp lib/Transforms/Scalar/LoopUnswitch.cpp lib/Transforms/Scalar/TailDuplication.cpp lib/Transforms/Scalar/TailRecursionElimination.cpp lib/Transforms/Utils/Local.cpp lib/VMCore/Instruction.cpp test/Transforms/ADCE/dce_pure_call.ll

Duncan Sands baldrick at free.fr
Tue May 5 23:49:54 PDT 2009


Author: baldrick
Date: Wed May  6 01:49:50 2009
New Revision: 71071

URL: http://llvm.org/viewvc/llvm-project?rev=71071&view=rev
Log:
Allow readonly functions to unwind exceptions.  Teach
the optimizers about this.  For example, a readonly
function with no uses cannot be removed unless it is
also marked nounwind.

Modified:
    llvm/trunk/docs/LangRef.html
    llvm/trunk/include/llvm/Instruction.h
    llvm/trunk/lib/Transforms/Scalar/ADCE.cpp
    llvm/trunk/lib/Transforms/Scalar/GVN.cpp
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
    llvm/trunk/lib/Transforms/Scalar/TailDuplication.cpp
    llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
    llvm/trunk/lib/Transforms/Utils/Local.cpp
    llvm/trunk/lib/VMCore/Instruction.cpp
    llvm/trunk/test/Transforms/ADCE/dce_pure_call.ll

Modified: llvm/trunk/docs/LangRef.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=71071&r1=71070&r2=71071&view=diff

==============================================================================
--- llvm/trunk/docs/LangRef.html (original)
+++ llvm/trunk/docs/LangRef.html Wed May  6 01:49:50 2009
@@ -1061,23 +1061,24 @@
 behavior is undefined.</dd>
 
 <dt><tt>readnone</tt></dt>
-<dd>This attribute indicates that the function computes its result (or the
-exception it throws) based strictly on its arguments, without dereferencing any
+<dd>This attribute indicates that the function computes its result (or decides to
+unwind an exception) based strictly on its arguments, without dereferencing any
 pointer arguments or otherwise accessing any mutable state (e.g. memory, control
 registers, etc) visible to caller functions.  It does not write through any
 pointer arguments (including <tt><a href="#byval">byval</a></tt> arguments) and
-never changes any state visible to callers.  readnone functions may not throw
-an exception that escapes into the caller.</dd>
+never changes any state visible to callers.  This means that it cannot unwind
+exceptions by calling the <tt>C++</tt> exception throwing methods, but could
+use the <tt>unwind</tt> instruction.</dd>
 
 <dt><tt><a name="readonly">readonly</a></tt></dt>
 <dd>This attribute indicates that the function does not write through any
 pointer arguments (including <tt><a href="#byval">byval</a></tt> arguments)
 or otherwise modify any state (e.g. memory, control registers, etc) visible to
 caller functions.  It may dereference pointer arguments and read state that may
-be set in the caller.  A readonly function always returns the same value when
-called with the same set of arguments and global
-state.  readonly functions may not throw an exception that escapes into the
-caller.</dd>
+be set in the caller.  A readonly function always returns the same value (or
+unwinds an exception identically) when called with the same set of arguments
+and global state.  It cannot unwind an exception by calling the <tt>C++</tt>
+exception throwing methods, but may use the <tt>unwind</tt> instruction.</dd>
 
 <dt><tt><a name="ssp">ssp</a></tt></dt>
 <dd>This attribute indicates that the function should emit a stack smashing

Modified: llvm/trunk/include/llvm/Instruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instruction.h?rev=71071&r1=71070&r2=71071&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Instruction.h (original)
+++ llvm/trunk/include/llvm/Instruction.h Wed May  6 01:49:50 2009
@@ -40,14 +40,6 @@
   // Out of line virtual method, so the vtable, etc has a home.
   ~Instruction();
   
-  /// mayWriteToMemory - Return true if this instruction may modify memory.
-  ///
-  bool mayWriteToMemory() const;
-
-  /// mayReadFromMemory - Return true if this instruction may read memory.
-  ///
-  bool mayReadFromMemory() const;
-  
   /// clone() - Create a copy of 'this' instruction that is identical in all
   /// ways except the following:
   ///   * The instruction has no parent
@@ -181,6 +173,24 @@
   }
   static bool isTrapping(unsigned op);
 
+  /// mayWriteToMemory - Return true if this instruction may modify memory.
+  ///
+  bool mayWriteToMemory() const;
+
+  /// mayReadFromMemory - Return true if this instruction may read memory.
+  ///
+  bool mayReadFromMemory() const;
+
+  /// mayThrow - Return true if this instruction may throw an exception.
+  ///
+  bool mayThrow() const;
+
+  /// mayHaveSideEffects - Return true if the instruction may have side effects.
+  ///
+  bool mayHaveSideEffects() const {
+    return mayWriteToMemory() || mayThrow();
+  }
+
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const Instruction *) { return true; }
   static inline bool classof(const Value *V) {

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/ADCE.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/ADCE.cpp Wed May  6 01:49:50 2009
@@ -57,7 +57,7 @@
   for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
     if (isa<TerminatorInst>(I.getInstructionIterator()) ||
         isa<DbgInfoIntrinsic>(I.getInstructionIterator()) ||
-        I->mayWriteToMemory()) {
+        I->mayHaveSideEffects()) {
       alive.insert(I.getInstructionIterator());
       worklist.push_back(I.getInstructionIterator());
     }

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Wed May  6 01:49:50 2009
@@ -1479,13 +1479,13 @@
     for (BasicBlock::iterator BI = CurrentBlock->begin(),
          BE = CurrentBlock->end(); BI != BE; ) {
       Instruction *CurInst = BI++;
-      
+
       if (isa<AllocationInst>(CurInst) || isa<TerminatorInst>(CurInst) ||
           isa<PHINode>(CurInst) || (CurInst->getType() == Type::VoidTy) ||
-          CurInst->mayReadFromMemory() || CurInst->mayWriteToMemory() ||
+          CurInst->mayReadFromMemory() || CurInst->mayHaveSideEffects() ||
           isa<DbgInfoIntrinsic>(CurInst))
         continue;
-      
+
       uint32_t valno = VN.lookup(CurInst);
       
       // Look for the predecessors for PRE opportunities.  We're

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Wed May  6 01:49:50 2009
@@ -12579,7 +12579,7 @@
   assert(I->hasOneUse() && "Invariants didn't hold!");
 
   // Cannot move control-flow-involving, volatile loads, vaarg, etc.
-  if (isa<PHINode>(I) || I->mayWriteToMemory() || isa<TerminatorInst>(I))
+  if (isa<PHINode>(I) || I->mayHaveSideEffects() || isa<TerminatorInst>(I))
     return false;
 
   // Do not sink alloca instructions out of the entry block.

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp Wed May  6 01:49:50 2009
@@ -136,11 +136,8 @@
        LI != LE; ++LI) {
     for (BasicBlock::iterator BI = (*LI)->begin(), BE = (*LI)->end();
          BI != BE; ++BI) {
-      if (BI->mayWriteToMemory())
+      if (BI->mayHaveSideEffects())
         return false;
-      else if (LoadInst* L = dyn_cast<LoadInst>(BI))
-        if (L->isVolatile())
-          return false;
     }
   }
   

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp Wed May  6 01:49:50 2009
@@ -1148,7 +1148,7 @@
         || isa<DbgInfoIntrinsic>(I))
       continue;
 
-    if (I->mayWriteToMemory())
+    if (I->mayHaveSideEffects())
       return false;
 
     // I is used only inside this block then it is OK.

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Wed May  6 01:49:50 2009
@@ -300,7 +300,7 @@
   // Okay, everything after this looks good, check to make sure that this block
   // doesn't include any side effects.
   for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
-    if (I->mayWriteToMemory())
+    if (I->mayHaveSideEffects())
       return false;
   
   return true;
@@ -383,7 +383,7 @@
   // part of the loop that the code *would* execute.  We already checked the
   // tail, check the header now.
   for (BasicBlock::iterator I = Header->begin(), E = Header->end(); I != E; ++I)
-    if (I->mayWriteToMemory())
+    if (I->mayHaveSideEffects())
       return false;
   return true;
 }

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/TailDuplication.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/TailDuplication.cpp Wed May  6 01:49:50 2009
@@ -258,7 +258,7 @@
     while (!isa<TerminatorInst>(BBI)) {
       Instruction *I = BBI++;
 
-      bool CanHoist = !I->isTrapping() && !I->mayWriteToMemory();
+      bool CanHoist = !I->isTrapping() && !I->mayHaveSideEffects();
       if (CanHoist) {
         for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
           if (Instruction *OpI = dyn_cast<Instruction>(I->getOperand(op)))

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp Wed May  6 01:49:50 2009
@@ -201,7 +201,7 @@
 bool TailCallElim::CanMoveAboveCall(Instruction *I, CallInst *CI) {
   // FIXME: We can move load/store/call/free instructions above the call if the
   // call does not mod/ref the memory location being processed.
-  if (I->mayWriteToMemory() || isa<LoadInst>(I))
+  if (I->mayHaveSideEffects() || isa<LoadInst>(I))
     return false;
 
   // Otherwise, if this is a side-effect free instruction, check to make sure

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

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/Local.cpp Wed May  6 01:49:50 2009
@@ -164,17 +164,15 @@
 
   // We don't want debug info removed by anything this general.
   if (isa<DbgInfoIntrinsic>(I)) return false;
-    
-  if (!I->mayWriteToMemory())
-    return true;
 
-  // Special case intrinsics that "may write to memory" but can be deleted when
-  // dead.
+  if (!I->mayHaveSideEffects()) return true;
+
+  // Special case intrinsics that "may have side effects" but can be deleted
+  // when dead.
   if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
     // Safe to delete llvm.stacksave if dead.
     if (II->getIntrinsicID() == Intrinsic::stacksave)
       return true;
-  
   return false;
 }
 
@@ -230,7 +228,7 @@
   SmallPtrSet<PHINode *, 4> PHIs;
   PHIs.insert(PN);
   for (Instruction *J = cast<Instruction>(*PN->use_begin());
-       J->hasOneUse() && !J->mayWriteToMemory();
+       J->hasOneUse() && !J->mayHaveSideEffects();
        J = cast<Instruction>(*J->use_begin()))
     // If we find a PHI more than once, we're on a cycle that
     // won't prove fruitful.

Modified: llvm/trunk/lib/VMCore/Instruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instruction.cpp?rev=71071&r1=71070&r2=71071&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Instruction.cpp (original)
+++ llvm/trunk/lib/VMCore/Instruction.cpp Wed May  6 01:49:50 2009
@@ -320,6 +320,14 @@
   }
 }
 
+/// mayThrow - Return true if this instruction may throw an exception.
+///
+bool Instruction::mayThrow() const {
+  if (const CallInst *CI = dyn_cast<CallInst>(this))
+    return !CI->doesNotThrow();
+  return false;
+}
+
 /// isAssociative - Return true if the instruction is associative:
 ///
 ///   Associative operators satisfy:  x op (y op z) === (x op y) op z)

Modified: llvm/trunk/test/Transforms/ADCE/dce_pure_call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ADCE/dce_pure_call.ll?rev=71071&r1=71070&r2=71071&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/ADCE/dce_pure_call.ll (original)
+++ llvm/trunk/test/Transforms/ADCE/dce_pure_call.ll Wed May  6 01:49:50 2009
@@ -1,8 +1,8 @@
 ; RUN: llvm-as < %s | opt -adce | llvm-dis | not grep call
 
-declare i32 @strlen(i8*) readonly
+declare i32 @strlen(i8*) readonly nounwind
 
 define void @test() {
-	call i32 @strlen( i8* null ) readonly		; <i32>:1 [#uses=0]
+	call i32 @strlen( i8* null )		; <i32>:1 [#uses=0]
 	ret void
 }





More information about the llvm-commits mailing list