@@ -289,11 +289,30 @@ class Analyzer
289289 void analyze (SmallVectorImpl<ReductionCandidateGroup> &Result);
290290
291291private:
292+
293+ // Represents deconstructed SCEV expression { start, +, step }.
294+ // Start SCEV will be used to calculate base pointer, and Step SCEV
295+ // will increase new induction variable on each iteration.
296+ struct DeconstructedSCEV
297+ {
298+ DeconstructedSCEV () : Start(nullptr ), Step(nullptr ), ConvertedMulExpr(false ) {}
299+
300+ bool isValid ();
301+
302+ const SCEV* Start;
303+ const SCEV* Step;
304+
305+ // True if input SCEV:
306+ // x * { start, +, step }
307+ // Was converted into:
308+ // { x * start, +, x * step }
309+ bool ConvertedMulExpr;
310+ };
311+
292312 void analyzeGEP (GetElementPtrInst *GEP);
293313 bool doInitialValidation (GetElementPtrInst *GEP);
294314
295- bool deconstructSCEV (const SCEV *S, const SCEV *&Start, const SCEV *&Step);
296- bool isValidStep (const SCEV* S);
315+ bool deconstructSCEV (const SCEV *S, DeconstructedSCEV &Result);
297316
298317 DominatorTree &DT;
299318 Loop &L;
@@ -961,15 +980,16 @@ void Analyzer::analyzeGEP(GetElementPtrInst *GEP)
961980 if (!SCEVHelper::isValid (S))
962981 return ;
963982
964- const SCEV *Start = nullptr ;
965- const SCEV *Step = nullptr ;
966-
967- if (!deconstructSCEV (S, Start, Step))
983+ Analyzer::DeconstructedSCEV Result;
984+ if (!deconstructSCEV (S, Result))
968985 return ;
969986
970- if (!isValidStep (Step ))
987+ if (!Result. isValid ( ))
971988 return ;
972989
990+ const SCEV* Start = Result.Start ;
991+ const SCEV* Step = Result.Step ;
992+
973993 if (S->getType () != Start->getType ())
974994 Start = isa<SCEVSignExtendExpr>(S) ? SE.getSignExtendExpr (Start, S->getType ()) : SE.getZeroExtendExpr (Start, S->getType ());
975995
@@ -1063,7 +1083,7 @@ bool Analyzer::doInitialValidation(GetElementPtrInst *GEP)
10631083// Takes SCEV expression returned by ScalarEvolution and deconstructs it into
10641084// expected format { start, +, step }. Returns false if expressions can't be
10651085// parsed and reduced.
1066- bool Analyzer::deconstructSCEV (const SCEV *S, const SCEV *&Start, const SCEV *&Step )
1086+ bool Analyzer::deconstructSCEV (const SCEV *S, Analyzer::DeconstructedSCEV &Result )
10671087{
10681088 // Drop ext instructions to analyze nested content.
10691089 S = SCEVHelper::dropExt (S);
@@ -1075,8 +1095,8 @@ bool Analyzer::deconstructSCEV(const SCEV *S, const SCEV *&Start, const SCEV *&S
10751095 // induction variable.
10761096 if (SE.isLoopInvariant (S, &L))
10771097 {
1078- Start = S;
1079- Step = SE.getConstant (Type::getInt64Ty (L.getHeader ()->getContext ()), 0 );
1098+ Result. Start = S;
1099+ Result. Step = SE.getConstant (Type::getInt64Ty (L.getHeader ()->getContext ()), 0 );
10801100 return true ;
10811101 }
10821102
@@ -1097,10 +1117,10 @@ bool Analyzer::deconstructSCEV(const SCEV *S, const SCEV *&Start, const SCEV *&S
10971117 if (!SE.isLoopInvariant (OpStep, &L))
10981118 return false ;
10991119
1100- Start = Add->getStart ();
1101- Step = OpStep;
1120+ Result. Start = Add->getStart ();
1121+ Result. Step = OpStep;
11021122
1103- return IGCLLVM::isSafeToExpandAt (Start, &L.getLoopPreheader ()->back (), &SE, &E);
1123+ return IGCLLVM::isSafeToExpandAt (Result. Start , &L.getLoopPreheader ()->back (), &SE, &E);
11041124 }
11051125
11061126 // If expression is:
@@ -1114,30 +1134,30 @@ bool Analyzer::deconstructSCEV(const SCEV *S, const SCEV *&Start, const SCEV *&S
11141134 if (auto *Add = dyn_cast<SCEVAddExpr>(S))
11151135 {
11161136 // There can be only one expression with step != 0.
1117- Step = SE.getConstant (Type::getInt64Ty (L.getHeader ()->getContext ()), 0 );
1137+ Result. Step = SE.getConstant (Type::getInt64Ty (L.getHeader ()->getContext ()), 0 );
11181138
1119- const SCEV *OpSCEV = nullptr ;
1120- const SCEV *OpStep = nullptr ;
11211139 SCEVHelper::SCEVAddBuilder Builder (SE);
11221140
11231141 for (auto *Op : Add->operands ())
11241142 {
1125- if (!deconstructSCEV (Op, OpSCEV, OpStep))
1143+ Analyzer::DeconstructedSCEV OpResult;
1144+
1145+ if (!deconstructSCEV (Op, OpResult))
11261146 return false ;
11271147
1128- if (!OpStep ->isZero ())
1148+ if (!OpResult. Step ->isZero ())
11291149 {
1130- if (!Step->isZero ())
1150+ if (!Result. Step ->isZero ())
11311151 return false ; // unsupported expression with multiple steps
1132- Step = OpStep ;
1152+ Result. Step = OpResult. Step ;
11331153 }
11341154
1135- Builder.add (OpSCEV );
1155+ Builder.add (OpResult. Start );
11361156 }
11371157
1138- Start = Builder.build ();
1158+ Result. Start = Builder.build ();
11391159
1140- return IGCLLVM::isSafeToExpandAt (Start, &L.getLoopPreheader ()->back (), &SE, &E);
1160+ return IGCLLVM::isSafeToExpandAt (Result. Start , &L.getLoopPreheader ()->back (), &SE, &E);
11411161 }
11421162
11431163 // If expression is:
@@ -1148,60 +1168,62 @@ bool Analyzer::deconstructSCEV(const SCEV *S, const SCEV *&Start, const SCEV *&S
11481168 // Warning: GEP's new index will not be a constant integer, but a new SCEV expression.
11491169 if (auto *Mul = dyn_cast<SCEVMulExpr>(S))
11501170 {
1151- if (IGC_IS_FLAG_DISABLED (EnableGEPLSRMulExpr))
1152- return false ;
1153-
11541171 // SCEVAddRecExpr will be SCEV with step != 0. Any other SCEV is a multiplier.
11551172 bool FoundAddRec = false ;
11561173 SCEVHelper::SCEVMulBuilder StartBuilder (SE), StepBuilder (SE);
11571174
11581175 for (auto *Op : Mul->operands ())
11591176 {
1160- const SCEV *OpSCEV = nullptr ;
1161- const SCEV *OpStep = nullptr ;
1162- if (!deconstructSCEV (Op, OpSCEV, OpStep))
1177+ Analyzer::DeconstructedSCEV OpResult;
1178+ if (!deconstructSCEV (Op, OpResult))
11631179 return false ;
11641180
1165- if (OpStep ->isZero ())
1181+ if (OpResult. Step ->isZero ())
11661182 {
1167- StartBuilder.add (OpSCEV );
1168- StepBuilder.add (OpSCEV );
1183+ StartBuilder.add (OpResult. Start );
1184+ StepBuilder.add (OpResult. Start );
11691185 }
11701186 else
11711187 {
11721188 if (FoundAddRec)
11731189 return false ; // unsupported expression with multiple SCEVAddRecExpr
11741190 FoundAddRec = true ;
11751191
1176- StartBuilder.add (OpSCEV );
1177- StepBuilder.add (OpStep );
1192+ StartBuilder.add (OpResult. Start );
1193+ StepBuilder.add (OpResult. Step );
11781194 }
11791195 }
11801196
11811197 if (!FoundAddRec)
11821198 return false ;
11831199
1184- Start = StartBuilder.build ();
1185- Step = StepBuilder.build ();
1200+ Result.Start = StartBuilder.build ();
1201+ Result.Step = StepBuilder.build ();
1202+ Result.ConvertedMulExpr = true ;
11861203
1187- if (!SE.isLoopInvariant (Step, &L))
1204+ if (!SE.isLoopInvariant (Result. Step , &L))
11881205 return false ;
11891206
1190- return IGCLLVM::isSafeToExpandAt (Start, &L.getLoopPreheader ()->back (), &SE, &E);
1207+ return IGCLLVM::isSafeToExpandAt (Result. Start , &L.getLoopPreheader ()->back (), &SE, &E);
11911208 }
11921209
11931210 return false ;
11941211}
11951212
11961213
1197- bool Analyzer::isValidStep ( const SCEV* S )
1214+ bool Analyzer::DeconstructedSCEV::isValid ( )
11981215{
1199- auto Ty = SCEVHelper::dropExt (S)->getSCEVType ();
1216+ if (!Start || !Step)
1217+ return false ;
1218+
1219+ // Validate step.
1220+ auto Ty = SCEVHelper::dropExt (Step)->getSCEVType ();
12001221
12011222 if (Ty == scConstant)
12021223 return true ;
12031224
1204- if (Ty == scMulExpr && IGC_IS_FLAG_ENABLED (EnableGEPLSRMulExpr))
1225+ bool IsMul = Ty == scMulExpr || ConvertedMulExpr;
1226+ if (IsMul && IGC_IS_FLAG_ENABLED (EnableGEPLSRMulExpr))
12051227 return true ;
12061228
12071229 return IGC_IS_FLAG_ENABLED (EnableGEPLSRUnknownConstantStep);
0 commit comments