xref: /llvm-project/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp (revision ac9f3ea0b437d881bc9879601b0777139b9fd864)
1 //===- ScalarEvolutionNormalization.cpp - See below -----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements utilities for working with "normalized" expressions.
11 // See the comments at the top of ScalarEvolutionNormalization.h for details.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Analysis/LoopInfo.h"
16 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
17 #include "llvm/Analysis/ScalarEvolutionNormalization.h"
18 using namespace llvm;
19 
20 namespace {
21 
22 /// Hold the state used during post-inc expression transformation, including a
23 /// map of transformed expressions.
24 class PostIncTransform {
25   TransformKind Kind;
26   Optional<NormalizePredTy> Pred;
27   PostIncLoopSet &Loops;
28   ScalarEvolution &SE;
29 
30   DenseMap<const SCEV*, const SCEV*> Transformed;
31 
32 public:
33   PostIncTransform(TransformKind kind, Optional<NormalizePredTy> Pred,
34                    PostIncLoopSet &loops, ScalarEvolution &se)
35       : Kind(kind), Pred(Pred), Loops(loops), SE(se) {}
36 
37   const SCEV *TransformSubExpr(const SCEV *S);
38 
39 protected:
40   const SCEV *TransformImpl(const SCEV *S);
41 };
42 
43 } // namespace
44 
45 /// Implement post-inc transformation for all valid expression types.
46 const SCEV *PostIncTransform::TransformImpl(const SCEV *S) {
47   if (const SCEVCastExpr *X = dyn_cast<SCEVCastExpr>(S)) {
48     const SCEV *O = X->getOperand();
49     const SCEV *N = TransformSubExpr(O);
50     if (O != N)
51       switch (S->getSCEVType()) {
52       case scZeroExtend: return SE.getZeroExtendExpr(N, S->getType());
53       case scSignExtend: return SE.getSignExtendExpr(N, S->getType());
54       case scTruncate: return SE.getTruncateExpr(N, S->getType());
55       default: llvm_unreachable("Unexpected SCEVCastExpr kind!");
56       }
57     return S;
58   }
59 
60   if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
61     // An addrec. This is the interesting part.
62     SmallVector<const SCEV *, 8> Operands;
63     const Loop *L = AR->getLoop();
64 
65     transform(AR->operands(), std::back_inserter(Operands),
66               [&](const SCEV *Op) { return TransformSubExpr(Op); });
67 
68     // Conservatively use AnyWrap until/unless we need FlagNW.
69     const SCEV *Result = SE.getAddRecExpr(Operands, L, SCEV::FlagAnyWrap);
70     switch (Kind) {
71     case Normalize:
72       // We want to normalize step expression, because otherwise we might not be
73       // able to denormalize to the original expression.
74       //
75       // Here is an example what will happen if we don't normalize step:
76       //  ORIGINAL ISE:
77       //    {(100 /u {1,+,1}<%bb16>),+,(100 /u {1,+,1}<%bb16>)}<%bb25>
78       //  NORMALIZED ISE:
79       //    {((-1 * (100 /u {1,+,1}<%bb16>)) + (100 /u {0,+,1}<%bb16>)),+,
80       //     (100 /u {0,+,1}<%bb16>)}<%bb25>
81       //  DENORMALIZED BACK ISE:
82       //    {((2 * (100 /u {1,+,1}<%bb16>)) + (-1 * (100 /u {2,+,1}<%bb16>))),+,
83       //     (100 /u {1,+,1}<%bb16>)}<%bb25>
84       //  Note that the initial value changes after normalization +
85       //  denormalization, which isn't correct.
86       if ((Pred && (*Pred)(AR)) || (!Pred && Loops.count(L))) {
87         const SCEV *TransformedStep =
88             TransformSubExpr(AR->getStepRecurrence(SE));
89         Result = SE.getMinusSCEV(Result, TransformedStep);
90       }
91 #if 0
92       // See the comment on the assert above.
93       assert(S == TransformSubExpr(Result, User, OperandValToReplace) &&
94              "SCEV normalization is not invertible!");
95 #endif
96       break;
97     case Denormalize:
98       // Here we want to normalize step expressions for the same reasons, as
99       // stated above.
100       if (Loops.count(L)) {
101         const SCEV *TransformedStep =
102             TransformSubExpr(AR->getStepRecurrence(SE));
103         Result = SE.getAddExpr(Result, TransformedStep);
104       }
105       break;
106     }
107     return Result;
108   }
109 
110   if (const SCEVNAryExpr *X = dyn_cast<SCEVNAryExpr>(S)) {
111     SmallVector<const SCEV *, 8> Operands;
112     bool Changed = false;
113     // Transform each operand.
114     for (SCEVNAryExpr::op_iterator I = X->op_begin(), E = X->op_end();
115          I != E; ++I) {
116       const SCEV *O = *I;
117       const SCEV *N = TransformSubExpr(O);
118       Changed |= N != O;
119       Operands.push_back(N);
120     }
121     // If any operand actually changed, return a transformed result.
122     if (Changed)
123       switch (S->getSCEVType()) {
124       case scAddExpr: return SE.getAddExpr(Operands);
125       case scMulExpr: return SE.getMulExpr(Operands);
126       case scSMaxExpr: return SE.getSMaxExpr(Operands);
127       case scUMaxExpr: return SE.getUMaxExpr(Operands);
128       default: llvm_unreachable("Unexpected SCEVNAryExpr kind!");
129       }
130     return S;
131   }
132 
133   if (const SCEVUDivExpr *X = dyn_cast<SCEVUDivExpr>(S)) {
134     const SCEV *LO = X->getLHS();
135     const SCEV *RO = X->getRHS();
136     const SCEV *LN = TransformSubExpr(LO);
137     const SCEV *RN = TransformSubExpr(RO);
138     if (LO != LN || RO != RN)
139       return SE.getUDivExpr(LN, RN);
140     return S;
141   }
142 
143   llvm_unreachable("Unexpected SCEV kind!");
144 }
145 
146 /// Manage recursive transformation across an expression DAG. Revisiting
147 /// expressions would lead to exponential recursion.
148 const SCEV *PostIncTransform::TransformSubExpr(const SCEV *S) {
149   if (isa<SCEVConstant>(S) || isa<SCEVUnknown>(S))
150     return S;
151 
152   const SCEV *Result = Transformed.lookup(S);
153   if (Result)
154     return Result;
155 
156   Result = TransformImpl(S);
157   Transformed[S] = Result;
158   return Result;
159 }
160 
161 /// Top level driver for transforming an expression DAG into its requested
162 /// post-inc form (either "Normalized" or "Denormalized").
163 const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, const SCEV *S,
164                                          Optional<NormalizePredTy> Pred,
165                                          PostIncLoopSet &Loops,
166                                          ScalarEvolution &SE) {
167   PostIncTransform Transform(Kind, Pred, Loops, SE);
168   return Transform.TransformSubExpr(S);
169 }
170