From dfe826efd97e534da229ac6a3af41f562b573ff9 Mon Sep 17 00:00:00 2001 From: Rana Pratap Reddy N Date: Tue, 27 Feb 2024 13:07:00 +0530 Subject: [PATCH 1/5] [WIP] Extend data layout to add non zero null value for address space --- llvm/include/llvm/IR/DataLayout.h | 14 ++++++ llvm/lib/IR/DataLayout.cpp | 44 +++++++++++++++++++ .../datalayout-invalid-address-space-value.ll | 5 +++ ...datalayout-invalid-address-space-value1.ll | 5 +++ ...datalayout-invalid-address-space-value2.ll | 5 +++ ...datalayout-invalid-address-space-value3.ll | 5 +++ .../datalayout-invalid-address-space.ll | 5 +++ .../AMDGPU/datalayout-non-zero-lds-value.ll | 20 +++++++++ 8 files changed, 103 insertions(+) create mode 100644 llvm/test/Assembler/datalayout-invalid-address-space-value.ll create mode 100644 llvm/test/Assembler/datalayout-invalid-address-space-value1.ll create mode 100644 llvm/test/Assembler/datalayout-invalid-address-space-value2.ll create mode 100644 llvm/test/Assembler/datalayout-invalid-address-space-value3.ll create mode 100644 llvm/test/Assembler/datalayout-invalid-address-space.ll create mode 100644 llvm/test/CodeGen/AMDGPU/datalayout-non-zero-lds-value.ll diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h index d14adfe1590be..1b3501a1a4c72 100644 --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -21,6 +21,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -164,6 +165,8 @@ class DataLayout { /// well-defined bitwise representation. SmallVector NonIntegralAddressSpaces; + DenseMap AddrSpaceToNonZeroValueMap; + /// Attempts to set the alignment of the given type. Returns an error /// description on failure. Error setAlignment(AlignTypeEnum AlignType, Align ABIAlign, Align PrefAlign, @@ -299,6 +302,17 @@ class DataLayout { return ManglingMode == MM_WinCOFFX86; } + int64_t getNullPointerValue(unsigned AddrSpace) { + auto It = AddrSpaceToNonZeroValueMap.find(AddrSpace); + if (It == AddrSpaceToNonZeroValueMap.end()) + return 0; + return It->second; + } + + void setNullPointerValue(unsigned AddrSpace, int64_t Value) { + AddrSpaceToNonZeroValueMap[AddrSpace] = Value; + } + /// Returns true if symbols with leading question marks should not receive IR /// mangling. True for Windows mangling modes. bool doNotMangleLeadingQuestionMark() const { diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index 2741165332487..eaad624559c7c 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -216,6 +216,8 @@ void DataLayout::reset(StringRef Desc) { if (Error Err = setPointerAlignmentInBits(0, Align(8), Align(8), 64, 64)) return report_fatal_error(std::move(Err)); + setNullPointerValue(INT_MAX, 0); + if (Error Err = parseSpecifier(Desc)) return report_fatal_error(std::move(Err)); } @@ -251,6 +253,22 @@ template static Error getInt(StringRef R, IntTy &Result) { return Error::success(); } +template +static Error getIntForAddrSpace(StringRef R, IntTy &Result) { + if (R.starts_with("neg")) { + StringRef AfterNeg = R.slice(3, R.size()); + bool error = AfterNeg.getAsInteger(10, Result); + (void)error; + if (error || Result <= 0) + return reportError("not a number, or does not fit in an unsigned int"); + Result *= -1; + return Error::success(); + } else if (R.contains("neg")) + return reportError("not a valid value for address space"); + else + return getInt(R, Result); +} + /// Get an unsigned integer representing the number of bits and convert it into /// bytes. Error out of not a byte width multiple. template @@ -502,6 +520,32 @@ Error DataLayout::parseSpecifier(StringRef Desc) { return Err; break; } + case 'z': { + unsigned AddrSpace = 0; + int64_t Value; + // for unlisted address spaces e.g., z:0 + if (Tok.empty()) { + if (Error Err = getIntForAddrSpace(Rest, Value)) + return Err; + setNullPointerValue(INT_MAX, Value); + break; + } else { + if (Error Err = getInt(Tok, AddrSpace)) + return Err; + if (!isUInt<24>(AddrSpace)) + return reportError("Invalid address space, must be a 24-bit integer"); + } + if (Rest.empty()) + return reportError( + "Missing address space value specification for pointer in " + "datalayout string"); + if (Error Err = ::split(Rest, ':', Split)) + return Err; + if (Error Err = getIntForAddrSpace(Tok, Value)) + return Err; + setNullPointerValue(AddrSpace, Value); + break; + } case 'G': { // Default address space for global variables. if (Error Err = getAddrSpace(Tok, DefaultGlobalsAddrSpace)) return Err; diff --git a/llvm/test/Assembler/datalayout-invalid-address-space-value.ll b/llvm/test/Assembler/datalayout-invalid-address-space-value.ll new file mode 100644 index 0000000000000..bf90b3078add8 --- /dev/null +++ b/llvm/test/Assembler/datalayout-invalid-address-space-value.ll @@ -0,0 +1,5 @@ +; RUN: not llvm-as %s 2>&1 | FileCheck %s + +; CHECK: error: not a number, or does not fit in an unsigned int + +target datalayout = "z:neg" \ No newline at end of file diff --git a/llvm/test/Assembler/datalayout-invalid-address-space-value1.ll b/llvm/test/Assembler/datalayout-invalid-address-space-value1.ll new file mode 100644 index 0000000000000..3747af0b952f2 --- /dev/null +++ b/llvm/test/Assembler/datalayout-invalid-address-space-value1.ll @@ -0,0 +1,5 @@ +; RUN: not llvm-as %s 2>&1 | FileCheck %s + +; CHECK: error: not a number, or does not fit in an unsigned int + +target datalayout = "z:neg-1" \ No newline at end of file diff --git a/llvm/test/Assembler/datalayout-invalid-address-space-value2.ll b/llvm/test/Assembler/datalayout-invalid-address-space-value2.ll new file mode 100644 index 0000000000000..31160a599b2a3 --- /dev/null +++ b/llvm/test/Assembler/datalayout-invalid-address-space-value2.ll @@ -0,0 +1,5 @@ +; RUN: not llvm-as %s 2>&1 | FileCheck %s + +; CHECK: error: Trailing separator in datalayout string + +target datalayout = "z:" \ No newline at end of file diff --git a/llvm/test/Assembler/datalayout-invalid-address-space-value3.ll b/llvm/test/Assembler/datalayout-invalid-address-space-value3.ll new file mode 100644 index 0000000000000..57106758fbd0e --- /dev/null +++ b/llvm/test/Assembler/datalayout-invalid-address-space-value3.ll @@ -0,0 +1,5 @@ +; RUN: not llvm-as %s 2>&1 | FileCheck %s + +; CHECK: error: Trailing separator in datalayout string + +target datalayout = "z:-1" \ No newline at end of file diff --git a/llvm/test/Assembler/datalayout-invalid-address-space.ll b/llvm/test/Assembler/datalayout-invalid-address-space.ll new file mode 100644 index 0000000000000..78f8e7c6e9748 --- /dev/null +++ b/llvm/test/Assembler/datalayout-invalid-address-space.ll @@ -0,0 +1,5 @@ +; RUN: not llvm-as %s 2>&1 | FileCheck %s + +; CHECK: error: not a number, or does not fit in an unsigned int + +target datalayout = "za:0" diff --git a/llvm/test/CodeGen/AMDGPU/datalayout-non-zero-lds-value.ll b/llvm/test/CodeGen/AMDGPU/datalayout-non-zero-lds-value.ll new file mode 100644 index 0000000000000..c73128fed3961 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/datalayout-non-zero-lds-value.ll @@ -0,0 +1,20 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -S -mtriple=amdgcn-- | 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-z:0-z2:neg1-z3:neg1-z5:neg1-S32-A5-G1-ni:7:8:9" +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-z:0-z2:neg1-z3:neg1-z5:neg1-S32-A5-G1-ni:7:8:9" +@lds = addrspace(3) global [8 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8] + +define amdgpu_kernel void @load_init_lds_global(ptr addrspace(1) %out, i1 %p) { +; CHECK-LABEL: define amdgpu_kernel void @load_init_lds_global( +; CHECK-SAME: ptr addrspace(1) [[OUT:%.*]], i1 [[P:%.*]]) { +; CHECK-NEXT: [[GEP:%.*]] = getelementptr [8 x i32], ptr addrspace(3) @lds, i32 0, i32 10 +; CHECK-NEXT: [[LD:%.*]] = load i32, ptr addrspace(3) [[GEP]], align 4 +; CHECK-NEXT: store i32 [[LD]], ptr addrspace(1) [[OUT]], align 4 +; CHECK-NEXT: ret void +; + %gep = getelementptr [8 x i32], ptr addrspace(3) @lds, i32 0, i32 10 + %ld = load i32, ptr addrspace(3) %gep + store i32 %ld, ptr addrspace(1) %out + ret void +} From d0306c73de958af59df81d8949fac711e3d74a4a Mon Sep 17 00:00:00 2001 From: Rana Pratap Reddy N Date: Thu, 14 Mar 2024 12:36:22 +0530 Subject: [PATCH 2/5] Added default null address space value specification in Data Layout string --- llvm/docs/LangRef.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index f169ab941c457..86b4697083ec2 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -3061,6 +3061,14 @@ as follows: ``n32:64`` for PowerPC 64, or ``n8:16:32:64`` for X86-64. Elements of this set are considered to support most general arithmetic operations efficiently. +``z[n]:`` + This specifies the default null value for an address space. ``n`` denotes + the address space number, and if not specified, it is considered to be + for the unlisted address space. For unlisted address space, the default + null value is ``0``. ``value`` denotes the default null value for an + address space ``n``. To represent negatives values, prefix ``neg`` is + added to ``value``. for e.g., ``z0:neg1`` represents for ``0`` address + space ``-1`` is the default null value. ``ni:
:
:
...`` This specifies pointer types with the specified address spaces as :ref:`Non-Integral Pointer Type ` s. The ``0`` @@ -3093,6 +3101,7 @@ specifications are given in this list: - ``v64:64:64`` - 64-bit vector is 64-bit aligned - ``v128:128:128`` - 128-bit vector is 128-bit aligned - ``a:0:64`` - aggregates are 64-bit aligned +- ``z:0`` - default null value of 0 for unlisted(INT_MAX) address space When LLVM is determining the alignment for a given type, it uses the following rules: From 0f1412dbe5c89a3a6ae35198bd2f152ac229b082 Mon Sep 17 00:00:00 2001 From: Rana Pratap Reddy N Date: Thu, 14 Mar 2024 12:41:40 +0530 Subject: [PATCH 3/5] Renamed the function from Null to defaultNull --- llvm/include/llvm/IR/DataLayout.h | 4 ++-- llvm/lib/IR/DataLayout.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h index 1b3501a1a4c72..0dc0c2df16221 100644 --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -302,14 +302,14 @@ class DataLayout { return ManglingMode == MM_WinCOFFX86; } - int64_t getNullPointerValue(unsigned AddrSpace) { + int64_t getDefaultNullPointerValue(unsigned AddrSpace) { auto It = AddrSpaceToNonZeroValueMap.find(AddrSpace); if (It == AddrSpaceToNonZeroValueMap.end()) return 0; return It->second; } - void setNullPointerValue(unsigned AddrSpace, int64_t Value) { + void setDefaultNullPointerValue(unsigned AddrSpace, int64_t Value) { AddrSpaceToNonZeroValueMap[AddrSpace] = Value; } diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index eaad624559c7c..c976dcde061ee 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -216,7 +216,7 @@ void DataLayout::reset(StringRef Desc) { if (Error Err = setPointerAlignmentInBits(0, Align(8), Align(8), 64, 64)) return report_fatal_error(std::move(Err)); - setNullPointerValue(INT_MAX, 0); + setDefaultNullPointerValue(INT_MAX, 0); if (Error Err = parseSpecifier(Desc)) return report_fatal_error(std::move(Err)); @@ -262,11 +262,11 @@ static Error getIntForAddrSpace(StringRef R, IntTy &Result) { if (error || Result <= 0) return reportError("not a number, or does not fit in an unsigned int"); Result *= -1; - return Error::success(); } else if (R.contains("neg")) return reportError("not a valid value for address space"); else return getInt(R, Result); + return Error::success(); } /// Get an unsigned integer representing the number of bits and convert it into @@ -527,7 +527,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { if (Tok.empty()) { if (Error Err = getIntForAddrSpace(Rest, Value)) return Err; - setNullPointerValue(INT_MAX, Value); + setDefaultNullPointerValue(INT_MAX, Value); break; } else { if (Error Err = getInt(Tok, AddrSpace)) @@ -543,7 +543,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { return Err; if (Error Err = getIntForAddrSpace(Tok, Value)) return Err; - setNullPointerValue(AddrSpace, Value); + setDefaultNullPointerValue(AddrSpace, Value); break; } case 'G': { // Default address space for global variables. From 8e1aea0561dcd077c19da25e05c5b3ea39ca73a9 Mon Sep 17 00:00:00 2001 From: Rana Pratap Reddy N Date: Thu, 14 Mar 2024 16:00:15 +0530 Subject: [PATCH 4/5] Renamed from defaultNull to Sentinel pointer value and updated the LangRef --- llvm/docs/LangRef.rst | 15 ++++++++------- llvm/include/llvm/IR/DataLayout.h | 12 ++++++------ llvm/lib/IR/DataLayout.cpp | 6 +++--- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 86b4697083ec2..687babb8f1841 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -3062,13 +3062,14 @@ as follows: this set are considered to support most general arithmetic operations efficiently. ``z[n]:`` - This specifies the default null value for an address space. ``n`` denotes - the address space number, and if not specified, it is considered to be - for the unlisted address space. For unlisted address space, the default - null value is ``0``. ``value`` denotes the default null value for an - address space ``n``. To represent negatives values, prefix ``neg`` is - added to ``value``. for e.g., ``z0:neg1`` represents for ``0`` address - space ``-1`` is the default null value. + This specifies the sentinel pointer value for an address space. Sentinel + pointer value is the default non zero null value for a given address + space. ``n`` denotes the address space number, and if not specified, it + is considered to be for the unlisted address space. For unlisted address + space, the sentinel pointer value is ``0``. ``value`` denotes the sentinel + pointer value for an address space ``n``. To represent negatives values, + prefix ``neg`` is added to ``value``. for e.g., ``z0:neg1`` represents for + ``0`` address space ``-1`` is the sentinel pointer value. ``ni:
:
:
...`` This specifies pointer types with the specified address spaces as :ref:`Non-Integral Pointer Type ` s. The ``0`` diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h index 0dc0c2df16221..811cd4f77aff7 100644 --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -165,7 +165,7 @@ class DataLayout { /// well-defined bitwise representation. SmallVector NonIntegralAddressSpaces; - DenseMap AddrSpaceToNonZeroValueMap; + DenseMap AddrSpaceToSentinelValueMap; /// Attempts to set the alignment of the given type. Returns an error /// description on failure. @@ -302,15 +302,15 @@ class DataLayout { return ManglingMode == MM_WinCOFFX86; } - int64_t getDefaultNullPointerValue(unsigned AddrSpace) { - auto It = AddrSpaceToNonZeroValueMap.find(AddrSpace); - if (It == AddrSpaceToNonZeroValueMap.end()) + int64_t getSentinelPointerValue(unsigned AddrSpace) { + auto It = AddrSpaceToSentinelValueMap.find(AddrSpace); + if (It == AddrSpaceToSentinelValueMap.end()) return 0; return It->second; } - void setDefaultNullPointerValue(unsigned AddrSpace, int64_t Value) { - AddrSpaceToNonZeroValueMap[AddrSpace] = Value; + void setSentinelPointerValue(unsigned AddrSpace, int64_t Value) { + AddrSpaceToSentinelValueMap[AddrSpace] = Value; } /// Returns true if symbols with leading question marks should not receive IR diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index c976dcde061ee..64fbdc4e2bf3e 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -216,7 +216,7 @@ void DataLayout::reset(StringRef Desc) { if (Error Err = setPointerAlignmentInBits(0, Align(8), Align(8), 64, 64)) return report_fatal_error(std::move(Err)); - setDefaultNullPointerValue(INT_MAX, 0); + setSentinelPointerValue(INT_MAX, 0); if (Error Err = parseSpecifier(Desc)) return report_fatal_error(std::move(Err)); @@ -527,7 +527,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { if (Tok.empty()) { if (Error Err = getIntForAddrSpace(Rest, Value)) return Err; - setDefaultNullPointerValue(INT_MAX, Value); + setSentinelPointerValue(INT_MAX, Value); break; } else { if (Error Err = getInt(Tok, AddrSpace)) @@ -543,7 +543,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { return Err; if (Error Err = getIntForAddrSpace(Tok, Value)) return Err; - setDefaultNullPointerValue(AddrSpace, Value); + setSentinelPointerValue(AddrSpace, Value); break; } case 'G': { // Default address space for global variables. From abbff8b6667f6f49a053d7e275fddf74d650998e Mon Sep 17 00:00:00 2001 From: Rana Pratap Reddy N Date: Mon, 29 Apr 2024 13:38:08 +0530 Subject: [PATCH 5/5] Update copy operator for AddrSpaceToSentinelValueMap and sentinelValueDefined --- llvm/include/llvm/IR/DataLayout.h | 7 ++++++- llvm/lib/IR/DataLayout.cpp | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h index 811cd4f77aff7..e80b2611bba2f 100644 --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -166,6 +166,7 @@ class DataLayout { SmallVector NonIntegralAddressSpaces; DenseMap AddrSpaceToSentinelValueMap; + bool sentinelValueDefined = false; /// Attempts to set the alignment of the given type. Returns an error /// description on failure. @@ -222,6 +223,8 @@ class DataLayout { StructAlignment = DL.StructAlignment; Pointers = DL.Pointers; NonIntegralAddressSpaces = DL.NonIntegralAddressSpaces; + AddrSpaceToSentinelValueMap = DL.AddrSpaceToSentinelValueMap; + sentinelValueDefined = DL.isSentinelValueDefined(); return *this; } @@ -302,7 +305,7 @@ class DataLayout { return ManglingMode == MM_WinCOFFX86; } - int64_t getSentinelPointerValue(unsigned AddrSpace) { + int64_t getSentinelPointerValue(unsigned AddrSpace) const { auto It = AddrSpaceToSentinelValueMap.find(AddrSpace); if (It == AddrSpaceToSentinelValueMap.end()) return 0; @@ -313,6 +316,8 @@ class DataLayout { AddrSpaceToSentinelValueMap[AddrSpace] = Value; } + bool isSentinelValueDefined() const { return sentinelValueDefined; } + /// Returns true if symbols with leading question marks should not receive IR /// mangling. True for Windows mangling modes. bool doNotMangleLeadingQuestionMark() const { diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index 64fbdc4e2bf3e..42053746a6c11 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -521,6 +521,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { break; } case 'z': { + sentinelValueDefined = true; unsigned AddrSpace = 0; int64_t Value; // for unlisted address spaces e.g., z:0 @@ -748,6 +749,7 @@ class StructLayoutMap { } // end anonymous namespace void DataLayout::clear() { + LegalIntWidths.clear(); IntAlignments.clear(); FloatAlignments.clear();