mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-07 14:33:15 +00:00
Use a total ordering to compare instructions.
Fixes infinite loop in resolve(). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30540 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4563326472
commit
406fc0cb49
@ -49,60 +49,30 @@ namespace {
|
|||||||
Statistic<>
|
Statistic<>
|
||||||
NumInstruction("predsimplify", "Number of instructions removed");
|
NumInstruction("predsimplify", "Number of instructions removed");
|
||||||
|
|
||||||
/// Returns true if V1 is a better choice than V2. Note that it is
|
class PropertySet;
|
||||||
/// not a total ordering.
|
|
||||||
struct compare {
|
|
||||||
bool operator()(Value *V1, Value *V2) const {
|
|
||||||
if (isa<Constant>(V1)) {
|
|
||||||
if (!isa<Constant>(V2)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (isa<Argument>(V1)) {
|
|
||||||
if (!isa<Constant>(V2) && !isa<Argument>(V2)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (User *U = dyn_cast<User>(V2)) {
|
|
||||||
for (User::const_op_iterator I = U->op_begin(), E = U->op_end();
|
|
||||||
I != E; ++I) {
|
|
||||||
if (*I == V1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Used for choosing the canonical Value in a synonym set.
|
|
||||||
/// Leaves the better choice in V1.
|
|
||||||
static void order(Value *&V1, Value *&V2) {
|
|
||||||
static compare c;
|
|
||||||
if (c(V2, V1))
|
|
||||||
std::swap(V1, V2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Similar to EquivalenceClasses, this stores the set of equivalent
|
/// Similar to EquivalenceClasses, this stores the set of equivalent
|
||||||
/// types. Beyond EquivalenceClasses, it allows the user to specify
|
/// types. Beyond EquivalenceClasses, it allows us to specify which
|
||||||
/// which element will act as leader through a StrictWeakOrdering
|
/// element will act as leader.
|
||||||
/// function.
|
template<typename ElemTy>
|
||||||
template<typename ElemTy, typename StrictWeak>
|
|
||||||
class VISIBILITY_HIDDEN Synonyms {
|
class VISIBILITY_HIDDEN Synonyms {
|
||||||
std::map<ElemTy, unsigned> mapping;
|
std::map<ElemTy, unsigned> mapping;
|
||||||
std::vector<ElemTy> leaders;
|
std::vector<ElemTy> leaders;
|
||||||
StrictWeak swo;
|
PropertySet *PS;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef unsigned iterator;
|
typedef unsigned iterator;
|
||||||
typedef const unsigned const_iterator;
|
typedef const unsigned const_iterator;
|
||||||
|
|
||||||
|
Synonyms(PropertySet *PS) : PS(PS) {}
|
||||||
|
|
||||||
// Inspection
|
// Inspection
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
return leaders.empty();
|
return leaders.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned countLeaders() const {
|
typename std::vector<ElemTy>::size_type countLeaders() const {
|
||||||
return leaders.size();
|
return leaders.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,50 +121,8 @@ namespace {
|
|||||||
/// Combine two sets referring to the same element, inserting the
|
/// Combine two sets referring to the same element, inserting the
|
||||||
/// elements as needed. Returns a valid iterator iff two already
|
/// elements as needed. Returns a valid iterator iff two already
|
||||||
/// existing disjoint synonym sets were combined. The iterator
|
/// existing disjoint synonym sets were combined. The iterator
|
||||||
/// points to the removed element.
|
/// points to the no longer existing element.
|
||||||
iterator unionSets(ElemTy E1, ElemTy E2) {
|
iterator unionSets(ElemTy E1, ElemTy E2);
|
||||||
if (swo(E2, E1)) std::swap(E1, E2);
|
|
||||||
|
|
||||||
iterator I1 = findLeader(E1),
|
|
||||||
I2 = findLeader(E2);
|
|
||||||
|
|
||||||
if (!I1 && !I2) { // neither entry is in yet
|
|
||||||
leaders.push_back(E1);
|
|
||||||
I1 = leaders.size();
|
|
||||||
mapping[E1] = I1;
|
|
||||||
mapping[E2] = I1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!I1 && I2) {
|
|
||||||
mapping[E1] = I2;
|
|
||||||
std::swap(getLeader(I2), E1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (I1 && !I2) {
|
|
||||||
mapping[E2] = I1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (I1 == I2) return 0;
|
|
||||||
|
|
||||||
// This is the case where we have two sets, [%a1, %a2, %a3] and
|
|
||||||
// [%p1, %p2, %p3] and someone says that %a2 == %p3. We need to
|
|
||||||
// combine the two synsets.
|
|
||||||
|
|
||||||
if (I1 > I2) --I1;
|
|
||||||
|
|
||||||
for (std::map<Value *, unsigned>::iterator I = mapping.begin(),
|
|
||||||
E = mapping.end(); I != E; ++I) {
|
|
||||||
if (I->second == I2) I->second = I1;
|
|
||||||
else if (I->second > I2) --I->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
leaders.erase(leaders.begin() + I2 - 1);
|
|
||||||
|
|
||||||
return I2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator pointing to the synonym set containing
|
/// Returns an iterator pointing to the synonym set containing
|
||||||
/// element e. If none exists, a new one is created and returned.
|
/// element e. If none exists, a new one is created and returned.
|
||||||
@ -212,13 +140,51 @@ namespace {
|
|||||||
/// Represents the set of equivalent Value*s and provides insertion
|
/// Represents the set of equivalent Value*s and provides insertion
|
||||||
/// and fast lookup. Also stores the set of inequality relationships.
|
/// and fast lookup. Also stores the set of inequality relationships.
|
||||||
class PropertySet {
|
class PropertySet {
|
||||||
|
/// Returns true if V1 is a better choice than V2. Note that it is
|
||||||
|
/// not a total ordering.
|
||||||
|
bool compare(Value *V1, Value *V2) const {
|
||||||
|
if (isa<Constant>(V1)) {
|
||||||
|
if (!isa<Constant>(V2)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (isa<Argument>(V1)) {
|
||||||
|
if (!isa<Constant>(V2) && !isa<Argument>(V2)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Instruction *I1 = dyn_cast<Instruction>(V1)) {
|
||||||
|
if (Instruction *I2 = dyn_cast<Instruction>(V2)) {
|
||||||
|
BasicBlock *BB1 = I1->getParent(),
|
||||||
|
*BB2 = I2->getParent();
|
||||||
|
if (BB1 == BB2) {
|
||||||
|
for (BasicBlock::const_iterator I = BB1->begin(), E = BB1->end();
|
||||||
|
I != E; ++I) {
|
||||||
|
if (&*I == I1) return true;
|
||||||
|
if (&*I == I2) return false;
|
||||||
|
}
|
||||||
|
assert(0 && "Instructions not found in parent BasicBlock?");
|
||||||
|
} else
|
||||||
|
return DT->getNode(BB1)->properlyDominates(DT->getNode(BB2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct Property;
|
struct Property;
|
||||||
public:
|
public:
|
||||||
class Synonyms<Value *, compare> union_find;
|
/// Choose the canonical Value in a synonym set.
|
||||||
|
/// Leaves the more canonical choice in V1.
|
||||||
|
void order(Value *&V1, Value *&V2) const {
|
||||||
|
if (compare(V2, V1)) std::swap(V1, V2);
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertySet(DominatorTree *DT) : union_find(this), DT(DT) {}
|
||||||
|
|
||||||
|
class Synonyms<Value *> union_find;
|
||||||
|
|
||||||
typedef std::vector<Property>::iterator PropertyIterator;
|
typedef std::vector<Property>::iterator PropertyIterator;
|
||||||
typedef std::vector<Property>::const_iterator ConstPropertyIterator;
|
typedef std::vector<Property>::const_iterator ConstPropertyIterator;
|
||||||
typedef Synonyms<Value *, compare>::iterator SynonymIterator;
|
typedef Synonyms<Value *>::iterator SynonymIterator;
|
||||||
|
|
||||||
enum Ops {
|
enum Ops {
|
||||||
EQ,
|
EQ,
|
||||||
@ -231,7 +197,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Value *lookup(Value *V) const {
|
Value *lookup(Value *V) const {
|
||||||
Synonyms<Value *, compare>::iterator SI = union_find.findLeader(V);
|
SynonymIterator SI = union_find.findLeader(V);
|
||||||
if (!SI) return NULL;
|
if (!SI) return NULL;
|
||||||
return union_find.getLeader(SI);
|
return union_find.getLeader(SI);
|
||||||
}
|
}
|
||||||
@ -313,7 +279,7 @@ namespace {
|
|||||||
// Represents Head OP [Tail1, Tail2, ...]
|
// Represents Head OP [Tail1, Tail2, ...]
|
||||||
// For example: %x != %a, %x != %b.
|
// For example: %x != %a, %x != %b.
|
||||||
struct VISIBILITY_HIDDEN Property {
|
struct VISIBILITY_HIDDEN Property {
|
||||||
typedef Synonyms<Value *, compare>::iterator Iter;
|
typedef SynonymIterator Iter;
|
||||||
|
|
||||||
Property(Ops opcode, Iter i1, Iter i2)
|
Property(Ops opcode, Iter i1, Iter i2)
|
||||||
: Opcode(opcode), I1(i1), I2(i2)
|
: Opcode(opcode), I1(i1), I2(i2)
|
||||||
@ -421,6 +387,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DominatorTree *DT;
|
||||||
public:
|
public:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void debug(std::ostream &os) const {
|
void debug(std::ostream &os) const {
|
||||||
@ -484,6 +451,52 @@ namespace {
|
|||||||
|
|
||||||
RegisterPass<PredicateSimplifier> X("predsimplify",
|
RegisterPass<PredicateSimplifier> X("predsimplify",
|
||||||
"Predicate Simplifier");
|
"Predicate Simplifier");
|
||||||
|
|
||||||
|
template <typename ElemTy>
|
||||||
|
typename Synonyms<ElemTy>::iterator
|
||||||
|
Synonyms<ElemTy>::unionSets(ElemTy E1, ElemTy E2) {
|
||||||
|
PS->order(E1, E2);
|
||||||
|
|
||||||
|
iterator I1 = findLeader(E1),
|
||||||
|
I2 = findLeader(E2);
|
||||||
|
|
||||||
|
if (!I1 && !I2) { // neither entry is in yet
|
||||||
|
leaders.push_back(E1);
|
||||||
|
I1 = leaders.size();
|
||||||
|
mapping[E1] = I1;
|
||||||
|
mapping[E2] = I1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!I1 && I2) {
|
||||||
|
mapping[E1] = I2;
|
||||||
|
std::swap(getLeader(I2), E1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (I1 && !I2) {
|
||||||
|
mapping[E2] = I1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (I1 == I2) return 0;
|
||||||
|
|
||||||
|
// This is the case where we have two sets, [%a1, %a2, %a3] and
|
||||||
|
// [%p1, %p2, %p3] and someone says that %a2 == %p3. We need to
|
||||||
|
// combine the two synsets.
|
||||||
|
|
||||||
|
if (I1 > I2) --I1;
|
||||||
|
|
||||||
|
for (std::map<Value *, unsigned>::iterator I = mapping.begin(),
|
||||||
|
E = mapping.end(); I != E; ++I) {
|
||||||
|
if (I->second == I2) I->second = I1;
|
||||||
|
else if (I->second > I2) --I->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
leaders.erase(leaders.begin() + I2 - 1);
|
||||||
|
|
||||||
|
return I2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionPass *llvm::createPredicateSimplifierPass() {
|
FunctionPass *llvm::createPredicateSimplifierPass() {
|
||||||
@ -494,7 +507,7 @@ bool PredicateSimplifier::runOnFunction(Function &F) {
|
|||||||
DT = &getAnalysis<DominatorTree>();
|
DT = &getAnalysis<DominatorTree>();
|
||||||
|
|
||||||
modified = false;
|
modified = false;
|
||||||
PropertySet KnownProperties;
|
PropertySet KnownProperties(DT);
|
||||||
visitBasicBlock(DT->getRootNode()->getBlock(), KnownProperties);
|
visitBasicBlock(DT->getRootNode()->getBlock(), KnownProperties);
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
@ -614,6 +627,7 @@ void PredicateSimplifier::visitInstruction(Instruction *I,
|
|||||||
if (V != I) {
|
if (V != I) {
|
||||||
modified = true;
|
modified = true;
|
||||||
++NumInstruction;
|
++NumInstruction;
|
||||||
|
DEBUG(std::cerr << "Removing " << *I);
|
||||||
I->replaceAllUsesWith(V);
|
I->replaceAllUsesWith(V);
|
||||||
I->eraseFromParent();
|
I->eraseFromParent();
|
||||||
return;
|
return;
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
; RUN: llvm-as < %s | opt -predsimplify -disable-output
|
||||||
|
|
||||||
|
void %gs_image_next() {
|
||||||
|
entry:
|
||||||
|
%tmp = load uint* null ; <uint> [#uses=2]
|
||||||
|
br bool false, label %cond_next21, label %UnifiedReturnBlock
|
||||||
|
|
||||||
|
cond_next21: ; preds = %entry
|
||||||
|
br bool false, label %cond_next42, label %UnifiedReturnBlock
|
||||||
|
|
||||||
|
cond_next42: ; preds = %cond_next21
|
||||||
|
br label %cond_true158
|
||||||
|
|
||||||
|
cond_next134: ; preds = %cond_true158
|
||||||
|
%tmp1571 = seteq uint 0, %min ; <bool> [#uses=0]
|
||||||
|
ret void
|
||||||
|
|
||||||
|
cond_true158: ; preds = %cond_true158, %cond_next42
|
||||||
|
%tmp47 = sub uint %tmp, 0 ; <uint> [#uses=2]
|
||||||
|
%tmp49 = setle uint %tmp47, 0 ; <bool> [#uses=1]
|
||||||
|
%min = select bool %tmp49, uint %tmp47, uint 0 ; <uint> [#uses=2]
|
||||||
|
%tmp92 = add uint %min, 0 ; <uint> [#uses=1]
|
||||||
|
%tmp101 = seteq uint %tmp92, %tmp ; <bool> [#uses=1]
|
||||||
|
br bool %tmp101, label %cond_next134, label %cond_true158
|
||||||
|
|
||||||
|
UnifiedReturnBlock: ; preds = %cond_next21, %entry
|
||||||
|
ret void
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user