Skip to content

[AMDGPULowerBufferFatPointers] Handle ptrtoaddr by extending the offset #139413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

98 changes: 88 additions & 10 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3147,14 +3147,21 @@ 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>]``
This specifies the *size* of a pointer and its ``<abi>`` and
``<pref>``\erred alignments for address space ``n``.
The fourth parameter ``<idx>`` is the size of the
index that used for address calculation, which must be less than or equal
to the pointer size. If not
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,
``p[n]:<size>:<abi>[:<pref>[:<idx>]]``
This specifies the properties of a pointer in address space ``n``.
The ``<size>`` parameter specifies the size of the bitwise representation.
For :ref:`non-integral pointers <nointptrtype>` the representation size may
be larger than the address width of the underlying address space (e.g. to
accommodate additional metadata).
The alignment requirements are specified via the ``<abi>`` and
``<pref>``\erred alignments parameters.
The fourth parameter ``<idx>`` is the size of the index that used for
address calculations such as :ref:`getelementptr <i_getelementptr>`.
It must be less than or equal to the pointer size. If not specified, the
default index size is equal to the pointer size.
The index size also specifies the width of addresses in this address space.
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).
``i<size>:<abi>[:<pref>]``
Expand Down Expand Up @@ -4266,6 +4273,16 @@ address spaces defined in the :ref:`datalayout string<langref_datalayout>`.
the default globals address space and ``addrspace("P")`` the program address
space.

The representation of pointers can be different for each address space and does
not necessarily need to be a plain integer address (e.g. for
:ref:`non-integral pointers <nointptrtype>`). In addition to a representation
bits size, pointers in each address space also have an index size which defines
the bitwidth of indexing operations as well as the size of `integer addresses`
in this address space. For example, CHERI capabilities are twice the size of the
underlying addresses to accommodate for additional metadata such as bounds and
permissions: on a 32-bit system the bitwidth of the pointer representation size
is 64, but the underlying address width remains 32 bits.

The default address space is number zero.

The semantics of non-zero address spaces are target-specific. Memory
Expand Down Expand Up @@ -12396,12 +12413,15 @@ Semantics:
""""""""""

The '``ptrtoint``' instruction converts ``value`` to integer type
``ty2`` by interpreting the pointer value as an integer and either
truncating or zero extending that value to the size of the integer type.
``ty2`` by interpreting the all pointer representation bits as an integer
(equivalent to a ``bitcast``) and either truncating or zero extending that value
to the size of the integer type.
If ``value`` is smaller than ``ty2`` then a zero extension is done. If
``value`` is larger than ``ty2`` then a truncation is done. If they are
the same size, then nothing is done (*no-op cast*) other than a type
change.
The ``ptrtoint`` always :ref:`captures address and provenance <pointercapture>`
of the pointer argument.

Example:
""""""""
Expand All @@ -12412,6 +12432,61 @@ Example:
%Y = ptrtoint ptr %P to i64 ; yields zero extension on 32-bit architecture
%Z = ptrtoint <4 x ptr> %P to <4 x i64>; yields vector zero extension for a vector of addresses on 32-bit architecture

.. _i_ptrtoaddr:

'``ptrtoaddr .. to``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Syntax:
"""""""

::

<result> = ptrtoaddr <ty> <value> to <ty2> ; yields ty2

Overview:
"""""""""

The '``ptrtoaddr``' instruction converts the pointer or a vector of
pointers ``value`` to the underlying integer address (or vector of integers) of
type ``ty2``. This is different from :ref:`ptrtoint <i_ptrtoint>` in that it
only operates on the index bits of the pointer and ignores all other bits.

Arguments:
""""""""""

The '``ptrtoaddr``' instruction takes a ``value`` to cast, which must be
a value of type :ref:`pointer <t_pointer>` or a vector of pointers, and a
type to cast it to ``ty2``, which must be an :ref:`integer <t_integer>` or
a vector of integers type.

Semantics:
""""""""""

The '``ptrtoaddr``' instruction converts ``value`` to integer type
``ty2`` by interpreting the lowest index-width pointer representation bits as an
integer and either truncating or zero extending that value to the size of the
integer type.
If the address of ``value`` is smaller than ``ty2`` then a zero extension is
done. If the address of ``value`` is larger than ``ty2`` then a truncation is
done. If the address size and the pointer representation size are the same and
``value`` and ``ty2`` are the same size, then nothing is done (*no-op cast*)
other than a type change.

The ``ptrtoaddr`` always :ref:`captures the address (but not provenance) <pointercapture>`
of the pointer argument.

Example:
""""""""
This example assumes pointers in address space 1 are 64 bits in size with an
address width of 32 bits (``p1:64:64:64:32`` :ref:`datalayout string<langref_datalayout>`)
.. code-block:: llvm

