[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