[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:32 PDT 2015


> 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


More information about the llvm-commits mailing list