diff --git a/lib/Transforms/ExprTypeConvert.cpp b/lib/Transforms/ExprTypeConvert.cpp index d7caa2e86a9..2277676416d 100644 --- a/lib/Transforms/ExprTypeConvert.cpp +++ b/lib/Transforms/ExprTypeConvert.cpp @@ -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((Value*)*UI) &&"Uses of Instruction remain!!!"); - } + for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) + assert(isa((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; diff --git a/lib/Transforms/LevelRaise.cpp b/lib/Transforms/LevelRaise.cpp index 94aebcbc658..7e27c5f7f0b 100644 --- a/lib/Transforms/LevelRaise.cpp +++ b/lib/Transforms/LevelRaise.cpp @@ -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(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(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; } diff --git a/lib/Transforms/TransformInternals.h b/lib/Transforms/TransformInternals.h index 6680d02b865..7a2dbf1b69c 100644 --- a/lib/Transforms/TransformInternals.h +++ b/lib/Transforms/TransformInternals.h @@ -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,9 +52,43 @@ const Type *ConvertableToGEP(const Type *Ty, Value *V, BasicBlock::iterator *BI = 0); +//===----------------------------------------------------------------------===// +// 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 { + ValueMapCache &Cache; +public: + ValueHandle(ValueMapCache &VMC, Value *V); + ValueHandle(const ValueHandle &); + ~ValueHandle(); + + virtual Instruction *clone() const { abort(); return 0; } + + virtual const char *getOpcodeName() const { + 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) { + return (I->getOpcode() == Instruction::UserOp1); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + + // ------------- Expression Conversion --------------------- -typedef std::map ValueTypeCache; +typedef std::map ValueTypeCache; struct ValueMapCache { // Operands mapped - Contains an entry if the first value (the user) has had @@ -68,6 +101,14 @@ struct ValueMapCache { // std::map ExprMap; typedef std::map 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 NewCasts; }; @@ -81,34 +122,6 @@ bool ValueConvertableToType(Value *V, const Type *Ty, 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 ValueHandle : public Instruction { - ValueHandle(const ValueHandle &); // DO NOT IMPLEMENT - ValueMapCache &Cache; -public: - ValueHandle(ValueMapCache &VMC, Value *V); - ~ValueHandle(); - - virtual Instruction *clone() const { abort(); return 0; } - - virtual const char *getOpcodeName() const { - return "ValueHandle"; - } - - // 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) { - return (I->getOpcode() == Instruction::UserOp1); - } - static inline bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } -}; - // 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