[llvm] [SandboxIR] Add pointer-diff utility function (PR #110176)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 26 16:07:23 PDT 2024
https://github.com/Sterling-Augustine updated https://github.com/llvm/llvm-project/pull/110176
>From cba50ef42245e2c33e85c18e61be815e2b2840c2 Mon Sep 17 00:00:00 2001
From: Sterling Augustine <saugustine at google.com>
Date: Wed, 25 Sep 2024 13:18:32 -0700
Subject: [PATCH 1/2] [SandboxIR] Add pointer-diff utility function.
This will be used when gathering seeds to calculate the lane
an instruction in the bundle uses.
---
llvm/include/llvm/SandboxIR/Utils.h | 33 +++++++++++
llvm/unittests/SandboxIR/UtilsTest.cpp | 77 ++++++++++++++++++++++++++
2 files changed, 110 insertions(+)
diff --git a/llvm/include/llvm/SandboxIR/Utils.h b/llvm/include/llvm/SandboxIR/Utils.h
index 4e8a175f547059..9f1c08d2b6c308 100644
--- a/llvm/include/llvm/SandboxIR/Utils.h
+++ b/llvm/include/llvm/SandboxIR/Utils.h
@@ -12,8 +12,12 @@
#ifndef LLVM_SANDBOXIR_UTILS_H
#define LLVM_SANDBOXIR_UTILS_H
+#include "llvm/Analysis/LoopAccessAnalysis.h"
#include "llvm/Analysis/MemoryLocation.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ValueTracking.h"
#include "llvm/SandboxIR/SandboxIR.h"
+#include <optional>
namespace llvm::sandboxir {
@@ -57,6 +61,35 @@ class Utils {
memoryLocationGetOrNone(const Instruction *I) {
return llvm::MemoryLocation::getOrNone(cast<llvm::Instruction>(I->Val));
}
+ /// \Returns true if \p I1 accesses a memory location lower than \p I2.
+ template <typename LoadOrStoreT>
+ static bool atLowerAddress(LoadOrStoreT *I0, LoadOrStoreT *I1,
+ ScalarEvolution &SE, const DataLayout &DL) {
+ auto Diff = getPointerDiffInBytes(I0, I1, SE, DL);
+ if (!Diff)
+ return false;
+ return *Diff > 0;
+ }
+
+ /// \Returns the number gap between the memory locations accessed by \p I0 and
+ /// \p I1 in bytes.
+ template <typename LoadOrStoreT>
+ static std::optional<int>
+ getPointerDiffInBytes(LoadOrStoreT *I0, LoadOrStoreT *I1, ScalarEvolution &SE,
+ const DataLayout &DL) {
+ static_assert(std::is_same<LoadOrStoreT, sandboxir::LoadInst>::value ||
+ std::is_same<LoadOrStoreT, sandboxir::StoreInst>::value,
+ "Expected sandboxir::Load or sandboxir::Store!");
+ llvm::Value *Opnd0 = I0->getPointerOperand()->Val;
+ llvm::Value *Opnd1 = I1->getPointerOperand()->Val;
+ llvm::Value *Ptr0 = getUnderlyingObject(Opnd0);
+ llvm::Value *Ptr1 = getUnderlyingObject(Opnd1);
+ if (Ptr0 != Ptr1)
+ return false;
+ llvm::Type *ElemTy = llvm::Type::getInt8Ty(SE.getContext());
+ return getPointersDiff(ElemTy, Opnd0, ElemTy, Opnd1, DL, SE,
+ /*StrictCheck=*/false, /*CheckType=*/false);
+ }
};
} // namespace llvm::sandboxir
diff --git a/llvm/unittests/SandboxIR/UtilsTest.cpp b/llvm/unittests/SandboxIR/UtilsTest.cpp
index ded3edf1206a4b..7b2ce3c9b7f05e 100644
--- a/llvm/unittests/SandboxIR/UtilsTest.cpp
+++ b/llvm/unittests/SandboxIR/UtilsTest.cpp
@@ -7,9 +7,14 @@
//===----------------------------------------------------------------------===//
#include "llvm/SandboxIR/Utils.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/BasicAliasAnalysis.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Module.h"
@@ -54,3 +59,75 @@ define void @foo(ptr %arg0) {
EXPECT_EQ(sandboxir::Utils::memoryLocationGetOrNone(Ld),
MemoryLocation::getOrNone(LLVMLd));
}
+
+TEST_F(UtilsTest, GetPointerDiffInBytes) {
+ parseIR(C, R"IR(
+define void @foo(ptr %ptr) {
+ %gep0 = getelementptr inbounds float, ptr %ptr, i64 0
+ %gep1 = getelementptr inbounds float, ptr %ptr, i64 1
+ %gep2 = getelementptr inbounds float, ptr %ptr, i64 2
+ %gep3 = getelementptr inbounds float, ptr %ptr, i64 3
+
+ %ld0 = load float, ptr %gep0
+ %ld1 = load float, ptr %gep1
+ %ld2 = load float, ptr %gep2
+ %ld3 = load float, ptr %gep3
+
+ %v2ld0 = load <2 x float>, ptr %gep0
+ %v2ld1 = load <2 x float>, ptr %gep1
+ %v2ld2 = load <2 x float>, ptr %gep2
+ %v2ld3 = load <2 x float>, ptr %gep3
+
+ %v3ld0 = load <3 x float>, ptr %gep0
+ %v3ld1 = load <3 x float>, ptr %gep1
+ %v3ld2 = load <3 x float>, ptr %gep2
+ %v3ld3 = load <3 x float>, ptr %gep3
+ ret void
+}
+)IR");
+ llvm::Function &LLVMF = *M->getFunction("foo");
+ DominatorTree DT(LLVMF);
+ TargetLibraryInfoImpl TLII;
+ TargetLibraryInfo TLI(TLII);
+ DataLayout DL(M->getDataLayout());
+ AssumptionCache AC(LLVMF);
+ BasicAAResult BAA(DL, LLVMF, TLI, AC, &DT);
+ AAResults AA(TLI);
+ AA.addAAResult(BAA);
+ LoopInfo LI(DT);
+ ScalarEvolution SE(LLVMF, TLI, AC, DT, LI);
+ sandboxir::Context Ctx(C);
+
+ auto &F = *Ctx.createFunction(&LLVMF);
+ auto &BB = *F.begin();
+ auto It = std::next(BB.begin(), 4);
+ auto *L0 = cast<sandboxir::LoadInst>(&*It++);
+ auto *L1 = cast<sandboxir::LoadInst>(&*It++);
+ auto *L2 = cast<sandboxir::LoadInst>(&*It++);
+ auto *L3 = cast<sandboxir::LoadInst>(&*It++);
+ (void)L3;
+
+ auto *V2L0 = cast<sandboxir::LoadInst>(&*It++);
+ auto *V2L1 = cast<sandboxir::LoadInst>(&*It++);
+ auto *V2L2 = cast<sandboxir::LoadInst>(&*It++);
+ auto *V2L3 = cast<sandboxir::LoadInst>(&*It++);
+
+ auto *V3L0 = cast<sandboxir::LoadInst>(&*It++);
+ (void)V3L0;
+ auto *V3L1 = cast<sandboxir::LoadInst>(&*It++);
+ auto *V3L2 = cast<sandboxir::LoadInst>(&*It++);
+ (void)V3L2;
+ auto *V3L3 = cast<sandboxir::LoadInst>(&*It++);
+ (void)V3L3;
+
+ EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, L1, SE, DL), 4);
+ EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, L2, SE, DL), 8);
+ EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L1, L0, SE, DL), -4);
+ EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, V2L0, SE, DL), 0);
+
+ EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, V2L1, SE, DL), 4);
+ EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, V3L1, SE, DL), 4);
+ EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L0, V2L2, SE, DL), 8);
+ EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L0, V2L3, SE, DL), 12);
+ EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L3, V2L0, SE, DL), -12);
+}
>From c2100473d3fd44939d4daccc418ba2ecccabeeb7 Mon Sep 17 00:00:00 2001
From: Sterling Augustine <saugustine at google.com>
Date: Thu, 26 Sep 2024 16:06:47 -0700
Subject: [PATCH 2/2] Address comments
---
llvm/include/llvm/SandboxIR/Utils.h | 29 ++++++++++++++------------
llvm/unittests/SandboxIR/UtilsTest.cpp | 18 +++++++++-------
2 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/llvm/include/llvm/SandboxIR/Utils.h b/llvm/include/llvm/SandboxIR/Utils.h
index 9f1c08d2b6c308..82a6a8fb0357a6 100644
--- a/llvm/include/llvm/SandboxIR/Utils.h
+++ b/llvm/include/llvm/SandboxIR/Utils.h
@@ -61,24 +61,15 @@ class Utils {
memoryLocationGetOrNone(const Instruction *I) {
return llvm::MemoryLocation::getOrNone(cast<llvm::Instruction>(I->Val));
}
- /// \Returns true if \p I1 accesses a memory location lower than \p I2.
- template <typename LoadOrStoreT>
- static bool atLowerAddress(LoadOrStoreT *I0, LoadOrStoreT *I1,
- ScalarEvolution &SE, const DataLayout &DL) {
- auto Diff = getPointerDiffInBytes(I0, I1, SE, DL);
- if (!Diff)
- return false;
- return *Diff > 0;
- }
- /// \Returns the number gap between the memory locations accessed by \p I0 and
- /// \p I1 in bytes.
+ /// \Returns the number of bytes between the memory locations accessed by \p
+ /// I0 and \p I1 in bytes.
template <typename LoadOrStoreT>
static std::optional<int>
getPointerDiffInBytes(LoadOrStoreT *I0, LoadOrStoreT *I1, ScalarEvolution &SE,
const DataLayout &DL) {
- static_assert(std::is_same<LoadOrStoreT, sandboxir::LoadInst>::value ||
- std::is_same<LoadOrStoreT, sandboxir::StoreInst>::value,
+ static_assert(std::is_same<LoadOrStoreT, LoadInst>::value ||
+ std::is_same<LoadOrStoreT, StoreInst>::value,
"Expected sandboxir::Load or sandboxir::Store!");
llvm::Value *Opnd0 = I0->getPointerOperand()->Val;
llvm::Value *Opnd1 = I1->getPointerOperand()->Val;
@@ -90,6 +81,18 @@ class Utils {
return getPointersDiff(ElemTy, Opnd0, ElemTy, Opnd1, DL, SE,
/*StrictCheck=*/false, /*CheckType=*/false);
}
+
+ /// \Returns true if \p I0 accesses a memory location lower than \p I1.
+ /// Returns false if the difference cannot be determined, if the memory
+ /// locations are equal, or if I1 accesses a memory location greater than I0.
+ template <typename LoadOrStoreT>
+ static bool atLowerAddress(LoadOrStoreT *I0, LoadOrStoreT *I1,
+ ScalarEvolution &SE, const DataLayout &DL) {
+ auto Diff = getPointerDiffInBytes(I0, I1, SE, DL);
+ if (!Diff)
+ return false;
+ return *Diff > 0;
+ }
};
} // namespace llvm::sandboxir
diff --git a/llvm/unittests/SandboxIR/UtilsTest.cpp b/llvm/unittests/SandboxIR/UtilsTest.cpp
index 7b2ce3c9b7f05e..f3ec1ace869f99 100644
--- a/llvm/unittests/SandboxIR/UtilsTest.cpp
+++ b/llvm/unittests/SandboxIR/UtilsTest.cpp
@@ -104,22 +104,19 @@ define void @foo(ptr %ptr) {
auto *L0 = cast<sandboxir::LoadInst>(&*It++);
auto *L1 = cast<sandboxir::LoadInst>(&*It++);
auto *L2 = cast<sandboxir::LoadInst>(&*It++);
- auto *L3 = cast<sandboxir::LoadInst>(&*It++);
- (void)L3;
+ [[maybe_unused]] auto *L3 = cast<sandboxir::LoadInst>(&*It++);
auto *V2L0 = cast<sandboxir::LoadInst>(&*It++);
auto *V2L1 = cast<sandboxir::LoadInst>(&*It++);
auto *V2L2 = cast<sandboxir::LoadInst>(&*It++);
auto *V2L3 = cast<sandboxir::LoadInst>(&*It++);
- auto *V3L0 = cast<sandboxir::LoadInst>(&*It++);
- (void)V3L0;
+ [[maybe_unused]] auto *V3L0 = cast<sandboxir::LoadInst>(&*It++);
auto *V3L1 = cast<sandboxir::LoadInst>(&*It++);
- auto *V3L2 = cast<sandboxir::LoadInst>(&*It++);
- (void)V3L2;
- auto *V3L3 = cast<sandboxir::LoadInst>(&*It++);
- (void)V3L3;
+ [[maybe_unused]] auto *V3L2 = cast<sandboxir::LoadInst>(&*It++);
+ [[maybe_unused]] auto *V3L3 = cast<sandboxir::LoadInst>(&*It++);
+ // getPointerDiffInBytes
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, L1, SE, DL), 4);
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, L2, SE, DL), 8);
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L1, L0, SE, DL), -4);
@@ -130,4 +127,9 @@ define void @foo(ptr %ptr) {
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L0, V2L2, SE, DL), 8);
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L0, V2L3, SE, DL), 12);
EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L3, V2L0, SE, DL), -12);
+
+ // atLowerAddress
+ EXPECT_TRUE(sandboxir::Utils::atLowerAddress(L0, L1, SE, DL));
+ EXPECT_FALSE(sandboxir::Utils::atLowerAddress(L1, L0, SE, DL));
+ EXPECT_FALSE(sandboxir::Utils::atLowerAddress(L3, V3L3, SE, DL));
}
More information about the llvm-commits
mailing list