@@ -250,6 +250,7 @@ std::pair<MemoryLocationRange, bool> aggregate(
250250 DFRegion *R, const MemoryLocationRange &Loc, const ReachDFFwk *Fwk) {
251251 typedef MemoryLocationRange::Dimension Dimension;
252252 typedef MemoryLocationRange::LocKind LocKind;
253+ typedef ICmpInst::Predicate Predicate;
253254 assert (Fwk && " Data-flow framework must not be null" );
254255 assert (!(Loc.Kind & LocKind::Collapsed) || Loc.DimList .size () > 0 &&
255256 " Collapsed array location must not be empty!" );
@@ -351,28 +352,113 @@ std::pair<MemoryLocationRange, bool> aggregate(
351352 LLVM_DEBUG (dbgs () << " [AGGREGATE] Non-constant step.\n " );
352353 break ;
353354 }
355+ auto AddRecStep = cast<SCEVConstant>(StepSCEV)->getAPInt ().getSExtValue ();
354356 auto TripCount = SE->getSmallConstantTripCount (C->getLoop ());
355- if (TripCount <= 1 ) {
356- LLVM_DEBUG (dbgs () << " [AGGREGATE] Unknown or non-constant "
357- " trip count.\n " );
358- break ;
359- }
360- auto StartValue = SE->getSignedRangeMin (SCEV).getSExtValue ();
361- if (StartValue < 0 ) {
362- LLVM_DEBUG (dbgs () << " [AGGREGATE] Range bounds must be "
363- " non-negative.\n " );
357+ if (TripCount > 1 ) {
358+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Aggregate constant range.\n " );
359+ int64_t SignedRangeMin = SE->getSignedRangeMin (SCEV).getSExtValue ();
360+ if (SignedRangeMin < 0 ) {
361+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Range bounds must be "
362+ " non-negative.\n " );
363+ break ;
364+ }
365+ DimInfo.Start = SE->getConstant (Int64Ty, SignedRangeMin);
366+ DimInfo.End = SE->getConstant (Int64Ty,
367+ SignedRangeMin + std::abs (AddRecStep) * (TripCount - 2 ));
368+ } else if (TripCount == 0 ) {
369+ if (std::abs (AddRecStep) != 1 )
370+ break ;
371+ auto Bounds = C->getLoop ()->getBounds (*SE);
372+ if (!Bounds) {
373+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Failed to get loop bounds.\n " );
374+ break ;
375+ }
376+ auto *InitValue = &Bounds->getInitialIVValue ();
377+ auto *FinalValue = &Bounds->getFinalIVValue ();
378+ if (!SE->isSCEVable (InitValue->getType ()) ||
379+ !SE->isSCEVable (FinalValue->getType ())) {
380+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Loop bound is not SCEVable.\n " );
381+ break ;
382+ }
383+ if (!InitValue->getType ()->isIntegerTy () ||
384+ !FinalValue->getType ()->isIntegerTy ()) {
385+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Non-integer loop bound.\n " );
386+ break ;
387+ }
388+ auto Predicate = Bounds->getCanonicalPredicate ();
389+ if (!ICmpInst::isRelational (Predicate)) {
390+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Bad predicate.\n " );
391+ break ;
392+ }
393+ if (Bounds->getDirection () == Loop::LoopBounds::Direction::Unknown) {
394+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Unknown direction.\n " );
395+ break ;
396+ }
397+ auto LoopStep = cast<SCEVConstant>(
398+ SE->getSCEV (Bounds->getStepValue ()))->getAPInt ().getSExtValue ();
399+ auto InitSCEV = SE->getSCEV (InitValue);
400+ auto FinalSCEV = SE->getSCEV (FinalValue);
401+ if (Bounds->getDirection () == Loop::LoopBounds::Direction::Increasing &&
402+ (Predicate == Predicate::ICMP_SGT ||
403+ Predicate == Predicate::ICMP_SGE ||
404+ Predicate == Predicate::ICMP_UGT ||
405+ Predicate == Predicate::ICMP_UGE) ||
406+ (Bounds->getDirection () == Loop::LoopBounds::Direction::Decreasing &&
407+ (Predicate == Predicate::ICMP_SLT ||
408+ Predicate == Predicate::ICMP_SLE ||
409+ Predicate == Predicate::ICMP_ULT ||
410+ Predicate == Predicate::ICMP_ULE))) {
411+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Unpredictable predicate.\n " );
412+ break ;
413+ }
414+ if (Bounds->getDirection () == Loop::LoopBounds::Direction::Increasing) {
415+ if (Predicate == Predicate::ICMP_SLT ||
416+ Predicate == Predicate::ICMP_ULT) {
417+ FinalSCEV = SE->getMinusSCEV (FinalSCEV, SE->getOne (Int64Ty));
418+ }
419+ } else {
420+ // std::swap(InitSCEV, FinalSCEV);
421+ if (Predicate == Predicate::ICMP_SGT ||
422+ Predicate == Predicate::ICMP_UGT) {
423+ FinalSCEV = SE->getAddExpr (SE->getOne (Int64Ty), FinalSCEV);
424+ }
425+ }
426+ auto ZeroItr = C->evaluateAtIteration (SE->getZero (Int64Ty), *SE);
427+ auto IdxExprStep = AddRecStep / LoopStep;
428+ LLVM_DEBUG (dbgs () << " [AGGREGATE] LoopStep: " << LoopStep <<
429+ " , IdxExprStep: " << IdxExprStep << " \n " );
430+ if (LoopStep > 0 && IdxExprStep > 0 ) {
431+ DimInfo.Start = ZeroItr;
432+ DimInfo.End = C->evaluateAtIteration (
433+ SE->getMinusSCEV (FinalSCEV, InitSCEV), *SE);
434+ } else if (LoopStep > 0 && IdxExprStep < 0 ) {
435+ DimInfo.Start = C->evaluateAtIteration (
436+ SE->getMinusSCEV (FinalSCEV, InitSCEV), *SE);
437+ DimInfo.End = ZeroItr;
438+ } else if (LoopStep < 0 && IdxExprStep > 0 ) {
439+ DimInfo.Start = C->evaluateAtIteration (
440+ SE->getMinusSCEV (InitSCEV, FinalSCEV), *SE);
441+ DimInfo.End = ZeroItr;
442+ } else {
443+ DimInfo.Start = ZeroItr;
444+ DimInfo.End = C->evaluateAtIteration (
445+ SE->getMinusSCEV (InitSCEV, FinalSCEV), *SE);
446+ }
447+ auto CmpStartEnd = compareSCEVs (DimInfo.Start , DimInfo.End , SE);
448+ if (CmpStartEnd && *CmpStartEnd > 0 ) {
449+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Incorrect bounds.\n " );
450+ break ;
451+ }
452+ } else {
453+ LLVM_DEBUG (dbgs () << " [AGGREGATE] Invalid trip count.\n " );
364454 break ;
365455 }
366- DimInfo.Start = SE->getConstant (Int64Ty, StartValue);
367- auto StepValue = std::abs (cast<SCEVConstant>(StepSCEV)->getAPInt ().
368- getSExtValue ());
369- DimInfo.Step = SE->getConstant (Int64Ty, StepValue);
370- DimInfo.End = SE->getConstant (Int64Ty,
371- StartValue + (TripCount - 2 ) * StepValue);
456+ DimInfo.Step = SE->getConstant (Int64Ty, std::abs (AddRecStep));
372457 assert (DimInfo.Start && DimInfo.End && DimInfo.Step &&
373458 " Dimension bounds and step must be specified!" );
374- if (StartValue + StepValue * (TripCount - 2 ) >= DimInfo.DimSize &&
375- DimensionN != 0 ) {
459+ if (isa<SCEVConstant>(DimInfo.End ) &&
460+ cast<SCEVConstant>(DimInfo.End )->getAPInt ().
461+ getSExtValue () >= DimInfo.DimSize && DimensionN != 0 ) {
376462 LLVM_DEBUG (dbgs () << " [AGGREGATE] Array index out of bounds." );
377463 break ;
378464 }
0 commit comments