LLVM: include/llvm/Analysis/LoopAccessAnalysis.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14#ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H

15#define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H

16

20#include

21#include

22

23namespace llvm {

24

25class AAResults;

26class DataLayout;

27class Loop;

28class raw_ostream;

29class TargetTransformInfo;

30

31

32

34

36

37

39

41

43

44

45

47

48

49

50

51

52

54};

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

91public:

94

96

97

98

99

101

102

104

106

108 };

109

110

112

114

116

118

119

120

121

123

124

125

126

127

128

129

130

131

132

134

135

137

139

140

142

145

146

148

149

151

153

155

158

159

161

163

164

166

167

169

171

172

174

175

176

179 };

180

183 unsigned MaxTargetVectorWidthInBits)

184 : PSE(PSE), InnermostLoop(L), SymbolicStrides(SymbolicStrides),

185 MaxTargetVectorWidthInBits(MaxTargetVectorWidthInBits) {}

186

187

188

190

191

192

194

195

196

197

200

201

202

205 }

206

207

208

210 return MaxSafeVectorWidthInBits == UINT_MAX;

211 }

212

213

214

216 return MaxSafeVectorWidthInBits;

217 }

218

219

220

222 return FoundNonConstantDistanceDependence &&

224 }

225

226

227

228

230 return RecordDependences ? &Dependences : nullptr;

231 }

232

234

235

236

238 return InstMap;

239 }

240

241

242

245

246 for (unsigned I = 0; I < InstMap.size(); ++I)

248

250 }

251

252

254 bool isWrite) const;

255

256

257

259 auto I = Accesses.find({Ptr, IsWrite});

260 if (I != Accesses.end())

261 return I->second;

262 return {};

263 }

264

266

268 std::pair<const SCEV *, const SCEV *>> &

271 }

272

273private:

274

275

276

277

278

279

281 const Loop *InnermostLoop;

282

283

284

286

287

289

290

292

293

294 unsigned AccessIdx = 0;

295

296

297

298

299 uint64_t MinDepDistBytes = 0;

300

301

302

303

304

305 uint64_t MaxSafeVectorWidthInBits = -1U;

306

307

308

309 bool FoundNonConstantDistanceDependence = false;

310

311

312

313

315

316

317

318

319 bool RecordDependences = true;

320

321

322

324

325

326

327

328

329 unsigned MaxTargetVectorWidthInBits = 0;

330

331

332

334 std::pair<const SCEV *, const SCEV *>>

336

337

338 std::optionalScalarEvolution::LoopGuards LoopGuards;

339

340

341

342

343

344

345

346

347

348

349

350

351

354

355

356

357

358

359

360 bool couldPreventStoreLoadForward(uint64_t Distance, uint64_t TypeByteSize);

361

362

363

364

366

367 struct DepDistanceStrideAndSizeInfo {

368 const SCEV *Dist;

369

370

371

372

373

375 std::optional<uint64_t> CommonStride;

376

377 bool ShouldRetryWithRuntimeCheck;

379 bool AIsWrite;

380 bool BIsWrite;

381

382 DepDistanceStrideAndSizeInfo(const SCEV *Dist, uint64_t MaxStride,

383 std::optional<uint64_t> CommonStride,

384 bool ShouldRetryWithRuntimeCheck,

385 uint64_t TypeByteSize, bool AIsWrite,

386 bool BIsWrite)

387 : Dist(Dist), MaxStride(MaxStride), CommonStride(CommonStride),

388 ShouldRetryWithRuntimeCheck(ShouldRetryWithRuntimeCheck),

389 TypeByteSize(TypeByteSize), AIsWrite(AIsWrite), BIsWrite(BIsWrite) {}

390 };

391

392

393

394

395

396

397

398

399 std::variant<Dependence::DepType, DepDistanceStrideAndSizeInfo>

400 getDependenceDistanceStrideAndSize(const MemAccessInfo &A, Instruction *AInst,

402 Instruction *BInst);

403};

404

405class RuntimePointerChecking;

406

407

409

410

413

414

415

416

417

418

422

423

424

426

427

429

431

433

434

436};

