* 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 llvm-svn: 2936
This commit is contained in:
parent
2b3cc2e69c
commit
60ebba51c4
|
@ -377,7 +377,9 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
||||||
|
|
||||||
switch (I->getOpcode()) {
|
switch (I->getOpcode()) {
|
||||||
case Instruction::Cast:
|
case Instruction::Cast:
|
||||||
|
assert(VMC.NewCasts.count(ValueHandle(VMC, I)) == 0);
|
||||||
Res = new CastInst(I->getOperand(0), Ty, Name);
|
Res = new CastInst(I->getOperand(0), Ty, Name);
|
||||||
|
VMC.NewCasts.insert(ValueHandle(VMC, Res));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction::Add:
|
case Instruction::Add:
|
||||||
|
@ -540,14 +542,6 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
||||||
DEBUG(cerr << "ExpIn: " << (void*)I << " " << I
|
DEBUG(cerr << "ExpIn: " << (void*)I << " " << I
|
||||||
<< "ExpOut: " << (void*)Res << " " << Res);
|
<< "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;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,7 +900,8 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
||||||
BasicBlock *BB = I->getParent();
|
BasicBlock *BB = I->getParent();
|
||||||
assert(BB != 0 && "Instruction not embedded in basic block!");
|
assert(BB != 0 && "Instruction not embedded in basic block!");
|
||||||
BasicBlock::InstListType &BIL = BB->getInstList();
|
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
|
Instruction *Res; // Result of conversion
|
||||||
|
|
||||||
//cerr << endl << endl << "Type:\t" << Ty << "\nInst: " << I << "BB Before: " << BB << endl;
|
//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()) {
|
switch (I->getOpcode()) {
|
||||||
case Instruction::Cast:
|
case Instruction::Cast:
|
||||||
assert(I->getOperand(0) == OldVal);
|
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);
|
Res = new CastInst(NewVal, I->getType(), Name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction::Add:
|
case Instruction::Add:
|
||||||
|
@ -1154,22 +1159,10 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
||||||
Use->replaceUsesOfWith(I, Res);
|
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();
|
for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
|
||||||
UI != UE; ++UI)
|
UI != UE; ++UI)
|
||||||
assert(isa<ValueHandle>((Value*)*UI) &&"Uses of Instruction remain!!!");
|
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));
|
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) {
|
static void RecursiveDelete(ValueMapCache &Cache, Instruction *I) {
|
||||||
if (!I || !I->use_empty()) return;
|
if (!I || !I->use_empty()) return;
|
||||||
|
|
||||||
|
|
|
@ -225,17 +225,20 @@ static bool PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
|
||||||
PRINT_PEEPHOLE3("CAST-SRC-EXPR-CONV:in ", Src, CI, BB->getParent());
|
PRINT_PEEPHOLE3("CAST-SRC-EXPR-CONV:in ", Src, CI, BB->getParent());
|
||||||
|
|
||||||
DEBUG(cerr << "\nCONVERTING SRC EXPR TYPE:\n");
|
DEBUG(cerr << "\nCONVERTING SRC EXPR TYPE:\n");
|
||||||
|
{ // ValueMap must be destroyed before function verified!
|
||||||
ValueMapCache ValueMap;
|
ValueMapCache ValueMap;
|
||||||
Value *E = ConvertExpressionToType(Src, DestTy, ValueMap);
|
Value *E = ConvertExpressionToType(Src, DestTy, ValueMap);
|
||||||
|
|
||||||
if (Constant *CPV = dyn_cast<Constant>(E))
|
if (Constant *CPV = dyn_cast<Constant>(E))
|
||||||
CI->replaceAllUsesWith(CPV);
|
CI->replaceAllUsesWith(CPV);
|
||||||
|
|
||||||
BI = BB->begin(); // Rescan basic block. BI might be invalidated.
|
|
||||||
PRINT_PEEPHOLE1("CAST-SRC-EXPR-CONV:out", E);
|
PRINT_PEEPHOLE1("CAST-SRC-EXPR-CONV:out", E);
|
||||||
DEBUG(cerr << "DONE CONVERTING SRC EXPR TYPE: \n" << BB->getParent());
|
DEBUG(cerr << "DONE CONVERTING SRC EXPR TYPE: \n" << BB->getParent());
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG(assert(verifyFunction(*BB->getParent()) == false &&
|
DEBUG(assert(verifyFunction(*BB->getParent()) == false &&
|
||||||
"Function broken!"));
|
"Function broken!"));
|
||||||
|
BI = BB->begin(); // Rescan basic block. BI might be invalidated.
|
||||||
++NumExprTreesConv;
|
++NumExprTreesConv;
|
||||||
return true;
|
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());
|
PRINT_PEEPHOLE3("CAST-DEST-EXPR-CONV:in ", Src, CI, BB->getParent());
|
||||||
|
|
||||||
DEBUG(cerr << "\nCONVERTING EXPR TYPE:\n");
|
DEBUG(cerr << "\nCONVERTING EXPR TYPE:\n");
|
||||||
|
{ // ValueMap must be destroyed before function verified!
|
||||||
ValueMapCache ValueMap;
|
ValueMapCache ValueMap;
|
||||||
ConvertValueToNewType(CI, Src, ValueMap); // This will delete CI!
|
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);
|
PRINT_PEEPHOLE1("CAST-DEST-EXPR-CONV:out", Src);
|
||||||
DEBUG(cerr << "DONE CONVERTING EXPR TYPE: \n\n" << BB->getParent());
|
DEBUG(cerr << "DONE CONVERTING EXPR TYPE: \n\n" << BB->getParent());
|
||||||
|
|
||||||
DEBUG(assert(verifyFunction(*BB->getParent()) == false &&
|
DEBUG(assert(verifyFunction(*BB->getParent()) == false &&
|
||||||
"Function broken!"));
|
"Function broken!"));
|
||||||
|
BI = BB->begin(); // Rescan basic block. BI might be invalidated.
|
||||||
++NumExprTreesConv;
|
++NumExprTreesConv;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#define TRANSFORM_INTERNALS_H
|
#define TRANSFORM_INTERNALS_H
|
||||||
|
|
||||||
#include "llvm/BasicBlock.h"
|
#include "llvm/BasicBlock.h"
|
||||||
#include "llvm/Instruction.h"
|
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
|
@ -53,6 +52,40 @@ const Type *ConvertableToGEP(const Type *Ty, Value *V,
|
||||||
BasicBlock::iterator *BI = 0);
|
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<Instruction>(V) && classof(cast<Instruction>(V));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// ------------- Expression Conversion ---------------------
|
// ------------- Expression Conversion ---------------------
|
||||||
|
|
||||||
typedef std::map<const Value*, const Type*> ValueTypeCache;
|
typedef std::map<const Value*, const Type*> ValueTypeCache;
|
||||||
|
@ -68,6 +101,14 @@ struct ValueMapCache {
|
||||||
//
|
//
|
||||||
std::map<const Value *, Value *> ExprMap;
|
std::map<const Value *, Value *> ExprMap;
|
||||||
typedef std::map<const Value *, Value *> ExprMapTy;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,34 +122,6 @@ bool ValueConvertableToType(Value *V, const Type *Ty,
|
||||||
void ConvertValueToNewType(Value *V, Value *NewVal, ValueMapCache &VMC);
|
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<Instruction>(V) && classof(cast<Instruction>(V));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// getStructOffsetType - Return a vector of offsets that are to be used to index
|
// 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
|
// 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
|
// can. Note that it is possible that we cannot get exactly to Offset, in which
|
||||||
|
|
Loading…
Reference in New Issue