[PATCH] D105209: [WIP][SCEVExpander] Discount cost of umin(x,1) expressions

Philip Reames via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 30 09:51:05 PDT 2021


reames created this revision.
Herald added subscribers: javed.absar, bollu, hiraditya, mcrosier.
reames requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

(This needs tests, doing that is currently a pain since we don't have a way to exercise SCEVExpander independently.)

umin(x,1) reduces to checking if x != 0 as the expression can only be zero if x == 0.  As a result, there's a cheaper, not select, form available for lowering.  This allows LFTR to trigger in more cases with an upcoming change to howManyLessThans in SCEV.


https://reviews.llvm.org/D105209

Files:
  llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp


Index: llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
===================================================================
--- llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -1815,6 +1815,33 @@
 }
 
 Value *SCEVExpander::visitUMinExpr(const SCEVUMinExpr *S) {
+  if (llvm::any_of(S->operands(), [](const SCEV* S) {
+        return S->getType()->isIntegerTy() && S->isOne();
+      })) {
+    SmallVector<Value*> Ops;
+    for (const SCEV *Op : S->operands()) {
+      if (S->getType()->isIntegerTy() && S->isOne())
+        continue;
+      Type *Ty = Op->getType();
+      if (!Ty->isIntegerTy()) {
+        Ty = SE.getEffectiveSCEVType(Ty);
+      }
+      Value *V = expandCodeForImpl(Op, Ty, false);
+      Ops.emplace_back(V);
+    }
+    assert(!Ops.empty() && "should have constant folded?");    
+    Type *Ty = Ops[0]->getType();
+    Value *Reduce = Builder.CreateAnd(Ops);
+    Value *Zero = ConstantInt::get(Ty, 0);
+    Value *Cmp = Builder.CreateICmpNE(Reduce, Zero);
+    Value *Res = Builder.CreateZExt(Cmp, Ty);
+    // In the case of mixed integer and pointer types, cast the
+    // final result back to the pointer type.
+    if (Res->getType() != S->getType())
+      Res = InsertNoopCastOfTo(Res, S->getType());
+    return Res;
+  } 
+  
   Value *LHS = expand(S->getOperand(S->getNumOperands() - 1));
   Type *Ty = LHS->getType();
   for (int i = S->getNumOperands() - 2; i >= 0; --i) {
@@ -2308,10 +2335,22 @@
     // see SCEVExpander::visitMulExpr(), ExpandOpBinPowN().
     Cost = ArithCost(Instruction::Mul, S->getNumOperands() - 1);
     break;
+  case scUMinExpr:
+    // umin(x1, x2, ..., xn, 1) is zero if any x1..xn is zero, and one
+    // otherwise.  This is equivalent to zext(icmp ne and_reduce(x1..xn), 0).
+    if (llvm::any_of(S->operands(), [](const SCEV *S) {
+          return S->getType()->isIntegerTy() && S->isOne();
+        })) {
+      if (S->getNumOperands() > 2)
+        Cost = ArithCost(Instruction::And, S->getNumOperands() - 2);
+      Cost += CmpSelCost(Instruction::ICmp, 2, 0, 1);
+      Cost = CastCost(Instruction::ZExt);
+      break;
+    }
+    LLVM_FALLTHROUGH;
   case scSMaxExpr:
   case scUMaxExpr:
-  case scSMinExpr:
-  case scUMinExpr: {
+  case scSMinExpr: {
     // FIXME: should this ask the cost for Intrinsic's?
     Cost += CmpSelCost(Instruction::ICmp, S->getNumOperands() - 1, 0, 1);
     Cost += CmpSelCost(Instruction::Select, S->getNumOperands() - 1, 0, 2);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D105209.355604.patch
Type: text/x-patch
Size: 2513 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210630/e917d331/attachment.bin>


More information about the llvm-commits mailing list