437

438

442

448

453};

454

455

456

459

460public:

462

464

465

467

468

470

472

473

475

477

479

481

488 };

489

491 : DC(DC), SE(SE) {}

492

493

495 Need = false;

496 CanUseDiffCheck = true;

499 DiffChecks.clear();

500 }

501

502

503

504

505

506

508 bool WritePtr, unsigned DepSetId, unsigned ASId,

510

511

513

514

515

517 bool UseDependencies);

518

519

520

522 return Checks;

523 }

524

525

526

527

528

529

530 std::optional<ArrayRef> getDiffChecks() const {

531 if (!CanUseDiffCheck)

532 return std::nullopt;

533 return {DiffChecks};

534 }

535

536

537

540

541

542

544

545

547

548

551 unsigned Depth = 0) const;

552

553

555

556

558

559

561

562

563

564

565

566 static bool

568 unsigned PtrIdx1, unsigned PtrIdx2);

569

570

571

573

574

577 }

578

580

581private:

582

583

584

585

587 bool UseDependencies);

588

589

591

592

593

594

597

599

600

602

603

604

606

607

608 bool CanUseDiffCheck = true;

609

610

611

613};

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

637public:

641

642

643

644

645

646

647

649

650

651

652

654

656 return PtrRtChecking.get();

657 }

658

659

660

662 return PtrRtChecking->getNumberOfChecks();

663 }

664

665

666

669

670

672

675

676

677

679

680

681

683

684

685

687 bool isWrite) const {

688 return DepChecker->getInstructionsForAccess(Ptr, isWrite);

689 }

690

691

692

694 return SymbolicStrides;

695 }

696

697

699

700

701

703 return HasStoreStoreDependenceInvolvingLoopInvariantAddress;

704 }

705

706

707

709 return HasLoadStoreDependenceInvolvingLoopInvariantAddress;

710 }

711

712

714 return StoresToInvariantAddresses;

715 }

716

717

718

719

720

721

723

724private:

725

726

729

730

731

732 bool canAnalyzeLoop();

733

734

735

736

737

738

741

742

743

744

745

746 void collectStridedAccess(Value *LoadOrStoreInst);

747

748

749

750

751 void emitUnsafeDependenceRemark();

752

753 std::unique_ptr PSE;

754

755

756

757 std::unique_ptr PtrRtChecking;

758

759

760

761 std::unique_ptr DepChecker;

762

763 Loop *TheLoop;

764

765 unsigned NumLoads = 0;

766 unsigned NumStores = 0;

767

768

769 bool CanVecMem = false;

770 bool HasConvergentOp = false;

771

772

773

774 bool HasStoreStoreDependenceInvolvingLoopInvariantAddress = false;

775

776

777 bool HasLoadStoreDependenceInvolvingLoopInvariantAddress = false;

778

779

781

782

783

784 std::unique_ptr Report;

785

786

787

789};

790

791

792

793

794

795

796

797

798

799

800const SCEV *

802 const DenseMap<Value *, const SCEV *> &PtrToStride,

803 Value *Ptr);

804

805

806

807

808

809

810

811

812

813

814

815

816

817

818

819

820std::optional<int64_t>

821getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,

822 const Loop *Lp,

823 const DenseMap<Value *, const SCEV *> &StridesMap = DenseMap<Value *, const SCEV *>(),

824 bool Assume = false, bool ShouldCheckWrap = true);

825

826

827

828

829

830

831std::optional getPointersDiff(Type *ElemTyA, Value *PtrA, Type *ElemTyB,

832 Value *PtrB, const DataLayout &DL,

833 ScalarEvolution &SE,

834 bool StrictCheck = false,

836

837

838

839

840

841

842

843

844

845

846

847bool sortPtrAccesses(ArrayRef<Value *> VL, Type *ElemTy, const DataLayout &DL,

848 ScalarEvolution &SE,

849 SmallVectorImpl &SortedIndices);

850

851

852

854 ScalarEvolution &SE, bool CheckType = true);

855

857

859

860

867

868public:

872 : SE(SE), AA(AA), DT(DT), LI(LI), TTI(TTI), TLI(TLI) {}

