Bug 1577263: Use memcmp for nsID::Equals. r=froydnj
authorKris Maglione <maglione.k@gmail.com>
Wed, 28 Aug 2019 19:08:44 +0000
changeset 554231 3e2987e01215fb9ce600074886866766da1444dd
parent 554230 0e3a4fb87da3b39e3a15ddb9e8dd6de42f9fd1c9
child 554232 be7cbc61f825fdfc36b20d476bef710ef275ad73
push id2165
push userffxbld-merge
push dateMon, 14 Oct 2019 16:30:58 +0000
treeherdermozilla-release@0eae18af659f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1577263
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1577263: Use memcmp for nsID::Equals. r=froydnj Compilers have gotten a lot better since the last time we tried this, and the generated SIMD code for the inlined memcmp is more efficient than our manual comparison operations. Differential Revision: https://phabricator.services.mozilla.com/D43802
xpcom/base/nsID.h
--- a/xpcom/base/nsID.h
+++ b/xpcom/base/nsID.h
@@ -40,21 +40,31 @@ struct nsID {
   void Clear();
 
   /**
    * Equivalency method. Compares this nsID with another.
    * @return <b>true</b> if they are the same, <b>false</b> if not.
    */
 
   inline bool Equals(const nsID& aOther) const {
-    // Unfortunately memcmp isn't faster than this.
+    // At the time of this writing, modern compilers (namely Clang) inline this
+    // memcmp call into a single SIMD operation on x86/x86-64 architectures (as
+    // long as we compare to zero rather than returning the full integer return
+    // value), which is measurably more efficient to any manual comparisons we
+    // can do directly.
+#if defined(__x86_64__) || defined(__i386__)
+    return !memcmp(this, &aOther, sizeof *this);
+#else
+    // However, on ARM architectures, compilers still tend to generate a direct
+    // memcmp call, which we'd like to avoid.
     return (((uint32_t*)&m0)[0] == ((uint32_t*)&aOther.m0)[0]) &&
            (((uint32_t*)&m0)[1] == ((uint32_t*)&aOther.m0)[1]) &&
            (((uint32_t*)&m0)[2] == ((uint32_t*)&aOther.m0)[2]) &&
            (((uint32_t*)&m0)[3] == ((uint32_t*)&aOther.m0)[3]);
+#endif
   }
 
   inline bool operator==(const nsID& aOther) const { return Equals(aOther); }
 
   /**
    * nsID Parsing method. Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
    * string into an nsID
    */