mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-06 06:33:24 +00:00
Use the expression map correctly.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1140 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8448fb5b24
commit
e4f4d8c3ec
@ -19,6 +19,22 @@
|
|||||||
|
|
||||||
#include "llvm/Assembly/Writer.h"
|
#include "llvm/Assembly/Writer.h"
|
||||||
|
|
||||||
|
//#define DEBUG_EXPR_CONVERT 1
|
||||||
|
|
||||||
|
static inline const Type *getTy(const Value *V, ValueTypeCache &CT) {
|
||||||
|
ValueTypeCache::iterator I = CT.find(V);
|
||||||
|
if (I == CT.end()) return V->getType();
|
||||||
|
return I->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool OperandConvertableToType(User *U, Value *V, const Type *Ty,
|
||||||
|
ValueTypeCache &ConvertedTypes);
|
||||||
|
|
||||||
|
static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
||||||
|
ValueMapCache &VMC);
|
||||||
|
|
||||||
|
|
||||||
// ExpressionConvertableToType - Return true if it is possible
|
// ExpressionConvertableToType - Return true if it is possible
|
||||||
static bool ExpressionConvertableToType(Value *V, const Type *Ty,
|
static bool ExpressionConvertableToType(Value *V, const Type *Ty,
|
||||||
ValueTypeCache &CTMap) {
|
ValueTypeCache &CTMap) {
|
||||||
@ -26,6 +42,14 @@ static bool ExpressionConvertableToType(Value *V, const Type *Ty,
|
|||||||
if (CTMI != CTMap.end()) return CTMI->second == Ty;
|
if (CTMI != CTMap.end()) return CTMI->second == Ty;
|
||||||
CTMap[V] = Ty;
|
CTMap[V] = Ty;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I)
|
||||||
|
if (!OperandConvertableToType(*I, V, Ty, CTMap))
|
||||||
|
return false;
|
||||||
|
|
||||||
Instruction *I = dyn_cast<Instruction>(V);
|
Instruction *I = dyn_cast<Instruction>(V);
|
||||||
if (I == 0) {
|
if (I == 0) {
|
||||||
// It's not an instruction, check to see if it's a constant... all constants
|
// It's not an instruction, check to see if it's a constant... all constants
|
||||||
@ -101,6 +125,10 @@ static bool ExpressionConvertableToType(Value *V, const Type *Ty,
|
|||||||
|
|
||||||
static Value *ConvertExpressionToType(Value *V, const Type *Ty,
|
static Value *ConvertExpressionToType(Value *V, const Type *Ty,
|
||||||
ValueMapCache &VMC) {
|
ValueMapCache &VMC) {
|
||||||
|
ValueMapCache::ExprMapTy::iterator VMCI = VMC.ExprMap.find(V);
|
||||||
|
if (VMCI != VMC.ExprMap.end())
|
||||||
|
return VMCI->second;
|
||||||
|
|
||||||
Instruction *I = dyn_cast<Instruction>(V);
|
Instruction *I = dyn_cast<Instruction>(V);
|
||||||
if (I == 0)
|
if (I == 0)
|
||||||
if (ConstPoolVal *CPV = cast<ConstPoolVal>(V)) {
|
if (ConstPoolVal *CPV = cast<ConstPoolVal>(V)) {
|
||||||
@ -109,6 +137,9 @@ static Value *ConvertExpressionToType(Value *V, const Type *Ty,
|
|||||||
Value *Result = opt::ConstantFoldCastInstruction(CPV, Ty);
|
Value *Result = opt::ConstantFoldCastInstruction(CPV, Ty);
|
||||||
if (!Result) cerr << "Couldn't fold " << CPV << " to " << Ty << endl;
|
if (!Result) cerr << "Couldn't fold " << CPV << " to " << Ty << endl;
|
||||||
assert(Result && "ConstantFoldCastInstruction Failed!!!");
|
assert(Result && "ConstantFoldCastInstruction Failed!!!");
|
||||||
|
|
||||||
|
// Add the instruction to the expression map
|
||||||
|
VMC.ExprMap[V] = Result;
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,27 +225,30 @@ static Value *ConvertExpressionToType(Value *V, const Type *Ty,
|
|||||||
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);
|
||||||
|
|
||||||
//cerr << "RInst: " << Res << "BB After: " << BB << endl << endl;
|
// Add the instruction to the expression map
|
||||||
|
VMC.ExprMap[I] = Res;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
unsigned NumUses = I->use_size();
|
||||||
|
for (unsigned It = 0; It < NumUses; ) {
|
||||||
|
unsigned OldSize = NumUses;
|
||||||
|
ConvertOperandToType(*(I->use_begin()+It), I, Res, VMC);
|
||||||
|
NumUses = I->use_size();
|
||||||
|
if (NumUses == OldSize) ++It;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
|
cerr << "ExpIn: " << I << "ExpOut: " << Res;
|
||||||
|
#endif
|
||||||
|
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline const Type *getTy(const Value *V, ValueTypeCache &CT) {
|
|
||||||
ValueTypeCache::iterator I = CT.find(V);
|
|
||||||
if (I == CT.end()) return V->getType();
|
|
||||||
return I->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool OperandConvertableToType(User *U, Value *V, const Type *Ty,
|
|
||||||
ValueTypeCache &ConvertedTypes);
|
|
||||||
|
|
||||||
// RetValConvertableToType - Return true if it is possible
|
// RetValConvertableToType - Return true if it is possible
|
||||||
bool RetValConvertableToType(Value *V, const Type *Ty,
|
bool RetValConvertableToType(Value *V, const Type *Ty,
|
||||||
ValueTypeCache &ConvertedTypes) {
|
ValueTypeCache &ConvertedTypes) {
|
||||||
@ -233,6 +267,11 @@ 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
|
||||||
@ -347,22 +386,29 @@ static bool OperandConvertableToType(User *U, Value *V, const Type *Ty,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
|
||||||
ValueMapCache &VMC);
|
|
||||||
|
|
||||||
void ConvertUsersType(Value *V, Value *NewVal, ValueMapCache &VMC) {
|
void ConvertUsersType(Value *V, Value *NewVal, ValueMapCache &VMC) {
|
||||||
|
unsigned NumUses = V->use_size();
|
||||||
|
for (unsigned It = 0; It < NumUses; ) {
|
||||||
|
unsigned OldSize = NumUses;
|
||||||
|
ConvertOperandToType(*(V->use_begin()+It), V, NewVal, VMC);
|
||||||
|
NumUses = V->use_size();
|
||||||
|
if (NumUses == OldSize) ++It;
|
||||||
|
}
|
||||||
|
|
||||||
// It is safe to convert the specified value to the specified type IFF all of
|
if (NumUses == 0)
|
||||||
// the uses of the value can be converted to accept the new typed value.
|
if (Instruction *I = dyn_cast<Instruction>(V)) {
|
||||||
|
BasicBlock *BB = I->getParent();
|
||||||
|
|
||||||
|
// 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.
|
||||||
//
|
//
|
||||||
while (!V->use_empty()) {
|
BasicBlock::iterator It = find(BB->begin(), BB->end(), I);
|
||||||
unsigned OldSize = V->use_size();
|
assert(It != BB->end() && "Instruction no longer in basic block??");
|
||||||
ConvertOperandToType(V->use_back(), V, NewVal, VMC);
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
assert(V->use_size() != OldSize && "Use didn't detatch from value!");
|
cerr << "DELETING: " << (void*)I << " " << I;
|
||||||
|
#endif
|
||||||
|
delete BB->getInstList().remove(It);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,6 +416,12 @@ void ConvertUsersType(Value *V, Value *NewVal, ValueMapCache &VMC) {
|
|||||||
|
|
||||||
static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
||||||
ValueMapCache &VMC) {
|
ValueMapCache &VMC) {
|
||||||
|
if (isa<ValueHandle>(U)) return; // Valuehandles don't let go of operands...
|
||||||
|
|
||||||
|
if (VMC.OperandsMapped.count(make_pair(U, OldVal))) return;
|
||||||
|
|
||||||
|
VMC.OperandsMapped.insert(make_pair(U, OldVal));
|
||||||
|
|
||||||
Instruction *I = cast<Instruction>(U); // Only Instructions convertable
|
Instruction *I = cast<Instruction>(U); // Only Instructions convertable
|
||||||
|
|
||||||
BasicBlock *BB = I->getParent();
|
BasicBlock *BB = I->getParent();
|
||||||
@ -379,6 +431,12 @@ 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...
|
||||||
|
ValueHandle IHandle(I);
|
||||||
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
|
cerr << "VH AQUIRING: " << I;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (I->getOpcode()) {
|
switch (I->getOpcode()) {
|
||||||
case Instruction::Cast:
|
case Instruction::Cast:
|
||||||
assert(I->getOperand(0) == OldVal);
|
assert(I->getOperand(0) == OldVal);
|
||||||
@ -472,23 +530,63 @@ static void ConvertOperandToType(User *U, Value *OldVal, Value *NewVal,
|
|||||||
assert(It != BIL.end() && "Instruction not in own basic block??");
|
assert(It != BIL.end() && "Instruction not in own basic block??");
|
||||||
BIL.insert(It, Res); // Keep It pointing to old instruction
|
BIL.insert(It, Res); // Keep It pointing to old instruction
|
||||||
|
|
||||||
#if DEBUG_PEEPHOLE_INSTS
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
cerr << "In: " << I << "Out: " << Res;
|
cerr << "In: " << I << "Out: " << Res;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//cerr << "RInst: " << Res << "BB After: " << BB << endl << endl;
|
|
||||||
|
|
||||||
if (I->getType() != Res->getType())
|
if (I->getType() != Res->getType())
|
||||||
ConvertUsersType(I, Res, VMC);
|
ConvertUsersType(I, Res, VMC);
|
||||||
|
else {
|
||||||
|
for (unsigned It = 0; It < I->use_size(); ) {
|
||||||
|
User *Use = *(I->use_begin()+It);
|
||||||
|
if (isa<ValueHandle>(Use)) // Don't remove ValueHandles!
|
||||||
|
++It;
|
||||||
else
|
else
|
||||||
I->replaceAllUsesWith(Res);
|
Use->replaceUsesOfWith(I, Res);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (I->use_size() == 0) {
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
BasicBlock::iterator It = find(BIL.begin(), BIL.end(), I);
|
||||||
|
assert(It != BIL.end() && "Instruction no longer in basic block??");
|
||||||
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
|
cerr << "DELETING: " << (void*)I << " " << I;
|
||||||
|
#endif
|
||||||
|
delete BIL.remove(It);
|
||||||
|
} 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!!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ValueHandle::~ValueHandle() {
|
||||||
|
if (Operands[0]->use_size() == 1) {
|
||||||
|
Value *V = Operands[0];
|
||||||
|
Operands.clear(); // Drop use!
|
||||||
|
|
||||||
// Now we just need to remove the old instruction so we don't get infinite
|
// 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
|
// loops. Note that we cannot use DCE because DCE won't remove a store
|
||||||
// instruction, for example.
|
// instruction, for example.
|
||||||
assert(I->use_size() == 0 && "Uses of Instruction remain!!!");
|
//
|
||||||
|
Instruction *I = cast<Instruction>(V);
|
||||||
|
BasicBlock *BB = I->getParent();
|
||||||
|
assert(BB && "Inst not in basic block!");
|
||||||
|
|
||||||
It = find(BIL.begin(), BIL.end(), I);
|
BasicBlock::iterator It = find(BB->begin(), BB->end(), I);
|
||||||
assert(It != BIL.end() && "Instruction no longer in basic block??");
|
assert(It != BB->end() && "Instruction no longer in basic block??");
|
||||||
delete BIL.remove(It);
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
|
cerr << "VH DELETING: " << (void*)I << " " << I;
|
||||||
|
#endif
|
||||||
|
delete BB->getInstList().remove(It);
|
||||||
|
} else {
|
||||||
|
#ifdef DEBUG_EXPR_CONVERT
|
||||||
|
cerr << "VH RELEASING: " << Operands[0];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
#include "llvm/Assembly/Writer.h"
|
#include "llvm/Assembly/Writer.h"
|
||||||
|
|
||||||
#define DEBUG_PEEPHOLE_INSTS 1
|
//#define DEBUG_PEEPHOLE_INSTS 1
|
||||||
|
|
||||||
#ifdef DEBUG_PEEPHOLE_INSTS
|
#ifdef DEBUG_PEEPHOLE_INSTS
|
||||||
#define PRINT_PEEPHOLE(ID, NUM, I) \
|
#define PRINT_PEEPHOLE(ID, NUM, I) \
|
||||||
@ -356,11 +356,8 @@ static bool PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
|
|||||||
PRINT_PEEPHOLE2("CAST-DEST-EXPR-CONV:in ", CI, Src);
|
PRINT_PEEPHOLE2("CAST-DEST-EXPR-CONV:in ", CI, Src);
|
||||||
|
|
||||||
ValueMapCache ValueMap;
|
ValueMapCache ValueMap;
|
||||||
ConvertUsersType(CI, Src, ValueMap);
|
ConvertUsersType(CI, Src, ValueMap); // This will delete CI!
|
||||||
if (!Src->hasName() && CI->hasName()) {
|
|
||||||
string Name = CI->getName(); CI->setName("");
|
|
||||||
Src->setName(Name, BB->getParent()->getSymbolTable());
|
|
||||||
}
|
|
||||||
BI = BB->begin(); // Rescan basic block. BI might be invalidated.
|
BI = BB->begin(); // Rescan basic block. BI might be invalidated.
|
||||||
PRINT_PEEPHOLE1("CAST-DEST-EXPR-CONV:out", I);
|
PRINT_PEEPHOLE1("CAST-DEST-EXPR-CONV:out", I);
|
||||||
return true;
|
return true;
|
||||||
|
@ -9,8 +9,10 @@
|
|||||||
#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 <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
// TargetData Hack: Eventually we will have annotations given to us by the
|
// TargetData Hack: Eventually we will have annotations given to us by the
|
||||||
// backend so that we know stuff about type size and alignments. For now
|
// backend so that we know stuff about type size and alignments. For now
|
||||||
@ -44,7 +46,19 @@ void ReplaceInstWithInst(BasicBlock::InstListType &BIL,
|
|||||||
// ------------- Expression Conversion ---------------------
|
// ------------- Expression Conversion ---------------------
|
||||||
|
|
||||||
typedef map<const Value*, const Type*> ValueTypeCache;
|
typedef map<const Value*, const Type*> ValueTypeCache;
|
||||||
typedef map<const Value*, Value*> ValueMapCache;
|
|
||||||
|
struct ValueMapCache {
|
||||||
|
// Operands mapped - Contains an entry if the first value (the user) has had
|
||||||
|
// the second value (the operand) mapped already.
|
||||||
|
//
|
||||||
|
set<pair<const User*, const Value*> > OperandsMapped;
|
||||||
|
|
||||||
|
// Expression Map - Contains an entry from the old value to the new value of
|
||||||
|
// an expression that has been converted over.
|
||||||
|
//
|
||||||
|
map<const Value *, Value *> ExprMap;
|
||||||
|
typedef map<const Value *, Value *> ExprMapTy;
|
||||||
|
};
|
||||||
|
|
||||||
// RetValConvertableToType - Return true if it is possible
|
// RetValConvertableToType - Return true if it is possible
|
||||||
bool RetValConvertableToType(Value *V, const Type *Ty,
|
bool RetValConvertableToType(Value *V, const Type *Ty,
|
||||||
@ -53,4 +67,34 @@ bool RetValConvertableToType(Value *V, const Type *Ty,
|
|||||||
void ConvertUsersType(Value *V, Value *NewVal, ValueMapCache &VMC);
|
void ConvertUsersType(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
|
||||||
|
public:
|
||||||
|
ValueHandle(Value *V) : Instruction(Type::VoidTy, UserOp1, "") {
|
||||||
|
Operands.push_back(Use(V, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
~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));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user