Skip to content

Commit a08a000

Browse files
committed
[WIP][IR][Constants] Use ptr addrspace(N) zeroinitializer to represent a zero-value pointer
1 parent e330985 commit a08a000

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+365
-215
lines changed

clang/lib/Basic/Targets/AMDGPU.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ static const char *const DataLayoutStringR600 =
3131
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1";
3232

3333
static const char *const DataLayoutStringAMDGCN =
34-
"e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32"
34+
"e-m:e-p:64:64-p1:64:64-p2:32:32-po3:32:32-p4:64:64-po5:32:32-p6:32:32"
3535
"-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-"
3636
"v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-"
3737
"v2048:2048-n32:64-S32-A5-G1-ni:7:8:9";

clang/test/CodeGen/target-data.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,12 @@
160160

161161
// RUN: %clang_cc1 -triple amdgcn-unknown -target-cpu hawaii -o - -emit-llvm %s \
162162
// RUN: | FileCheck %s -check-prefix=R600SI
163-
// R600SI: target datalayout = "e-m: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:128:48-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"
163+
// R600SI: target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-po3:32:32-p4:64:64-po5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-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"
164164

165165
// Test default -target-cpu
166166
// RUN: %clang_cc1 -triple amdgcn-unknown -o - -emit-llvm %s \
167167
// RUN: | FileCheck %s -check-prefix=R600SIDefault
168-
// R600SIDefault: target datalayout = "e-m: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:128:48-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"
168+
// R600SIDefault: target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-po3:32:32-p4:64:64-po5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-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"
169169

170170
// RUN: %clang_cc1 -triple arm64-unknown -o - -emit-llvm %s | \
171171
// RUN: FileCheck %s -check-prefix=AARCH64
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %clang_cc1 %s -O0 -triple amdgcn -emit-llvm -o - | FileCheck %s
22
// RUN: %clang_cc1 %s -O0 -triple amdgcn---opencl -emit-llvm -o - | FileCheck %s
33

4-
// CHECK: target datalayout = "e-m: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:128:48-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"
4+
// CHECK: target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-po3:32:32-p4:64:64-po5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-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"
55
void foo(void) {}

lld/test/ELF/lto/amdgcn-oses.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
;--- amdhsa.ll
2727
target triple = "amdgcn-amd-amdhsa"
28-
target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32: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"
28+
target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-po3:32:32-p4:64:64-po5:32:32-p6:32: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"
2929

