[PATCH] [SCEV] Extract and strengthen isHighCostExpansion.

Justin Bogner mail at justinbogner.com
Sun Apr 12 00:29:08 PDT 2015


Sanjoy Das <sanjoy at playingwithpointers.com> writes:
> Hi atrick,
>
>   1. extract `isHighCostExpansion` from IndVarSimplify into
>      SCEVExpander. This part is NFC.
>
>   2. teach `isHighCostExpansion` to consider divisions by power-of-two
>      constants as cheap.

It's kind of nice to move code in a separate change from updating it, so
that it's easier to see what actually changed.

> A test case is added for (2).  (2) is needed for a new user of
> `isHighCostExpansion` that will be added in a subsequent change.
>
> http://reviews.llvm.org/D8993
>
> Files:
>   include/llvm/Analysis/ScalarEvolutionExpander.h
>   lib/Analysis/ScalarEvolutionExpander.cpp
>   lib/Transforms/Scalar/IndVarSimplify.cpp
>   test/Transforms/IndVarSimplify/lftr-udiv-tripcount.ll
>
> EMAIL PREFERENCES
>   http://reviews.llvm.org/settings/panel/emailpreferences/
>
> Index: include/llvm/Analysis/ScalarEvolutionExpander.h
> ===================================================================
> --- include/llvm/Analysis/ScalarEvolutionExpander.h
> +++ include/llvm/Analysis/ScalarEvolutionExpander.h
> @@ -116,6 +116,13 @@
>        ChainedPhis.clear();
>      }
>  
> +    /// isHighCostExpansion - Return true for expressions that may incur
> +    /// non-trivial cost to evaluate at runtime.

We don't usually repeat the function name in the doc comment for new
code.

