forked from OSchip/llvm-project
Use a total ordering to compare instructions.
Fixes infinite loop in resolve(). llvm-svn: 30540
This commit is contained in:
parent
44cb67af5c
commit
cfff1c3f86
|
@ -49,60 +49,30 @@ namespace {
|
|||
Statistic<>
|
||||
NumInstruction("predsimplify", "Number of instructions removed");
|
||||
|
||||
/// Returns true if V1 is a better choice than V2. Note that it is
|
||||
/// 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);
|
||||
}
|
||||
class PropertySet;
|
||||
|
||||
/// Similar to EquivalenceClasses, this stores the set of equivalent
|
||||
/// types. Beyond EquivalenceClasses, it allows the user to specify
|
||||
/// which element will act as leader through a StrictWeakOrdering
|
||||
/// function.
|
||||
template<typename ElemTy, typename StrictWeak>
|
||||
/// types. Beyond EquivalenceClasses, it allows us to specify which
|
||||
/// element will act as leader.
|
||||
template<typename ElemTy>
|
||||
class VISIBILITY_HIDDEN Synonyms {
|
||||
std::map<ElemTy, unsigned> mapping;
|
||||
std::vector<ElemTy> leaders;
|
||||
StrictWeak swo;
|
||||
PropertySet *PS;
|
||||
|
||||
public:
|
||||
typedef unsigned iterator;
|
||||
typedef const unsigned const_iterator;
|
||||
|
||||
Synonyms(PropertySet *PS) : PS(PS) {}
|
||||
|
||||
// Inspection
|
||||
|
||||
bool empty() const {
|
||||
return leaders.empty();
|
||||
}
|
||||
|
||||
unsigned countLeaders() const {
|
||||
typename std::vector<ElemTy>::size_type countLeaders() const {
|
||||
return leaders.size();
|
||||
}
|
||||
|
||||
|
@ -151,50 +121,8 @@ namespace {
|
|||
/// Combine two sets referring to the same element, inserting the
|
||||
/// elements as needed. Returns a valid iterator iff two already
|
||||
/// existing disjoint synonym sets were combined. The iterator
|
||||
/// points to the removed element.
|
||||
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;
|
||||
}
|
||||
/// points to the no longer existing element.
|
||||
iterator unionSets(ElemTy E1, ElemTy E2);
|
||||
|
||||
/// Returns an iterator pointing to the synonym set containing
|
||||
/// 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
|
||||
/// and fast lookup. Also stores the set of inequality relationships.
|
||||
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;
|
||||
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>::const_iterator ConstPropertyIterator;
|
||||
typedef Synonyms<Value *, compare>::iterator SynonymIterator;
|
||||
typedef Synonyms<Value *>::iterator SynonymIterator;
|
||||
|
||||
enum Ops {
|
||||
EQ,
|
||||
|
@ -231,7 +197,7 @@ namespace {
|
|||
}
|
||||
|
||||
Value *lookup(Value *V) const {
|
||||
Synonyms<Value *, compare>::iterator SI = union_find.findLeader(V);
|
||||
SynonymIterator SI = union_find.findLeader(V);
|
||||
if (!SI) return NULL;
|
||||
return union_find.getLeader(SI);
|
||||
}
|
||||
|
@ -313,7 +279,7 @@ namespace {
|
|||
// Represents Head OP [Tail1, Tail2, ...]
|
||||
// For example: %x != %a, %x != %b.
|
||||
struct VISIBILITY_HIDDEN Property {
|
||||
typedef Synonyms<Value *, compare>::iterator Iter;
|
||||
typedef SynonymIterator Iter;
|
||||
|
||||
Property(Ops opcode, Iter i1, Iter i2)
|
||||
: Opcode(opcode), I1(i1), I2(i2)
|
||||
|
@ -421,6 +387,7 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
DominatorTree *DT;
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
void debug(std::ostream &os) const {
|
||||
|
@ -484,6 +451,52 @@ namespace {
|
|||
|
||||
RegisterPass<PredicateSimplifier> X("predsimplify",
|
||||
"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() {
|
||||
|
@ -494,7 +507,7 @@ bool PredicateSimplifier::runOnFunction(Function &F) {
|
|||
DT = &getAnalysis<DominatorTree>();
|
||||
|
||||
modified = false;
|
||||
PropertySet KnownProperties;
|
||||
PropertySet KnownProperties(DT);
|
||||
visitBasicBlock(DT->getRootNode()->getBlock(), KnownProperties);
|
||||
return modified;
|
||||
}
|
||||
|
@ -614,6 +627,7 @@ void PredicateSimplifier::visitInstruction(Instruction *I,
|
|||
if (V != I) {
|
||||
modified = true;
|
||||
++NumInstruction;
|
||||
DEBUG(std::cerr << "Removing " << *I);
|
||||
I->replaceAllUsesWith(V);
|
||||
I->eraseFromParent();
|
||||
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…
Reference in New Issue