873

875

877

880};

881

882

883

884

885

886

887

888

893

894public:

896

898};

899

903}

904

908}

909

910}

911

912#endif

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

MapVector< const Value *, unsigned > OrderMap

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...

static LLVM_ATTRIBUTE_ALWAYS_INLINE bool CheckType(MVT::SimpleValueType VT, SDValue N, const TargetLowering *TLI, const DataLayout &DL)

API to communicate dependencies between analyses during invalidation.

A container for analyses that lazily runs them and caches their results.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

LLVM Basic Block Representation.

Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.

EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...

An instruction for reading from memory.

This analysis provides dependence information for the memory accesses of a loop.

LoopAccessInfoManager Result

Result run(Function &F, FunctionAnalysisManager &AM)

bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv)

const LoopAccessInfo & getInfo(Loop &L)

LoopAccessInfoManager(ScalarEvolution &SE, AAResults &AA, DominatorTree &DT, LoopInfo &LI, TargetTransformInfo *TTI, const TargetLibraryInfo *TLI)

Drive the analysis of memory accesses in the loop.

const MemoryDepChecker & getDepChecker() const

the Memory Dependence Checker which can determine the loop-independent and loop-carried dependences b...

ArrayRef< StoreInst * > getStoresToInvariantAddresses() const

Return the list of stores to invariant addresses.

const OptimizationRemarkAnalysis * getReport() const

The diagnostics report generated for the analysis.

const RuntimePointerChecking * getRuntimePointerChecking() const

bool canVectorizeMemory() const

Return true we can analyze the memory accesses in the loop and there are no memory dependence cycles.

unsigned getNumLoads() const

unsigned getNumRuntimePointerChecks() const

Number of memchecks required to prove independence of otherwise may-alias pointers.

bool isInvariant(Value *V) const

Returns true if value V is loop invariant.

bool hasLoadStoreDependenceInvolvingLoopInvariantAddress() const

Return true if the loop has memory dependence involving a load and a store to an invariant address,...

void print(raw_ostream &OS, unsigned Depth=0) const

Print the information about the memory accesses in the loop.

const PredicatedScalarEvolution & getPSE() const

Used to add runtime SCEV checks.

unsigned getNumStores() const

static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop, DominatorTree *DT)

Return true if the block BB needs to be predicated in order for the loop to be vectorized.

SmallVector< Instruction *, 4 > getInstructionsForAccess(Value *Ptr, bool isWrite) const

Return the list of instructions that use Ptr to read or write memory.

const DenseMap< Value *, const SCEV * > & getSymbolicStrides() const

If an access has a symbolic strides, this maps the pointer value to the stride symbol.

bool hasStoreStoreDependenceInvolvingLoopInvariantAddress() const

Return true if the loop has memory dependence involving two stores to an invariant address,...

bool hasConvergentOp() const

Return true if there is a convergent operation in the loop.

Represents a single loop in the control flow graph.

Checks memory dependences among accesses to the same underlying object to determine whether there vec...

ArrayRef< unsigned > getOrderForAccess(Value *Ptr, bool IsWrite) const

Return the program order indices for the access location (Ptr, IsWrite).

bool isSafeForAnyVectorWidth() const

Return true if the number of elements that are safe to operate on simultaneously is not bounded.

bool areDepsSafe(const DepCandidates &AccessSets, const MemAccessInfoList &CheckDeps)

Check whether the dependencies between the accesses are safe.

EquivalenceClasses< MemAccessInfo > DepCandidates

Set of potential dependent memory accesses.

MemoryDepChecker(PredicatedScalarEvolution &PSE, const Loop *L, const DenseMap< Value *, const SCEV * > &SymbolicStrides, unsigned MaxTargetVectorWidthInBits)

const SmallVectorImpl< Instruction * > & getMemoryInstructions() const

The vector of memory access instructions.

const Loop * getInnermostLoop() const

uint64_t getMaxSafeVectorWidthInBits() const

Return the number of elements that are safe to operate on simultaneously, multiplied by the size of t...

bool isSafeForVectorization() const

