From b1b4262387b0060af9c01297d146bb17ed361a84 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 17 Jul 2002 17:11:33 +0000 Subject: [PATCH] * Remove dead code from ExprTypeConvert.cpp - 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 | 51 ++++++++++---------- lib/Transforms/LevelRaise.cpp | 25 ++++++---- lib/Transforms/TransformInternals.h | 73 +++++++++++++++++------------ 3 files changed, 83 insertions(+), 66 deletions(-) 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,44 +52,17 @@ const Type *ConvertableToGEP(const Type *Ty, Value *V, BasicBlock::iterator *BI = 0); -// ------------- Expression Conversion --------------------- - -typedef std::map 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 OperandsMapped; - - // Expression Map - Contains an entry from the old value to the new value of - // an expression that has been converted over. - // - std::map ExprMap; - typedef std::map 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 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 OperandsMapped; + + // Expression Map - Contains an entry from the old value to the new value of + // an expression that has been converted over. + // + 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; +}; + + +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 -- 2.34.1