mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-06 01:24:35 +00:00
* Change ExpressionConvertableToType to more closely match map behavior of
ConvertExpressionToType * Make ValueHandle's remove instruction from maps when they are deleted so that no false map hits occur if a subsequent instruction is allocated to the same space in memory. This was a VERY VERY VERY EVIL NASTY BUG to track down. :-P git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1288 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -73,6 +73,7 @@ bool ExpressionConvertableToType(Value *V, const Type *Ty,
|
|||||||
|
|
||||||
ValueTypeCache::iterator CTMI = CTMap.find(V);
|
ValueTypeCache::iterator CTMI = CTMap.find(V);
|
||||||
if (CTMI != CTMap.end()) return CTMI->second == Ty;
|
if (CTMI != CTMap.end()) return CTMI->second == Ty;
|
||||||
|
|
||||||
CTMap[V] = Ty;
|
CTMap[V] = Ty;
|
||||||
|
|
||||||
Instruction *I = dyn_cast<Instruction>(V);
|
Instruction *I = dyn_cast<Instruction>(V);
|
||||||
@ -89,31 +90,26 @@ bool ExpressionConvertableToType(Value *V, const Type *Ty,
|
|||||||
return false; // Otherwise, we can't convert!
|
return false; // Otherwise, we can't convert!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expressions are only convertable if all of the users of the expression can
|
|
||||||
// have this value converted. This makes use of the map to avoid infinite
|
|
||||||
// recursion.
|
|
||||||
//
|
|
||||||
if (isa<Instruction>(V)) {
|
|
||||||
for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I)
|
|
||||||
if (!OperandConvertableToType(*I, V, Ty, CTMap))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (I->getOpcode()) {
|
switch (I->getOpcode()) {
|
||||||
case Instruction::Cast:
|
case Instruction::Cast:
|
||||||
// We can convert the expr if the cast destination type is losslessly
|
// We can convert the expr if the cast destination type is losslessly
|
||||||
// convertable to the requested type.
|
// convertable to the requested type.
|
||||||
return losslessCastableTypes(Ty, I->getType());
|
if (!losslessCastableTypes(Ty, I->getType())) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
case Instruction::Add:
|
case Instruction::Add:
|
||||||
case Instruction::Sub:
|
case Instruction::Sub:
|
||||||
return ExpressionConvertableToType(I->getOperand(0), Ty, CTMap) &&
|
if (!ExpressionConvertableToType(I->getOperand(0), Ty, CTMap) ||
|
||||||
ExpressionConvertableToType(I->getOperand(1), Ty, CTMap);
|
!ExpressionConvertableToType(I->getOperand(1), Ty, CTMap))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
case Instruction::Shr:
|
case Instruction::Shr:
|
||||||
if (Ty->isSigned() != V->getType()->isSigned()) return false;
|
if (Ty->isSigned() != V->getType()->isSigned()) return false;
|
||||||
// FALL THROUGH
|
// FALL THROUGH
|
||||||
case Instruction::Shl:
|
case Instruction::Shl:
|
||||||
return ExpressionConvertableToType(I->getOperand(0), Ty, CTMap);
|
if (!ExpressionConvertableToType(I->getOperand(0), Ty, CTMap))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
case Instruction::Load: {
|
case Instruction::Load: {
|
||||||
LoadInst *LI = cast<LoadInst>(I);
|
LoadInst *LI = cast<LoadInst>(I);
|
||||||
@ -125,15 +121,17 @@ bool ExpressionConvertableToType(Value *V, const Type *Ty,
|
|||||||
if (!CPV[i]->isNullValue()) return false;
|
if (!CPV[i]->isNullValue()) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExpressionConvertableToType(LI->getPtrOperand(),
|
if (!ExpressionConvertableToType(LI->getPtrOperand(), PointerType::get(Ty),
|
||||||
PointerType::get(Ty), CTMap);
|
CTMap))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Instruction::PHINode: {
|
case Instruction::PHINode: {
|
||||||
PHINode *PN = cast<PHINode>(I);
|
PHINode *PN = cast<PHINode>(I);
|
||||||
for (unsigned i = 0; i < PN->getNumIncomingValues(); ++i)
|
for (unsigned i = 0; i < PN->getNumIncomingValues(); ++i)
|
||||||
if (!ExpressionConvertableToType(PN->getIncomingValue(i), Ty, CTMap))
|
if (!ExpressionConvertableToType(PN->getIncomingValue(i), Ty, CTMap))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Instruction::GetElementPtr: {
|
case Instruction::GetElementPtr: {
|
||||||
@ -163,21 +161,35 @@ bool ExpressionConvertableToType(Value *V, const Type *Ty,
|
|||||||
const Type *ElTy = GetElementPtrInst::getIndexedType(BaseType, Indices,
|
const Type *ElTy = GetElementPtrInst::getIndexedType(BaseType, Indices,
|
||||||
true);
|
true);
|
||||||
if (ElTy == PTy->getValueType())
|
if (ElTy == PTy->getValueType())
|
||||||
return true; // Found a match!!
|
break; // Found a match!!
|
||||||
}
|
|
||||||
break; // No match, maybe next time.
|
|
||||||
}
|
}
|
||||||
|
return false; // No match, maybe next time.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expressions are only convertable if all of the users of the expression can
|
||||||
|
// have this value converted. This makes use of the map to avoid infinite
|
||||||
|
// recursion.
|
||||||
|
//
|
||||||
|
if (isa<Instruction>(V)) {
|
||||||
|
for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I)
|
||||||
|
if (!OperandConvertableToType(*I, V, Ty, CTMap))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
||||||
ValueMapCache::ExprMapTy::iterator VMCI = VMC.ExprMap.find(V);
|
ValueMapCache::ExprMapTy::iterator VMCI = VMC.ExprMap.find(V);
|
||||||
if (VMCI != VMC.ExprMap.end())
|
if (VMCI != VMC.ExprMap.end()) {
|
||||||
|
assert(VMCI->second->getType() == Ty);
|
||||||
return VMCI->second;
|
return VMCI->second;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_EXPR_CONVERT
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
cerr << "CETT: " << (void*)V << " " << V;
|
cerr << "CETT: " << (void*)V << " " << V;
|
||||||
@ -190,6 +202,7 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
|||||||
// We assume here that all casts are implemented for constant prop.
|
// We assume here that all casts are implemented for constant prop.
|
||||||
Value *Result = opt::ConstantFoldCastInstruction(CPV, Ty);
|
Value *Result = opt::ConstantFoldCastInstruction(CPV, Ty);
|
||||||
assert(Result && "ConstantFoldCastInstruction Failed!!!");
|
assert(Result && "ConstantFoldCastInstruction Failed!!!");
|
||||||
|
assert(Result->getType() == Ty && "Const prop of cast failed!");
|
||||||
|
|
||||||
// Add the instruction to the expression map
|
// Add the instruction to the expression map
|
||||||
VMC.ExprMap[V] = Result;
|
VMC.ExprMap[V] = Result;
|
||||||
@ -202,7 +215,7 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
|||||||
string Name = I->getName(); if (!Name.empty()) I->setName("");
|
string Name = I->getName(); if (!Name.empty()) I->setName("");
|
||||||
Instruction *Res; // Result of conversion
|
Instruction *Res; // Result of conversion
|
||||||
|
|
||||||
ValueHandle IHandle(I); // Prevent I from being removed!
|
ValueHandle IHandle(VMC, I); // Prevent I from being removed!
|
||||||
|
|
||||||
ConstPoolVal *Dummy = ConstPoolVal::getNullConstant(Ty);
|
ConstPoolVal *Dummy = ConstPoolVal::getNullConstant(Ty);
|
||||||
|
|
||||||
@ -247,6 +260,9 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
|||||||
VMC.ExprMap[I] = Res;
|
VMC.ExprMap[I] = Res;
|
||||||
Res->setOperand(0, ConvertExpressionToType(LI->getPtrOperand(),
|
Res->setOperand(0, ConvertExpressionToType(LI->getPtrOperand(),
|
||||||
PointerType::get(Ty), VMC));
|
PointerType::get(Ty), VMC));
|
||||||
|
assert(Res->getOperand(0)->getType() == PointerType::get(Ty));
|
||||||
|
assert(Ty == Res->getType());
|
||||||
|
assert(isFirstClassType(Res->getType()) && "Load of structure or array!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +274,7 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
|||||||
while (OldPN->getNumOperands()) {
|
while (OldPN->getNumOperands()) {
|
||||||
BasicBlock *BB = OldPN->getIncomingBlock(0);
|
BasicBlock *BB = OldPN->getIncomingBlock(0);
|
||||||
Value *OldVal = OldPN->getIncomingValue(0);
|
Value *OldVal = OldPN->getIncomingValue(0);
|
||||||
ValueHandle OldValHandle(OldVal);
|
ValueHandle OldValHandle(VMC, OldVal);
|
||||||
OldPN->removeIncomingValue(BB);
|
OldPN->removeIncomingValue(BB);
|
||||||
Value *V = ConvertExpressionToType(OldVal, Ty, VMC);
|
Value *V = ConvertExpressionToType(OldVal, Ty, VMC);
|
||||||
NewPN->addIncoming(V, BB);
|
NewPN->addIncoming(V, BB);
|
||||||
@ -308,6 +324,8 @@ Value *ConvertExpressionToType(Value *V, const Type *Ty, ValueMapCache &VMC) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(Res->getType() == Ty && "Didn't convert expr to correct type!");
|
||||||
|
|
||||||
BasicBlock::iterator It = find(BIL.begin(), BIL.end(), I);
|
BasicBlock::iterator It = find(BIL.begin(), BIL.end(), I);
|
||||||
assert(It != BIL.end() && "Instruction not in own basic block??");
|
assert(It != BIL.end() && "Instruction not in own basic block??");
|
||||||
BIL.insert(It, Res);
|
BIL.insert(It, Res);
|
||||||
@ -369,8 +387,6 @@ bool RetValConvertableToType(Value *V, const Type *Ty,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// OperandConvertableToType - Return true if it is possible to convert operand
|
// OperandConvertableToType - Return true if it is possible to convert operand
|
||||||
// V of User (instruction) U to the specified type. This is true iff it is
|
// V of User (instruction) U to the specified type. This is true iff it is
|
||||||
// possible to change the specified instruction to accept this. CTMap is a map
|
// possible to change the specified instruction to accept this. CTMap is a map
|
||||||
@ -529,7 +545,7 @@ static bool OperandConvertableToType(User *U, Value *V, const Type *Ty,
|
|||||||
|
|
||||||
|
|
||||||
void ConvertUsersType(Value *V, Value *NewVal, ValueMapCache &VMC) {
|
void ConvertUsersType(Value *V, Value *NewVal, ValueMapCache &VMC) {
|
||||||
ValueHandle VH(V);
|
ValueHandle VH(VMC, V);
|
||||||
|
|
||||||
unsigned NumUses = V->use_size();
|
unsigned NumUses = V->use_size();
|
||||||
for (unsigned It = 0; It < NumUses; ) {
|
for (unsigned It = 0; It < NumUses; ) {
|
||||||
@ -564,7 +580,7 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
|||||||
//cerr << endl << endl << "Type:\t" << Ty << "\nInst: " << I << "BB Before: " << BB << endl;
|
//cerr << endl << endl << "Type:\t" << Ty << "\nInst: " << I << "BB Before: " << BB << endl;
|
||||||
|
|
||||||
// Prevent I from being removed...
|
// Prevent I from being removed...
|
||||||
ValueHandle IHandle(I);
|
ValueHandle IHandle(VMC, I);
|
||||||
|
|
||||||
const Type *NewTy = NewVal->getType();
|
const Type *NewTy = NewVal->getType();
|
||||||
ConstPoolVal *Dummy = (NewTy != Type::VoidTy) ?
|
ConstPoolVal *Dummy = (NewTy != Type::VoidTy) ?
|
||||||
@ -740,14 +756,16 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueHandle::ValueHandle(Value *V) : Instruction(Type::VoidTy, UserOp1, "") {
|
|
||||||
|
ValueHandle::ValueHandle(ValueMapCache &VMC, Value *V) : Instruction(Type::VoidTy, UserOp1, ""),
|
||||||
|
Cache(VMC) {
|
||||||
#ifdef DEBUG_EXPR_CONVERT
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
cerr << "VH AQUIRING: " << (void*)V << " " << V;
|
cerr << "VH AQUIRING: " << (void*)V << " " << V;
|
||||||
#endif
|
#endif
|
||||||
Operands.push_back(Use(V, this));
|
Operands.push_back(Use(V, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RecursiveDelete(Instruction *I) {
|
static void RecursiveDelete(ValueMapCache &Cache, Instruction *I) {
|
||||||
if (!I || !I->use_empty()) return;
|
if (!I || !I->use_empty()) return;
|
||||||
|
|
||||||
assert(I->getParent() && "Inst not in basic block!");
|
assert(I->getParent() && "Inst not in basic block!");
|
||||||
@ -761,15 +779,17 @@ static void RecursiveDelete(Instruction *I) {
|
|||||||
Instruction *U = dyn_cast<Instruction>(*OI);
|
Instruction *U = dyn_cast<Instruction>(*OI);
|
||||||
if (U) {
|
if (U) {
|
||||||
*OI = 0;
|
*OI = 0;
|
||||||
RecursiveDelete(dyn_cast<Instruction>(U));
|
RecursiveDelete(Cache, dyn_cast<Instruction>(U));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
I->getParent()->getInstList().remove(I);
|
I->getParent()->getInstList().remove(I);
|
||||||
|
|
||||||
|
Cache.OperandsMapped.erase(I);
|
||||||
|
Cache.ExprMap.erase(I);
|
||||||
delete I;
|
delete I;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ValueHandle::~ValueHandle() {
|
ValueHandle::~ValueHandle() {
|
||||||
if (Operands[0]->use_size() == 1) {
|
if (Operands[0]->use_size() == 1) {
|
||||||
Value *V = Operands[0];
|
Value *V = Operands[0];
|
||||||
@ -779,7 +799,7 @@ ValueHandle::~ValueHandle() {
|
|||||||
// loops. Note that we cannot use DCE because DCE won't remove a store
|
// loops. Note that we cannot use DCE because DCE won't remove a store
|
||||||
// instruction, for example.
|
// instruction, for example.
|
||||||
//
|
//
|
||||||
RecursiveDelete(dyn_cast<Instruction>(V));
|
RecursiveDelete(Cache, dyn_cast<Instruction>(V));
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG_EXPR_CONVERT
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
cerr << "VH RELEASING: " << (void*)Operands[0].get() << " " << Operands[0]->use_size() << " " << Operands[0];
|
cerr << "VH RELEASING: " << (void*)Operands[0].get() << " " << Operands[0]->use_size() << " " << Operands[0];
|
||||||
|
@ -95,8 +95,9 @@ void ConvertUsersType(Value *V, Value *NewVal, ValueMapCache &VMC);
|
|||||||
//
|
//
|
||||||
class ValueHandle : public Instruction {
|
class ValueHandle : public Instruction {
|
||||||
ValueHandle(const ValueHandle &); // DO NOT IMPLEMENT
|
ValueHandle(const ValueHandle &); // DO NOT IMPLEMENT
|
||||||
|
ValueMapCache &Cache;
|
||||||
public:
|
public:
|
||||||
ValueHandle(Value *V);
|
ValueHandle(ValueMapCache &VMC, Value *V);
|
||||||
~ValueHandle();
|
~ValueHandle();
|
||||||
|
|
||||||
virtual Instruction *clone() const { abort(); return 0; }
|
virtual Instruction *clone() const { abort(); return 0; }
|
||||||
|
Reference in New Issue
Block a user