[clang] [llvm] [DataLayout] Introduce sentinel pointer value (PR #131557)
Shilei Tian via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 17 10:48:53 PDT 2025
https://github.com/shiltian updated https://github.com/llvm/llvm-project/pull/131557
>From 053949d4dd8f28a2daa57a6143f0267c0bd3af6c Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Mon, 17 Mar 2025 13:45:09 +0900
Subject: [PATCH 1/2] [LoopVectorize] Add test for follow-up metadata for loops
(NFC) (#131337)
When pragma of loop transformations are encoded in LLVM IR, follow-up
metadata is used if multiple transformations are specified. They are
used to explicitly express the order of the transformations. However,
they are not properly processed on each transformation pass, so now only
the first one is attempted to be applied. This is a pre-commit to add a
test that causes the problem.
ref:
https://github.com/llvm/llvm-project/pull/127474#issuecomment-2717790398
---
clang/lib/Basic/Targets/AMDGPU.cpp | 6 +--
llvm/docs/LangRef.rst | 7 +++-
llvm/include/llvm/IR/DataLayout.h | 8 +++-
llvm/lib/IR/DataLayout.cpp | 55 +++++++++++++++++++++++-----
llvm/unittests/IR/DataLayoutTest.cpp | 20 ++++++++--
5 files changed, 77 insertions(+), 19 deletions(-)
diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp
index a42b4589fb5ac..a1d3ea2dfbfb6 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -32,9 +32,9 @@ static const char *const DataLayoutStringR600 =
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1";
static const char *const DataLayoutStringAMDGCN =
- "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32"
- "-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:"
- "32-v48:64-v96:128"
+ "e-p:64:64-p1:64:64-p2:32:32:32:32:f-p3:32:32:32:32:f-p4:64:64"
+ "-p5:32:32:32:32:f-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32"
+ "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1"
"-ni:7:8:9";
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 13b72f408715f..a22020da38f83 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -3134,7 +3134,7 @@ as follows:
``A<address space>``
Specifies the address space of objects created by '``alloca``'.
Defaults to the default address space of 0.
-``p[n]:<size>:<abi>[:<pref>][:<idx>]``
+``p[<n>]:<size>:<abi>[:<pref>[:<idx>[:<sentinel>]]]``
This specifies the *size* of a pointer and its ``<abi>`` and
``<pref>``\erred alignments for address space ``n``. ``<pref>`` is optional
and defaults to ``<abi>``. The fourth parameter ``<idx>`` is the size of the
@@ -3143,7 +3143,10 @@ as follows:
specified, the default index size is equal to the pointer size. All sizes
are in bits. The address space, ``n``, is optional, and if not specified,
denotes the default address space 0. The value of ``n`` must be
- in the range [1,2^24).
+ in the range [1,2^24). The fifth parameter ``<sentinel>`` specifies the
+ sentinel value of the pointer for the corresponding address space. It
+ currently accepts two values: ``0`` for an all-zero value and ``f`` for a
+ full-bit set value. The default sentinel pointer value is all-zero.
``i<size>:<abi>[:<pref>]``
This specifies the alignment for an integer type of a given bit
``<size>``. The value of ``<size>`` must be in the range [1,2^24).
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index 2ad080e6d0cd2..1257ffb32a4df 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -78,6 +78,7 @@ class DataLayout {
Align ABIAlign;
Align PrefAlign;
uint32_t IndexBitWidth;
+ APInt SentinelValue;
/// Pointers in this address space don't have a well-defined bitwise
/// representation (e.g. may be relocated by a copying garbage collector).
/// Additionally, they may also be non-integral (i.e. containing additional
@@ -148,7 +149,7 @@ class DataLayout {
/// Sets or updates the specification for pointer in the given address space.
void setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign,
Align PrefAlign, uint32_t IndexBitWidth,
- bool IsNonIntegral);
+ APInt SentinelValue, bool IsNonIntegral);
/// Internal helper to get alignment for integer of given bitwidth.
Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const;
@@ -552,6 +553,11 @@ class DataLayout {
///
/// This includes an explicitly requested alignment (if the global has one).
Align getPreferredAlign(const GlobalVariable *GV) const;
+
+ /// Returns the sentinel pointer value for a given address space. If the
+ /// address space is invalid, it defaults to the sentinel pointer value of
+ /// address space 0, aligning with the behavior of \p getPointerSpec.
+ APInt getSentinelPointerValue(unsigned AS) const;
};
inline DataLayout *unwrap(LLVMTargetDataRef P) {
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 0cf0bfc9702d3..1215aabefe69a 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -152,6 +152,7 @@ bool DataLayout::PointerSpec::operator==(const PointerSpec &Other) const {
return AddrSpace == Other.AddrSpace && BitWidth == Other.BitWidth &&
ABIAlign == Other.ABIAlign && PrefAlign == Other.PrefAlign &&
IndexBitWidth == Other.IndexBitWidth &&
+ SentinelValue == Other.SentinelValue &&
IsNonIntegral == Other.IsNonIntegral;
}
@@ -206,9 +207,10 @@ constexpr DataLayout::PrimitiveSpec DefaultVectorSpecs[] = {
};
// Default pointer type specifications.
-constexpr DataLayout::PointerSpec DefaultPointerSpecs[] = {
- // p0:64:64:64:64
- {0, 64, Align::Constant<8>(), Align::Constant<8>(), 64, false},
+const DataLayout::PointerSpec DefaultPointerSpecs[] = {
+ // p0:64:64:64:64:0
+ {0, 64, Align::Constant<8>(), Align::Constant<8>(), 64, APInt(64, 0),
+ false},
};
DataLayout::DataLayout()
@@ -296,6 +298,22 @@ static Error parseSize(StringRef Str, unsigned &BitWidth,
return Error::success();
}
+static Error parseSentinelValue(StringRef Str, APInt &V) {
+ if (Str.empty())
+ return createStringError("sentinel value component cannot be empty");
+ if (Str.size() != 1)
+ return createStringError("sentinel value component must be a '0' or 'f'");
+ if (Str[0] == '0') {
+ V.clearAllBits();
+ return Error::success();
+ }
+ if (Str[0] == 'f') {
+ V.setAllBits();
+ return Error::success();
+ }
+ return createStringError("sentinel value component must be a '0' or 'f'");
+}
+
/// Attempts to parse an alignment component of a specification.
///
/// On success, returns the value converted to byte amount in \p Alignment.
@@ -409,13 +427,14 @@ Error DataLayout::parseAggregateSpec(StringRef Spec) {
}
Error DataLayout::parsePointerSpec(StringRef Spec) {
- // p[<n>]:<size>:<abi>[:<pref>[:<idx>]]
+ // p[<n>]:<size>:<abi>[:<pref>[:<idx>[:<sentinel>]]]
SmallVector<StringRef, 5> Components;
assert(Spec.front() == 'p');
Spec.drop_front().split(Components, ':');
- if (Components.size() < 3 || Components.size() > 5)
- return createSpecFormatError("p[<n>]:<size>:<abi>[:<pref>[:<idx>]]");
+ if (Components.size() < 3 || Components.size() > 6)
+ return createSpecFormatError(
+ "p[<n>]:<size>:<abi>[:<pref>[:<idx>[:<sentinel>]]]");
// Address space. Optional, defaults to 0.
unsigned AddrSpace = 0;
@@ -454,8 +473,14 @@ Error DataLayout::parsePointerSpec(StringRef Spec) {
return createStringError(
"index size cannot be larger than the pointer size");
+ APInt SentinelValue(BitWidth, 0);
+ if (Components.size() > 5) {
+ if (Error Err = parseSentinelValue(Components[5], SentinelValue))
+ return Err;
+ }
+
setPointerSpec(AddrSpace, BitWidth, ABIAlign, PrefAlign, IndexBitWidth,
- false);
+ SentinelValue, /*IsNonIntegral=*/false);
return Error::success();
}
@@ -631,7 +656,7 @@ Error DataLayout::parseLayoutString(StringRef LayoutString) {
// the spec for AS0, and we then update that to mark it non-integral.
const PointerSpec &PS = getPointerSpec(AS);
setPointerSpec(AS, PS.BitWidth, PS.ABIAlign, PS.PrefAlign, PS.IndexBitWidth,
- true);
+ PS.SentinelValue, /*IsNonIntegral=*/true);
}
return Error::success();
@@ -679,16 +704,19 @@ DataLayout::getPointerSpec(uint32_t AddrSpace) const {
void DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth,
Align ABIAlign, Align PrefAlign,
- uint32_t IndexBitWidth, bool IsNonIntegral) {
+ uint32_t IndexBitWidth, APInt SentinelValue,
+ bool IsNonIntegral) {
auto I = lower_bound(PointerSpecs, AddrSpace, LessPointerAddrSpace());
if (I == PointerSpecs.end() || I->AddrSpace != AddrSpace) {
PointerSpecs.insert(I, PointerSpec{AddrSpace, BitWidth, ABIAlign, PrefAlign,
- IndexBitWidth, IsNonIntegral});
+ IndexBitWidth, SentinelValue,
+ IsNonIntegral});
} else {
I->BitWidth = BitWidth;
I->ABIAlign = ABIAlign;
I->PrefAlign = PrefAlign;
I->IndexBitWidth = IndexBitWidth;
+ I->SentinelValue = SentinelValue;
I->IsNonIntegral = IsNonIntegral;
}
}
@@ -1020,3 +1048,10 @@ Align DataLayout::getPreferredAlign(const GlobalVariable *GV) const {
}
return Alignment;
}
+
+APInt DataLayout::getSentinelPointerValue(unsigned AS) const {
+ auto I = lower_bound(PointerSpecs, AS, LessPointerAddrSpace());
+ if (I != PointerSpecs.end() || I->AddrSpace == AS)
+ return I->SentinelValue;
+ return PointerSpecs[0].SentinelValue;
+}
diff --git a/llvm/unittests/IR/DataLayoutTest.cpp b/llvm/unittests/IR/DataLayoutTest.cpp
index 16a603ff6416f..79d46ebfd7d8e 100644
--- a/llvm/unittests/IR/DataLayoutTest.cpp
+++ b/llvm/unittests/IR/DataLayoutTest.cpp
@@ -313,11 +313,12 @@ TEST(DataLayout, ParsePointerSpec) {
EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded());
for (StringRef Str :
- {"p", "p0", "p:32", "p0:32", "p:32:32:32:32:32", "p0:32:32:32:32:32"})
+ {"p", "p0", "p:32", "p0:32", "p:32:32:32:32:32:0", "p0:32:32:32:32:32:0"})
EXPECT_THAT_EXPECTED(
DataLayout::parse(Str),
- FailedWithMessage("malformed specification, must be of the form "
- "\"p[<n>]:<size>:<abi>[:<pref>[:<idx>]]\""));
+ FailedWithMessage(
+ "malformed specification, must be of the form "
+ "\"p[<n>]:<size>:<abi>[:<pref>[:<idx>[:<sentinel>]]]\""));
// address space
for (StringRef Str : {"p0x0:32:32", "px:32:32:32", "p16777216:32:32:32:32"})
@@ -401,6 +402,19 @@ TEST(DataLayout, ParsePointerSpec) {
EXPECT_THAT_EXPECTED(
DataLayout::parse(Str),
FailedWithMessage("index size cannot be larger than the pointer size"));
+
+ // sentinel value
+ for (StringRef Str :
+ {"p:32:32:32:32:a", "p0:32:32:32:32:ab", "p42:32:32:32:32:123"})
+ EXPECT_THAT_EXPECTED(
+ DataLayout::parse(Str),
+ FailedWithMessage("sentinel value component must be a '0' or 'f'"));
+
+ for (StringRef Str :
+ {"p:32:32:32:32:", "p0:32:32:32:32:", "p42:32:32:32:32:"})
+ EXPECT_THAT_EXPECTED(
+ DataLayout::parse(Str),
+ FailedWithMessage("sentinel value component cannot be empty"));
}
TEST(DataLayoutTest, ParseNativeIntegersSpec) {
>From 2f0682a405940f6e085af91d7b2e7df7f6ea4896 Mon Sep 17 00:00:00 2001
From: Shilei Tian <i at tianshilei.me>
Date: Mon, 17 Mar 2025 12:50:09 -0400
Subject: [PATCH 2/2] Update backend data layout for AMDGPU as well
---
clang/test/CodeGen/target-data.c | 4 ++--
clang/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl | 2 +-
llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 10 +++++-----
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/clang/test/CodeGen/target-data.c b/clang/test/CodeGen/target-data.c
index fe29aadb1dd53..7a59b404a12a3 100644
--- a/clang/test/CodeGen/target-data.c
+++ b/clang/test/CodeGen/target-data.c
@@ -176,12 +176,12 @@
// RUN: %clang_cc1 -triple amdgcn-unknown -target-cpu hawaii -o - -emit-llvm %s \
// RUN: | FileCheck %s -check-prefix=R600SI
-// R600SI: target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
+// R600SI: target datalayout = "e-p:64:64-p1:64:64-p2:32:32:32:32:f-p3:32:32:32:32:f-p4:64:64-p5:32:32:32:32:f-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
// Test default -target-cpu
// RUN: %clang_cc1 -triple amdgcn-unknown -o - -emit-llvm %s \
// RUN: | FileCheck %s -check-prefix=R600SIDefault
-// R600SIDefault: target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
+// R600SIDefault: target datalayout = "e-p:64:64-p1:64:64-p2:32:32:32:32:f-p3:32:32:32:32:f-p4:64:64-p5:32:32:32:32:f-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
// RUN: %clang_cc1 -triple arm64-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=AARCH64
diff --git a/clang/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl b/clang/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl
index bb52f87615214..c30e47b84d2d6 100644
--- a/clang/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl
+++ b/clang/test/CodeGenOpenCL/amdgpu-env-amdgcn.cl
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -O0 -triple amdgcn -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 %s -O0 -triple amdgcn---opencl -emit-llvm -o - | FileCheck %s
-// CHECK: target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
+// CHECK: target datalayout = "e-p:64:64-p1:64:64-p2:32:32:32:32:f-p3:32:32:32:32:f-p4:64:64-p5:32:32:32:32:f-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
void foo(void) {}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
index d0454cce15756..b638aeb19d431 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
@@ -677,11 +677,11 @@ static StringRef computeDataLayout(const Triple &TT) {
// (address space 7), and 128-bit non-integral buffer resourcees (address
// space 8) which cannot be non-trivilally accessed by LLVM memory operations
// like getelementptr.
- return "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32"
- "-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-"
- "v32:32-v48:64-v96:"
- "128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-"
- "G1-ni:7:8:9";
+ return "e-p:64:64-p1:64:64-p2:32:32:32:32:f-p3:32:32:32:32:f-p4:64:64"
+ "-p5:32:32:32:32:f-p6:32:32-p7:160:256:256:32-p8:128:128"
+ "-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
+ "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1"
+ "-ni:7:8:9";
}
LLVM_READNONE
More information about the llvm-commits
mailing list