[PATCH] D86843: [EarlyCSE] Equivalent SELECTs should hash equally

Bryan Chan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 29 15:39:46 PDT 2020


bryanpkc created this revision.
bryanpkc added reviewers: spatel, efriedma, JosephTremoulet.
Herald added subscribers: llvm-commits, danielkiss, hiraditya.
Herald added a project: LLVM.
bryanpkc requested review of this revision.

DenseMap<SimpleValue> assumes that, if its isEqual method returns true
for two elements, then its getHashValue method must return the same value
for them. This invariant is broken when one SELECT node is a min/max
operation, and the other can be transformed into an equivalent min/max by
inverting its predicate and swapping its operands. This patch adds logic
to getHashValueImpl to ensure that the same value is returned for both
elements in this case, and fixes an assertion failure that would occur
intermittently while compiling the following IR:

  define i32 @t(i32 %i) {
    %cmp = icmp sle i32 0, %i
    %twin1 = select i1 %cmp, i32 %i, i32 0
    %cmpinv = icmp sgt i32 0, %i
    %twin2 = select i1 %cmpinv,  i32 0, i32 %i
    %sink = add i32 %twin1, %twin2
    ret i32 %sink
  }


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D86843

Files:
  llvm/lib/Transforms/Scalar/EarlyCSE.cpp


Index: llvm/lib/Transforms/Scalar/EarlyCSE.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -258,6 +258,24 @@
     if (!match(Cond, m_Cmp(Pred, m_Value(X), m_Value(Y))))
       return hash_combine(Inst->getOpcode(), Cond, A, B);
 
+    // Prefer to hash the select as a min/max if possible.
+    CmpInst::Predicate InvPred = CmpInst::getInversePredicate(Pred);
+    if (X == B && Y == A) {
+      switch (InvPred) {
+      case CmpInst::ICMP_UGT: SPF = SPF_UMAX; break;
+      case CmpInst::ICMP_ULT: SPF = SPF_UMIN; break;
+      case CmpInst::ICMP_SGT: SPF = SPF_SMAX; break;
+      case CmpInst::ICMP_SLT: SPF = SPF_SMIN; break;
+      default: break;
+      }
+      if (SPF == SPF_SMIN || SPF == SPF_SMAX ||
+          SPF == SPF_UMIN || SPF == SPF_UMAX) {
+        if (A > B)
+          std::swap(A, B);
+        return hash_combine(Inst->getOpcode(), SPF, A, B);
+      }
+    }
+
     // Similar to cmp normalization (above) - canonicalize the predicate value:
     // select (icmp Pred, X, Y), A, B --> select (icmp InvPred, X, Y), B, A
     if (CmpInst::getInversePredicate(Pred) < Pred) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D86843.288815.patch
Type: text/x-patch
Size: 1214 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200829/de4a7f3f/attachment.bin>


More information about the llvm-commits mailing list