* Remove dead code from ExprTypeConvert.cpp
authorChris Lattner <sabre@nondot.org>
Wed, 17 Jul 2002 17:11:33 +0000 (17:11 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 17 Jul 2002 17:11:33 +0000 (17:11 +0000)
   - I->use_empty() can never be true because of the IHolder's
* Fix bug: test/Regression/Transforms/LevelRaise/2002-07-16-SourceAndDestCrash.ll
   - Add a new NewCasts member to VMC to keep track of casts that have been
     created and to ensure there is always a reference to the cast.
   - Extend ValueHandle a bit so it can be used in an STL container
   - Make sure we destroy the ValueMapCache before verifying the function
     in LevelRaise.cpp

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

lib/Transforms/ExprTypeConvert.cpp
lib/Transforms/LevelRaise.cpp
lib/Transforms/TransformInternals.h

index d7caa2e86a96813de9996cbd93bacc138d6a04c1..2277676416d518d9fec34744f5b2c4548640f2c4 100644 (file)
@@ -377,7 +377,9 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
 
   switch (I->getOpcode()) {
   case Instruction::Cast:
+    assert(VMC.NewCasts.count(ValueHandle(VMC, I)) == 0);
     Res = new CastInst(I->getOperand(0), Ty, Name);
+    VMC.NewCasts.insert(ValueHandle(VMC, Res));
     break;
     
   case Instruction::Add:
@@ -540,14 +542,6 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
   DEBUG(cerr << "ExpIn: " << (void*)I << " " << I
              << "ExpOut: " << (void*)Res << " " << Res);
 
-  if (I->use_empty()) {
-    DEBUG(cerr << "EXPR DELETING: " << (void*)I << " " << I);
-    BIL.remove(I);
-    VMC.OperandsMapped.erase(I);
-    VMC.ExprMap.erase(I);
-    delete I;
-  }
-
   return Res;
 }
 
@@ -906,7 +900,8 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
   BasicBlock *BB = I->getParent();
   assert(BB != 0 && "Instruction not embedded in basic block!");
   BasicBlock::InstListType &BIL = BB->getInstList();
-  std::string Name = I->getName();  if (!Name.empty()) I->setName("");
+  std::string Name = I->getName();
+  I->setName("");
   Instruction *Res;     // Result of conversion
 
   //cerr << endl << endl << "Type:\t" << Ty << "\nInst: " << I << "BB Before: " << BB << endl;
@@ -920,8 +915,18 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
 
   switch (I->getOpcode()) {
   case Instruction::Cast:
-    assert(I->getOperand(0) == OldVal);
-    Res = new CastInst(NewVal, I->getType(), Name);
+    if (VMC.NewCasts.count(ValueHandle(VMC, I))) {
+      // This cast has already had it's value converted, causing a new cast to
+      // be created.  We don't want to create YET ANOTHER cast instruction
+      // representing the original one, so just modify the operand of this cast
+      // instruction, which we know is newly created.
+      I->setOperand(0, NewVal);
+      I->setName(Name);  // give I its name back
+      return;
+
+    } else {
+      Res = new CastInst(NewVal, I->getType(), Name);
+    }
     break;
 
   case Instruction::Add:
@@ -1154,21 +1159,9 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
         Use->replaceUsesOfWith(I, Res);
     }
 
-    if (I->use_empty()) {
-      // Now we just need to remove the old instruction so we don't get infinite
-      // loops.  Note that we cannot use DCE because DCE won't remove a store
-      // instruction, for example.
-      //
-      DEBUG(cerr << "DELETING: " << (void*)I << " " << I);
-      BIL.remove(I);
-      VMC.OperandsMapped.erase(I);
-      VMC.ExprMap.erase(I);
-      delete I;
-    } else {
-      for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
-           UI != UE; ++UI)
-        assert(isa<ValueHandle>((Value*)*UI) &&"Uses of Instruction remain!!!");
-    }
+    for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
+         UI != UE; ++UI)
+      assert(isa<ValueHandle>((Value*)*UI) &&"Uses of Instruction remain!!!");
   }
 }
 
