Skip to content

Commit

Permalink
[IR] Add a target extension type to LLVM.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jcranmer-intel committed Dec 20, 2022
1 parent e43924a commit e6b0221
Show file tree
Hide file tree
Showing 34 changed files with 717 additions and 7 deletions.
15 changes: 15 additions & 0 deletions llvm/docs/BitCodeFormat.rst
Expand Up @@ -1338,6 +1338,21 @@ TYPE_CODE_X86_AMX Record

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

TYPE_CODE_TARGET_TYPE Record
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

``[TARGET_TYPE, num_tys, ...ty_params..., ...int_params... ]``

The ``TARGET_TYPE`` record (code 26) adds a target extension type to the type
table, with a name defined by a previously encountered ``STRUCT_NAME`` record.
The operand fields are

* *num_tys*: The number of parameters that are types (as opposed to integers)

* *ty_params*: Type indices that represent type parameters

* *int_params*: Numbers that correspond to the integer parameters.

.. _CONSTANTS_BLOCK:

CONSTANTS_BLOCK Contents
Expand Down
47 changes: 47 additions & 0 deletions llvm/docs/LangRef.rst
Expand Up @@ -3631,6 +3631,53 @@ Prior to LLVM 15, pointer types also specified a pointee type, such as
pointers" are still supported under non-default options. See the
`opaque pointers document <OpaquePointers.html>`__ for more information.

.. _t_target_type:

