Skip to content

Commit e6b0221

Browse files
[IR] Add a target extension type to LLVM.
Target-extension types represent types that need to be preserved through optimization, but otherwise are not introspectable by target-independent optimizations. This patch doesn't add any uses of these types by an existing backend, it only provides basic infrastructure such that these types would work correctly. Reviewed By: nikic, barannikov88 Differential Revision: https://reviews.llvm.org/D135202
1 parent e43924a commit e6b0221

34 files changed

+717
-7
lines changed

llvm/docs/BitCodeFormat.rst

+15
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,21 @@ TYPE_CODE_X86_AMX Record
13381338

13391339
The ``X86_AMX`` record (code 24) adds an ``x86_amx`` type to the type table.
13401340

1341+
TYPE_CODE_TARGET_TYPE Record
1342+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1343+
1344+
``[TARGET_TYPE, num_tys, ...ty_params..., ...int_params... ]``
1345+
1346+
The ``TARGET_TYPE`` record (code 26) adds a target extension type to the type
1347+
table, with a name defined by a previously encountered ``STRUCT_NAME`` record.
1348+
The operand fields are
1349+
1350+
* *num_tys*: The number of parameters that are types (as opposed to integers)
1351+
1352+
* *ty_params*: Type indices that represent type parameters
1353+
1354+
* *int_params*: Numbers that correspond to the integer parameters.
1355+
13411356
.. _CONSTANTS_BLOCK:
13421357

13431358
CONSTANTS_BLOCK Contents

llvm/docs/LangRef.rst

+47
Original file line numberDiff line numberDiff line change
@@ -3631,6 +3631,53 @@ Prior to LLVM 15, pointer types also specified a pointee type, such as
36313631
pointers" are still supported under non-default options. See the
36323632
`opaque pointers document <OpaquePointers.html>`__ for more information.
36333633

