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:
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;
}
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;
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:
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!!!");
}
}
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;
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;
}
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;
}
#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"
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; }
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) {
}
};
+
+// ------------- 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