Target Extension Type
"""""""""""""""""""""

:Overview:

Target extension types represent types that must be preserved through
optimization, but are otherwise generally opaque to the compiler. They may be
used as function parameters or arguments, and in :ref:`phi <i_phi>` or
:ref:`select <i_select>` instructions. Some types may be also used in
:ref:`alloca <i_alloca>` instructions or as global values, and correspondingly
it is legal to use :ref:`load <i_load>` and :ref:`store <i_store>` instructions
on them. Full semantics for these types are defined by the target.

The only constants that target extension types may have are ``zeroinitializer``,
``undef``, and ``poison``. Other possible values for target extension types may
arise from target-specific intrinsics and functions.

These types cannot be converted to other types. As such, it is not legal to use
them in :ref:`bitcast <i_bitcast>` instructions (as a source or target type),
nor is it legal to use them in :ref:`ptrtoint <i_ptrtoint>` or
:ref:`inttoptr <i_inttoptr>` instructions. Similarly, they are not legal to use
in an :ref:`icmp <i_icmp>` instruction.

Target extension types have a name and optional type or integer parameters. The
meanings of name and parameters are defined by the target. When being defined in
LLVM IR, all of the type parameters must precede all of the integer parameters.

Specific target extension types are registered with LLVM as having specific
properties. These properties can be used to restrict the type from appearing in
certain contexts, such as being the type of a global variable or having a
``zeroinitializer`` constant be valid. A complete list of type properties may be
found in the documentation for ``llvm::TargetExtType::Property`` (`doxygen
<https://llvm.org/doxygen/classllvm_1_1TargetExtType.html>`_).

:Syntax:

.. code-block:: llvm

target("label")
target("label", void)
target("label", void, i32)
target("label", 0, 1, 2)
target("label", void, i32, 0, 1, 2)


.. _t_vector:

Vector Type
Expand Down
4 changes: 4 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Expand Up @@ -104,6 +104,10 @@ Changes to the LLVM IR

* ``fneg``

* Target extension types have been added, which allow targets to have
types that need to be preserved through the optimizer, but otherwise are not
introspectable by target-independent optimizations.

Changes to building LLVM
------------------------

Expand Down
15 changes: 13 additions & 2 deletions llvm/include/llvm-c/Core.h
Expand Up @@ -165,7 +165,8 @@ typedef enum {
LLVMTokenTypeKind, /**< Tokens */
LLVMScalableVectorTypeKind, /**< Scalable SIMD vector type */
LLVMBFloatTypeKind, /**< 16 bit brain floating point type */
LLVMX86_AMXTypeKind /**< X86 AMX */
LLVMX86_AMXTypeKind, /**< X86 AMX */
LLVMTargetExtTypeKind, /**< Target extension type */
} LLVMTypeKind;

typedef enum {
Expand Down Expand Up @@ -284,7 +285,8 @@ typedef enum {
LLVMInlineAsmValueKind,

LLVMInstructionValueKind,
LLVMPoisonValueValueKind
LLVMPoisonValueValueKind,
LLVMConstantTargetNoneValueKind,
} LLVMValueKind;

typedef enum {
Expand Down Expand Up @@ -1571,6 +1573,15 @@ LLVMTypeRef LLVMLabelType(void);
LLVMTypeRef LLVMX86MMXType(void);
LLVMTypeRef LLVMX86AMXType(void);

/**
* Create a target extension type in LLVM context.
*/
LLVMTypeRef LLVMTargetExtTypeInContext(LLVMContextRef C, const char *Name,
LLVMTypeRef *TypeParams,
unsigned TypeParamCount,
unsigned *IntParams,
unsigned IntParamCount);

/**
* @}
*/
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/AsmParser/LLParser.h
Expand Up @@ -433,6 +433,7 @@ namespace llvm {

bool parseArrayVectorType(Type *&Result, bool IsVector);
bool parseFunctionType(Type *&Result);
bool parseTargetExtType(Type *&Result);

// Function Semantic Analysis.
class PerFunctionState {
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Bitcode/LLVMBitCodes.h
Expand Up @@ -175,6 +175,8 @@ enum TypeCodes {
TYPE_CODE_X86_AMX = 24, // X86 AMX

TYPE_CODE_OPAQUE_POINTER = 25, // OPAQUE_POINTER: [addrspace]

TYPE_CODE_TARGET_TYPE = 26, // TARGET_TYPE
};

enum OperandBundleTagCode {
Expand Down
27 changes: 27 additions & 0 deletions llvm/include/llvm/IR/Constants.h
Expand Up @@ -843,6 +843,33 @@ class ConstantTokenNone final : public ConstantData {
}
};

/// A constant target extension type default initializer
class ConstantTargetNone final : public ConstantData {
friend class Constant;

explicit ConstantTargetNone(TargetExtType *T)
: ConstantData(T, Value::ConstantTargetNoneVal) {}

void destroyConstantImpl();

public:
ConstantTargetNone(const ConstantTargetNone &) = delete;

/// Static factory methods - Return objects of the specified value.
static ConstantTargetNone *get(TargetExtType *T);

/// Specialize the getType() method to always return an TargetExtType,
/// which reduces the amount of casting needed in parts of the compiler.
inline TargetExtType *getType() const {
return cast<TargetExtType>(Value::getType());
}

/// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Value *V) {
return V->getValueID() == ConstantTargetNoneVal;
}
};

/// The address of a basic block.
///
class BlockAddress final : public Constant {
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/DataLayout.h
Expand Up @@ -713,6 +713,10 @@ inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const {
getTypeSizeInBits(VTy->getElementType()).getFixedSize();
return TypeSize(MinBits, EltCnt.isScalable());
}
case Type::TargetExtTyID: {
Type *LayoutTy = cast<TargetExtType>(Ty)->getLayoutType();
return getTypeSizeInBits(LayoutTy);
}
default:
llvm_unreachable("DataLayout::getTypeSizeInBits(): Unsupported type");
}
Expand Down
76 changes: 76 additions & 0 deletions llvm/include/llvm/IR/DerivedTypes.h
Expand Up @@ -730,6 +730,82 @@ unsigned Type::getPointerAddressSpace() const {
return cast<PointerType>(getScalarType())->getAddressSpace();
}

/// Class to represent target extensions types, which are generally
/// unintrospectable from target-independent optimizations.
///
/// Target extension types have a string name, and optionally have type and/or
/// integer parameters. The exact meaning of any parameters is dependent on the
/// target.
class TargetExtType : public Type {
TargetExtType(LLVMContext &C, StringRef Name, ArrayRef<Type *> Types,
ArrayRef<unsigned> Ints);

std::string Name;
unsigned *IntParams;

public:
TargetExtType(const TargetExtType &) = delete;
TargetExtType &operator=(const TargetExtType &) = delete;

/// Return a target extension type having the specified name and optional
/// type and integer parameters.
static TargetExtType *get(LLVMContext &Context, StringRef Name,
ArrayRef<Type *> Types = std::nullopt,
ArrayRef<unsigned> Ints = std::nullopt);

/// Return the name for this target extension type. Two distinct target
/// extension types may have the same name if their type or integer parameters
/// differ.
StringRef getName() const { return Name; }

/// Return the type parameters for this particular target extension type. If
/// there are no parameters, an empty array is returned.
ArrayRef<Type *> type_params() const {
return makeArrayRef(type_param_begin(), type_param_end());
}

using type_param_iterator = Type::subtype_iterator;
type_param_iterator type_param_begin() const { return ContainedTys; }
type_param_iterator type_param_end() const {
return &ContainedTys[NumContainedTys];
}

Type *getTypeParameter(unsigned i) const { return getContainedType(i); }
unsigned getNumTypeParameters() const { return getNumContainedTypes(); }

/// Return the integer parameters for this particular target extension type.
/// If there are no parameters, an empty array is returned.
ArrayRef<unsigned> int_params() const {
return makeArrayRef(IntParams, getNumIntParameters());
}

unsigned getIntParameter(unsigned i) const { return IntParams[i]; }
unsigned getNumIntParameters() const { return getSubclassData(); }

enum Property {
/// zeroinitializer is valid for this target extension type.
HasZeroInit = 1U << 0,
/// This type may be used as the value type of a global variable.
CanBeGlobal = 1U << 1,
};

/// Returns true if the target extension type contains the given property.
bool hasProperty(Property Prop) const;

/// Returns an underlying layout type for the target extension type. This
/// type can be used to query size and alignment information, if it is
/// appropriate (although note that the layout type may also be void). It is
/// not legal to bitcast between this type and the layout type, however.
Type *getLayoutType() const;

/// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Type *T) { return T->getTypeID() == TargetExtTyID; }
};

StringRef Type::getTargetExtName() const {
return cast<TargetExtType>(this)->getName();
}

} // end namespace llvm

#endif // LLVM_IR_DERIVEDTYPES_H
11 changes: 9 additions & 2 deletions llvm/include/llvm/IR/Type.h
Expand Up @@ -76,6 +76,7 @@ class Type {
FixedVectorTyID, ///< Fixed width SIMD vector type
ScalableVectorTyID, ///< Scalable SIMD vector type
TypedPointerTyID, ///< Typed pointer used by some GPU targets
TargetExtTyID, ///< Target extension type
};

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

/// Return true if this is a target extension type.
bool isTargetExtTy() const { return getTypeID() == TargetExtTyID; }

/// Return true if this is a FP type or a vector of FP.
bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); }

Expand Down Expand Up @@ -267,7 +271,7 @@ class Type {
/// includes all first-class types except struct and array types.
bool isSingleValueType() const {
return isFloatingPointTy() || isX86_MMXTy() || isIntegerTy() ||
isPointerTy() || isVectorTy() || isX86_AMXTy();
isPointerTy() || isVectorTy() || isX86_AMXTy() || isTargetExtTy();
}

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

inline StringRef getTargetExtName() const;

/// This method is deprecated without replacement. Pointer element types are
/// not available with opaque pointers.
[[deprecated("Deprecated without replacement, see "
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/Value.def
Expand Up @@ -95,6 +95,7 @@ HANDLE_CONSTANT(ConstantDataArray)
HANDLE_CONSTANT(ConstantDataVector)
HANDLE_CONSTANT(ConstantInt)
HANDLE_CONSTANT(ConstantFP)
HANDLE_CONSTANT(ConstantTargetNone)
HANDLE_CONSTANT(ConstantPointerNull)
HANDLE_CONSTANT(ConstantTokenNone)

Expand Down

0 comments on commit e6b0221

Please sign in to comment.