Subzero: Deterministically sort constant pool entries.

Otherwise, constant pools are emitted in hash table order, which can vary across systems.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4129
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/1069453003
diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp
index c710edf..1c9e3c4 100644
--- a/src/IceGlobalContext.cpp
+++ b/src/IceGlobalContext.cpp
@@ -64,6 +64,54 @@
   }
 };
 
+// Define a key comparison function for sorting the constant pool's
+// values after they are dumped to a vector.  This covers integer
+// types, floating point types, and ConstantRelocatable values.
+template <typename ValueType, class Enable = void> struct KeyCompareLess {};
+
+template <typename ValueType>
+struct KeyCompareLess<ValueType,
+                      typename std::enable_if<std::is_floating_point<
+                          typename ValueType::PrimType>::value>::type> {
+  bool operator()(const Constant *Const1, const Constant *Const2) const {
+    typedef uint64_t CompareType;
+    static_assert(sizeof(typename ValueType::PrimType) <= sizeof(CompareType),
+                  "Expected floating-point type of width 64-bit or less");
+    typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
+    typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
+    // We avoid "V1<V2" because of NaN.
+    // We avoid "memcmp(&V1,&V2,sizeof(V1))<0" which depends on the
+    // endian-ness of the host system running Subzero.
+    // Instead, compare the result of bit_cast to uint64_t.
+    uint64_t I1 = 0, I2 = 0;
+    memcpy(&I1, &V1, sizeof(V1));
+    memcpy(&I2, &V2, sizeof(V2));
+    return I1 < I2;
+  }
+};
+template <typename ValueType>
+struct KeyCompareLess<ValueType,
+                      typename std::enable_if<std::is_integral<
+                          typename ValueType::PrimType>::value>::type> {
+  bool operator()(const Constant *Const1, const Constant *Const2) const {
+    typename ValueType::PrimType V1 = llvm::cast<ValueType>(Const1)->getValue();
+    typename ValueType::PrimType V2 = llvm::cast<ValueType>(Const2)->getValue();
+    return V1 < V2;
+  }
+};
+template <typename ValueType>
+struct KeyCompareLess<
+    ValueType, typename std::enable_if<
+                   std::is_same<ValueType, ConstantRelocatable>::value>::type> {
+  bool operator()(const Constant *Const1, const Constant *Const2) const {
+    auto V1 = llvm::cast<ValueType>(Const1);
+    auto V2 = llvm::cast<ValueType>(Const2);
+    if (V1->getName() == V2->getName())
+      return V1->getOffset() < V2->getOffset();
+    return V1->getName() < V2->getName();
+  }
+};
+
 // TypePool maps constants of type KeyType (e.g. float) to pointers to
 // type ValueType (e.g. ConstantFloat).
 template <Type Ty, typename KeyType, typename ValueType> class TypePool {
@@ -85,6 +133,10 @@
     Constants.reserve(Pool.size());
     for (auto &I : Pool)
       Constants.push_back(I.second);
+    // The sort (and its KeyCompareLess machinery) is not strictly
+    // necessary, but is desirable for producing output that is
+    // deterministic across unordered_map::iterator implementations.
+    std::sort(Constants.begin(), Constants.end(), KeyCompareLess<ValueType>());
     return Constants;
   }
 
diff --git a/tests_lit/llvm2ice_tests/elf_container.ll b/tests_lit/llvm2ice_tests/elf_container.ll
index aff0cf5..f95ed2a 100644
--- a/tests_lit/llvm2ice_tests/elf_container.ll
+++ b/tests_lit/llvm2ice_tests/elf_container.ll
@@ -330,7 +330,7 @@
 ; CHECK:     AddressAlignment: 8
 ; CHECK:     EntrySize: 8
 ; CHECK:     SectionData (
-; CHECK:       0000: 03000000 0000F8FF FFFFFFFF FFFFF7FF
+; CHECK:       0000: FFFFFFFF FFFFF7FF 03000000 0000F8FF
 ; CHECK:       0010: FFFFFFFF FFFFFFFF
 ; CHECK:     )
 ; CHECK:   }
@@ -429,7 +429,7 @@
 ; CHECK-NEXT:   }
 ; CHECK:        Symbol {
 ; CHECK:          Name: .L$double$2
-; CHECK-NEXT:     Value: 0x0
+; CHECK-NEXT:     Value: 0x8
 ; CHECK-NEXT:     Size: 0
 ; CHECK-NEXT:     Binding: Local (0x0)
 ; CHECK-NEXT:     Type: None (0x0)