[llvm-commits] [llvm-gcc-4.2] r51640 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h tree-inline.c

Duncan Sands baldrick at free.fr
Wed May 28 06:11:32 PDT 2008


Author: baldrick
Date: Wed May 28 08:11:30 2008
New Revision: 51640

URL: http://llvm.org/viewvc/llvm-project?rev=51640&view=rev
Log:
Fix the handling of multiply defined gimple
temporaries.  The current code assumes that
if a temporary has a second definition then
that definition will be seen before any uses
of it.  But since we don't output basic blocks
in any particular order there is no reason
why this should be true.  The obvious solution
is to not special case gimple temporaries, but
this results in a 30% increase in the bitcode
size at -O0.  Instead, uniquify the value used
as the first definition of a gimple temp, and
fix up its uses if a second definition is seen.
Since this still gives a 4% increase in the size
of the bitcode at -O0, I've added some logic to
un-uniquify values once the function is emitted.
With this change both bitcode size at -O0 and
compile time at -O1 do not increase significantly. 

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
    llvm-gcc-4.2/trunk/gcc/llvm-internal.h
    llvm-gcc-4.2/trunk/gcc/tree-inline.c

Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=51640&r1=51639&r2=51640&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Wed May 28 08:11:30 2008
@@ -843,6 +843,17 @@
   // may be deleted when the optimizers run, so would be dangerous to keep.
   eraseLocalLLVMValues();
 
+  // Simplify any values that were uniqued using a no-op bitcast.
+  for (std::vector<BitCastInst *>::iterator I = UniquedValues.begin(),
+       E = UniquedValues.end(); I != E; ++I) {
+    BitCastInst *BI = *I;
+    assert(BI->getSrcTy() == BI->getDestTy() && "Not a no-op bitcast!");
+    BI->replaceAllUsesWith(BI->getOperand(0));
+    // Safe to erase because after the call to eraseLocalLLVMValues.
+    BI->eraseFromParent();
+  }
+  UniquedValues.clear();
+
   return Fn;
 }
 
@@ -2734,19 +2745,18 @@
   return 0;
 }
 
-/// HandleMultiplyDefinedGCCTemp - GCC temporaries are *mostly* single
-/// definition, and always have all uses dominated by the definition.  In cases
-/// where the temporary has multiple uses, we will first see the initial 
-/// definition, some uses of that definition, then subsequently see another
-/// definition with uses of this second definition.
+/// HandleMultiplyDefinedGimpleTemporary - Gimple temporaries *mostly* have a
+/// single definition, in which case all uses are dominated by the definition.
+/// This routine exists to handle the rare case of a gimple temporary with
+/// multiple definitions.  It turns the temporary into an ordinary automatic
+/// variable by creating an alloca for it, initializing the alloca with the
+/// first definition that was seen, and fixing up any existing uses to load
+/// the alloca instead.
 ///
-/// Because LLVM temporaries *must* be single definition, when we see the second
-/// definition, we actually change the temporary to mark it as not being a GCC
-/// temporary anymore.  We then create an alloca for it, initialize it with the
-/// first value seen, then treat it as a normal variable definition.
-///
-void TreeToLLVM::HandleMultiplyDefinedGCCTemp(tree Var) {
-  Value *FirstVal = DECL_LLVM(Var);
+void TreeToLLVM::HandleMultiplyDefinedGimpleTemporary(tree Var) {
+  Value *UniqVal = DECL_LLVM(Var);
+  assert(isa<CastInst>(UniqVal) && "Invalid value for gimple temporary!");
+  Value *FirstVal = cast<CastInst>(UniqVal)->getOperand(0);
 
   // Create a new temporary and set the VAR_DECL to use it as the llvm location.
   Value *NewTmp = CreateTemporary(FirstVal->getType());
@@ -2756,11 +2766,11 @@
   // being stored is an instruction, emit the store right after the instruction,
   // otherwise, emit it into the entry block.
   StoreInst *SI = new StoreInst(FirstVal, NewTmp);
-  
+
   BasicBlock::iterator InsertPt;
   if (Instruction *I = dyn_cast<Instruction>(FirstVal)) {
     InsertPt = I;                      // Insert after the init instruction.
-    
+
     // If the instruction is an alloca in the entry block, the insert point
     // will be before the alloca.  Advance to the AllocaInsertionPoint if we are
     // before it.
@@ -2774,7 +2784,7 @@
         }
       }
     }