3030
!llvm.module.flags = !{!0}
3131
!0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
@@ -36,15 +36,15 @@ define void @_start() {
3636

3737
;--- amdpal.ll
3838
target triple = "amdgcn-amd-amdpal"
39-
target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32: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"
39+
target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-po3:32:32-p4:64:64-po5:32:32-p6:32: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"
4040

4141
define amdgpu_cs void @_start() {
4242
ret void
4343
}
4444

4545
;--- mesa3d.ll
4646
target triple = "amdgcn-amd-mesa3d"
47-
target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32: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"
47+
target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-po3:32:32-p4:64:64-po5:32:32-p6:32: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"
4848

4949
define void @_start() {
5050
ret void

lld/test/ELF/lto/amdgcn.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
; Make sure the amdgcn triple is handled
66

77
target triple = "amdgcn-amd-amdhsa"
8-
target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32: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"
8+
target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-po3:32:32-p4:64:64-po5:32:32-p6:32: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"
99

1010
define void @_start() {
1111
ret void

llvm/docs/LangRef.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3301,8 +3301,12 @@ as follows:
33013301
default address space 0. The value of ``<as>`` must be in the range [1,2^24).
33023302
The optional ``<flags>`` are used to specify properties of pointers in this
33033303
address space: the character ``u`` marks pointers as having an unstable
3304-
representation, and ``e`` marks pointers having external state. See
3305-
:ref:`Non-Integral Pointer Types <nointptrtype>`.
3304+
representation; ``e`` marks pointers having external state; ``z`` marks the
3305+
value of the nullptr as all-zeros (default behavior if it is not specified);
3306+
``o`` marks the value of the nullptr as all-ones; ``c`` marks the value of
3307+
the nullptr as custom (neither all-zeros nor all-ones), such that LLVM will
3308+
not be able to fold various casts involving nullptr.
3309+
See :ref:`Non-Integral Pointer Types <nointptrtype>`.
33063310

33073311
``i<size>:<abi>[:<pref>]``
33083312
This specifies the alignment for an integer type of a given bit

llvm/include/llvm/IR/Constant.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ class Constant : public User {
189189

190190
LLVM_ABI static Constant *getNullValue(Type *Ty);
191191

192+
LLVM_ABI static Constant *getZeroValue(Type *Ty);
193+
192194
/// @returns the value for an integer or vector of integer constant of the
193195
/// given type that has all its bits set to true.
194196
/// Get the all ones value

llvm/include/llvm/IR/DataLayout.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ class DataLayout {
8383
/// for additional metadata (e.g. AMDGPU buffer fat pointers with bounds
8484
/// and other flags or CHERI capabilities that contain bounds+permissions).
8585
uint32_t IndexBitWidth;
86+
/// The value of the nullptr in this address space. It can be three values:
87+
/// all-zeros, all-ones, or std::nullopt. Since we don't have a way to
88+
/// represent an arbitrary bit pattern, we use std::nullopt to represent the
89+
/// case where the nullptr value is neither 0 nor -1.
90+
std::optional<APInt> NullPtrValue;
8691
/// Pointers in this address space don't have a well-defined bitwise
8792
/// representation (e.g. they may be relocated by a copying garbage
8893
/// collector and thus have different addresses at different times).
@@ -158,7 +163,8 @@ class DataLayout {
158163
/// Sets or updates the specification for pointer in the given address space.
159164
void setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign,
160165
Align PrefAlign, uint32_t IndexBitWidth,
161-
bool HasUnstableRepr, bool HasExternalState);
166+
std::optional<APInt> NullPtrValue, bool HasUnstableRepr,
167+
bool HasExternalState);
162168

163169
/// Internal helper to get alignment for integer of given bitwidth.
164170
LLVM_ABI Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const;
@@ -697,6 +703,11 @@ class DataLayout {
697703
///
698704
/// This includes an explicitly requested alignment (if the global has one).
699705
LLVM_ABI Align getPreferredAlign(const GlobalVariable *GV) const;
706+
707+
/// Returns the value of the nullptr in the given address space.
708+
LLVM_ABI std::optional<APInt> getNullPtrValue(unsigned AddrSpace) const {
709+
return getPointerSpec(AddrSpace).NullPtrValue;
710+
}
700711
};
701712

702713
inline DataLayout *unwrap(LLVMTargetDataRef P) {

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,19 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
14971497
llvm_unreachable("Missing case");
14981498
case Instruction::PtrToAddr:
14991499
case Instruction::PtrToInt:
1500+
// If the input is a nullptr, we can fold it to the corresponding nullptr
1501+
// value.
1502+
if (Opcode == Instruction::PtrToInt && C->isNullValue()) {
1503+
if (std::optional<APInt> NullPtrValue = DL.getNullPtrValue(
1504+
C->getType()->getScalarType()->getPointerAddressSpace())) {
1505+
if (NullPtrValue->isZero())
1506+
return Constant::getZeroValue(DestTy);
1507+
else if (NullPtrValue->isAllOnes())
1508+
return Constant::getAllOnesValue(DestTy);
1509+
else
1510+
llvm_unreachable("invalid nullptr value");
1511+
}
1512+
}
15001513
if (auto *CE = dyn_cast<ConstantExpr>(C)) {
15011514
Constant *FoldedValue = nullptr;
15021515
// If the input is an inttoptr, eliminate the pair. This requires knowing
@@ -1543,6 +1556,13 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
15431556
}
15441557
break;
15451558
case Instruction::IntToPtr:
1559+
// We can fold it to a null pointer if the input is the nullptr value.
1560+
if (std::optional<APInt> NullPtrValue = DL.getNullPtrValue(
1561+
DestTy->getScalarType()->getPointerAddressSpace())) {
1562+
if ((NullPtrValue->isZero() && C->isZeroValue()) ||
1563+
(NullPtrValue->isAllOnes() && C->isAllOnesValue()))
1564+
return Constant::getNullValue(DestTy);
1565+
}
15461566
// If the input is a ptrtoint, turn the pair into a ptr to ptr bitcast if
15471567
// the int size is >= the ptr size and the address spaces are the same.
15481568
// This requires knowing the width of a pointer, so it can't be done in
@@ -1561,6 +1581,24 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
15611581
}
15621582
}
15631583
break;
1584+
case Instruction::AddrSpaceCast:
1585+
// A null pointer (`ptr addrspace(N) null` in IR presentation,
1586+
// `ConstantPointerNull` in LLVM class, not `nullptr` in C/C++) used to
1587+
// represent a zero-value pointer in the corresponding address space.
1588+
// Therefore, we can't simply fold an address space cast of a null pointer
1589+
// from one address space to another, because on some targets, the nullptr
1590+
// of an address space could be non-zero.
1591+
//
1592+
// Recently, the semantic of `ptr addrspace(N) null` is changed to represent
1593+
// the actual nullptr in the corresponding address space. It can be zero or
1594+
// non-zero, depending on the target. Therefore, we can fold an address
1595+
// space cast of a nullptr from one address space to another.
1596+
1597+
// If the input is a nullptr, we can fold it to the corresponding
1598+
// nullptr in the destination address space.
1599+
if (C->isNullValue())
1600+
return Constant::getNullValue(DestTy);
1601+
[[fallthrough]];
15641602
case Instruction::Trunc:
15651603
case Instruction::ZExt:
15661604
case Instruction::SExt:
@@ -1570,7 +1608,6 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
15701608
case Instruction::SIToFP:
15711609
case Instruction::FPToUI:
15721610
case Instruction::FPToSI:
1573-
case Instruction::AddrSpaceCast:
15741611
break;
15751612
case Instruction::BitCast:
15761613
return FoldBitCast(C, DestTy, DL);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6575,7 +6575,7 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V,
65756575
if (auto *TETy = dyn_cast<TargetExtType>(Ty))
65766576
if (!TETy->hasProperty(TargetExtType::HasZeroInit))
65776577
return error(ID.Loc, "invalid type for null constant");
6578-
V = Constant::getNullValue(Ty);
6578+
V = Constant::getZeroValue(Ty);
65796579
return false;
65806580
case ValID::t_None:
65816581
if (!Ty->isTokenTy())

0 commit comments

Comments
 (0)