3634+
.. _t_target_type:
3635+
3636+
Target Extension Type
3637+
"""""""""""""""""""""
3638+
3639+
:Overview:
3640+
3641+
Target extension types represent types that must be preserved through
3642+
optimization, but are otherwise generally opaque to the compiler. They may be
3643+
used as function parameters or arguments, and in :ref:`phi <i_phi>` or
3644+
:ref:`select <i_select>` instructions. Some types may be also used in
3645+
:ref:`alloca <i_alloca>` instructions or as global values, and correspondingly
3646+
it is legal to use :ref:`load <i_load>` and :ref:`store <i_store>` instructions
3647+
on them. Full semantics for these types are defined by the target.
3648+
3649+
The only constants that target extension types may have are ``zeroinitializer``,
3650+
``undef``, and ``poison``. Other possible values for target extension types may
3651+
arise from target-specific intrinsics and functions.
3652+
3653+
These types cannot be converted to other types. As such, it is not legal to use
3654+
them in :ref:`bitcast <i_bitcast>` instructions (as a source or target type),
3655+
nor is it legal to use them in :ref:`ptrtoint <i_ptrtoint>` or
3656+
:ref:`inttoptr <i_inttoptr>` instructions. Similarly, they are not legal to use
3657+
in an :ref:`icmp <i_icmp>` instruction.
3658+
3659+
Target extension types have a name and optional type or integer parameters. The
3660+
meanings of name and parameters are defined by the target. When being defined in
3661+
LLVM IR, all of the type parameters must precede all of the integer parameters.
3662+
3663+
Specific target extension types are registered with LLVM as having specific
3664+
properties. These properties can be used to restrict the type from appearing in
3665+
certain contexts, such as being the type of a global variable or having a
3666+
``zeroinitializer`` constant be valid. A complete list of type properties may be
3667+
found in the documentation for ``llvm::TargetExtType::Property`` (`doxygen
3668+
<https://llvm.org/doxygen/classllvm_1_1TargetExtType.html>`_).
3669+
3670+
:Syntax:
3671+
3672+
.. code-block:: llvm
3673+
3674+
target("label")
3675+
target("label", void)
3676+
target("label", void, i32)
3677+
target("label", 0, 1, 2)
3678+
target("label", void, i32, 0, 1, 2)
3679+
3680+
36343681
.. _t_vector:
36353682

36363683
Vector Type

llvm/docs/ReleaseNotes.rst

+4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ Changes to the LLVM IR
104104

105105
* ``fneg``
106106

107+
* Target extension types have been added, which allow targets to have
108+
types that need to be preserved through the optimizer, but otherwise are not
109+
introspectable by target-independent optimizations.
110+
107111
Changes to building LLVM
108112
------------------------
109113

llvm/include/llvm-c/Core.h

+13-2
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ typedef enum {
165165
LLVMTokenTypeKind, /**< Tokens */
166166
LLVMScalableVectorTypeKind, /**< Scalable SIMD vector type */
167167
LLVMBFloatTypeKind, /**< 16 bit brain floating point type */
168-
LLVMX86_AMXTypeKind /**< X86 AMX */
168+
LLVMX86_AMXTypeKind, /**< X86 AMX */
169+
LLVMTargetExtTypeKind, /**< Target extension type */
169170
} LLVMTypeKind;
170171

171172
typedef enum {
@@ -284,7 +285,8 @@ typedef enum {
284285
LLVMInlineAsmValueKind,
285286

286287
LLVMInstructionValueKind,
287-
LLVMPoisonValueValueKind
288+
LLVMPoisonValueValueKind,
289+
LLVMConstantTargetNoneValueKind,
288290
} LLVMValueKind;
289291

290292
typedef enum {
@@ -1571,6 +1573,15 @@ LLVMTypeRef LLVMLabelType(void);
15711573
LLVMTypeRef LLVMX86MMXType(void);
15721574
LLVMTypeRef LLVMX86AMXType(void);
15731575

1576+
/**
1577+
* Create a target extension type in LLVM context.
1578+
*/
1579+
LLVMTypeRef LLVMTargetExtTypeInContext(LLVMContextRef C, const char *Name,
1580+
LLVMTypeRef *TypeParams,
1581+
unsigned TypeParamCount,
1582+
unsigned *IntParams,
1583+
unsigned IntParamCount);
1584+
15741585
/**
15751586
* @}
15761587
*/

llvm/include/llvm/AsmParser/LLParser.h

+1
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ namespace llvm {
433433

434434
bool parseArrayVectorType(Type *&Result, bool IsVector);
435435
bool parseFunctionType(Type *&Result);
436+
bool parseTargetExtType(Type *&Result);
436437

437438
// Function Semantic Analysis.
438439
class PerFunctionState {

llvm/include/llvm/Bitcode/LLVMBitCodes.h

+2
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ enum TypeCodes {
175175
TYPE_CODE_X86_AMX = 24, // X86 AMX
176176

177177
TYPE_CODE_OPAQUE_POINTER = 25, // OPAQUE_POINTER: [addrspace]
178+
179+
TYPE_CODE_TARGET_TYPE = 26, // TARGET_TYPE
178180
};
179181

180182
enum OperandBundleTagCode {

llvm/include/llvm/IR/Constants.h

+27
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,33 @@ class ConstantTokenNone final : public ConstantData {
843843
}
844844
};
845845

846+
/// A constant target extension type default initializer
847+
class ConstantTargetNone final : public ConstantData {
848+
friend class Constant;
849+
850+
explicit ConstantTargetNone(TargetExtType *T)
851+
: ConstantData(T, Value::ConstantTargetNoneVal) {}
852+
853+
void destroyConstantImpl();
854+
855+
public:
856+
ConstantTargetNone(const ConstantTargetNone &) = delete;
857+
858+
/// Static factory methods - Return objects of the specified value.
859+
static ConstantTargetNone *get(TargetExtType *T);
860+
861+
/// Specialize the getType() method to always return an TargetExtType,
862+
/// which reduces the amount of casting needed in parts of the compiler.
863+
inline TargetExtType *getType() const {
864+
return cast<TargetExtType>(Value::getType());
865+
}
866+
867+
/// Methods for support type inquiry through isa, cast, and dyn_cast.
868+
static bool classof(const Value *V) {
869+
return V->getValueID() == ConstantTargetNoneVal;
870+
}
871+
};
872+
846873
/// The address of a basic block.
847874
///
848875
class BlockAddress final : public Constant {

llvm/include/llvm/IR/DataLayout.h

+4
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,10 @@ inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const {
713713
getTypeSizeInBits(VTy->getElementType()).getFixedSize();
714714
return TypeSize(MinBits, EltCnt.isScalable());
715715
}
716+
case Type::TargetExtTyID: {
717+
Type *LayoutTy = cast<TargetExtType>(Ty)->getLayoutType();
718+
return getTypeSizeInBits(LayoutTy);
719+
}
716720
default:
717721
llvm_unreachable("DataLayout::getTypeSizeInBits(): Unsupported type");
718722
}

llvm/include/llvm/IR/DerivedTypes.h

+76
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,82 @@ unsigned Type::getPointerAddressSpace() const {
730730
return cast<PointerType>(getScalarType())->getAddressSpace();
731731
}
732732

733+
/// Class to represent target extensions types, which are generally
734+
/// unintrospectable from target-independent optimizations.
735+
///
736+
/// Target extension types have a string name, and optionally have type and/or
737+
/// integer parameters. The exact meaning of any parameters is dependent on the
738+
/// target.
739+
class TargetExtType : public Type {
740+
TargetExtType(LLVMContext &C, StringRef Name, ArrayRef<Type *> Types,
741+
ArrayRef<unsigned> Ints);
742+
743+
std::string Name;
744+
unsigned *IntParams;
745+
746+
public:
747+
TargetExtType(const TargetExtType &) = delete;
748+
TargetExtType &operator=(const TargetExtType &) = delete;
749+
750+
/// Return a target extension type having the specified name and optional
751+
/// type and integer parameters.
752+
static TargetExtType *get(LLVMContext &Context, StringRef Name,
753+
ArrayRef<Type *> Types = std::nullopt,
754+
ArrayRef<unsigned> Ints = std::nullopt);
755+
756+
/// Return the name for this target extension type. Two distinct target
757+
/// extension types may have the same name if their type or integer parameters
758+
/// differ.
759+
StringRef getName() const { return Name; }
760+
761+
/// Return the type parameters for this particular target extension type. If
762+
/// there are no parameters, an empty array is returned.
763+
ArrayRef<Type *> type_params() const {
764+
return makeArrayRef(type_param_begin(), type_param_end());
765+
}
766+
767+
using type_param_iterator = Type::subtype_iterator;
768+
type_param_iterator type_param_begin() const { return ContainedTys; }
769+
type_param_iterator type_param_end() const {
770+
return &ContainedTys[NumContainedTys];
771+
}
772+
773+
Type *getTypeParameter(unsigned i) const { return getContainedType(i); }
774+
unsigned getNumTypeParameters() const { return getNumContainedTypes(); }
775+
776+
/// Return the integer parameters for this particular target extension type.
777+
/// If there are no parameters, an empty array is returned.
778+
ArrayRef<unsigned> int_params() const {
779+
return makeArrayRef(IntParams, getNumIntParameters());
780+
}
781+
782+
unsigned getIntParameter(unsigned i) const { return IntParams[i]; }
783+
unsigned getNumIntParameters() const { return getSubclassData(); }
784+
785+
enum Property {
786+
/// zeroinitializer is valid for this target extension type.
787+
HasZeroInit = 1U << 0,
788+
/// This type may be used as the value type of a global variable.
789+
CanBeGlobal = 1U << 1,
790+
};
791+
792+
/// Returns true if the target extension type contains the given property.
793+
bool hasProperty(Property Prop) const;
794+
795+
/// Returns an underlying layout type for the target extension type. This
796+
/// type can be used to query size and alignment information, if it is
797+
/// appropriate (although note that the layout type may also be void). It is
798+
/// not legal to bitcast between this type and the layout type, however.
799+
Type *getLayoutType() const;
800+
801+
/// Methods for support type inquiry through isa, cast, and dyn_cast.
802+
static bool classof(const Type *T) { return T->getTypeID() == TargetExtTyID; }
803+
};
804+
805+
StringRef Type::getTargetExtName() const {
806+
return cast<TargetExtType>(this)->getName();
807+
}
808+
733809
} // end namespace llvm
734810

735811
#endif // LLVM_IR_DERIVEDTYPES_H

llvm/include/llvm/IR/Type.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class Type {
7676
FixedVectorTyID, ///< Fixed width SIMD vector type
7777
ScalableVectorTyID, ///< Scalable SIMD vector type
7878
TypedPointerTyID, ///< Typed pointer used by some GPU targets
79+
TargetExtTyID, ///< Target extension type
7980
};
8081

8182
private:
@@ -194,6 +195,9 @@ class Type {
194195
/// Return true if this is X86 AMX.
195196
bool isX86_AMXTy() const { return getTypeID() == X86_AMXTyID; }
196197

198+
/// Return true if this is a target extension type.
199+
bool isTargetExtTy() const { return getTypeID() == TargetExtTyID; }
200+
197201
/// Return true if this is a FP type or a vector of FP.
198202
bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); }
199203

@@ -267,7 +271,7 @@ class Type {
267271
/// includes all first-class types except struct and array types.
268272
bool isSingleValueType() const {
269273
return isFloatingPointTy() || isX86_MMXTy() || isIntegerTy() ||
270-
isPointerTy() || isVectorTy() || isX86_AMXTy();
274+
isPointerTy() || isVectorTy() || isX86_AMXTy() || isTargetExtTy();
271275
}
272276

273277
/// Return true if the type is an aggregate type. This means it is valid as
@@ -288,7 +292,8 @@ class Type {
288292
return true;
289293
// If it is not something that can have a size (e.g. a function or label),
290294
// it doesn't have a size.
291-
if (getTypeID() != StructTyID && getTypeID() != ArrayTyID && !isVectorTy())
295+
if (getTypeID() != StructTyID && getTypeID() != ArrayTyID &&
296+
!isVectorTy() && getTypeID() != TargetExtTyID)
292297
return false;
293298
// Otherwise we have to try harder to decide.
294299
return isSizedDerivedType(Visited);
@@ -386,6 +391,8 @@ class Type {
386391
return ContainedTys[0];
387392
}
388393

394+
inline StringRef getTargetExtName() const;
395+
389396
/// This method is deprecated without replacement. Pointer element types are
390397
/// not available with opaque pointers.
391398
[[deprecated("Deprecated without replacement, see "

llvm/include/llvm/IR/Value.def

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ HANDLE_CONSTANT(ConstantDataArray)
9595
HANDLE_CONSTANT(ConstantDataVector)
9696
HANDLE_CONSTANT(ConstantInt)
9797
HANDLE_CONSTANT(ConstantFP)
98+
HANDLE_CONSTANT(ConstantTargetNone)
9899
HANDLE_CONSTANT(ConstantPointerNull)
99100
HANDLE_CONSTANT(ConstantTokenNone)
100101

0 commit comments

Comments
 (0)