@@ -1179,6 +1172,12 @@ ValueHandle::ValueHandle(ValueMapCache &VMC, Value *V)
   Operands.push_back(Use(V, this));
 }
 
+ValueHandle::ValueHandle(const ValueHandle &VH)
+  : Instruction(Type::VoidTy, UserOp1, ""), Cache(VH.Cache) {
+  //DEBUG(cerr << "VH AQUIRING: " << (void*)V << " " << V);
+  Operands.push_back(Use((Value*)VH.getOperand(0), this));
+}
+
 static void RecursiveDelete(ValueMapCache &Cache, Instruction *I) {
   if (!I || !I->use_empty()) return;
 
index 94aebcbc658cf2e1fc95b00b24df7f82ec1bf9fa..7e27c5f7f0b9b44fbd4f6744407003d0d45d1ea1 100644 (file)
@@ -225,17 +225,20 @@ static bool PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
         PRINT_PEEPHOLE3("CAST-SRC-EXPR-CONV:in ", Src, CI, BB->getParent());
           
         DEBUG(cerr << "\nCONVERTING SRC EXPR TYPE:\n");
-        ValueMapCache ValueMap;
-        Value *E = ConvertExpressionToType(Src, DestTy, ValueMap);
-        if (Constant *CPV = dyn_cast<Constant>(E))
-          CI->replaceAllUsesWith(CPV);
+        { // ValueMap must be destroyed before function verified!
+          ValueMapCache ValueMap;
+          Value *E = ConvertExpressionToType(Src, DestTy, ValueMap);
 
-        BI = BB->begin();  // Rescan basic block.  BI might be invalidated.
-        PRINT_PEEPHOLE1("CAST-SRC-EXPR-CONV:out", E);
-        DEBUG(cerr << "DONE CONVERTING SRC EXPR TYPE: \n" << BB->getParent());
+          if (Constant *CPV = dyn_cast<Constant>(E))
+            CI->replaceAllUsesWith(CPV);
+          
+          PRINT_PEEPHOLE1("CAST-SRC-EXPR-CONV:out", E);
+          DEBUG(cerr << "DONE CONVERTING SRC EXPR TYPE: \n" << BB->getParent());
+        }
 
         DEBUG(assert(verifyFunction(*BB->getParent()) == false &&
                      "Function broken!"));
+        BI = BB->begin();  // Rescan basic block.  BI might be invalidated.
         ++NumExprTreesConv;
         return true;
       }
@@ -249,15 +252,17 @@ static bool PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
         PRINT_PEEPHOLE3("CAST-DEST-EXPR-CONV:in ", Src, CI, BB->getParent());
 
         DEBUG(cerr << "\nCONVERTING EXPR TYPE:\n");
-        ValueMapCache ValueMap;
-        ConvertValueToNewType(CI, Src, ValueMap);  // This will delete CI!
+        { // ValueMap must be destroyed before function verified!
+          ValueMapCache ValueMap;
+          ConvertValueToNewType(CI, Src, ValueMap);  // This will delete CI!
+        }
 
-        BI = BB->begin();  // Rescan basic block.  BI might be invalidated.
         PRINT_PEEPHOLE1("CAST-DEST-EXPR-CONV:out", Src);
         DEBUG(cerr << "DONE CONVERTING EXPR TYPE: \n\n" << BB->getParent());
 
         DEBUG(assert(verifyFunction(*BB->getParent()) == false &&
                      "Function broken!"));
+        BI = BB->begin();  // Rescan basic block.  BI might be invalidated.
         ++NumExprTreesConv;
         return true;
       }
index 6680d02b86551e9013a4ab47d0e7502132cd8b9d..7a2dbf1b69cf3c7e635134d52f81f71acf260c81 100644 (file)
@@ -9,7 +9,6 @@
 #define TRANSFORM_INTERNALS_H
 
 #include "llvm/BasicBlock.h"