No memory dependence was encountered that would inhibit vectorization.

const SmallVectorImpl< Dependence > * getDependences() const

Returns the memory dependences.

DenseMap< std::pair< const SCEV *, Type * >, std::pair< const SCEV *, const SCEV * > > & getPointerBounds()

SmallVector< MemAccessInfo, 8 > MemAccessInfoList

SmallVector< Instruction *, 4 > getInstructionsForAccess(Value *Ptr, bool isWrite) const

Find the set of instructions that read or write via Ptr.

VectorizationSafetyStatus

Type to keep track of the status of the dependence check.

@ PossiblySafeWithRtChecks

bool shouldRetryWithRuntimeCheck() const

In same cases when the dependency check fails we can still vectorize the loop with a dynamic array ac...

void addAccess(StoreInst *SI)

Register the location (instructions are given increasing numbers) of a write access.

PointerIntPair< Value *, 1, bool > MemAccessInfo

DenseMap< Instruction *, unsigned > generateInstructionOrderMap() const

Generate a mapping between the memory instructions and their indices according to program order.

PointerIntPair - This class implements a pair of a pointer and small integer.

An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...

A set of analyses that are preserved following a run of a transformation pass.

Holds information about the memory runtime legality checks to verify that a group of pointers do not ...

bool Need

This flag indicates if we need to add the runtime check.

void reset()

Reset the state of the pointer runtime information.

unsigned getNumberOfChecks() const

Returns the number of run-time checks required according to needsChecking.

RuntimePointerChecking(MemoryDepChecker &DC, ScalarEvolution *SE)

void printChecks(raw_ostream &OS, const SmallVectorImpl< RuntimePointerCheck > &Checks, unsigned Depth=0) const

Print Checks.

bool needsChecking(const RuntimeCheckingPtrGroup &M, const RuntimeCheckingPtrGroup &N) const

Decide if we need to add a check between two groups of pointers, according to needsChecking.

void print(raw_ostream &OS, unsigned Depth=0) const

Print the list run-time memory checks necessary.

std::optional< ArrayRef< PointerDiffInfo > > getDiffChecks() const

SmallVector< RuntimeCheckingPtrGroup, 2 > CheckingGroups

Holds a partitioning of pointers into "check groups".

static bool arePointersInSamePartition(const SmallVectorImpl< int > &PtrToPartition, unsigned PtrIdx1, unsigned PtrIdx2)

Check if pointers are in the same partition.

bool empty() const

No run-time memory checking is necessary.

SmallVector< PointerInfo, 2 > Pointers

Information about the pointers that may require checking.

ScalarEvolution * getSE() const

void insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr, Type *AccessTy, bool WritePtr, unsigned DepSetId, unsigned ASId, PredicatedScalarEvolution &PSE, bool NeedsFreeze)

Insert a pointer and calculate the start and end SCEVs.

const SmallVectorImpl< RuntimePointerCheck > & getChecks() const

Returns the checks that generateChecks created.

const PointerInfo & getPointerInfo(unsigned PtrIdx) const

Return PointerInfo for pointer at index PtrIdx.

This class represents an analyzed expression in the program.

The main scalar evolution driver.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

An instruction for storing to memory.

StringRef - Represent a constant reference to a string, i.e.

Provides information about what library functions are available for the current target.

This pass provides access to the codegen interfaces that are needed for IR-level transformations.

Value handle that tracks a Value across RAUW.

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM Value Representation.

This class implements an extremely fast bulk output stream that can only output to a stream.

This is an optimization pass for GlobalISel generic memory operations.

std::optional< int > getPointersDiff(Type *ElemTyA, Value *PtrA, Type *ElemTyB, Value *PtrB, const DataLayout &DL, ScalarEvolution &SE, bool StrictCheck=false, bool CheckType=true)

Returns the distance between the pointers PtrA and PtrB iff they are compatible and it is possible to...

std::pair< const RuntimeCheckingPtrGroup *, const RuntimeCheckingPtrGroup * > RuntimePointerCheck

A memcheck which made up of a pair of grouped pointers.

