[PATCH] D50222: [CodeGen] [SelectionDAG] More efficient code for X % C == 0 (UREM case)
Roman Lebedev via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 30 04:47:05 PDT 2018
lebedev.ri added a comment.
Starting to look much better. Some more nits.
================
Comment at: lib/CodeGen/SelectionDAG/TargetLowering.cpp:3727
+ const SDLoc &DL) const {
+ // fold (seteq/ne (urem N, D), 0) -> (setule/gte (rotr (mul N, P), K), Q)
+ // - D must be constant with D = D0 * 2^K where D0 is odd
----------------
```
assert((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
"Only applicable for [in]equality comparisons.");
```
================
Comment at: lib/CodeGen/SelectionDAG/TargetLowering.cpp:3727
+ const SDLoc &DL) const {
+ // fold (seteq/ne (urem N, D), 0) -> (setule/gte (rotr (mul N, P), K), Q)
+ // - D must be constant with D = D0 * 2^K where D0 is odd
----------------
lebedev.ri wrote:
> ```
> assert((Cond == ISD::SETEQ || Cond == ISD::SETNE) &&
> "Only applicable for [in]equality comparisons.");
> ```
```
// fold (seteq/ne (urem N, D), 0) -> (setule/ugt (rotr (mul N, P), K), Q)
```
(it would be great to use more descriptive names to differentiate between `C`onstants and not constants, too)
================
Comment at: lib/CodeGen/SelectionDAG/TargetLowering.cpp:3749
+
+ // Rewrite D = D0 * 2^K
+ unsigned K = D.countTrailingZeros();
----------------
```
// Decompose D into D0 * 2^K
```
================
Comment at: lib/CodeGen/SelectionDAG/TargetLowering.cpp:3750
+ // Rewrite D = D0 * 2^K
+ unsigned K = D.countTrailingZeros();
+ APInt D0 = D.lshr(K);
----------------
```
bool DivisorIsEven = K != 0;
```
================
Comment at: lib/CodeGen/SelectionDAG/TargetLowering.cpp:3753-3755
+ // If D0 == 1, we cannot build this fold. Otherwise, D0 > 1, as needed.
+ if (D0.isOneValue())
+ return SDValue();
----------------
So what we are really checking here, is that `D` is not power of two.
How about simplifying this into:
```
APInt D = Divisor->getAPIntValue();
unsigned W = D.getBitWidth();
// If D is power of two, D0 would be 1, and we cannot build this fold.
if(D.isPowerOf2())
return SDValue();
// Decompose D into D0 * 2^K
...
```
BUT. I do not understand from where does this requirement comes from?
Can you quote specific part of [[ https://doc.lagout.org/security/Hackers%20Delight.pdf | `10–17 Test for Zero Remainder after Division by a Constant` ]] that warrants this?
================
Comment at: lib/CodeGen/SelectionDAG/TargetLowering.cpp:3757-3761
+ // Calculate the multiplicative inverse P of D0 using Newton's method.
+ APInt tmp;
+ APInt P = D0;
+ while ((tmp = D0 * P) != 1)
+ P *= APInt(D0.getBitWidth(), 2) - tmp;
----------------
Would [[ http://llvm.org/doxygen/classllvm_1_1APInt.html#a28ee15b0286415cce5599d4fb9f9ce02 | `APInt::multiplicativeInverse()` ]] work here?
================
Comment at: lib/CodeGen/SelectionDAG/TargetLowering.cpp:3764-3765
+ // Q = floor((2^W - 1) / D0)
+ APInt Q = APInt::getAllOnesValue(W);
+ Q = Q.udiv(D0);
+
----------------
I would think just writing this as one line would be as clean
```
APInt Q = APInt::getAllOnesValue(W).udiv(D0);
```
================
Comment at: lib/CodeGen/SelectionDAG/TargetLowering.cpp:3771
+ SDValue Op1 = DAG.getNode(ISD::MUL, DL, REMVT, REMNode->getOperand(0), PVal);
+ DCI.AddToWorklist(Op1.getNode());
+ // Will change in the signed case
----------------
I do not know if this is needed?
At least rL338079 removed such a call.
================
Comment at: lib/CodeGen/SelectionDAG/TargetLowering.cpp:3776
+ // Rotate right only if D was even and thus shifted (K > 0)
+ if (K) {
+ SDValue ShAmt =
----------------
```
if(DivisorIsEven) {
```
Repository:
rL LLVM
https://reviews.llvm.org/D50222
More information about the llvm-commits
mailing list