-    
+
     // If the instruction is an invoke, the init is inserted on the normal edge.
     if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
       InsertPt = II->getNormalDest()->begin();
@@ -2788,7 +2798,12 @@
   }
   BasicBlock *BB = InsertPt->getParent();
   BB->getInstList().insert(InsertPt, SI);
-  
+
+  // Replace any uses of the original value with a load of the alloca.
+  for (Value::use_iterator U = UniqVal->use_begin(), E = UniqVal->use_end();
+       U != E; ++U)
+    U.getUse().set(new LoadInst(NewTmp, "mtmp", cast<Instruction>(*U)));
+
   // Finally, This is no longer a GCC temporary.
   DECL_GIMPLE_FORMAL_TEMP_P(Var) = 0;
 }
@@ -2806,13 +2821,22 @@
   if (isGimpleTemporary(lhs)) {
     // If DECL_LLVM is already set, this is a multiply defined gimple temporary.
     if (DECL_LLVM_SET_P(lhs)) {
-      HandleMultiplyDefinedGCCTemp(lhs);
+      HandleMultiplyDefinedGimpleTemporary(lhs);
       return EmitMODIFY_EXPR(exp, DestLoc);
     }
     Value *RHS = Emit(rhs, 0);
-    RHS = CastToAnyType(RHS, RHSSigned, ConvertType(TREE_TYPE(lhs)), LHSSigned);
-    SET_DECL_LLVM(lhs, RHS);
-    return RHS;
+    const Type *LHSTy = ConvertType(TREE_TYPE(lhs));
+    // The value may need to be replaced later if this temporary is multiply
+    // defined - ensure it can be uniquely identified by not folding the cast.
+    Instruction::CastOps opc = CastInst::getCastOpcode(RHS, RHSSigned,
+                                                       LHSTy, LHSSigned);
+    CastInst *Cast = CastInst::Create(opc, RHS, LHSTy, RHS->getNameStart());
+    if (opc == Instruction::BitCast && RHS->getType() == LHSTy)
+      // Simplify this no-op bitcast once the function is emitted.
+      UniquedValues.push_back(cast<BitCastInst>(Cast));
+    Builder.Insert(Cast);
+    SET_DECL_LLVM(lhs, Cast);
+    return Cast;
   } else if (TREE_CODE(lhs) == VAR_DECL && DECL_REGISTER(lhs) &&
              TREE_STATIC(lhs)) {
     // If this is a store to a register variable, EmitLV can't handle the dest

Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=51640&r1=51639&r2=51640&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Wed May 28 08:11:30 2008
@@ -285,6 +285,10 @@
   // and managed by CreateTemporary.
   Instruction *AllocaInsertionPoint;
   
+  /// UniquedValues - Values defined using a no-op bitcast in order to make them
+  /// unique.  These can be simplified once the function has been emitted.
+  std::vector<BitCastInst *> UniquedValues;
+
   //===---------------------- Exception Handling --------------------------===//
 
   /// LandingPads - The landing pad for a given EH region.
@@ -448,7 +452,7 @@
   ///
   static bool isNoopCast(Value *V, const Type *Ty);
 
-  void HandleMultiplyDefinedGCCTemp(tree_node *var);
+  void HandleMultiplyDefinedGimpleTemporary(tree_node *var);
   
   /// EmitAnnotateIntrinsic - Emits call to annotate attr intrinsic
   void EmitAnnotateIntrinsic(Value *V, tree_node *decl);

Modified: llvm-gcc-4.2/trunk/gcc/tree-inline.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/tree-inline.c?rev=51640&r1=51639&r2=51640&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/tree-inline.c (original)
+++ llvm-gcc-4.2/trunk/gcc/tree-inline.c Wed May 28 08:11:30 2008
@@ -1261,16 +1261,6 @@
 	{
 	  var = modify_dest;
 	  use = NULL;
-    
-    /* LLVM LOCAL begin */
-#ifdef ENABLE_LLVM
-    /* The return node can suddenly become multiple assignment.  Because of this
-     * conservatively don't consider this thing for SSA form anymore.
-    */
-    if (TREE_CODE (var) == VAR_DECL)
-      DECL_GIMPLE_FORMAL_TEMP_P (var) = 0;
-#endif
-    /* LLVM LOCAL end */
 	  goto done;
 	}
     }





More information about the llvm-commits mailing list