[llvm-dev] ROTR availability detected inconsistently

Harold Aptroot via llvm-dev llvm-dev at lists.llvm.org
Fri Jan 8 09:02:22 PST 2016


Hi,

Apologies for the bit of a repost, last time was in the holidays and
did not receive much attention.
In short, using isOperationLegalOrCustom(ISD::ROTR, VT) in
TargetLowering returns an inconsistent result.
The context of this is the optimization of divisibility tests, where a
test of the form "less than c and the k lowest bits are zero" is used,
which can be rolled into one test by using a right rotate by k.
The attached path dumps the result of the ROTR check in err() in a
kind of lame way. It can prints things such as
HasROTR: 0
HasROTR: 1
HasROTR: 0
HasROTR: 1
HasROTR: 1
HasROTR: 0
HasROTR: 1
Which I find very odd, the legality of an instruction shouldn't be
changing like that, right?
What's going on and what should I do about it in the context of what I
am trying to do?

Regards,
Harold
-------------- next part --------------
Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/TargetLowering.cpp	(revision 256471)
+++ lib/CodeGen/SelectionDAG/TargetLowering.cpp	(working copy)
@@ -1790,6 +1790,42 @@
         }
       }
     }
+
+    if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
+        C1.isMinValue() &&
+        N0.getOpcode() == ISD::UREM &&
+        N0.hasOneUse()) {
+      if (ConstantSDNode *RemRHS =
+            dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
+        const APInt &RemRHSC = RemRHS->getAPIntValue();
+        if (!RemRHSC.isPowerOf2()) {
+          bool HasROTR = isOperationLegalOrCustom(ISD::ROTR, VT);
+          errs() << "HasROTR: " << HasROTR << "\n";
+          auto &DL = DAG.getDataLayout();
+          auto Ty = N0.getValueType();
+          auto shTy = getShiftAmountTy(Ty, DL);
+          auto NewCond = (Cond == ISD::SETEQ) ? ISD::SETULE : ISD::SETUGE;
+          unsigned rotAmt = RemRHSC.countTrailingZeros();
+          unsigned W = Ty.getSizeInBits();
+          APInt Mod(W + 1, 0);
+          Mod.setBit(W);
+          APInt Inverse = RemRHSC.lshr(rotAmt).zext(W + 1)
+                          .multiplicativeInverse(Mod).trunc(W);
+          APInt Maxval = APInt::getMaxValue(W).udiv(RemRHSC);
+          SDValue Max = DAG.getConstant(Maxval, dl, Ty);
+          SDValue Mul = DAG.getNode(ISD::MUL, dl, Ty, N0.getOperand(0),
+                                    DAG.getConstant(Inverse, dl, Ty));
+          if (rotAmt && HasROTR) {
+            SDValue Ror = DAG.getNode(ISD::ROTR, dl, Ty, Mul,
+                                      DAG.getConstant(rotAmt, dl, shTy));
+            return DAG.getSetCC(dl, VT, Ror, Max, NewCond);
+          }
+          else if (!rotAmt) {
+            return DAG.getSetCC(dl, VT, Mul, Max, NewCond);
+          }
+        }
+      }
+    }
   }
 
   if (isa<ConstantFPSDNode>(N0.getNode())) {


More information about the llvm-dev mailing list