@@ -97,9 +97,6 @@ using namespace IGC;
97
97
// global float *p = buf + id + i;
98
98
// *(p + 1) = *p + 3.0f;
99
99
// }
100
- //
101
- // TODO: At the moment pass accepts constant indices as llvm::Constant. These could be any llvm::Value
102
- // as long as value doesn't change inside loop body (is constant for full loop lifetime).
103
100
104
101
105
102
enum ReductionType
@@ -187,10 +184,10 @@ friend class Scorer;
187
184
188
185
public:
189
186
190
- ReductionCandidateGroup (Loop *L, const DominatorTree *DT, GetElementPtrInst *GEP, const SCEV *S, int64_t Step)
187
+ ReductionCandidateGroup (Loop *L, const DominatorTree *DT, GetElementPtrInst *GEP, const SCEV *S, const SCEV * Step)
191
188
: L(L), DT(DT), Step(Step), Base(GEP, S, 0 ), RT(REDUCE_TO_PREHEADER) {}
192
189
193
- bool addToGroup (ScalarEvolution &SE, GetElementPtrInst *GEP, const SCEV *S, int64_t Step);
190
+ bool addToGroup (ScalarEvolution &SE, GetElementPtrInst *GEP, const SCEV *S, const SCEV * Step);
194
191
195
192
void transform (IGCLLVM::IRBuilder<> &IRB, SCEVExpander &E);
196
193
@@ -223,14 +220,16 @@ friend class Scorer;
223
220
void reduceToPreheader (IGCLLVM::IRBuilder<> &IRB, SCEVExpander &E);
224
221
void reduceIndexOnly (IGCLLVM::IRBuilder<> &IRB, SCEVExpander &E);
225
222
223
+ Value *getStepValue (IGCLLVM::IRBuilder<> &IRB);
224
+
226
225
// Base GEP to reduce
227
226
ReductionCandidate Base;
228
227
229
228
// Other GEPs that can be reduced together with base
230
229
SmallVector<ReductionCandidate, 4 > Others;
231
230
232
231
// Increment step value
233
- int64_t Step;
232
+ const SCEV * Step;
234
233
235
234
// Group member with the smallest SCEV expression. Preferred for reduction
236
235
// to preheader, as it should give smallest increase in register pressure.
@@ -289,7 +288,7 @@ class Analyzer
289
288
void analyzeGEP (GetElementPtrInst *GEP);
290
289
bool doInitialValidation (GetElementPtrInst *GEP);
291
290
292
- bool deconstructSCEV (const SCEV *S, const SCEV *&Start, int64_t &Step);
291
+ bool deconstructSCEV (const SCEV *S, const SCEV *&Start, const SCEV * &Step);
293
292
294
293
DominatorTree &DT;
295
294
Loop &L;
@@ -355,6 +354,9 @@ namespace SCEVHelper
355
354
{
356
355
const SCEV *dropExt (const SCEV *S);
357
356
357
+ bool isValidStep (const SCEV *S);
358
+ bool isEqual (const SCEV *A, const SCEV *B);
359
+
358
360
// ScalarEvolution::getAddExpr requires all operands to have the same
359
361
// type. Extend type if required.
360
362
@@ -481,9 +483,9 @@ bool ReductionCandidate::isBetterForReduction(const ReductionCandidate &Other)
481
483
// New candidate can take position of group's base if it uses less instructions
482
484
// to calculate.
483
485
// Returns true if candidate was added to group.
484
- bool ReductionCandidateGroup::addToGroup (ScalarEvolution &SE, GetElementPtrInst *GEP, const SCEV *S, int64_t Step)
486
+ bool ReductionCandidateGroup::addToGroup (ScalarEvolution &SE, GetElementPtrInst *GEP, const SCEV *S, const SCEV * Step)
485
487
{
486
- if (this ->Step != Step)
488
+ if (! SCEVHelper::isEqual ( this ->Step , Step) )
487
489
return false ;
488
490
489
491
if (Base.GEP ->getPointerOperand () != GEP->getPointerOperand ())
@@ -619,7 +621,7 @@ void ReductionCandidateGroup::reduceToPreheader(IGCLLVM::IRBuilder<> &IRB, SCEVE
619
621
Value *Pointer = IRB.CreateGEP (Base.GEP ->getSourceElementType (), Base.GEP ->getPointerOperand (), Indices);
620
622
621
623
// Create phi node if pointer is moved in loop
622
- if (Step != 0 )
624
+ if (!Step-> isZero () )
623
625
{
624
626
// Add new phi node with pointer as induction variable
625
627
SmallVector<BasicBlock*, 4 > Latches;
@@ -634,7 +636,7 @@ void ReductionCandidateGroup::reduceToPreheader(IGCLLVM::IRBuilder<> &IRB, SCEVE
634
636
for (auto *L : Latches)
635
637
{
636
638
IRB.SetInsertPoint (&L->back ());
637
- Value *Inc = IRB.CreateGEP (Phi, IRB. getInt64 (Step ));
639
+ Value *Inc = IRB.CreateGEP (Phi, getStepValue (IRB ));
638
640
Phi->addIncoming (Inc, L);
639
641
}
640
642
@@ -675,6 +677,19 @@ void ReductionCandidateGroup::reduceIndexOnly(IGCLLVM::IRBuilder<> &IRB, SCEVExp
675
677
}
676
678
677
679
680
+ Value *ReductionCandidateGroup::getStepValue (IGCLLVM::IRBuilder<> &IRB)
681
+ {
682
+ if (auto *S = dyn_cast<SCEVConstant>(Step))
683
+ return IRB.getInt64 (dyn_cast<SCEVConstant>(Step)->getValue ()->getSExtValue ());
684
+
685
+ if (auto *S = dyn_cast<SCEVUnknown>(Step))
686
+ return S->getValue ();
687
+
688
+ IGC_ASSERT_MESSAGE (0 , " invalid induction value type" );
689
+ return nullptr ;
690
+ }
691
+
692
+
678
693
void Scorer::score (SmallVectorImpl<ReductionCandidateGroup> &Candidates)
679
694
{
680
695
for (auto &C : Candidates)
@@ -704,7 +719,7 @@ void Scorer::scoreReducedInstructions(ReductionCandidateGroup &Candidate)
704
719
// 3. "+ base_ptr" - single "add" instruction
705
720
int score = 0 ;
706
721
707
- if (Candidate.Step != 0 )
722
+ if (! Candidate.Step -> isZero () )
708
723
{
709
724
// Reduction adds new instruction - incrementation of new induction variable at the end
710
725
// of the iteration.
@@ -901,7 +916,7 @@ void Analyzer::analyzeGEP(GetElementPtrInst *GEP)
901
916
return ;
902
917
903
918
const SCEV *Start = nullptr ;
904
- int64_t Step = 0 ;
919
+ const SCEV * Step = nullptr ;
905
920
906
921
if (!deconstructSCEV (S, Start, Step))
907
922
return ;
@@ -999,7 +1014,7 @@ bool Analyzer::doInitialValidation(GetElementPtrInst *GEP)
999
1014
// Takes SCEV expression returned by ScalarEvolution and deconstructs it into
1000
1015
// expected format { start, +, step }. Returns false if expressions can't be
1001
1016
// parsed and reduced.
1002
- bool Analyzer::deconstructSCEV (const SCEV *S, const SCEV *&Start, int64_t &Step)
1017
+ bool Analyzer::deconstructSCEV (const SCEV *S, const SCEV *&Start, const SCEV * &Step)
1003
1018
{
1004
1019
// Drop ext instructions to analyze nested content.
1005
1020
S = SCEVHelper::dropExt (S);
@@ -1009,10 +1024,10 @@ bool Analyzer::deconstructSCEV(const SCEV *S, const SCEV *&Start, int64_t &Step)
1009
1024
// { start, +, 0 }
1010
1025
// This will do LICM-like reduction moving GEP to preheader, without adding new
1011
1026
// induction variable.
1012
- if (IGCLLVM::isSafeToExpandAt (S, &L. getLoopPreheader ()-> back (), &SE, &E ))
1027
+ if (SE. isLoopInvariant (S, &L))
1013
1028
{
1014
1029
Start = S;
1015
- Step = 0 ;
1030
+ Step = SE. getConstant ( Type::getInt64Ty (L. getHeader ()-> getContext ()), 0 ) ;
1016
1031
return true ;
1017
1032
}
1018
1033
@@ -1027,12 +1042,17 @@ bool Analyzer::deconstructSCEV(const SCEV *S, const SCEV *&Start, int64_t &Step)
1027
1042
if (Add->getNumOperands () != 2 )
1028
1043
return false ;
1029
1044
1030
- const SCEVConstant *Op = dyn_cast<SCEVConstant>(Add->getOperand (1 ));
1031
- if (!Op)
1045
+ const SCEV *OpStep = Add->getOperand (1 );
1046
+
1047
+ // Step must be constant in loop's body.
1048
+ if (!SE.isLoopInvariant (OpStep, &L))
1049
+ return false ;
1050
+
1051
+ if (!SCEVHelper::isValidStep (OpStep))
1032
1052
return false ;
1033
1053
1034
1054
Start = Add->getStart ();
1035
- Step = Op-> getValue ()-> getSExtValue () ;
1055
+ Step = OpStep ;
1036
1056
1037
1057
return IGCLLVM::isSafeToExpandAt (Start, &L.getLoopPreheader ()->back (), &SE, &E);
1038
1058
}
@@ -1048,20 +1068,20 @@ bool Analyzer::deconstructSCEV(const SCEV *S, const SCEV *&Start, int64_t &Step)
1048
1068
if (auto *Add = dyn_cast<SCEVAddExpr>(S))
1049
1069
{
1050
1070
// There can be only one expression with step != 0.
1051
- Step = 0 ;
1071
+ Step = SE. getConstant ( Type::getInt64Ty (L. getHeader ()-> getContext ()), 0 ) ;
1052
1072
1053
1073
const SCEV *OpSCEV = nullptr ;
1054
- int64_t OpStep = 0 ;
1074
+ const SCEV * OpStep = nullptr ;
1055
1075
SCEVHelper::SCEVAddBuilder Builder (SE);
1056
1076
1057
1077
for (auto *Op : Add->operands ())
1058
1078
{
1059
1079
if (!deconstructSCEV (Op, OpSCEV, OpStep))
1060
1080
return false ;
1061
1081
1062
- if (OpStep != 0 )
1082
+ if (!OpStep-> isZero () )
1063
1083
{
1064
- if (Step != 0 )
1084
+ if (!Step-> isZero () )
1065
1085
return false ; // unsupported expression with multiple steps
1066
1086
Step = OpStep;
1067
1087
}
@@ -1306,6 +1326,39 @@ const SCEV *SCEVHelper::dropExt(const SCEV *S)
1306
1326
}
1307
1327
1308
1328
1329
+ bool SCEVHelper::isValidStep (const SCEV *S)
1330
+ {
1331
+ switch (S->getSCEVType ())
1332
+ {
1333
+ case scConstant:
1334
+ case scUnknown:
1335
+ return true ;
1336
+ default :
1337
+ return false ;
1338
+ }
1339
+ }
1340
+
1341
+
1342
+ bool SCEVHelper::isEqual (const SCEV *A, const SCEV *B)
1343
+ {
1344
+ // Scalar Evolution keeps unique SCEV instances, so we can compare pointers.
1345
+ if (A == B)
1346
+ return true ;
1347
+
1348
+ if (A->getSCEVType () != B->getSCEVType ())
1349
+ return false ;
1350
+
1351
+ switch (A->getSCEVType ())
1352
+ {
1353
+ case scConstant:
1354
+ // Can be different bit width, but same integer value.
1355
+ return cast<SCEVConstant>(A)->getValue ()->getZExtValue () == cast<SCEVConstant>(B)->getValue ()->getZExtValue ();
1356
+ default :
1357
+ return false ;
1358
+ }
1359
+ }
1360
+
1361
+
1309
1362
SCEVHelper::SCEVAddBuilder &SCEVHelper::SCEVAddBuilder::add (const SCEV *S, bool Negative)
1310
1363
{
1311
1364
IGC_ASSERT (S->getType ()->isIntegerTy ());
0 commit comments