[PATCH] D34207: [IndVarSimplify] Add AShr exact flags using induction variables ranges.

Sanjoy Das via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 20 10:03:36 PDT 2017


sanjoy requested changes to this revision.
sanjoy added inline comments.
This revision now requires changes to proceed.


================
Comment at: lib/Transforms/Utils/SimplifyIndVar.cpp:529
+  // match (X << IVOperand) >> C, marking the AShr as exact using the
+  // information from the IV's range
+  if(BO->getOpcode() == Instruction::Shl) {
----------------
Please clang-format the change.


================
Comment at: lib/Transforms/Utils/SimplifyIndVar.cpp:532
+    bool Changed = false;
+    for(auto* user : BO->users()) {
+      BinaryOperator* AShr = dyn_cast<BinaryOperator>(user);
----------------
LLVM style is `auto *User` or `auto *U` (I prefer the latter since there is also a `llvm::User`).


================
Comment at: lib/Transforms/Utils/SimplifyIndVar.cpp:535
+      if(!AShr || AShr->getOpcode() != Instruction::AShr ||
+          AShr->getOperand(0) != BO || AShr->isExact())
+        continue;
----------------
Use `llvm::PatternMatch` here.  You can then fold in the `dyn_cast<ConstantInt>(AShr->getOperand(1))` check into the same patternmatch expression.

If you do the `dyn_cast<ConstantInt>(AShr->getOperand(1))` check, then the `AShr->getOperand(0) != BO` check should not be necessary.


================
Comment at: lib/Transforms/Utils/SimplifyIndVar.cpp:542
+      if(ShlOp1 == IVOperand || !BO->getType()->isIntegerTy() ||
+          IVRange.getUpper().uge(BO->getType()->getPrimitiveSizeInBits()))
+        continue;
----------------
Do you really mean `getUpper` or do you want `getUnsignedMax`?

Secondly, `BO` will always be an integer (as opposed to a vector of integers); since the induction variable is an integer.

Thirdly, if I'm not missing something, the `IVRange.getUpper().uge(BO->getType()->getPrimitiveSizeInBits())` check should be unnecessary.  If the IV is larger than the bitwidth then `BO` is poison, and so is `AShr` (and making it exact does not make it any more poison).


================
Comment at: lib/Transforms/Utils/SimplifyIndVar.cpp:545
+
+      ConstantInt* AShrOp2 = dyn_cast<ConstantInt>(AShr->getOperand(1));
+      if(!AShrOp2 || IVRange.getLower().ult(AShrOp2->getValue()))
----------------
In cases like this, I think a more indented version is easier to read:

```
if (IVOperand == BO->getOperand(1) && IVMax.ult(BitWidth))
  if (auto *AShrCI = dyn_cast<ConstantInt>(AShr->getOperand(1))
    if (IVMin.uge(AShrOp2->getValue()) {
      AShr->setIsExact(true);
      Changed = true;
    }
```



================
Comment at: lib/Transforms/Utils/SimplifyIndVar.cpp:546
+      ConstantInt* AShrOp2 = dyn_cast<ConstantInt>(AShr->getOperand(1));
+      if(!AShrOp2 || IVRange.getLower().ult(AShrOp2->getValue()))
+        continue;
----------------
Perhaps you need `IVRange.getUnsignedMin()` instead of `IVRange.getLower()`?


================
Comment at: test/Transforms/IndVarSimplify/strengthen-overflow.ll:116
+  %shl = shl i32 1, %k.021
+  %shr = ashr i32 %shl, 1
+; CHECK: %shr = ashr exact i32 %shl, 1
----------------
Add a few more tests here, check that

 - We don't do this transform when illegal (e.g. `shl` by 2, `ashr` by 3).
 - We do the transform when the `shl` amount is strictly greater than the `ashr` amount
 - If I'm right about `shl` ing more than the bitwidth amount above, then please add a test case that checks that situation.


================
Comment at: test/Transforms/IndVarSimplify/strengthen-overflow.ll:123
+  %0 = load i32, i32* %arrayidx, align 4
+  %1 = load i32, i32* %arrayidx1, align 4
+  %sub = sub nsw i32 %1, %0
----------------
I think most of the load/store stuff here can be pruned.


https://reviews.llvm.org/D34207





More information about the llvm-commits mailing list