[PATCH] D17921: [CorrelatedValuePropagation] Convert an SDiv to a UDiv if both operands are known to be nonnegative

Haicheng Wu via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 6 17:50:34 PST 2016


haicheng created this revision.
haicheng added reviewers: mcrosier, gberry, mssimpso, sanjoy, reames.
haicheng added a subscriber: llvm-commits.
haicheng set the repository for this revision to rL LLVM.
Herald added a subscriber: mcrosier.

The motivating example is this 


```
for (j = n; j > 1; j = i) {
   i = j / 2;
}
```

The signed division is safely to be changed to an unsigned division (j is known to be larger than 1 from the loop guard) and later turned into a shift.  LLVM currently cannot figure it out and translates the division into at least 3 instructions.

Repository:
  rL LLVM

http://reviews.llvm.org/D17921

Files:
  lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
  test/Transforms/CorrelatedValuePropagation/sdiv.ll

Index: test/Transforms/CorrelatedValuePropagation/sdiv.ll
===================================================================
--- /dev/null
+++ test/Transforms/CorrelatedValuePropagation/sdiv.ll
@@ -0,0 +1,21 @@
+; RUN: opt < %s -correlated-propagation -S | FileCheck %s
+
+; CHECK-LABEL: @test(
+define void @test(i32 %n, i32* nocapture %p) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %j.0 = phi i32 [ %n, %entry ], [ %div, %for.body ]
+  %cmp = icmp sgt i32 %j.0, 1
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %cmp1 = icmp sgt i32 %j.0, 0
+; CHECK: %div1 = udiv i32 %j.0, 2 
+  %div = sdiv i32 %j.0, 2
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
Index: lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
===================================================================
--- lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -35,6 +35,7 @@
 STATISTIC(NumCmps,      "Number of comparisons propagated");
 STATISTIC(NumReturns,   "Number of return values propagated");
 STATISTIC(NumDeadCases, "Number of switch cases removed");
+STATISTIC(NumSDivs,     "Number of sdiv propagated");
 
 namespace {
   class CorrelatedValuePropagation : public FunctionPass {
@@ -46,6 +47,7 @@
     bool processCmp(CmpInst *C);
     bool processSwitch(SwitchInst *SI);
     bool processCallSite(CallSite CS);
+    bool processSDiv(BinaryOperator *SDI);
 
     /// Return a constant value for V usable at At and everything it
     /// dominates.  If no such Constant can be found, return nullptr.
@@ -337,6 +339,41 @@
   return true;
 }
 
+/// processSDiv - See if LazyValueInfo's ability to exploit edge conditions,
+/// or range information is sufficient to prove the both operands of this SDiv
+/// are nonnegative.  If this is the case, replace the SDiv with a UDiv. Even
+/// for local conditions, this can sometimes prove conditions instcombine can't
+/// by exploiting range information.
+bool CorrelatedValuePropagation::processSDiv(BinaryOperator *SDI) {
+  if (!SDI->getType()->isIntegerTy())
+    return false;
+
+  for (Value *O : SDI->operands()) {
+    // As a policy choice, we choose not to waste compile time on anything where
+    // the operands are local defs.  While LVI can sometimes reason about such
+    // cases, it's not its primary purpose.
+    auto *I = dyn_cast<Instruction>(O);
+    if (I && I->getParent() == SDI->getParent())
+      return false;
+  }
+
+  for (Value *O : SDI->operands()) {
+    LazyValueInfo::Tristate Result = LVI->getPredicateAt(
+        ICmpInst::ICMP_SGT, O, ConstantInt::get(O->getType(), 0), SDI);
+    if (Result != LazyValueInfo::True)
+      return false;
+  }
+
+  ++NumSDivs;
+  auto *BO = BinaryOperator::CreateUDiv(SDI->getOperand(0), SDI->getOperand(1),
+                                        SDI->getName(), SDI);
+  BO->setIsExact(SDI->isExact());
+  SDI->replaceAllUsesWith(BO);
+  SDI->eraseFromParent();
+
+  return true;
+}
+
 Constant *CorrelatedValuePropagation::getConstantAt(Value *V, Instruction *At) {
   if (Constant *C = LVI->getConstant(V, At->getParent(), At))
     return C;
@@ -391,6 +428,9 @@
       case Instruction::Invoke:
         BBChanged |= processCallSite(CallSite(II));
         break;
+      case Instruction::SDiv:
+        BBChanged |= processSDiv(cast<BinaryOperator>(II));
+        break;
       }
     }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D17921.49927.patch
Type: text/x-patch
Size: 3574 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160307/2684c527/attachment.bin>


More information about the llvm-commits mailing list