Do not sort by the address of LLVM ConstantInt* objects. This produces
authorChris Lattner <sabre@nondot.org>
Sat, 19 Jun 2004 07:02:14 +0000 (07:02 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 19 Jun 2004 07:02:14 +0000 (07:02 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14243 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/SimplifyCFG.cpp

index 446bad88f7514ebb0b7e0f1696949fd255431e03..a0c86fea4fe6ec88ef633eee1932583ccb0c9b80 100644 (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.