[llvm] r226531 - IR: Detect whether to call recalculateHash() via SFINAE, NFC

Duncan P. N. Exon Smith dexonsmith at apple.com
Mon Jan 19 16:57:33 PST 2015


Author: dexonsmith
Date: Mon Jan 19 18:57:33 2015
New Revision: 226531

URL: http://llvm.org/viewvc/llvm-project?rev=226531&view=rev
Log:
IR: Detect whether to call recalculateHash() via SFINAE, NFC

Rather than relying on updating switch statements correctly, detect
whether `setHash()` exists in the subclass.  If so, call
`recalculateHash()` and `setHash(0)` appropriately.

Modified:
    llvm/trunk/include/llvm/IR/Metadata.h
    llvm/trunk/lib/IR/Metadata.cpp

Modified: llvm/trunk/include/llvm/IR/Metadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=226531&r1=226530&r2=226531&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Metadata.h (original)
+++ llvm/trunk/include/llvm/IR/Metadata.h Mon Jan 19 18:57:33 2015
@@ -825,6 +825,20 @@ private:
   MDNode *uniquify();
   void eraseFromStore();
 
+  template <class NodeTy> struct HasCachedHash;
+  template <class NodeTy>
+  static void dispatchRecalculateHash(NodeTy *N, std::true_type) {
+    N->recalculateHash();
+  }
+  template <class NodeTy>
+  static void dispatchRecalculateHash(NodeTy *N, std::false_type) {}
+  template <class NodeTy>
+  static void dispatchResetHash(NodeTy *N, std::true_type) {
+    N->setHash(0);
+  }
+  template <class NodeTy>
+  static void dispatchResetHash(NodeTy *N, std::false_type) {}
+
 public:
   typedef const MDOperand *op_iterator;
   typedef iterator_range<op_iterator> op_range;

Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=226531&r1=226530&r2=226531&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Mon Jan 19 18:57:33 2015
@@ -620,26 +620,31 @@ static T *uniquifyImpl(T *N, DenseSet<T
   return N;
 }
 
-MDNode *MDNode::uniquify() {
-  // Recalculate hash, if necessary.
-  switch (getMetadataID()) {
-  default:
-    break;
-  case MDTupleKind:
-    cast<MDTuple>(this)->recalculateHash();
-    break;
-  case GenericDwarfNodeKind:
-    cast<GenericDwarfNode>(this)->recalculateHash();
-    break;
-  }
+template <class NodeTy> struct MDNode::HasCachedHash {
+  typedef char Yes[1];
+  typedef char No[2];
+  template <class U, U Val> struct SFINAE {};
+
+  template <class U>
+  static Yes &check(SFINAE<void (U::*)(unsigned), &U::setHash> *);
+  template <class U> static No &check(...);
+
+  static const bool value = sizeof(check<NodeTy>(nullptr)) == sizeof(Yes);
+};
 
+MDNode *MDNode::uniquify() {
   // Try to insert into uniquing store.
   switch (getMetadataID()) {
   default:
     llvm_unreachable("Invalid subclass of MDNode");
 #define HANDLE_MDNODE_LEAF(CLASS)                                              \
-  case CLASS##Kind:                                                            \
-    return uniquifyImpl(cast<CLASS>(this), getContext().pImpl->CLASS##s);
+  case CLASS##Kind: {                                                          \
+    CLASS *SubclassThis = cast<CLASS>(this);                                   \
+    std::integral_constant<bool, HasCachedHash<CLASS>::value>                  \
+        ShouldRecalculateHash;                                                 \
+    dispatchRecalculateHash(SubclassThis, ShouldRecalculateHash);              \
+    return uniquifyImpl(SubclassThis, getContext().pImpl->CLASS##s);           \
+  }
 #include "llvm/IR/Metadata.def"
   }
 }
@@ -774,10 +779,20 @@ void MDNode::deleteTemporary(MDNode *N)
 void MDNode::storeDistinctInContext() {
   assert(isResolved() && "Expected resolved nodes");
   Storage = Distinct;
-  if (auto *T = dyn_cast<MDTuple>(this))
-    T->setHash(0);
-  else if (auto *G = dyn_cast<GenericDwarfNode>(this))
-    G->setHash(0);
+
+  // Reset the hash.
+  switch (getMetadataID()) {
+  default:
+    llvm_unreachable("Invalid subclass of MDNode");
+#define HANDLE_MDNODE_LEAF(CLASS)                                              \
+  case CLASS##Kind: {                                                          \
+    std::integral_constant<bool, HasCachedHash<CLASS>::value> ShouldResetHash; \
+    dispatchResetHash(cast<CLASS>(this), ShouldResetHash);                     \
+    break;                                                                     \
+  }
+#include "llvm/IR/Metadata.def"
+  }
+
   getContext().pImpl->DistinctMDNodes.insert(this);
 }
 





More information about the llvm-commits mailing list