-#include "llvm/Instruction.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Constants.h"
@@ -53,44 +52,17 @@ const Type *ConvertableToGEP(const Type *Ty, Value *V,
                              BasicBlock::iterator *BI = 0);
 
 
-// ------------- Expression Conversion ---------------------
-
-typedef std::map<const Value*, const Type*>         ValueTypeCache;
-
-struct ValueMapCache {
-  // Operands mapped - Contains an entry if the first value (the user) has had
-  // the second value (the operand) mapped already.
-  //
-  std::set<const User*> OperandsMapped;
-
-  // Expression Map - Contains an entry from the old value to the new value of
-  // an expression that has been converted over.
-  //
-  std::map<const Value *, Value *> ExprMap;
-  typedef std::map<const Value *, Value *> ExprMapTy;
-};
-
-
-bool ExpressionConvertableToType(Value *V, const Type *Ty, ValueTypeCache &Map);
-Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC);
-
-// ValueConvertableToType - Return true if it is possible
-bool ValueConvertableToType(Value *V, const Type *Ty,
-                            ValueTypeCache &ConvertedTypes);
-
-void ConvertValueToNewType(Value *V, Value *NewVal, ValueMapCache &VMC);
-
-
 //===----------------------------------------------------------------------===//
 //  ValueHandle Class - Smart pointer that occupies a slot on the users USE list
 //  that prevents it from being destroyed.  This "looks" like an Instruction
 //  with Opcode UserOp1.
 // 
+class ValueMapCache;
 class ValueHandle : public Instruction {
-  ValueHandle(const ValueHandle &); // DO NOT IMPLEMENT
   ValueMapCache &Cache;
 public:
   ValueHandle(ValueMapCache &VMC, Value *V);
+  ValueHandle(const ValueHandle &);
   ~ValueHandle();
 
   virtual Instruction *clone() const { abort(); return 0; }
@@ -99,6 +71,10 @@ public:
     return "ValueHandle";
   }
 
+  inline bool operator<(const ValueHandle &VH) const {
+    return getOperand(0) < VH.getOperand(0);
+  }
+
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const ValueHandle *) { return true; }
   static inline bool classof(const Instruction *I) {
@@ -109,6 +85,43 @@ public:
   }
 };
 
+
+// ------------- Expression Conversion ---------------------
+
+typedef std::map<const Value*, const Type*> ValueTypeCache;
+
+struct ValueMapCache {
+  // Operands mapped - Contains an entry if the first value (the user) has had
+  // the second value (the operand) mapped already.
+  //
+  std::set<const User*> OperandsMapped;
+
+  // Expression Map - Contains an entry from the old value to the new value of
+  // an expression that has been converted over.
+  //
+  std::map<const Value *, Value *> ExprMap;
+  typedef std::map<const Value *, Value *> ExprMapTy;
+
+  // Cast Map - Cast instructions can have their source and destination values
+  // changed independantly for each part.  Because of this, our old naive
+  // implementation would create a TWO new cast instructions, which would cause
+  // all kinds of problems.  Here we keep track of the newly allocated casts, so
+  // that we only create one for a particular instruction.
+  //
+  std::set<ValueHandle> NewCasts;
+};
+
+
+bool ExpressionConvertableToType(Value *V, const Type *Ty, ValueTypeCache &Map);
+Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC);
+
+// ValueConvertableToType - Return true if it is possible
+bool ValueConvertableToType(Value *V, const Type *Ty,
+                            ValueTypeCache &ConvertedTypes);
+
+void ConvertValueToNewType(Value *V, Value *NewVal, ValueMapCache &VMC);
+
+
 // getStructOffsetType - Return a vector of offsets that are to be used to index
 // into the specified struct type to get as close as possible to index as we
 // can.  Note that it is possible that we cannot get exactly to Offset, in which