From 1654cff8e80acdddf5e5f2261595007878924aac Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 19 Jun 2004 07:02:14 +0000 Subject: [PATCH] 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 ] ; [#uses=5] %tmp.1 = load sbyte* %s_addr.1 ; [#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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14243 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/SimplifyCFG.cpp | 31 +++++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 446bad88f75..a0c86fea4fe 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -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 &Values) { +static Value *GatherConstantSetEQs(Value *V, std::vector &Values){ if (Instruction *Inst = dyn_cast(V)) if (Inst->getOpcode() == Instruction::SetEQ) { - if (Constant *C = dyn_cast(Inst->getOperand(1))) { + if (ConstantInt *C = dyn_cast(Inst->getOperand(1))) { Values.push_back(C); return Inst->getOperand(0); - } else if (Constant *C = dyn_cast(Inst->getOperand(0))) { + } else if (ConstantInt *C = dyn_cast(Inst->getOperand(0))) { Values.push_back(C); return Inst->getOperand(1); } @@ -263,20 +263,20 @@ static Value *GatherConstantSetEQs(Value *V, std::vector &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 &Values) { +static Value *GatherConstantSetNEs(Value *V, std::vector &Values){ if (Instruction *Inst = dyn_cast(V)) if (Inst->getOpcode() == Instruction::SetNE) { - if (Constant *C = dyn_cast(Inst->getOperand(1))) { + if (ConstantInt *C = dyn_cast(Inst->getOperand(1))) { Values.push_back(C); return Inst->getOperand(0); - } else if (Constant *C = dyn_cast(Inst->getOperand(0))) { + } else if (ConstantInt *C = dyn_cast(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 &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 &Values) { + std::vector &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 Values; + std::vector 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.