%X = ptrtoaddr ptr addrspace(1) %P to i8 ; extracts low 32 bits and truncates
%Y = ptrtoaddr ptr addrspace(1) %P to i64 ; extracts low 32 bits and zero extends
%Z = ptrtoaddr <4 x ptr addrspace(1)> %P to <4 x i64>; yields vector zero extension of low 32 bits for each pointer


.. _i_inttoptr:

'``inttoptr .. to``' Instruction
Expand Down Expand Up @@ -12456,6 +12531,9 @@ of the integer ``value``. If ``value`` is larger than the size of a
pointer then a truncation is done. If ``value`` is smaller than the size
of a pointer then a zero extension is done. If they are the same size,
nothing is done (*no-op cast*).
The behavior is equivalent to a ``bitcast``, however, the resulting value is not
guaranteed to be dereferenceable (e.g. if the result type is a
:ref:`non-integral pointers <nointptrtype>`).

Example:
""""""""
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ typedef enum {
LLVMFPTrunc = 37,
LLVMFPExt = 38,
LLVMPtrToInt = 39,
LLVMPtrToAddr = 69,
LLVMIntToPtr = 40,
LLVMBitCast = 41,
LLVMAddrSpaceCast = 60,
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,13 @@ class TargetTransformInfoImplBase {
return 0;
break;
}
case Instruction::PtrToAddr: {
unsigned DstSize = Dst->getScalarSizeInBits();
if (DL.isLegalInteger(DstSize) &&
DstSize >= DL.getPointerAddressSizeInBits(Src))
return 0;
break;
}
case Instruction::PtrToInt: {
unsigned DstSize = Dst->getScalarSizeInBits();
if (DL.isLegalInteger(DstSize) &&
Expand Down Expand Up @@ -1441,6 +1448,7 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase {
Op2Info, Operands, I);
}
case Instruction::IntToPtr:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
case Instruction::SIToFP:
case Instruction::UIToFP:
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ enum Kind {
kw_fptoui,
kw_fptosi,
kw_inttoptr,
kw_ptrtoaddr,
kw_ptrtoint,
kw_bitcast,
kw_addrspacecast,
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,8 @@ enum CastOpcodes {
CAST_PTRTOINT = 9,
CAST_INTTOPTR = 10,
CAST_BITCAST = 11,
CAST_ADDRSPACECAST = 12
CAST_ADDRSPACECAST = 12,
CAST_PTRTOADDR = 13,
};

/// UnaryOpcodes - These are values used in the bitcode files to encode which
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,9 @@ class IRTranslator : public MachineFunctionPass {
bool translatePtrToInt(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_PTRTOINT, U, MIRBuilder);
}
bool translatePtrToAddr(const User &U, MachineIRBuilder &MIRBuilder) {
return translatePtrToInt(U, MIRBuilder);
}
bool translateTrunc(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_TRUNC, U, MIRBuilder);
}
Expand Down
62 changes: 54 additions & 8 deletions llvm/include/llvm/IR/DataLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,16 +324,38 @@ class DataLayout {
/// the backends/clients are updated.
Align getPointerPrefAlignment(unsigned AS = 0) const;

/// Layout pointer size in bytes, rounded up to a whole
/// number of bytes.
/// The pointer representation size in bytes, rounded up to a whole number of
/// bytes. The difference between this function and getPointerAddressSize() is
/// this one returns the size of the entire pointer type (this includes
/// metadata bits for fat pointers) and the latter only returns the number of
/// address bits.
/// \sa DataLayout::getPointerAddressSizeInBits
/// FIXME: The defaults need to be removed once all of
/// the backends/clients are updated.
unsigned getPointerSize(unsigned AS = 0) const;

// Index size in bytes used for address calculation,
/// rounded up to a whole number of bytes.
/// The index size in bytes used for address calculation, rounded up to a
/// whole number of bytes. This not only defines the size used in
/// getelementptr operations, but also the size of addresses in this \p AS.
/// For example, a 64-bit CHERI-enabled target has 128-bit pointers of which
/// only 64 are used to represent the address and the remaining ones are used
/// for metadata such as bounds and access permissions. In this case
/// getPointerSize() returns 16, but getIndexSize() returns 8.
/// To help with code understanding, the alias getPointerAddressSize() can be
/// used instead of getIndexSize() to clarify that an address width is needed.
unsigned getIndexSize(unsigned AS) const;

/// The integral size of a pointer in a given address space in bytes, which
/// is defined to be the same as getIndexSize(). This exists as a separate
/// function to make it clearer when reading code that the size of an address
/// is being requested. While targets exist where index size and the
/// underlying address width are not identical (e.g. AMDGPU fat pointers with
/// 48-bit addresses and 32-bit offsets indexing), there is currently no need
/// to differentiate these properties in LLVM.
/// \sa DataLayout::getIndexSize
/// \sa DataLayout::getPointerAddressSizeInBits
unsigned getPointerAddressSize(unsigned AS) const { return getIndexSize(AS); }

/// Return the address spaces containing non-integral pointers. Pointers in
/// this address space don't have a well-defined bitwise representation.
SmallVector<unsigned, 8> getNonIntegralAddressSpaces() const {
Expand All @@ -358,29 +380,53 @@ class DataLayout {
return PTy && isNonIntegralPointerType(PTy);
}

/// Layout pointer size, in bits
/// The size in bits of the pointer representation in a given address space.
/// This is not necessarily the same as the integer address of a pointer (e.g.
/// for fat pointers).
/// \sa DataLayout::getPointerAddressSizeInBits()
/// FIXME: The defaults need to be removed once all of
/// the backends/clients are updated.
unsigned getPointerSizeInBits(unsigned AS = 0) const {
return getPointerSpec(AS).BitWidth;
}

/// Size in bits of index used for address calculation in getelementptr.
/// The size in bits of indices used for address calculation in getelementptr
/// and for addresses in the given AS. See getIndexSize() for more
/// information.
/// \sa DataLayout::getPointerAddressSizeInBits()
unsigned getIndexSizeInBits(unsigned AS) const {
return getPointerSpec(AS).IndexBitWidth;
}

/// Layout pointer size, in bits, based on the type. If this function is
/// The size in bits of an address in for the given AS. This is defined to
/// return the same value as getIndexSizeInBits() since there is currently no
/// target that requires these two properties to have different values. See
/// getIndexSize() for more information.
/// \sa DataLayout::getIndexSizeInBits()
unsigned getPointerAddressSizeInBits(unsigned AS) const {
return getIndexSizeInBits(AS);
}

/// The pointer representation size in bits for this type. If this function is
/// called with a pointer type, then the type size of the pointer is returned.
/// If this function is called with a vector of pointers, then the type size
/// of the pointer is returned. This should only be called with a pointer or
/// vector of pointers.
unsigned getPointerTypeSizeInBits(Type *) const;

/// Layout size of the index used in GEP calculation.
/// The size in bits of the index used in GEP calculation for this type.
/// The function should be called with pointer or vector of pointers type.
/// This is defined to return the same value as getPointerAddressSizeInBits(),
/// but separate functions exist for code clarity.
unsigned getIndexTypeSizeInBits(Type *Ty) const;

/// The size in bits of an address for this type.
/// This is defined to return the same value as getIndexTypeSizeInBits(),
/// but separate functions exist for code clarity.
unsigned getPointerAddressSizeInBits(Type *Ty) const {
return getIndexTypeSizeInBits(Ty);
}

unsigned getPointerTypeSize(Type *Ty) const {
return getPointerTypeSizeInBits(Ty) / 8;
}
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/InstVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class InstVisitor {
RetTy visitUIToFPInst(UIToFPInst &I) { DELEGATE(CastInst);}
RetTy visitSIToFPInst(SIToFPInst &I) { DELEGATE(CastInst);}
RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst);}
RetTy visitPtrToAddrInst(PtrToAddrInst &I) { DELEGATE(PtrToIntInst);}
RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst);}
RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst);}
RetTy visitAddrSpaceCastInst(AddrSpaceCastInst &I) { DELEGATE(CastInst);}
Expand Down
53 changes: 27 additions & 26 deletions llvm/include/llvm/IR/Instruction.def
Original file line number Diff line number Diff line change
Expand Up @@ -190,35 +190,36 @@ HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(50)
HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer (bitcast)
HANDLE_CAST_INST(48, PtrToAddr, PtrToAddrInst) // Pointer -> Address
HANDLE_CAST_INST(49, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(50, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(51, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(51)

FIRST_FUNCLETPAD_INST(51)
HANDLE_FUNCLETPAD_INST(51, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(52, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(52)
FIRST_FUNCLETPAD_INST(52)
HANDLE_FUNCLETPAD_INST(52, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(53, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(53)

// Other operators...
FIRST_OTHER_INST(53)
HANDLE_OTHER_INST(53, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(54, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(55, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(56, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(57, Select , SelectInst ) // select instruction
HANDLE_USER_INST (58, UserOp1, Instruction) // May be used internally in a pass
HANDLE_USER_INST (59, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(60, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(61, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(62, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(63, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(64, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(65, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(66, LandingPad, LandingPadInst) // Landing pad instruction.
HANDLE_OTHER_INST(67, Freeze, FreezeInst) // Freeze instruction.
LAST_OTHER_INST(67)
FIRST_OTHER_INST(54)
HANDLE_OTHER_INST(54, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(55, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(56, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(57, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(58, Select , SelectInst ) // select instruction
HANDLE_USER_INST (59, UserOp1, Instruction) // May be used internally in a pass
HANDLE_USER_INST (60, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(61, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(62, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(63, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(64, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(65, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(66, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(67, LandingPad, LandingPadInst) // Landing pad instruction.
HANDLE_OTHER_INST(68, Freeze, FreezeInst) // Freeze instruction.
LAST_OTHER_INST(68)

#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST
Expand Down
Loading
Loading