> +    bool isHighCostExpansion(const SCEV *Expr, Loop *L) {
> +      SmallPtrSet<const SCEV *, 8> Processed;
> +      return isHighCostExpansionHelper(Expr, L, Processed);
> +    }
> +
>      /// getOrInsertCanonicalInductionVariable - This method returns the
>      /// canonical induction variable of the specified type for the specified
>      /// loop (inserting one if there is none).  A canonical induction variable
> @@ -192,6 +199,11 @@
>    private:
>      LLVMContext &getContext() const { return SE.getContext(); }
>  
> +    /// isHighCostExpansionHelper - Recursive helper function for
> +    /// isHighCostExpansion.
> +    bool isHighCostExpansionHelper(const SCEV *S, Loop *L,
> +                                   SmallPtrSetImpl<const SCEV *> &Processed);
> +
>      /// InsertBinop - Insert the specified binary operator, doing a small amount
>      /// of work to avoid inserting an obviously redundant operation.
>      Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS);
> Index: lib/Analysis/ScalarEvolutionExpander.cpp
> ===================================================================
> --- lib/Analysis/ScalarEvolutionExpander.cpp
> +++ lib/Analysis/ScalarEvolutionExpander.cpp
> @@ -23,6 +23,7 @@
>  #include "llvm/IR/Dominators.h"
>  #include "llvm/IR/IntrinsicInst.h"
>  #include "llvm/IR/LLVMContext.h"
> +#include "llvm/IR/Module.h"
>  #include "llvm/Support/Debug.h"
>  #include "llvm/Support/raw_ostream.h"
>  
> @@ -1804,6 +1805,72 @@
>    return NumElim;
>  }
>  
> +bool SCEVExpander::isHighCostExpansionHelper(
> +    const SCEV *S, Loop *L, SmallPtrSetImpl<const SCEV *> &Processed) {
> +  if (!Processed.insert(S).second)
> +    return false;
> +
> +  if (auto *UDivExpr = dyn_cast<SCEVUDivExpr>(S)) {
> +    // If the divisor is a power of two and the SCEV type fits in a native
> +    // integer, consider the divison cheap irrespective of whether it occurs in
> +    // the user code since it can be lowered into a right shift.
> +    if (auto *SC = dyn_cast<SCEVConstant>(UDivExpr->getRHS()))
> +      if (SC->getValue()->getValue().isPowerOf2()) {
> +        const DataLayout &DL =
> +            L->getHeader()->getParent()->getParent()->getDataLayout();
> +        unsigned Width = cast<IntegerType>(UDivExpr->getType())->getBitWidth();
> +        return DL.isIllegalInteger(Width);
> +      }
> +
> +    // UDivExpr is very likely a UDiv that ScalarEvolution's HowFarToZero or
> +    // HowManyLessThans produced to compute a precise expression, rather than a
> +    // UDiv from the user's code. If we can't find a UDiv in the code with some
> +    // simple searching, assume the former consider UDivExpr expensive to
> +    // compute.
> +    BasicBlock *ExitingBB = L->getExitingBlock();
> +    if (!ExitingBB)
> +      return true;
> +
> +    BranchInst *ExitingBI = dyn_cast<BranchInst>(ExitingBB->getTerminator());
> +    if (!ExitingBI || !ExitingBI->isConditional())
> +      return true;
> +
> +    ICmpInst *OrigCond = dyn_cast<ICmpInst>(ExitingBI->getCondition());
> +    if (!OrigCond)
> +      return true;
> +
> +    const SCEV *RHS = SE.getSCEV(OrigCond->getOperand(1));
> +    RHS = SE.getMinusSCEV(RHS, SE.getConstant(RHS->getType(), 1));
> +    if (RHS != S) {
> +      const SCEV *LHS = SE.getSCEV(OrigCond->getOperand(0));
> +      LHS = SE.getMinusSCEV(LHS, SE.getConstant(LHS->getType(), 1));
> +      if (LHS != S)
> +        return true;
> +    }
> +  }
> +
> +  // Recurse past add expressions, which commonly occur in the
> +  // BackedgeTakenCount. They may already exist in program code, and if not,
> +  // they are not too expensive rematerialize.
> +  if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
> +    for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end();
> +         I != E; ++I) {
> +      if (isHighCostExpansionHelper(*I, L, Processed))
> +        return true;
> +    }
> +    return false;
> +  }
> +
> +  // HowManyLessThans uses a Max expression whenever the loop is not guarded by
> +  // the exit condition.
> +  if (isa<SCEVSMaxExpr>(S) || isa<SCEVUMaxExpr>(S))
> +    return true;
> +
> +  // If we haven't recognized an expensive SCEV pattern, assume it's an
> +  // expression produced by program code.
> +  return false;
> +}
> +
>  namespace {
>  // Search for a SCEV subexpression that is not safe to expand.  Any expression
>  // that may expand to a !isSafeToSpeculativelyExecute value is unsafe, namely
> Index: lib/Transforms/Scalar/IndVarSimplify.cpp
> ===================================================================
> --- lib/Transforms/Scalar/IndVarSimplify.cpp
> +++ lib/Transforms/Scalar/IndVarSimplify.cpp
> @@ -1274,55 +1274,6 @@
>  //  LinearFunctionTestReplace and its kin. Rewrite the loop exit condition.
>  //===----------------------------------------------------------------------===//
>  
> -/// Check for expressions that ScalarEvolution generates to compute
> -/// BackedgeTakenInfo. If these expressions have not been reduced, then
> -/// expanding them may incur additional cost (albeit in the loop preheader).
> -static bool isHighCostExpansion(const SCEV *S, BranchInst *BI,
> -                                SmallPtrSetImpl<const SCEV*> &Processed,
> -                                ScalarEvolution *SE) {
> -  if (!Processed.insert(S).second)
> -    return false;
> -
> -  // If the backedge-taken count is a UDiv, it's very likely a UDiv that
> -  // ScalarEvolution's HowFarToZero or HowManyLessThans produced to compute a
> -  // precise expression, rather than a UDiv from the user's code. If we can't
> -  // find a UDiv in the code with some simple searching, assume the former and
> -  // forego rewriting the loop.
> -  if (isa<SCEVUDivExpr>(S)) {
> -    ICmpInst *OrigCond = dyn_cast<ICmpInst>(BI->getCondition());
> -    if (!OrigCond) return true;
> -    const SCEV *R = SE->getSCEV(OrigCond->getOperand(1));
> -    R = SE->getMinusSCEV(R, SE->getConstant(R->getType(), 1));
> -    if (R != S) {
> -      const SCEV *L = SE->getSCEV(OrigCond->getOperand(0));
> -      L = SE->getMinusSCEV(L, SE->getConstant(L->getType(), 1));
> -      if (L != S)
> -        return true;
> -    }
> -  }
> -
> -  // Recurse past add expressions, which commonly occur in the
> -  // BackedgeTakenCount. They may already exist in program code, and if not,
> -  // they are not too expensive rematerialize.
> -  if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
> -    for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end();
> -         I != E; ++I) {
> -      if (isHighCostExpansion(*I, BI, Processed, SE))
> -        return true;
> -    }
> -    return false;
> -  }
> -
> -  // HowManyLessThans uses a Max expression whenever the loop is not guarded by
> -  // the exit condition.
> -  if (isa<SCEVSMaxExpr>(S) || isa<SCEVUMaxExpr>(S))
> -    return true;
> -
> -  // If we haven't recognized an expensive SCEV pattern, assume it's an
> -  // expression produced by program code.
> -  return false;
> -}
> -
>  /// canExpandBackedgeTakenCount - Return true if this loop's backedge taken
>  /// count expression can be safely and cheaply expanded into an instruction
>  /// sequence that can be used by LinearFunctionTestReplace.
> @@ -1336,7 +1287,8 @@
>  /// used by ABI constrained operation, as opposed to inttoptr/ptrtoint).
>  /// However, we don't yet have a strong motivation for converting loop tests
>  /// into inequality tests.
> -static bool canExpandBackedgeTakenCount(Loop *L, ScalarEvolution *SE) {
> +static bool canExpandBackedgeTakenCount(Loop *L, ScalarEvolution *SE,
> +                                        SCEVExpander &Rewriter) {
>    const SCEV *BackedgeTakenCount = SE->getBackedgeTakenCount(L);
>    if (isa<SCEVCouldNotCompute>(BackedgeTakenCount) ||
>        BackedgeTakenCount->isZero())
> @@ -1346,12 +1298,10 @@
>      return false;
>  
>    // Can't rewrite non-branch yet.
> -  BranchInst *BI = dyn_cast<BranchInst>(L->getExitingBlock()->getTerminator());
> -  if (!BI)
> +  if (!isa<BranchInst>(L->getExitingBlock()->getTerminator()))
>      return false;
>  
> -  SmallPtrSet<const SCEV*, 8> Processed;
> -  if (isHighCostExpansion(BackedgeTakenCount, BI, Processed, SE))
> +  if (Rewriter.isHighCostExpansion(BackedgeTakenCount, L))
>      return false;
>  
>    return true;
> @@ -1691,7 +1641,7 @@
>                            const SCEV *BackedgeTakenCount,
>                            PHINode *IndVar,
>                            SCEVExpander &Rewriter) {
> -  assert(canExpandBackedgeTakenCount(L, SE) && "precondition");
> +  assert(canExpandBackedgeTakenCount(L, SE, Rewriter) && "precondition");
>  
>    // Initialize CmpIndVar and IVCount to their preincremented values.
>    Value *CmpIndVar = IndVar;
> @@ -1936,7 +1886,7 @@
>  
>    // If we have a trip count expression, rewrite the loop's exit condition
>    // using it.  We can currently only handle loops with a single exit.
> -  if (canExpandBackedgeTakenCount(L, SE) && needsLFTR(L, DT)) {
> +  if (canExpandBackedgeTakenCount(L, SE, Rewriter) && needsLFTR(L, DT)) {
>      PHINode *IndVar = FindLoopCounter(L, BackedgeTakenCount, SE, DT);
>      if (IndVar) {
>        // Check preconditions for proper SCEVExpander operation. SCEV does not
> Index: test/Transforms/IndVarSimplify/lftr-udiv-tripcount.ll
> ===================================================================
> --- /dev/null
> +++ test/Transforms/IndVarSimplify/lftr-udiv-tripcount.ll
> @@ -0,0 +1,25 @@
> +; RUN: opt < %s -indvars -S | FileCheck %s
> +
> +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> +
> +define void @foo(i8* %a, i8 %n) nounwind uwtable ssp {
> +; CHECK-LABEL: @foo(
> + entry:
> +  %e = icmp sgt i8 %n, 3
> +  br i1 %e, label %loop, label %exit
> +
> + loop:
> +; CHECK-LABEL: loop:
> +  %i = phi i8 [ 0, %entry ], [ %i.inc, %loop ]
> +  %i1 = phi i8 [ 0, %entry ], [ %i1.inc, %loop ]
> +  %i.inc = add nsw i8 %i, 4
> +  %i1.inc = add i8 %i1, 1
> +  store volatile i8 0, i8* %a
> +  %c = icmp slt i8 %i, %n
> +; CHECK-LABEL:  %exitcond = icmp ne i8 %i1.inc
> +  br i1 %c, label %loop, label %exit
> +
> + exit:
> +; CHECK-LABEL: exit:
> +  ret void
> +}
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list