Skip to content

Commit df4d7d3

Browse files
[SandboxIR] Add pointer-diff utility function (#110343)
This will be used when gathering seeds to calculate the lane an instruction in the bundle uses. This is a retry of PR 110176, which somehow got messed up while resolving a merge conflict.
1 parent 41dca01 commit df4d7d3

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

llvm/include/llvm/SandboxIR/Utils.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
#ifndef LLVM_SANDBOXIR_UTILS_H
1313
#define LLVM_SANDBOXIR_UTILS_H
1414

15+
#include "llvm/Analysis/LoopAccessAnalysis.h"
1516
#include "llvm/Analysis/MemoryLocation.h"
17+
#include "llvm/Analysis/ScalarEvolution.h"
18+
#include "llvm/Analysis/ValueTracking.h"
1619
#include "llvm/SandboxIR/Instruction.h"
20+
#include <optional>
1721

1822
namespace llvm::sandboxir {
1923

@@ -57,6 +61,38 @@ class Utils {
5761
memoryLocationGetOrNone(const Instruction *I) {
5862
return llvm::MemoryLocation::getOrNone(cast<llvm::Instruction>(I->Val));
5963
}
64+
65+
/// \Returns the gap between the memory locations accessed by \p I0 and
66+
/// \p I1 in bytes.
67+
template <typename LoadOrStoreT>
68+
static std::optional<int>
69+
getPointerDiffInBytes(LoadOrStoreT *I0, LoadOrStoreT *I1, ScalarEvolution &SE,
70+
const DataLayout &DL) {
71+
static_assert(std::is_same_v<LoadOrStoreT, LoadInst> ||
72+
std::is_same_v<LoadOrStoreT, StoreInst>,
73+
"Expected sandboxir::Load or sandboxir::Store!");
74+
llvm::Value *Opnd0 = I0->getPointerOperand()->Val;
75+
llvm::Value *Opnd1 = I1->getPointerOperand()->Val;
76+
llvm::Value *Ptr0 = getUnderlyingObject(Opnd0);
77+
llvm::Value *Ptr1 = getUnderlyingObject(Opnd1);
78+
if (Ptr0 != Ptr1)
79+
return false;
80+
llvm::Type *ElemTy = llvm::Type::getInt8Ty(SE.getContext());
81+
return getPointersDiff(ElemTy, Opnd0, ElemTy, Opnd1, DL, SE,
82+
/*StrictCheck=*/false, /*CheckType=*/false);
83+
}
84+
85+
/// \Returns true if \p I0 accesses a memory location lower than \p I1.
86+
/// Returns false if the difference cannot be determined, if the memory
87+
/// locations are equal, or if I1 accesses a memory location greater than I0.
88+
template <typename LoadOrStoreT>
89+
static bool atLowerAddress(LoadOrStoreT *I0, LoadOrStoreT *I1,
90+
ScalarEvolution &SE, const DataLayout &DL) {
91+
auto Diff = getPointerDiffInBytes(I0, I1, SE, DL);
92+
if (!Diff)
93+
return false;
94+
return *Diff > 0;
95+
}
6096
};
6197
} // namespace llvm::sandboxir
6298

llvm/unittests/SandboxIR/UtilsTest.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/SandboxIR/Utils.h"
10+
#include "llvm/Analysis/AssumptionCache.h"
11+
#include "llvm/Analysis/BasicAliasAnalysis.h"
12+
#include "llvm/Analysis/LoopInfo.h"
13+
#include "llvm/Analysis/TargetLibraryInfo.h"
1014
#include "llvm/AsmParser/Parser.h"
1115
#include "llvm/IR/BasicBlock.h"
1216
#include "llvm/IR/DataLayout.h"
17+
#include "llvm/IR/Dominators.h"
1318
#include "llvm/IR/Function.h"
1419
#include "llvm/IR/Instruction.h"
1520
#include "llvm/IR/Module.h"
@@ -55,3 +60,77 @@ define void @foo(ptr %arg0) {
5560
EXPECT_EQ(sandboxir::Utils::memoryLocationGetOrNone(Ld),
5661
MemoryLocation::getOrNone(LLVMLd));
5762
}
63+
64+
TEST_F(UtilsTest, GetPointerDiffInBytes) {
65+
parseIR(C, R"IR(
66+
define void @foo(ptr %ptr) {
67+
%gep0 = getelementptr inbounds float, ptr %ptr, i64 0
68+
%gep1 = getelementptr inbounds float, ptr %ptr, i64 1
69+
%gep2 = getelementptr inbounds float, ptr %ptr, i64 2
70+
%gep3 = getelementptr inbounds float, ptr %ptr, i64 3
71+
72+
%ld0 = load float, ptr %gep0
73+
%ld1 = load float, ptr %gep1
74+
%ld2 = load float, ptr %gep2
75+
%ld3 = load float, ptr %gep3
76+
77+
%v2ld0 = load <2 x float>, ptr %gep0
78+
%v2ld1 = load <2 x float>, ptr %gep1
79+
%v2ld2 = load <2 x float>, ptr %gep2
80+
%v2ld3 = load <2 x float>, ptr %gep3
81+
82+
%v3ld0 = load <3 x float>, ptr %gep0
83+
%v3ld1 = load <3 x float>, ptr %gep1
84+
%v3ld2 = load <3 x float>, ptr %gep2
85+
%v3ld3 = load <3 x float>, ptr %gep3
86+
ret void
87+
}
88+
)IR");
89+
llvm::Function &LLVMF = *M->getFunction("foo");
90+
DominatorTree DT(LLVMF);
91+
TargetLibraryInfoImpl TLII;
92+
TargetLibraryInfo TLI(TLII);
93+
DataLayout DL(M->getDataLayout());
94+
AssumptionCache AC(LLVMF);
95+
BasicAAResult BAA(DL, LLVMF, TLI, AC, &DT);
96+
AAResults AA(TLI);
97+
AA.addAAResult(BAA);
98+
LoopInfo LI(DT);
99+
ScalarEvolution SE(LLVMF, TLI, AC, DT, LI);
100+
sandboxir::Context Ctx(C);
101+
102+
auto &F = *Ctx.createFunction(&LLVMF);
103+
auto &BB = *F.begin();
104+
auto It = std::next(BB.begin(), 4);
105+
auto *L0 = cast<sandboxir::LoadInst>(&*It++);
106+
auto *L1 = cast<sandboxir::LoadInst>(&*It++);
107+
auto *L2 = cast<sandboxir::LoadInst>(&*It++);
108+
[[maybe_unused]] auto *L3 = cast<sandboxir::LoadInst>(&*It++);
109+
110+
auto *V2L0 = cast<sandboxir::LoadInst>(&*It++);
111+
auto *V2L1 = cast<sandboxir::LoadInst>(&*It++);
112+
auto *V2L2 = cast<sandboxir::LoadInst>(&*It++);
113+
auto *V2L3 = cast<sandboxir::LoadInst>(&*It++);
114+
115+
[[maybe_unused]] auto *V3L0 = cast<sandboxir::LoadInst>(&*It++);
116+
auto *V3L1 = cast<sandboxir::LoadInst>(&*It++);
117+
[[maybe_unused]] auto *V3L2 = cast<sandboxir::LoadInst>(&*It++);
118+
[[maybe_unused]] auto *V3L3 = cast<sandboxir::LoadInst>(&*It++);
119+
120+
// getPointerDiffInBytes
121+
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, L1, SE, DL), 4);
122+
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, L2, SE, DL), 8);
123+
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L1, L0, SE, DL), -4);
124+
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, V2L0, SE, DL), 0);
125+
126+
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, V2L1, SE, DL), 4);
127+
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, V3L1, SE, DL), 4);
128+
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L0, V2L2, SE, DL), 8);
129+
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L0, V2L3, SE, DL), 12);
130+
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L3, V2L0, SE, DL), -12);
131+
132+
// atLowerAddress
133+
EXPECT_TRUE(sandboxir::Utils::atLowerAddress(L0, L1, SE, DL));
134+
EXPECT_FALSE(sandboxir::Utils::atLowerAddress(L1, L0, SE, DL));
135+
EXPECT_FALSE(sandboxir::Utils::atLowerAddress(L3, V3L3, SE, DL));
136+
}

0 commit comments

Comments
 (0)