std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DenseMap< Value *, const SCEV * > &StridesMap=DenseMap< Value *, const SCEV * >(), bool Assume=false, bool ShouldCheckWrap=true)

If the pointer has a constant stride return it in units of the access type size.

bool sortPtrAccesses(ArrayRef< Value * > VL, Type *ElemTy, const DataLayout &DL, ScalarEvolution &SE, SmallVectorImpl< unsigned > &SortedIndices)

Attempt to sort the pointers in VL and return the sorted indices in SortedIndices,...

const SCEV * replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE, const DenseMap< Value *, const SCEV * > &PtrToStride, Value *Ptr)

Return the SCEV corresponding to a pointer with the symbolic stride replaced with constant one,...

bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL, ScalarEvolution &SE, bool CheckType=true)

Returns true if the memory operations A and B are consecutive.

IR Values for the lower and upper bounds of a pointer evolution.

A CRTP mix-in that provides informational APIs needed for analysis passes.

A special type used by analysis passes to provide an address that identifies that particular analysis...

Dependece between memory access instructions.

Instruction * getDestination(const MemoryDepChecker &DepChecker) const

Return the destination instruction of the dependence.

DepType Type

The type of the dependence.

unsigned Destination

Index of the destination of the dependence in the InstMap vector.

Dependence(unsigned Source, unsigned Destination, DepType Type)

bool isPossiblyBackward() const

May be a lexically backward dependence type (includes Unknown).

Instruction * getSource(const MemoryDepChecker &DepChecker) const

Return the source instruction of the dependence.

bool isForward() const

Lexically forward dependence.

bool isBackward() const

Lexically backward dependence.

void print(raw_ostream &OS, unsigned Depth, const SmallVectorImpl< Instruction * > &Instrs) const

Print the dependence.

unsigned Source

Index of the source of the dependence in the InstMap vector.

DepType

The type of the dependence.

@ BackwardVectorizableButPreventsForwarding

@ ForwardButPreventsForwarding

static const char * DepName[]

String version of the types.

PointerDiffInfo(const SCEV *SrcStart, const SCEV *SinkStart, unsigned AccessSize, bool NeedsFreeze)

unsigned AddressSpace

Address space of the involved pointers.

bool addPointer(unsigned Index, const RuntimePointerChecking &RtCheck)

Tries to add the pointer recorded in RtCheck at index Index to this pointer checking group.

bool NeedsFreeze

Whether the pointer needs to be frozen after expansion, e.g.

const SCEV * High

The SCEV expression which represents the upper bound of all the pointers in this group.

SmallVector< unsigned, 2 > Members

Indices of all the pointers that constitute this grouping.

const SCEV * Low

The SCEV expression which represents the lower bound of all the pointers in this group.

PointerInfo(Value *PointerValue, const SCEV *Start, const SCEV *End, bool IsWritePtr, unsigned DependencySetId, unsigned AliasSetId, const SCEV *Expr, bool NeedsFreeze)

const SCEV * Start

Holds the smallest byte address accessed by the pointer throughout all iterations of the loop.

const SCEV * Expr

SCEV for the access.

bool NeedsFreeze

True if the pointer expressions needs to be frozen after expansion.

bool IsWritePtr

Holds the information if this pointer is used for writing to memory.

unsigned DependencySetId

Holds the id of the set of pointers that could be dependent because of a shared underlying object.

unsigned AliasSetId

Holds the id of the disjoint alias set to which this pointer belongs.

const SCEV * End

Holds the largest byte address accessed by the pointer throughout all iterations of the loop,...

TrackingVH< Value > PointerValue

Holds the pointer value that we need to check.

Collection of parameters shared beetween the Loop Vectorizer and the Loop Access Analysis.

static const unsigned MaxVectorWidth

Maximum SIMD width.

static unsigned VectorizationFactor

VF as overridden by the user.

static unsigned RuntimeMemoryCheckThreshold

\When performing memory disambiguation checks at runtime do not make more than this number of compari...

static bool isInterleaveForced()

True if force-vector-interleave was specified by the user.

static unsigned VectorizationInterleave

Interleave factor as overridden by the user.

static bool HoistRuntimeChecks