Do not sort by the address of LLVM ConstantInt* objects. This produces

nondeterministic results that depend on where these objects land in memory.
Instead, sort by the value of the constant, which is stable.

Before this patch, the -simplifycfg pass run from two different compilers
could cause different code to be generated, though it was semantically the
same:

@@ -12258,8 +12258,8 @@
        %s_addr.1 = phi sbyte* [ %s, %entry ], [ %inc.0, %no_exit ]             ; <sbyte*> [#uses=5]
        %tmp.1 = load sbyte* %s_addr.1          ; <sbyte> [#uses=1]
        switch sbyte %tmp.1, label %no_exit [
-                sbyte 0, label %loopexit
                 sbyte 46, label %loopexit
+                sbyte 0, label %loopexit
        ]

We need to stomp all of this stuff out.

llvm-svn: 14243
This commit is contained in:
Chris Lattner 2004-06-19 07:02:14 +00:00
parent b5f8eb8315
commit b2b151d297
1 changed files with 21 additions and 10 deletions

View File

@ -241,13 +241,13 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB, bool AllowAggressive){
// GatherConstantSetEQs - Given a potentially 'or'd together collection of seteq
// instructions that compare a value against a constant, return the value being
// compared, and stick the constant into the Values vector.
static Value *GatherConstantSetEQs(Value *V, std::vector<Constant*> &Values) {
static Value *GatherConstantSetEQs(Value *V, std::vector<ConstantInt*> &Values){
if (Instruction *Inst = dyn_cast<Instruction>(V))
if (Inst->getOpcode() == Instruction::SetEQ) {
if (Constant *C = dyn_cast<Constant>(Inst->getOperand(1))) {
if (ConstantInt *C = dyn_cast<ConstantInt>(Inst->getOperand(1))) {
Values.push_back(C);
return Inst->getOperand(0);
} else if (Constant *C = dyn_cast<Constant>(Inst->getOperand(0))) {
} else if (ConstantInt *C = dyn_cast<ConstantInt>(Inst->getOperand(0))) {
Values.push_back(C);
return Inst->getOperand(1);
}
@ -263,20 +263,20 @@ static Value *GatherConstantSetEQs(Value *V, std::vector<Constant*> &Values) {
// GatherConstantSetNEs - Given a potentially 'and'd together collection of
// setne instructions that compare a value against a constant, return the value
// being compared, and stick the constant into the Values vector.
static Value *GatherConstantSetNEs(Value *V, std::vector<Constant*> &Values) {
static Value *GatherConstantSetNEs(Value *V, std::vector<ConstantInt*> &Values){
if (Instruction *Inst = dyn_cast<Instruction>(V))
if (Inst->getOpcode() == Instruction::SetNE) {
if (Constant *C = dyn_cast<Constant>(Inst->getOperand(1))) {
if (ConstantInt *C = dyn_cast<ConstantInt>(Inst->getOperand(1))) {
Values.push_back(C);
return Inst->getOperand(0);
} else if (Constant *C = dyn_cast<Constant>(Inst->getOperand(0))) {
} else if (ConstantInt *C = dyn_cast<ConstantInt>(Inst->getOperand(0))) {
Values.push_back(C);
return Inst->getOperand(1);
}
} else if (Inst->getOpcode() == Instruction::Cast) {
// Cast of X to bool is really a comparison against zero.
assert(Inst->getType() == Type::BoolTy && "Can only handle bool values!");
Values.push_back(Constant::getNullValue(Inst->getOperand(0)->getType()));
Values.push_back(ConstantInt::get(Inst->getOperand(0)->getType(), 0));
return Inst->getOperand(0);
} else if (Inst->getOpcode() == Instruction::And) {
if (Value *LHS = GatherConstantSetNEs(Inst->getOperand(0), Values))
@ -293,7 +293,7 @@ static Value *GatherConstantSetNEs(Value *V, std::vector<Constant*> &Values) {
/// bunch of comparisons of one value against constants, return the value and
/// the constants being compared.
static bool GatherValueComparisons(Instruction *Cond, Value *&CompVal,
std::vector<Constant*> &Values) {
std::vector<ConstantInt*> &Values) {
if (Cond->getOpcode() == Instruction::Or) {
CompVal = GatherConstantSetEQs(Cond, Values);
@ -533,6 +533,17 @@ static bool FoldValueComparisonIntoPredecessors(TerminatorInst *TI) {
return Changed;
}
namespace {
/// ConstantIntOrdering - This class implements a stable ordering of constant
/// integers that does not depend on their address. This is important for
/// applications that sort ConstantInt's to ensure uniqueness.
struct ConstantIntOrdering {
bool operator()(const ConstantInt *LHS, const ConstantInt *RHS) const {
return LHS->getRawValue() < RHS->getRawValue();
}
};
}
// SimplifyCFG - This function is used to do simplification of a CFG. For
// example, it adjusts branches to branches to eliminate the extra hop, it
@ -952,12 +963,12 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
// If this is a bunch of seteq's or'd together, or if it's a bunch of
// 'setne's and'ed together, collect them.
Value *CompVal = 0;
std::vector<Constant*> Values;
std::vector<ConstantInt*> Values;
bool TrueWhenEqual = GatherValueComparisons(Cond, CompVal, Values);
if (CompVal && CompVal->getType()->isInteger()) {
// There might be duplicate constants in the list, which the switch
// instruction can't handle, remove them now.
std::sort(Values.begin(), Values.end());
std::sort(Values.begin(), Values.end(), ConstantIntOrdering());
Values.erase(std::unique(Values.begin(), Values.end()), Values.end());
// Figure out which block is which destination.