[PATCH] D12066: Introduce the ScopExpander as a SCEVExpander replacement

Tobias Grosser via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 02:42:38 PDT 2015


grosser added a comment.

> jdoerfert updated this revision to Diff 32394.

>  jdoerfert marked 4 inline comments as done.

>  jdoerfert added a comment.

> 

> Added test cases and modified according to the review.

> 

> http://reviews.llvm.org/D12066

> 

> Files:

> 

>   include/polly/CodeGen/IslExprBuilder.h

>   include/polly/CodeGen/IslNodeBuilder.h

>   include/polly/Support/ScopHelper.h

>   lib/CodeGen/BlockGenerators.cpp

>   lib/CodeGen/IslExprBuilder.cpp

>   lib/CodeGen/IslNodeBuilder.cpp

>   lib/Support/ScopHelper.cpp

>   test/Isl/CodeGen/inner_scev.ll

>   test/Isl/CodeGen/inner_scev_2.ll

>   test/Isl/CodeGen/inner_scev_sdiv_1.ll

>   test/Isl/CodeGen/inner_scev_sdiv_2.ll

>   test/Isl/CodeGen/inner_scev_sdiv_3.ll

>   test/Isl/CodeGen/inner_scev_sdiv_in_lb.ll

>   test/Isl/CodeGen/inner_scev_sdiv_in_lb_invariant.ll

>   test/Isl/CodeGen/inner_scev_sdiv_in_rtc.ll




> +/// The SCEVExpander will __not__ generate any code for an existing SDiv/SRem

>  +/// instruction but just use it, if it is references as a SCEVUnknown. We want


referenced

> +/// however to generate new code if the instruction is in the analyzed region

>  +/// and we generate code outside/infront of that region. Hence, we generate the

>  +/// code for the SDiv/SRem operands in front of the analyzed region and then

>  +/// create a new SDiv/SRem operation there too.

>  +struct ScopExpander : SCEVVisitor<ScopExpander, const SCEV *> {

>  +  friend struct SCEVVisitor<ScopExpander, const SCEV *>;

>  +

>  +  explicit ScopExpander(const Region &R, ScalarEvolution &SE,

>  +                        const DataLayout &DL, const char *Name)

>  +      : Expander(SCEVExpander(SE, DL, Name)), SE(SE), Name(Name), R(R) {}

>  +

>  +  Value *expandCodeFor(const SCEV *E, Type *Ty, Instruction *I) {

>  +    // If we generate code in the region we will immediately fall back to the

>  +    // SCEVExpander, otherwise we will stop at all unknowns in the SCEV and if

>  +    // needed replace them by copies computed in the entering block.

>  +    if (!R.contains(I))

>  +      E = visit(E);

>  +    return Expander.expandCodeFor(E, Ty, I);

>  +  }

>  +

>  +private:

>  +  SCEVExpander Expander;

>  +  ScalarEvolution &SE;

>  +  const char *Name;

>  +  const Region &R;

>  +

>  +  const SCEV *visitUnknown(const SCEVUnknown *E) {

>  +    Instruction *Inst = dyn_cast<Instruction>(E->getValue());

>  +    if (!Inst || (Inst->getOpcode() != Instruction::SRem &&

>  +                  Inst->getOpcode() != Instruction::SDiv))

>  +      return E;

>  +

>  +    if (!R.contains(Inst))

>  +      return E;

>  +

>  +    Instruction *StartIP = R.getEnteringBlock()->getTerminator();

>  +

>  +    const SCEV *LHSScev = visit(SE.getSCEV(Inst->getOperand(0)));

>  +    const SCEV *RHSScev = visit(SE.getSCEV(Inst->getOperand(1)));

>  +

>  +    Value *LHS = Expander.expandCodeFor(LHSScev, E->getType(), StartIP);

>  +    Value *RHS = Expander.expandCodeFor(RHSScev, E->getType(), StartIP);

>  +

>  +    Inst = BinaryOperator::Create((Instruction::BinaryOps)Inst->getOpcode(),

>  +                                  LHS, RHS, Inst->getName() + Name, StartIP);

>  +    return SE.getSCEV(Inst);

>  +  }

>  +

>  +  /// The following functions will just traverse the SCEV and rebuild it with

>  +  /// the new operands returned by the traversal.

>  +  ///

>  +  ///{

>  +  const SCEV *visitConstant(const SCEVConstant *E) { return E; }

>  +  const SCEV *visitTruncateExpr(const SCEVTruncateExpr *E) {

>  +    return SE.getTruncateExpr(visit(E->getOperand()), E->getType());

>  +  }

>  +  const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *E) {

>  +    return SE.getZeroExtendExpr(visit(E->getOperand()), E->getType());

>  +  }

>  +  const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *E) {

>  +    return SE.getSignExtendExpr(visit(E->getOperand()), E->getType());

>  +  }

>  +  const SCEV *visitUDivExpr(const SCEVUDivExpr *E) {

>  +    return SE.getUDivExpr(visit(E->getLHS()), visit(E->getRHS()));

>  +  }

>  +  const SCEV *visitAddExpr(const SCEVAddExpr *E) {

>  +    SmallVector<const SCEV *, 4> NewOps;

>  +    for (const SCEV *Op : E->operands())

>  +      NewOps.push_back(visit(Op));

>  +    return SE.getAddExpr(NewOps);

>  +  }

>  +  const SCEV *visitMulExpr(const SCEVMulExpr *E) {

>  +    SmallVector<const SCEV *, 4> NewOps;

>  +    for (const SCEV *Op : E->operands())

>  +      NewOps.push_back(visit(Op));

>  +    return SE.getMulExpr(NewOps);

>  +  }

>  +  const SCEV *visitUMaxExpr(const SCEVUMaxExpr *E) {

>  +    SmallVector<const SCEV *, 4> NewOps;

>  +    for (const SCEV *Op : E->operands())

>  +      NewOps.push_back(visit(Op));

>  +    return SE.getUMaxExpr(NewOps);

>  +  }

>  +  const SCEV *visitSMaxExpr(const SCEVSMaxExpr *E) {

>  +    SmallVector<const SCEV *, 4> NewOps;

>  +    for (const SCEV *Op : E->operands())

>  +      NewOps.push_back(visit(Op));

>  +    return SE.getSMaxExpr(NewOps);

>  +  }

>  +  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) {

>  +    SmallVector<const SCEV *, 4> NewOps;

>  +    for (const SCEV *Op : E->operands())

>  +      NewOps.push_back(visit(Op));

>  +    return SE.getAddRecExpr(NewOps, E->getLoop(), E->getNoWrapFlags());

>  +  }

>  +  ///}

>  +};




> +/// This wrapper will internally call the SCEVExpander but also make sure that


makes sure

Tobias


http://reviews.llvm.org/D12066





More information about the llvm-commits mailing list