Skip to content

Commit 40463e6

Browse files
committed
record runtime predicates on each Dependence relation
1 parent a80c878 commit 40463e6

File tree

4 files changed

+73
-23
lines changed

4 files changed

+73
-23
lines changed

llvm/include/llvm/Analysis/DependenceAnalysis.h

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,12 @@ namespace llvm {
7676
Dependence &operator=(Dependence &&) = default;
7777

7878
public:
79-
Dependence(Instruction *Source, Instruction *Destination)
80-
: Src(Source), Dst(Destination) {}
79+
Dependence(Instruction *Source, Instruction *Destination,
80+
ScalarEvolution *SE,
81+
const SmallVectorImpl<const SCEVPredicate *> &Assumes)
82+
: Src(Source), Dst(Destination), SE(SE) {
83+
Assumptions.append(Assumes.begin(), Assumes.end());
84+
}
8185
virtual ~Dependence() = default;
8286

8387
/// Dependence::DVEntry - Each level in the distance/direction vector
@@ -205,6 +209,10 @@ namespace llvm {
205209
/// field.
206210
void setNextSuccessor(const Dependence *succ) { NextSuccessor = succ; }
207211

212+
/// getRuntimeAssumptions - Returns the runtime assumptions under which this
213+
/// Dependence relation is valid.
214+
SCEVUnionPredicate getRuntimeAssumptions() const;
215+
208216
/// dump - For debugging purposes, dumps a dependence to OS.
209217
///
210218
void dump(raw_ostream &OS) const;
@@ -213,6 +221,8 @@ namespace llvm {
213221
Instruction *Src, *Dst;
214222

215223
private:
224+
ScalarEvolution *SE;
225+
SmallVector<const SCEVPredicate *, 4> Assumptions;
216226
const Dependence *NextPredecessor = nullptr, *NextSuccessor = nullptr;
217227
friend class DependenceInfo;
218228
};
@@ -227,8 +237,10 @@ namespace llvm {
227237
/// input dependences are unordered.
228238
class FullDependence final : public Dependence {
229239
public:
230-
FullDependence(Instruction *Src, Instruction *Dst, bool LoopIndependent,
231-
unsigned Levels);
240+
FullDependence(Instruction *Source, Instruction *Destination,
241+
ScalarEvolution *SE,
242+
const SmallVectorImpl<const SCEVPredicate *> &Assumes,
243+
bool PossiblyLoopIndependent, unsigned Levels);
232244

233245
/// isLoopIndependent - Returns true if this is a loop-independent
234246
/// dependence.
@@ -304,9 +316,13 @@ namespace llvm {
304316

305317
/// depends - Tests for a dependence between the Src and Dst instructions.
306318
/// Returns NULL if no dependence; otherwise, returns a Dependence (or a
307-
/// FullDependence) with as much information as can be gleaned.
308-
std::unique_ptr<Dependence> depends(Instruction *Src,
309-
Instruction *Dst);
319+
/// FullDependence) with as much information as can be gleaned. By default,
320+
/// the dependence test collects a set of runtime assumptions that cannot be
321+
/// solved at compilation time. Set UnderRuntimeAssumptions to false for a
322+
/// safe approximation of the dependence relation that does not require
323+
/// runtime checks.
324+
std::unique_ptr<Dependence> depends(Instruction *Src, Instruction *Dst,
325+
bool UnderRuntimeAssumptions = true);
310326

311327
/// getSplitIteration - Give a dependence that's splittable at some
312328
/// particular level, return the iteration that should be used to split
@@ -351,7 +367,10 @@ namespace llvm {
351367
const SCEV *getSplitIteration(const Dependence &Dep, unsigned Level);
352368

353369
Function *getFunction() const { return F; }
354-
SCEVUnionPredicate getRuntimeAssumptions();
370+
371+
/// getRuntimeAssumptions - Returns all the runtime assumptions under which
372+
/// the dependence test is valid.
373+
SCEVUnionPredicate getRuntimeAssumptions() const;
355374

356375
private:
357376
AAResults *AA;

llvm/lib/Analysis/DependenceAnalysis.cpp

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,11 @@ bool Dependence::isScalar(unsigned level) const {
268268
//===----------------------------------------------------------------------===//
269269
// FullDependence methods
270270

271-
FullDependence::FullDependence(Instruction *Source, Instruction *Destination,
272-
bool PossiblyLoopIndependent,
273-
unsigned CommonLevels)
274-
: Dependence(Source, Destination), Levels(CommonLevels),
271+
FullDependence::FullDependence(
272+
Instruction *Source, Instruction *Destination, ScalarEvolution *SE,
273+
const SmallVectorImpl<const SCEVPredicate *> &Assumes,
274+
bool PossiblyLoopIndependent, unsigned CommonLevels)
275+
: Dependence(Source, Destination, SE, Assumes), Levels(CommonLevels),
275276
LoopIndependent(PossiblyLoopIndependent) {
276277
Consistent = true;
277278
if (CommonLevels)
@@ -711,6 +712,12 @@ void Dependence::dump(raw_ostream &OS) const {
711712
OS << " splitable";
712713
}
713714
OS << "!\n";
715+
716+
SCEVUnionPredicate Assumptions = getRuntimeAssumptions();
717+
if (!Assumptions.isAlwaysTrue()) {
718+
OS << " Runtime Assumptions:\n";
719+
Assumptions.print(OS, 2);
720+
}
714721
}
715722

716723
// Returns NoAlias/MayAliass/MustAlias for two memory locations based upon their
@@ -3574,7 +3581,11 @@ bool DependenceInfo::invalidate(Function &F, const PreservedAnalyses &PA,
35743581
Inv.invalidate<LoopAnalysis>(F, PA);
35753582
}
35763583

3577-
SCEVUnionPredicate DependenceInfo::getRuntimeAssumptions() {
3584+
SCEVUnionPredicate DependenceInfo::getRuntimeAssumptions() const {
3585+
return SCEVUnionPredicate(Assumptions, *SE);
3586+
}
3587+
3588+
SCEVUnionPredicate Dependence::getRuntimeAssumptions() const {
35783589
return SCEVUnionPredicate(Assumptions, *SE);
35793590
}
35803591

@@ -3590,7 +3601,9 @@ SCEVUnionPredicate DependenceInfo::getRuntimeAssumptions() {
35903601
// Care is required to keep the routine below, getSplitIteration(),
35913602
// up to date with respect to this routine.
35923603
std::unique_ptr<Dependence>
3593-
DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
3604+
DependenceInfo::depends(Instruction *Src, Instruction *Dst,
3605+
bool UnderRuntimeAssumptions) {
3606+
SmallVector<const SCEVPredicate *, 4> Assume;
35943607
bool PossiblyLoopIndependent = true;
35953608
if (Src == Dst)
35963609
PossiblyLoopIndependent = false;
@@ -3602,7 +3615,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
36023615
if (!isLoadOrStore(Src) || !isLoadOrStore(Dst)) {
36033616
// can only analyze simple loads and stores, i.e., no calls, invokes, etc.
36043617
LLVM_DEBUG(dbgs() << "can only handle simple loads and stores\n");
3605-
return std::make_unique<Dependence>(Src, Dst);
3618+
return std::make_unique<Dependence>(Src, Dst, SE, Assume);
36063619
}
36073620

36083621
const MemoryLocation &DstLoc = MemoryLocation::get(Dst);
@@ -3613,7 +3626,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
36133626
case AliasResult::PartialAlias:
36143627
// cannot analyse objects if we don't understand their aliasing.
36153628
LLVM_DEBUG(dbgs() << "can't analyze may or partial alias\n");
3616-
return std::make_unique<Dependence>(Src, Dst);
3629+
return std::make_unique<Dependence>(Src, Dst, SE, Assume);
36173630
case AliasResult::NoAlias:
36183631
// If the objects noalias, they are distinct, accesses are independent.
36193632
LLVM_DEBUG(dbgs() << "no alias\n");
@@ -3626,7 +3639,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
36263639
// The dependence test gets confused if the size of the memory accesses
36273640
// differ.
36283641
LLVM_DEBUG(dbgs() << "can't analyze must alias with different sizes\n");
3629-
return std::make_unique<Dependence>(Src, Dst);
3642+
return std::make_unique<Dependence>(Src, Dst, SE, Assume);
36303643
}
36313644

36323645
Value *SrcPtr = getLoadStorePointerOperand(Src);
@@ -3645,7 +3658,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
36453658
// We check this upfront so we don't crash in cases where getMinusSCEV()
36463659
// returns a SCEVCouldNotCompute.
36473660
LLVM_DEBUG(dbgs() << "can't analyze SCEV with different pointer base\n");
3648-
return std::make_unique<Dependence>(Src, Dst);
3661+
return std::make_unique<Dependence>(Src, Dst, SE, Assume);
36493662
}
36503663

36513664
uint64_t EltSize = SrcLoc.Size.toRaw();
@@ -3656,18 +3669,28 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
36563669

36573670
if (Src != Dst) {
36583671
// Check that memory access offsets are multiples of element sizes.
3659-
if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assumptions) ||
3660-
!SE->isKnownMultipleOf(DstEv, EltSize, Assumptions)) {
3672+
if (!SE->isKnownMultipleOf(SrcEv, EltSize, Assume) ||
3673+
!SE->isKnownMultipleOf(DstEv, EltSize, Assume)) {
36613674
LLVM_DEBUG(dbgs() << "can't analyze SCEV with different offsets\n");
3662-
return std::make_unique<Dependence>(Src, Dst);
3675+
return std::make_unique<Dependence>(Src, Dst, SE, Assume);
36633676
}
36643677
}
36653678

3679+
if (Assumptions.empty())
3680+
Assumptions.append(Assume.begin(), Assume.end());
3681+
else
3682+
// Add non-redundant assumptions.
3683+
for (auto *P : Assume)
3684+
for (auto *A : Assumptions)
3685+
if (!A->implies(P, *SE))
3686+
Assumptions.push_back(P);
3687+
36663688
establishNestingLevels(Src, Dst);
36673689
LLVM_DEBUG(dbgs() << " common nesting levels = " << CommonLevels << "\n");
36683690
LLVM_DEBUG(dbgs() << " maximum nesting levels = " << MaxLevels << "\n");
36693691

3670-
FullDependence Result(Src, Dst, PossiblyLoopIndependent, CommonLevels);
3692+
FullDependence Result(Src, Dst, SE, Assume, PossiblyLoopIndependent,
3693+
CommonLevels);
36713694
++TotalArrayPairs;
36723695

36733696
unsigned Pairs = 1;
@@ -4065,7 +4088,7 @@ const SCEV *DependenceInfo::getSplitIteration(const Dependence &Dep,
40654088
// establish loop nesting levels
40664089
establishNestingLevels(Src, Dst);
40674090

4068-
FullDependence Result(Src, Dst, false, CommonLevels);
4091+
FullDependence Result(Src, Dst, SE, Dep.Assumptions, false, CommonLevels);
40694092

40704093
unsigned Pairs = 1;
40714094
SmallVector<Subscript, 2> Pair(Pairs);

llvm/test/Analysis/DependenceAnalysis/DifferentOffsets.ll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ define i32 @alias_with_parametric_offset(ptr nocapture %A, i64 %n) {
3030
; CHECK-NEXT: da analyze - none!
3131
; CHECK-NEXT: Src: store i32 2, ptr %arrayidx, align 1 --> Dst: %0 = load i32, ptr %A, align 1
3232
; CHECK-NEXT: da analyze - flow [|<]!
33+
; CHECK-NEXT: Runtime Assumptions:
34+
; CHECK-NEXT: Equal predicate: (zext i2 (trunc i64 %n to i2) to i64) == 0
3335
; CHECK-NEXT: Src: %0 = load i32, ptr %A, align 1 --> Dst: %0 = load i32, ptr %A, align 1
3436
; CHECK-NEXT: da analyze - none!
3537
; CHECK-NEXT: Runtime Assumptions:
@@ -48,6 +50,9 @@ define i32 @alias_with_parametric_expr(ptr nocapture %A, i64 %n, i64 %m) {
4850
; CHECK-NEXT: da analyze - none!
4951
; CHECK-NEXT: Src: store i32 2, ptr %arrayidx, align 1 --> Dst: %0 = load i32, ptr %arrayidx1, align 1
5052
; CHECK-NEXT: da analyze - flow [|<]!
53+
; CHECK-NEXT: Runtime Assumptions:
54+
; CHECK-NEXT: Equal predicate: (zext i2 ((trunc i64 %m to i2) + (-2 * (trunc i64 %n to i2))) to i64) == 0
55+
; CHECK-NEXT: Equal predicate: (zext i2 (-2 + (trunc i64 %m to i2)) to i64) == 0
5156
; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 1 --> Dst: %0 = load i32, ptr %arrayidx1, align 1
5257
; CHECK-NEXT: da analyze - none!
5358
; CHECK-NEXT: Runtime Assumptions:

llvm/test/Analysis/DependenceAnalysis/MIVCheckConst.ll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ define void @test(ptr %A, ptr %B, i1 %arg, i32 %n, i32 %m) #0 align 2 {
4242
; CHECK-NEXT: da analyze - consistent input [0 S S]!
4343
; CHECK-NEXT: Src: %v27 = load <32 x i32>, ptr %v25, align 256 --> Dst: %v32 = load <32 x i32>, ptr %v30, align 128
4444
; CHECK-NEXT: da analyze - input [* S S|<]!
45+
; CHECK-NEXT: Runtime Assumptions:
46+
; CHECK-NEXT: Equal predicate: (zext i7 (4 * (trunc i32 %v1 to i7) * (1 + (trunc i32 %n to i7))) to i32) == 0
47+
; CHECK-NEXT: Equal predicate: (8 * (zext i4 (trunc i32 %v1 to i4) to i32))<nuw><nsw> == 0
4548
; CHECK-NEXT: Src: %v32 = load <32 x i32>, ptr %v30, align 128 --> Dst: %v32 = load <32 x i32>, ptr %v30, align 128
4649
; CHECK-NEXT: da analyze - consistent input [0 S S]!
4750
; CHECK-NEXT: Runtime Assumptions:

0 commit comments

Comments
 (0)