[llvm] [IR] Add initial support for the byte type (PR #178666)
Pedro Lobo via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 31 12:18:48 PST 2026
https://github.com/pedroclobo updated https://github.com/llvm/llvm-project/pull/178666
>From afeb5bf065719aa67db1cb57aa56d1bfc9d37e31 Mon Sep 17 00:00:00 2001
From: George Mitenkov <georgemitenk0v at gmail.com>
Date: Thu, 22 Jul 2021 14:29:05 +0300
Subject: [PATCH 01/15] [IR] Introduce the byte type
- Adds the byte type
- Extends the `bitcast` instruction to accept the byte type as a destination type
- Fixes `IR2Vec` tests
---
llvm/include/llvm-c/Core.h | 93 +++++
llvm/include/llvm/Analysis/IR2Vec.h | 8 +-
llvm/include/llvm/Bitcode/LLVMBitCodes.h | 4 +
llvm/include/llvm/IR/Constants.h | 248 +++++++++++-
llvm/include/llvm/IR/DataLayout.h | 19 +
llvm/include/llvm/IR/DerivedTypes.h | 56 +++
llvm/include/llvm/IR/IRBuilder.h | 24 ++
llvm/include/llvm/IR/Type.h | 30 +-
llvm/include/llvm/IR/Value.def | 1 +
llvm/lib/AsmParser/LLLexer.cpp | 37 +-
llvm/lib/AsmParser/LLParser.cpp | 21 +-
llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 54 ++-
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 29 +-
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 6 +-
.../SelectionDAG/FunctionLoweringInfo.cpp | 2 +-
.../SelectionDAG/SelectionDAGBuilder.cpp | 3 +
llvm/lib/CodeGen/ValueTypes.cpp | 4 +
llvm/lib/IR/AsmWriter.cpp | 26 +-
llvm/lib/IR/Attributes.cpp | 4 +-
llvm/lib/IR/Constants.cpp | 357 +++++++++++++++++-
llvm/lib/IR/Core.cpp | 78 ++++
llvm/lib/IR/DataLayout.cpp | 37 ++
llvm/lib/IR/Instructions.cpp | 26 +-
llvm/lib/IR/Intrinsics.cpp | 3 +
llvm/lib/IR/LLVMContextImpl.cpp | 7 +-
llvm/lib/IR/LLVMContextImpl.h | 11 +
llvm/lib/IR/Type.cpp | 54 ++-
llvm/lib/IR/Verifier.cpp | 10 +-
.../DirectX/DXILWriter/DXILBitcodeWriter.cpp | 19 +
.../Inputs/reference_default_vocab_print.txt | 1 +
.../Inputs/reference_wtd1_vocab_print.txt | 1 +
.../Inputs/reference_wtd2_vocab_print.txt | 1 +
.../Assembler/2008-02-18-IntPointerCrash.ll | 2 +-
llvm/test/Assembler/byte-invalid-cast-1.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-2.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-3.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-4.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-5.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-6.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-7.ll | 7 +
llvm/test/Assembler/byte-invalid-cmp.ll | 7 +
llvm/test/Assembler/byte.ll | 79 ++++
llvm/test/Assembler/invalid-inttype.ll | 2 +-
llvm/test/Bindings/llvm-c/byte.ll | 11 +
llvm/test/Bindings/llvm-c/echo.ll | 1 +
llvm/test/Bitcode/compatibility.ll | 2 +
llvm/test/Verifier/atomics.ll | 4 +-
llvm/test/tools/llvm-ir2vec/entities.ll | 73 ++--
llvm/test/tools/llvm-ir2vec/triplets.ll | 38 +-
llvm/tools/llvm-c-test/echo.cpp | 2 +
llvm/unittests/Analysis/IR2VecTest.cpp | 29 +-
51 files changed, 1423 insertions(+), 150 deletions(-)
create mode 100644 llvm/test/Assembler/byte-invalid-cast-1.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-2.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-3.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-4.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-5.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-6.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-7.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cmp.ll
create mode 100644 llvm/test/Assembler/byte.ll
create mode 100644 llvm/test/Bindings/llvm-c/byte.ll
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 2bd971983e287..23f94408b86b5 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -169,6 +169,7 @@ typedef enum {
LLVMBFloatTypeKind = 18, /**< 16 bit brain floating point type */
LLVMX86_AMXTypeKind = 19, /**< X86 AMX */
LLVMTargetExtTypeKind = 20, /**< Target extension type */
+ LLVMByteTypeKind = 21, /**< Arbitrary bit width bytes */
} LLVMTypeKind;
typedef enum {
@@ -278,6 +279,7 @@ typedef enum {
LLVMConstantDataArrayValueKind,
LLVMConstantDataVectorValueKind,
LLVMConstantIntValueKind,
+ LLVMConstantByteValueKind,
LLVMConstantFPValueKind,
LLVMConstantPointerNullValueKind,
LLVMConstantTokenNoneValueKind,
@@ -1311,6 +1313,7 @@ LLVM_C_ABI void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm);
*
* types:
* integer type
+ * byte type
* real type
* function type
* sequence types:
@@ -1362,6 +1365,40 @@ LLVM_C_ABI void LLVMDumpType(LLVMTypeRef Val);
*/
LLVM_C_ABI char *LLVMPrintTypeToString(LLVMTypeRef Val);
+/**
+ * @}
+ */
+
+/**
+ * @defgroup LLVMCCoreTypeByte Byte Types
+ *
+ * Functions in this section operate on byte types.
+ *
+ * @{
+ */
+
+/**
+ * Obtain a byte type from a context with specified bit width.
+ */
+LLVMTypeRef LLVMByte8TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByte16TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByte32TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByte64TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByte128TypeInContext(LLVMContextRef C);
+LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C, unsigned NumBits);
+
+/**
+ * Obtain a byte type from the global context with a specified bit
+ * width.
+ */
+LLVMTypeRef LLVMByte8Type(void);
+LLVMTypeRef LLVMByte16Type(void);
+LLVMTypeRef LLVMByte32Type(void);
+LLVMTypeRef LLVMByte64Type(void);
+LLVMTypeRef LLVMByte128Type(void);
+LLVMTypeRef LLVMByteType(unsigned NumBits);
+unsigned LLVMGetByteTypeWidth(LLVMTypeRef ByteTy);
+
/**
* @defgroup LLVMCCoreTypeInt Integer Types
*
@@ -1978,6 +2015,7 @@ LLVM_C_ABI unsigned LLVMGetTargetExtTypeIntParam(LLVMTypeRef TargetExtTy,
macro(ConstantExpr) \
macro(ConstantFP) \
macro(ConstantInt) \
+ macro(ConstantByte) \
macro(ConstantPointerNull) \
macro(ConstantStruct) \
macro(ConstantTokenNone) \
@@ -2389,6 +2427,47 @@ LLVM_C_ABI LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy,
unsigned SLen,
uint8_t Radix);
+/**
+ * Obtain a constant value for a byte type.
+ *
+ * The returned value corresponds to a llvm::ConstantByte.
+ *
+ * @see llvm::ConstantByte::get()
+ *
+ * @param ByteTy Byte type to obtain value of.
+ * @param N The value the returned instance should refer to.
+ */
+LLVMValueRef LLVMConstByte(LLVMTypeRef ByteTy, unsigned long long N);
+
+/**
+ * Obtain a constant value for a byte of arbitrary precision.
+ *
+ * @see llvm::ConstantByte::get()
+ */
+LLVMValueRef LLVMConstByteOfArbitraryPrecision(LLVMTypeRef ByteTy,
+ unsigned NumWords,
+ const uint64_t Words[]);
+
+/**
+ * Obtain a constant value for a byte parsed from a string.
+ *
+ * A similar API, LLVMConstByteOfStringAndSize is also available. If the
+ * string's length is available, it is preferred to call that function
+ * instead.
+ *
+ * @see llvm::ConstantByte::get()
+ */
+LLVMValueRef LLVMConstByteOfString(LLVMTypeRef ByteTy, const char *Text,
+ uint8_t Radix);
+
+/**
+ * Obtain a constant value for a byte parsed from a string with specified
+ * length.
+ * @see llvm::ConstantByte::get()
+ */
+LLVMValueRef LLVMConstByteOfStringAndSize(LLVMTypeRef ByteTy, const char *Text,
+ unsigned SLen, uint8_t Radix);
+
/**
* Obtain a constant value referring to a double floating point value.
*/
@@ -2433,6 +2512,20 @@ LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal);
*/
LLVM_C_ABI long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal);
+/**
+ * Obtain the zero extended value for a byte constant value.
+ *
+ * @see llvm::ConstantByte::getZExtValue()
+ */
+unsigned long long LLVMConstByteGetZExtValue(LLVMValueRef ConstantVal);
+
+/**
+ * Obtain the sign extended value for a byte constant value.
+ *
+ * @see llvm::ConstantByte::getSExtValue()
+ */
+long long LLVMConstByteGetSExtValue(LLVMValueRef ConstantVal);
+
/**
* Obtain the double value for an floating point constant value.
* losesInfo indicates if some precision was lost in the conversion.
diff --git a/llvm/include/llvm/Analysis/IR2Vec.h b/llvm/include/llvm/Analysis/IR2Vec.h
index fdaed0f0901a9..e728e76fcc058 100644
--- a/llvm/include/llvm/Analysis/IR2Vec.h
+++ b/llvm/include/llvm/Analysis/IR2Vec.h
@@ -286,6 +286,7 @@ class Vocabulary {
VectorTy,
TokenTy,
IntegerTy,
+ ByteTy,
FunctionTy,
PointerTy,
StructTy,
@@ -459,9 +460,9 @@ class Vocabulary {
/// String mappings for CanonicalTypeID values
static constexpr StringLiteral CanonicalTypeNames[] = {
- "FloatTy", "VoidTy", "LabelTy", "MetadataTy",
- "VectorTy", "TokenTy", "IntegerTy", "FunctionTy",
- "PointerTy", "StructTy", "ArrayTy", "UnknownTy"};
+ "FloatTy", "VoidTy", "LabelTy", "MetadataTy", "VectorTy",
+ "TokenTy", "IntegerTy", "ByteTy", "FunctionTy", "PointerTy",
+ "StructTy", "ArrayTy", "UnknownTy"};
static_assert(std::size(CanonicalTypeNames) ==
static_cast<unsigned>(CanonicalTypeID::MaxCanonicalType),
"CanonicalTypeNames array size must match MaxCanonicalType");
@@ -488,6 +489,7 @@ class Vocabulary {
CanonicalTypeID::MetadataTy, // MetadataTyID
CanonicalTypeID::VectorTy, // X86_AMXTyID
CanonicalTypeID::TokenTy, // TokenTyID
+ CanonicalTypeID::ByteTy, // ByteTyID
CanonicalTypeID::IntegerTy, // IntegerTyID
CanonicalTypeID::FunctionTy, // FunctionTyID
CanonicalTypeID::PointerTy, // PointerTyID
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 20d19f21a64ce..592bdf3a34949 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -177,6 +177,8 @@ enum TypeCodes {
TYPE_CODE_OPAQUE_POINTER = 25, // OPAQUE_POINTER: [addrspace]
TYPE_CODE_TARGET_TYPE = 26, // TARGET_TYPE
+
+ TYPE_CODE_BYTE = 27, // BYTE: [width]
};
enum OperandBundleTagCode {
@@ -440,6 +442,8 @@ enum ConstantsCodes {
CST_CODE_PTRAUTH = 33, // [ptr, key, disc, addrdisc]
CST_CODE_PTRAUTH2 = 34, // [ptr, key, disc, addrdisc,
// deactivation_symbol]
+ CST_CODE_BYTE = 35, // BYTE: [intval]
+ CST_CODE_WIDE_BYTE = 36, // WIDE_BYTE: [n x intval]
};
/// CastOpcodes - These are values used in the bitcode files to encode which
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index f35b249e9686d..53d1b1ca9b059 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -276,6 +276,199 @@ class ConstantInt final : public ConstantData {
}
};
+//===----------------------------------------------------------------------===//
+/// Class for constant bytes.
+class ConstantByte final : public ConstantData {
+ friend class Constant;
+ friend class ConstantVector;
+
+ APInt Val;
+
+ ConstantByte(Type *Ty, const APInt &V);
+
+ void destroyConstantImpl();
+
+ /// Return a ConstantByte with the specified value and an implied Type. The
+ /// type is the vector type whose byte element type corresponds to the bit
+ /// width of the value.
+ static ConstantByte *get(LLVMContext &Context, ElementCount EC,
+ const APInt &V);
+
+public:
+ ConstantByte(const ConstantByte &) = delete;
+
+ LLVM_ABI static ConstantByte *getTrue(LLVMContext &Context);
+ LLVM_ABI static ConstantByte *getFalse(LLVMContext &Context);
+ LLVM_ABI static ConstantByte *getBool(LLVMContext &Context, bool V);
+ LLVM_ABI static Constant *getTrue(Type *Ty);
+ LLVM_ABI static Constant *getFalse(Type *Ty);
+ LLVM_ABI static Constant *getBool(Type *Ty, bool V);
+
+ /// If Ty is a vector type, return a Constant with a splat of the given
+ /// value. Otherwise return a ConstantByte for the given value.
+ /// \param ImplicitTrunc Whether to allow implicit truncation of the value.
+ LLVM_ABI static Constant *get(Type *Ty, uint64_t V, bool isSigned = false,
+ bool ImplicitTrunc = false);
+
+ /// Return a ConstantByte with the specified byte value for the specified
+ /// type. If the type is wider than 64 bits, the value will be zero-extended
+ /// to fit the type, unless IsSigned is true, in which case the value will
+ /// be interpreted as a 64-bit signed byte and sign-extended to fit
+ /// the type.
+ /// \param ImplicitTrunc Whether to allow implicit truncation of the value.
+ LLVM_ABI static ConstantByte *get(ByteType *Ty, uint64_t V,
+ bool isSigned = false,
+ bool ImplicitTrunc = false);
+
+ /// Return a ConstantByte with the specified value for the specified type. The
+ /// value V will be canonicalized to an unsigned APInt. Accessing it with
+ /// either getSExtValue() or getZExtValue() will yield a correctly sized and
+ /// signed value for the type Ty.
+ /// Get a ConstantByte for a specific signed value.
+ /// \param ImplicitTrunc Whether to allow implicit truncation of the value.
+ static ConstantByte *getSigned(ByteType *Ty, int64_t V,
+ bool ImplicitTrunc = false) {
+ return get(Ty, V, /*IsSigned=*/true, ImplicitTrunc);
+ }
+ static Constant *getSigned(Type *Ty, int64_t V, bool ImplicitTrunc = false) {
+ return get(Ty, V, /*IsSigned=*/true, ImplicitTrunc);
+ }
+
+ /// Return a ConstantByte with the specified value and an implied Type. The
+ /// type is the byte type that corresponds to the bit width of the value.
+ LLVM_ABI static ConstantByte *get(LLVMContext &Context, const APInt &V);
+
+ /// Return a ConstantByte constructed from the string strStart with the given
+ /// radix.
+ LLVM_ABI static ConstantByte *get(ByteType *Ty, StringRef Str, uint8_t Radix);
+
+ /// If Ty is a vector type, return a Constant with a splat of the given
+ /// value. Otherwise return a ConstantByte for the given value.
+ LLVM_ABI static Constant *get(Type *Ty, const APInt &V);
+
+ /// Return the constant as an APInt value reference. This allows clients to
+ /// obtain a full-precision copy of the value.
+ /// Return the constant's value.
+ inline const APInt &getValue() const { return Val; }
+
+ /// getBitWidth - Return the scalar bitwidth of this constant.
+ unsigned getBitWidth() const { return Val.getBitWidth(); }
+
+ /// Return the constant as a 64-bit byte value after it
+ /// has been zero extended as appropriate for the type of this constant. Note
+ /// that this method can assert if the value does not fit in 64 bits.
+ /// Return the zero extended value.
+ inline uint64_t getZExtValue() const { return Val.getZExtValue(); }
+
+ /// Return the constant as a 64-bit byte value after it has been sign
+ /// extended as appropriate for the type of this constant. Note that
+ /// this method can assert if the value does not fit in 64 bits.
+ /// Return the sign extended value.
+ inline int64_t getSExtValue() const { return Val.getSExtValue(); }
+
+ /// Return the constant as an llvm::MaybeAlign.
+ /// Note that this method can assert if the value does not fit in 64 bits or
+ /// is not a power of two.
+ inline MaybeAlign getMaybeAlignValue() const {
+ return MaybeAlign(getZExtValue());
+ }
+
+ /// Return the constant as an llvm::Align, interpreting `0` as `Align(1)`.
+ /// Note that this method can assert if the value does not fit in 64 bits or
+ /// is not a power of two.
+ inline Align getAlignValue() const {
+ return getMaybeAlignValue().valueOrOne();
+ }
+
+ /// A helper method that can be used to determine if the constant contained
+ /// within is equal to a constant. This only works for very small values,
+ /// because this is all that can be represented with all types.
+ /// Determine if this constant's value is same as an unsigned char.
+ bool equalsByte(uint64_t V) const { return Val == V; }
+
+ /// Variant of the getType() method to always return an ByteType, which
+ /// reduces the amount of casting needed in parts of the compiler.
+ inline ByteType *getByteType() const {
+ return cast<ByteType>(Value::getType());
+ }
+
+ /// This static method returns true if the type Ty is big enough to
+ /// represent the value V. This can be used to avoid having the get method
+ /// assert when V is larger than Ty can represent. Note that there are two
+ /// versions of this method, one for unsigned and one for signed integers.
+ /// Although ConstantByte canonicalizes everything to an unsigned integer,
+ /// the signed version avoids callers having to convert a signed quantity
+ /// to the appropriate unsigned type before calling the method.
+ /// @returns true if V is a valid value for type Ty
+ /// Determine if the value is in range for the given type.
+ LLVM_ABI static bool isValueValidForType(Type *Ty, uint64_t V);
+ LLVM_ABI static bool isValueValidForType(Type *Ty, int64_t V);
+
+ bool isNegative() const { return Val.isNegative(); }
+
+ /// This is just a convenience method to make client code smaller for a
+ /// common code. It also correctly performs the comparison without the
+ /// potential for an assertion from getZExtValue().
+ bool isZero() const { return Val.isZero(); }
+
+ /// This is just a convenience method to make client code smaller for a
+ /// common case. It also correctly performs the comparison without the
+ /// potential for an assertion from getZExtValue().
+ /// Determine if the value is one.
+ bool isOne() const { return Val.isOne(); }
+
+ /// This function will return true iff every bit in this constant is set
+ /// to true.
+ /// @returns true iff this constant's bits are all set to true.
+ /// Determine if the value is all ones.
+ bool isMinusOne() const { return Val.isAllOnes(); }
+
+ /// This function will return true iff this constant represents the largest
+ /// value that may be represented by the constant's type.
+ /// @returns true iff this is the largest value that may be represented
+ /// by this type.
+ /// Determine if the value is maximal.
+ bool isMaxValue(bool IsSigned) const {
+ if (IsSigned)
+ return Val.isMaxSignedValue();
+ else
+ return Val.isMaxValue();
+ }
+
+ /// This function will return true iff this constant represents the smallest
+ /// value that may be represented by this constant's type.
+ /// @returns true if this is the smallest value that may be represented by
+ /// this type.
+ /// Determine if the value is minimal.
+ bool isMinValue(bool IsSigned) const {
+ if (IsSigned)
+ return Val.isMinSignedValue();
+ else
+ return Val.isMinValue();
+ }
+
+ /// This function will return true iff this constant represents a value with
+ /// active bits bigger than 64 bits or a value greater than the given uint64_t
+ /// value.
+ /// @returns true iff this constant is greater or equal to the given number.
+ /// Determine if the value is greater or equal to the given number.
+ bool uge(uint64_t Num) const { return Val.uge(Num); }
+
+ /// getLimitedValue - If the value is smaller than the specified limit,
+ /// return it, otherwise return the limit value. This causes the value
+ /// to saturate to the limit.
+ /// @returns the min of the value of the constant and the specified value
+ /// Get the constant's value with a saturation limit
+ uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
+ return Val.getLimitedValue(Limit);
+ }
+
+ /// Methods to support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(const Value *V) {
+ return V->getValueID() == ConstantByteVal;
+ }
+};
+
//===----------------------------------------------------------------------===//
/// ConstantFP - Floating Point Values [float, double]
///
@@ -588,10 +781,10 @@ class ConstantPointerNull final : public ConstantData {
//===----------------------------------------------------------------------===//
/// ConstantDataSequential - A vector or array constant whose element type is a
-/// simple 1/2/4/8-byte integer or half/bfloat/float/double, and whose elements
-/// are just simple data values (i.e. ConstantInt/ConstantFP). This Constant
-/// node has no operands because it stores all of the elements of the constant
-/// as densely packed data, instead of as Value*'s.
+/// simple 1/2/4/8-byte integer/byte or half/bfloat/float/double, and whose
+/// elements are just simple data values (i.e. ConstantInt/ConstantByte/
+/// ConstantFP). This Constant node has no operands because it stores all of
+/// the elements of the constant as densely packed data, instead of as Value*'s.
///
/// This is the common base class of ConstantDataArray and ConstantDataVector.
///
@@ -661,7 +854,8 @@ class ConstantDataSequential : public ConstantData {
/// The size of the elements is known to be a multiple of one byte.
LLVM_ABI uint64_t getElementByteSize() const;
- /// This method returns true if this is an array of \p CharSize integers.
+ /// This method returns true if this is an array of \p CharSize integers or
+ /// bytes.
LLVM_ABI bool isString(unsigned CharSize = 8) const;
/// This method returns true if the array "isString", ends with a null byte,
@@ -699,8 +893,8 @@ class ConstantDataSequential : public ConstantData {
};
//===----------------------------------------------------------------------===//
-/// An array constant whose element type is a simple 1/2/4/8-byte integer or
-/// float/double, and whose elements are just simple data values
+/// An array constant whose element type is a simple 1/2/4/8-byte integer, bytes
+// or float/double, and whose elements are just simple data values
/// (i.e. ConstantInt/ConstantFP). This Constant node has no operands because it
/// stores all of the elements of the constant as densely packed data, instead
/// of as Value*'s.
@@ -733,9 +927,9 @@ class ConstantDataArray final : public ConstantDataSequential {
/// getRaw() constructor - Return a constant with array type with an element
/// count and element type matching the NumElements and ElementTy parameters
/// passed in. Note that this can return a ConstantAggregateZero object.
- /// ElementTy must be one of i8/i16/i32/i64/half/bfloat/float/double. Data is
- /// the buffer containing the elements. Be careful to make sure Data uses the
- /// right endianness, the buffer will be used as-is.
+ /// ElementTy must be one of i8/i16/i32/i64/b8/b16/b32/b64/half/bfloat/float/
+ /// double. Data is the buffer containing the elements. Be careful to make
+ /// sure Data uses the right endianness, the buffer will be used as-is.
static Constant *getRaw(StringRef Data, uint64_t NumElements,
Type *ElementTy) {
Type *Ty = ArrayType::get(ElementTy, NumElements);
@@ -752,13 +946,25 @@ class ConstantDataArray final : public ConstantDataSequential {
LLVM_ABI static Constant *getFP(Type *ElementType, ArrayRef<uint32_t> Elts);
LLVM_ABI static Constant *getFP(Type *ElementType, ArrayRef<uint64_t> Elts);
+ /// getByte() constructors - Return a constant of array type with a byte
+ /// element type taken from argument `ElementType', and count taken from
+ /// argument `Elts'. The amount of bits of the contained type must match the
+ /// number of bits of the type contained in the passed in ArrayRef.
+ /// Note that this can return a ConstantAggregateZero object.
+ LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint8_t> Elts);
+ LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint16_t> Elts);
+ LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint32_t> Elts);
+ LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint64_t> Elts);
+
/// This method constructs a CDS and initializes it with a text string.
/// The default behavior (AddNull==true) causes a null terminator to
/// be placed at the end of the array (increasing the length of the string by
/// one more than the StringRef would normally indicate. Pass AddNull=false
/// to disable this behavior.
- LLVM_ABI static Constant *
- getString(LLVMContext &Context, StringRef Initializer, bool AddNull = true);
+ LLVM_ABI static Constant *getString(LLVMContext &Context,
+ StringRef Initializer,
+ bool AddNull = true,
+ bool ByteString = false);
/// Specialize the getType() method to always return an ArrayType,
/// which reduces the amount of casting needed in parts of the compiler.
@@ -805,15 +1011,24 @@ class ConstantDataVector final : public ConstantDataSequential {
/// getRaw() constructor - Return a constant with vector type with an element
/// count and element type matching the NumElements and ElementTy parameters
/// passed in. Note that this can return a ConstantAggregateZero object.
- /// ElementTy must be one of i8/i16/i32/i64/half/bfloat/float/double. Data is
- /// the buffer containing the elements. Be careful to make sure Data uses the
- /// right endianness, the buffer will be used as-is.
+ /// ElementTy must be one of i8/i16/i32/i64/b8/b16/b32/b64/half/bfloat/float/
+ /// double. Data is the buffer containing the elements. Be careful to make
+ /// sure Data uses the right endianness, the buffer will be used as-is.
static Constant *getRaw(StringRef Data, uint64_t NumElements,
Type *ElementTy) {
Type *Ty = VectorType::get(ElementTy, ElementCount::getFixed(NumElements));
return getImpl(Data, Ty);
}
+ /// getByte() constructors - Return a constant of vector type with a byte
+ /// element type taken from argument `ElementType', and count taken from
+ /// argument `Elts'. The amount of bits of the contained type must match the
+ /// number of bits of the type contained in the passed in ArrayRef.
+ LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint8_t> Elts);
+ LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint16_t> Elts);
+ LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint32_t> Elts);
+ LLVM_ABI static Constant *getByte(Type *ElementType, ArrayRef<uint64_t> Elts);
+
/// getFP() constructors - Return a constant of vector type with a float
/// element type taken from argument `ElementType', and count taken from
/// argument `Elts'. The amount of bits of the contained type must match the
@@ -826,7 +1041,8 @@ class ConstantDataVector final : public ConstantDataSequential {
/// Return a ConstantVector with the specified constant in each element.
/// The specified constant has to be a of a compatible type (i8/i16/
- /// i32/i64/half/bfloat/float/double) and must be a ConstantFP or ConstantInt.
+ /// i32/i64/b8/b16/b32/b64/half/bfloat/float/double) and must be a ConstantFP,
+ /// ConstantByte or ConstantInt.
LLVM_ABI static Constant *getSplat(unsigned NumElts, Constant *Elt);
/// Returns true if this is a splat constant, meaning that all elements have
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index 4d695e1e5c566..bc54269e5e762 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -637,6 +637,11 @@ class DataLayout {
/// This is always at least as good as the ABI alignment.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const;
+ /// Returns a byte type with size at least as big as that of a
+ /// pointer in the given address space.
+ LLVM_ABI ByteType *getBytePtrType(LLVMContext &C,
+ unsigned AddressSpace = 0) const;
+
/// Returns an integer type with size at least as big as that of a
/// pointer in the given address space.
LLVM_ABI IntegerType *getIntPtrType(LLVMContext &C,
@@ -646,6 +651,18 @@ class DataLayout {
/// big as that of a pointer of the given pointer (vector of pointer) type.
LLVM_ABI Type *getIntPtrType(Type *) const;
+ /// Returns an integer (vector of integer) type with size at least as
+ /// big as that of a byte of the given byte (vector of byte) type.
+ LLVM_ABI Type *getIntByteType(Type *) const;
+
+ /// Returns a byte (vector of byte) type with size at least as big as that of
+ /// a pointer of the given pointer (vector of pointer) type.
+ LLVM_ABI Type *getBytePtrType(Type *) const;
+
+ /// Returns a byte (vector of byte) type with size at least as big as that of
+ /// an integer of the given integer (vector of integer) type.
+ LLVM_ABI Type *getByteIntType(Type *) const;
+
/// Returns the smallest integer type with size at least as big as
/// Width bits.
LLVM_ABI Type *getSmallestLegalIntType(LLVMContext &C,
@@ -784,6 +801,8 @@ inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const {
case Type::StructTyID:
// Get the layout annotation... which is lazily created on demand.
return getStructLayout(cast<StructType>(Ty))->getSizeInBits();
+ case Type::ByteTyID:
+ return TypeSize::getFixed(Ty->getByteBitWidth());
case Type::IntegerTyID:
return TypeSize::getFixed(Ty->getIntegerBitWidth());
case Type::HalfTyID:
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index b22177c9e6c2d..7c1fcb90952ec 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -100,6 +100,62 @@ unsigned Type::getIntegerBitWidth() const {
return cast<IntegerType>(this)->getBitWidth();
}
+/// Class to represent byte types. Note that this class is also used to
+/// represent the built-in byte types: Byte8Ty, Byte16Ty, Byte32Ty and
+/// Byte64Ty.
+/// Byte representation type
+class ByteType : public Type {
+ friend class LLVMContextImpl;
+
+protected:
+ explicit ByteType(LLVMContext &C, unsigned NumBits) : Type(C, ByteTyID) {
+ setSubclassData(NumBits);
+ }
+
+public:
+ /// This enum is just used to hold constants we need for ByteType.
+ enum {
+ MIN_BYTE_BITS = 1, ///< Minimum number of bits that can be specified
+ MAX_BYTE_BITS =
+ (1 << 23) ///< Maximum number of bits that can be specified
+ ///< Note that bit width is stored in the Type classes
+ ///< SubclassData field which has 24 bits. SelectionDAG type
+ ///< legalization can require a power of 2 ByteType, so limit
+ ///< to the largest representable power of 2, 8388608.
+ };
+
+ /// This static method is the primary way of constructing an ByteType.
+ /// If an ByteType with the same NumBits value was previously instantiated,
+ /// that instance will be returned. Otherwise a new one will be created. Only
+ /// one instance with a given NumBits value is ever created.
+ /// Get or create an ByteType instance.
+ LLVM_ABI static ByteType *get(LLVMContext &C, unsigned NumBits);
+
+ /// Returns type twice as wide the input type.
+ ByteType *getExtendedType() const {
+ return Type::getByteNTy(getContext(), 2 * getScalarSizeInBits());
+ }
+
+ /// Get the number of bits in this ByteType
+ unsigned getBitWidth() const { return getSubclassData(); }
+
+ /// Return a bitmask with ones set for all of the bits. This is 0xFF for i8,
+ /// 0xFFFF for i16, etc.
+ uint64_t getBitMask() const { return ~uint64_t(0UL) >> (64 - getBitWidth()); }
+
+ /// For example, this is 0xFF for an 8 bit byte, 0xFFFF for b16, etc.
+ /// @returns a bit mask with ones set for all the bits of this type.
+ /// Get a bit mask for this type.
+ LLVM_ABI APInt getMask() const;
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(const Type *T) { return T->getTypeID() == ByteTyID; }
+};
+
+unsigned Type::getByteBitWidth() const {
+ return cast<ByteType>(this)->getBitWidth();
+}
+
/// Class to represent function types
///
class FunctionType : public Type {
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 2d6bafdec2c16..ddf0538e0a30e 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -543,6 +543,24 @@ class IRBuilderBase {
// Type creation methods
//===--------------------------------------------------------------------===//
+ /// Fetch the type representing an 8-bit byte.
+ ByteType *getByte8Ty() { return Type::getByte8Ty(Context); }
+
+ /// Fetch the type representing a 16-bit byte.
+ ByteType *getByte16Ty() { return Type::getByte16Ty(Context); }
+
+ /// Fetch the type representing a 32-bit byte.
+ ByteType *getByte32Ty() { return Type::getByte32Ty(Context); }
+
+ /// Fetch the type representing a 64-bit byte.
+ ByteType *getByte64Ty() { return Type::getByte64Ty(Context); }
+
+ /// Fetch the type representing a 128-bit byte.
+ ByteType *getByte128Ty() { return Type::getByte128Ty(Context); }
+
+ /// Fetch the type representing an N-bit byte.
+ ByteType *getByteNTy(unsigned N) { return Type::getByteNTy(Context, N); }
+
/// Fetch the type representing a single bit
IntegerType *getInt1Ty() {
return Type::getInt1Ty(Context);
@@ -606,6 +624,12 @@ class IRBuilderBase {
return PointerType::get(Context, AddrSpace);
}
+ /// Fetch the type of a byte with size at least as big as that of a
+ /// pointer in the given address space.
+ ByteType *getBytePtrTy(const DataLayout &DL, unsigned AddrSpace = 0) {
+ return DL.getBytePtrType(Context, AddrSpace);
+ }
+
/// Fetch the type of an integer with size at least as big as that of a
/// pointer in the given address space.
IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) {
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 44db4ef163a64..1640de3b9fbd8 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -26,6 +26,7 @@
namespace llvm {
+class ByteType;
class IntegerType;
struct fltSemantics;
class LLVMContext;
@@ -67,6 +68,7 @@ class Type {
TokenTyID, ///< Tokens
// Derived types... see DerivedTypes.h file.
+ ByteTyID, ///< Arbitrary bit width bytes
IntegerTyID, ///< Arbitrary bit width integers
FunctionTyID, ///< Functions
PointerTyID, ///< Pointers
@@ -236,6 +238,21 @@ class Type {
/// Returns true if this is 'token' or a token-like target type.s
LLVM_ABI bool isTokenLikeTy() const;
+ /// True if this is an instance of ByteType.
+ bool isByteTy() const { return getTypeID() == ByteTyID; }
+
+ /// Return true if this is an ByteType of the given width.
+ LLVM_ABI bool isByteTy(unsigned BitWidth) const;
+
+ /// Return true if this is a byte type or a vector of byte types.
+ bool isByteOrByteVectorTy() const { return getScalarType()->isByteTy(); }
+
+ /// Return true if this is a byte type or a vector of byte types of
+ /// the given width.
+ bool isByteOrByteVectorTy(unsigned BitWidth) const {
+ return getScalarType()->isByteTy(BitWidth);
+ }
+
/// True if this is an instance of IntegerType.
bool isIntegerTy() const { return getTypeID() == IntegerTyID; }
@@ -295,7 +312,7 @@ class Type {
/// includes all first-class types except struct and array types.
bool isSingleValueType() const {
return isFloatingPointTy() || isIntegerTy() || isPointerTy() ||
- isVectorTy() || isX86_AMXTy() || isTargetExtTy();
+ isVectorTy() || isX86_AMXTy() || isTargetExtTy() || isByteTy();
}
/// Return true if the type is an aggregate type. This means it is valid as
@@ -311,7 +328,8 @@ class Type {
bool isSized(SmallPtrSetImpl<Type*> *Visited = nullptr) const {
// If it's a primitive, it is always sized.
if (getTypeID() == IntegerTyID || isFloatingPointTy() ||
- getTypeID() == PointerTyID || getTypeID() == X86_AMXTyID)
+ getTypeID() == PointerTyID || getTypeID() == X86_AMXTyID ||
+ getTypeID() == ByteTyID)
return true;
// If it is not something that can have a size (e.g. a function or label),
// it doesn't have a size.
@@ -394,6 +412,7 @@ class Type {
// methods should not be added here.
LLVM_ABI inline unsigned getIntegerBitWidth() const;
+ LLVM_ABI inline unsigned getByteBitWidth() const;
LLVM_ABI inline Type *getFunctionParamType(unsigned i) const;
LLVM_ABI inline unsigned getFunctionNumParams() const;
@@ -451,6 +470,13 @@ class Type {
LLVM_ABI static Type *getPPC_FP128Ty(LLVMContext &C);
LLVM_ABI static Type *getX86_AMXTy(LLVMContext &C);
LLVM_ABI static Type *getTokenTy(LLVMContext &C);
+ LLVM_ABI static ByteType *getByteNTy(LLVMContext &C, unsigned N);
+ LLVM_ABI static ByteType *getByte1Ty(LLVMContext &C);
+ LLVM_ABI static ByteType *getByte8Ty(LLVMContext &C);
+ LLVM_ABI static ByteType *getByte16Ty(LLVMContext &C);
+ LLVM_ABI static ByteType *getByte32Ty(LLVMContext &C);
+ LLVM_ABI static ByteType *getByte64Ty(LLVMContext &C);
+ LLVM_ABI static ByteType *getByte128Ty(LLVMContext &C);
LLVM_ABI static IntegerType *getIntNTy(LLVMContext &C, unsigned N);
LLVM_ABI static IntegerType *getInt1Ty(LLVMContext &C);
LLVM_ABI static IntegerType *getInt8Ty(LLVMContext &C);
diff --git a/llvm/include/llvm/IR/Value.def b/llvm/include/llvm/IR/Value.def
index 34b8d4967b28a..96160fbe3bcb4 100644
--- a/llvm/include/llvm/IR/Value.def
+++ b/llvm/include/llvm/IR/Value.def
@@ -82,6 +82,7 @@ HANDLE_CONSTANT(ConstantAggregateZero)
HANDLE_CONSTANT(ConstantDataArray)
HANDLE_CONSTANT(ConstantDataVector)
HANDLE_CONSTANT(ConstantInt)
+HANDLE_CONSTANT(ConstantByte)
HANDLE_CONSTANT(ConstantFP)
HANDLE_CONSTANT(ConstantTargetNone)
HANDLE_CONSTANT(ConstantPointerNull)
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 4e7e31da09a52..e5de7daa78aa0 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -487,20 +487,26 @@ lltok::Kind LLLexer::LexHash() {
return lltok::hash;
}
-/// Lex a label, integer type, keyword, or hexadecimal integer constant.
+/// Lex a label, integer or byte types, keyword, or hexadecimal integer
+/// constant.
/// Label [-a-zA-Z$._0-9]+:
+/// ByteType b[0-9]+
/// IntegerType i[0-9]+
/// Keyword sdiv, float, ...
/// HexIntConstant [us]0x[0-9A-Fa-f]+
lltok::Kind LLLexer::LexIdentifier() {
const char *StartChar = CurPtr;
- const char *IntEnd = CurPtr[-1] == 'i' ? nullptr : StartChar;
+ const char IntOrByteIdentifier = CurPtr[-1];
+ const char *IntOrByteEnd =
+ (IntOrByteIdentifier == 'i' || IntOrByteIdentifier == 'b') ? nullptr
+ : StartChar;
const char *KeywordEnd = nullptr;
for (; isLabelChar(*CurPtr); ++CurPtr) {
- // If we decide this is an integer, remember the end of the sequence.
- if (!IntEnd && !isdigit(static_cast<unsigned char>(*CurPtr)))
- IntEnd = CurPtr;
+ // If we decide this is a byte or an integer, remember the end of the
+ // sequence.
+ if (!IntOrByteEnd && !isdigit(static_cast<unsigned char>(*CurPtr)))
+ IntOrByteEnd = CurPtr;
if (!KeywordEnd && !isalnum(static_cast<unsigned char>(*CurPtr)) &&
*CurPtr != '_')
KeywordEnd = CurPtr;
@@ -513,18 +519,25 @@ lltok::Kind LLLexer::LexIdentifier() {
return lltok::LabelStr;
}
- // Otherwise, this wasn't a label. If this was valid as an integer type,
- // return it.
- if (!IntEnd) IntEnd = CurPtr;
- if (IntEnd != StartChar) {
- CurPtr = IntEnd;
+ // Otherwise, this wasn't a label. If this was valid as a byte or an integer
+ // type, return it.
+ if (!IntOrByteEnd)
+ IntOrByteEnd = CurPtr;
+ if (IntOrByteEnd != StartChar) {
+ CurPtr = IntOrByteEnd;
uint64_t NumBits = atoull(StartChar, CurPtr);
+
if (NumBits < IntegerType::MIN_INT_BITS ||
NumBits > IntegerType::MAX_INT_BITS) {
- LexError("bitwidth for integer type out of range");
+ LexError("bitwidth for integer or byte type out of range");
return lltok::Error;
}
- TyVal = IntegerType::get(Context, NumBits);
+
+ if (IntOrByteIdentifier == 'i')
+ TyVal = IntegerType::get(Context, NumBits);
+ else
+ TyVal = ByteType::get(Context, NumBits);
+
return lltok::Type;
}
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 068b52fcf0995..1965efd37b968 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4041,12 +4041,13 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
if (Elts.empty())
return error(ID.Loc, "constant vector must not be empty");
- if (!Elts[0]->getType()->isIntegerTy() &&
+ if (!Elts[0]->getType()->isIntegerTy() && !Elts[0]->getType()->isByteTy() &&
!Elts[0]->getType()->isFloatingPointTy() &&
!Elts[0]->getType()->isPointerTy())
return error(
FirstEltLoc,
- "vector elements must have integer, pointer or floating point type");
+ "vector elements must have integer, byte, pointer or floating point "
+ "type");
// Verify that all the vector elements have the same type.
for (unsigned i = 1, e = Elts.size(); i != e; ++i)
@@ -4093,15 +4094,16 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
ID.Kind = ValID::t_Constant;
return false;
}
- case lltok::kw_c: // c "foo"
+ case lltok::kw_c: { // c "foo"
Lex.Lex();
- ID.ConstantVal = ConstantDataArray::getString(Context, Lex.getStrVal(),
- false);
+ ArrayType *ATy = static_cast<ArrayType *>(ExpectedTy);
+ ID.ConstantVal = ConstantDataArray::getString(
+ Context, Lex.getStrVal(), false, ATy->getElementType()->isByteTy());
if (parseToken(lltok::StringConstant, "expected string"))
return true;
ID.Kind = ValID::t_Constant;
return false;
-
+ }
case lltok::kw_asm: {
// ValID ::= 'asm' SideEffect? AlignStack? IntelDialect? STRINGCONSTANT ','
// STRINGCONSTANT
@@ -6552,10 +6554,11 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V,
V = NoCFIValue::get(cast<GlobalValue>(V));
return V == nullptr;
case ValID::t_APSInt:
- if (!Ty->isIntegerTy())
- return error(ID.Loc, "integer constant must have integer type");
+ if (!Ty->isIntegerTy() && !Ty->isByteTy())
+ return error(ID.Loc, "integer/byte constant must have integer/byte type");
ID.APSIntVal = ID.APSIntVal.extOrTrunc(Ty->getPrimitiveSizeInBits());
- V = ConstantInt::get(Context, ID.APSIntVal);
+ Ty->isIntegerTy() ? V = ConstantInt::get(Context, ID.APSIntVal)
+ : V = ConstantByte::get(Context, ID.APSIntVal);
return false;
case ValID::t_APFloat:
if (!Ty->isFloatingPointTy() ||
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 036f3c2964997..550972a252e90 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2621,6 +2621,17 @@ Error BitcodeReader::parseTypeTableBody() {
case bitc::TYPE_CODE_TOKEN: // TOKEN
ResultTy = Type::getTokenTy(Context);
break;
+ case bitc::TYPE_CODE_BYTE: { // BYTE: [width]
+ if (Record.empty())
+ return error("Invalid record");
+
+ uint64_t NumBits = Record[0];
+ if (NumBits < ByteType::MIN_BYTE_BITS ||
+ NumBits > ByteType::MAX_BYTE_BITS)
+ return error("Bitwidth for byte type out of range");
+ ResultTy = ByteType::get(Context, NumBits);
+ break;
+ }
case bitc::TYPE_CODE_INTEGER: { // INTEGER: [width]
if (Record.empty())
return error("Invalid integer record");
@@ -3319,6 +3330,20 @@ Error BitcodeReader::parseConstants() {
V = ConstantInt::get(CurTy, VInt);
break;
}
+ case bitc::CST_CODE_BYTE: // BYTE: [byteval]
+ if (!CurTy->isByteOrByteVectorTy() || Record.empty())
+ return error("Invalid byte const record");
+ V = ConstantByte::get(CurTy, decodeSignRotatedValue(Record[0]));
+ break;
+ case bitc::CST_CODE_WIDE_BYTE: { // WIDE_BYTE: [n x byteval]
+ if (!CurTy->isByteOrByteVectorTy() || Record.empty())
+ return error("Invalid wide byte const record");
+
+ auto *ScalarTy = cast<ByteType>(CurTy->getScalarType());
+ APInt VByte = readWideAPInt(Record, ScalarTy->getBitWidth());
+ V = ConstantByte::get(CurTy, VByte);
+ break;
+ }
case bitc::CST_CODE_FLOAT: { // FLOAT: [fpval]
if (Record.empty())
return error("Invalid float const record");
@@ -3381,8 +3406,9 @@ Error BitcodeReader::parseConstants() {
return error("Invalid string record");
SmallString<16> Elts(Record.begin(), Record.end());
- V = ConstantDataArray::getString(Context, Elts,
- BitCode == bitc::CST_CODE_CSTRING);
+ V = ConstantDataArray::getString(
+ Context, Elts, BitCode == bitc::CST_CODE_CSTRING,
+ cast<ArrayType>(CurTy)->getElementType()->isByteTy());
break;
}
case bitc::CST_CODE_DATA: {// DATA: [n x value]
@@ -3418,6 +3444,30 @@ Error BitcodeReader::parseConstants() {
V = ConstantDataVector::get(Context, Elts);
else
V = ConstantDataArray::get(Context, Elts);
+ } else if (EltTy->isByteTy(8)) {
+ SmallVector<uint8_t, 16> Elts(Record.begin(), Record.end());
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::getByte(EltTy, Elts);
+ else
+ V = ConstantDataArray::getByte(EltTy, Elts);
+ } else if (EltTy->isByteTy(16)) {
+ SmallVector<uint16_t, 16> Elts(Record.begin(), Record.end());
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::getByte(EltTy, Elts);
+ else
+ V = ConstantDataArray::getByte(EltTy, Elts);
+ } else if (EltTy->isByteTy(32)) {
+ SmallVector<uint32_t, 16> Elts(Record.begin(), Record.end());
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::getByte(EltTy, Elts);
+ else
+ V = ConstantDataArray::getByte(EltTy, Elts);
+ } else if (EltTy->isByteTy(64)) {
+ SmallVector<uint64_t, 16> Elts(Record.begin(), Record.end());
+ if (isa<VectorType>(CurTy))
+ V = ConstantDataVector::getByte(EltTy, Elts);
+ else
+ V = ConstantDataArray::getByte(EltTy, Elts);
} else if (EltTy->isHalfTy()) {
SmallVector<uint16_t, 16> Elts(Record.begin(), Record.end());
if (isa<VectorType>(CurTy))
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 8bc98c92bc698..1e9058b9939b7 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -136,6 +136,7 @@ enum {
// CONSTANTS_BLOCK abbrev id's.
CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV,
CONSTANTS_INTEGER_ABBREV,
+ CONSTANTS_BYTE_ABBREV,
CONSTANTS_CE_CAST_Abbrev,
CONSTANTS_NULL_Abbrev,
@@ -1169,6 +1170,11 @@ void ModuleBitcodeWriter::writeTypeTable() {
break;
case Type::X86_AMXTyID: Code = bitc::TYPE_CODE_X86_AMX; break;
case Type::TokenTyID: Code = bitc::TYPE_CODE_TOKEN; break;
+ case Type::ByteTyID:
+ // BYTE: [width]
+ Code = bitc::TYPE_CODE_BYTE;
+ TypeVals.push_back(T->getByteBitWidth());
+ break;
case Type::IntegerTyID:
// INTEGER: [width]
Code = bitc::TYPE_CODE_INTEGER;
@@ -2863,6 +2869,16 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
emitWideAPInt(Record, IV->getValue());
Code = bitc::CST_CODE_WIDE_INTEGER;
}
+ } else if (const ConstantByte *BV = dyn_cast<ConstantByte>(C)) {
+ if (BV->getBitWidth() <= 64) {
+ uint64_t V = BV->getSExtValue();
+ emitSignedInt64(Record, V);
+ Code = bitc::CST_CODE_BYTE;
+ AbbrevToUse = CONSTANTS_BYTE_ABBREV;
+ } else { // Wide bytes, > 64 bits in size.
+ emitWideAPInt(Record, BV->getValue());
+ Code = bitc::CST_CODE_WIDE_BYTE;
+ }
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
Code = bitc::CST_CODE_FLOAT;
Type *Ty = CFP->getType()->getScalarType();
@@ -2912,10 +2928,10 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
else if (isCStr7)
AbbrevToUse = CString7Abbrev;
} else if (const ConstantDataSequential *CDS =
- dyn_cast<ConstantDataSequential>(C)) {
+ dyn_cast<ConstantDataSequential>(C)) {
Code = bitc::CST_CODE_DATA;
Type *EltTy = CDS->getElementType();
- if (isa<IntegerType>(EltTy)) {
+ if (isa<IntegerType>(EltTy) || isa<ByteType>(EltTy)) {
for (uint64_t i = 0, e = CDS->getNumElements(); i != e; ++i)
Record.push_back(CDS->getElementAsInteger(i));
} else {
@@ -3959,6 +3975,15 @@ void ModuleBitcodeWriter::writeBlockInfo() {
llvm_unreachable("Unexpected abbrev ordering!");
}
+ { // BYTE abbrev for CONSTANTS_BLOCK.
+ auto Abbv = std::make_shared<BitCodeAbbrev>();
+ Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_BYTE));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
+ if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, Abbv) !=
+ CONSTANTS_BYTE_ABBREV)
+ llvm_unreachable("Unexpected abbrev ordering!");
+ }
+
{ // CE_CAST abbrev for CONSTANTS_BLOCK.
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST));
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 420f09c514d63..c0b284ec865f6 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -3708,6 +3708,9 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV,
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
return MCConstantExpr::create(CI->getZExtValue(), Ctx);
+ if (const ConstantByte *CB = dyn_cast<ConstantByte>(CV))
+ return MCConstantExpr::create(CB->getZExtValue(), Ctx);
+
if (const ConstantPtrAuth *CPA = dyn_cast<ConstantPtrAuth>(CV))
return lowerConstantPtrAuth(*CPA);
@@ -3963,7 +3966,8 @@ static void emitGlobalConstantDataSequential(
// Otherwise, emit the values in successive locations.
uint64_t ElementByteSize = CDS->getElementByteSize();
- if (isa<IntegerType>(CDS->getElementType())) {
+ if (isa<IntegerType>(CDS->getElementType()) ||
+ isa<ByteType>(CDS->getElementType())) {
for (uint64_t I = 0, E = CDS->getNumElements(); I != E; ++I) {
emitGlobalAliasInline(AP, ElementByteSize * I, AliasList);
if (AP.isVerbose())
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 7eacdc0bd7bc4..d71ed4d4cb4ca 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -479,7 +479,7 @@ void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) {
LiveOutInfo &DestLOI = LiveOutRegInfo[DestReg];
Value *V = PN->getIncomingValue(0);
- if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
+ if (isa<UndefValue>(V) || isa<ConstantExpr>(V) || isa<ConstantByte>(V)) {
DestLOI.NumSignBits = 1;
DestLOI.Known = KnownBits(BitWidth);
continue;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 63c9d193421ea..2cbf2ae8105b7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1865,6 +1865,9 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
return DAG.getConstant(*CI, DL, VT);
}
+ if (const ConstantByte *CB = dyn_cast<ConstantByte>(C))
+ return DAG.getConstant(CB->getValue(), getCurSDLoc(), VT);
+
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
return DAG.getGlobalAddress(GV, getCurSDLoc(), VT);
diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp
index 0743c92c5b95b..e74068e22f4cd 100644
--- a/llvm/lib/CodeGen/ValueTypes.cpp
+++ b/llvm/lib/CodeGen/ValueTypes.cpp
@@ -254,6 +254,8 @@ MVT MVT::getVT(Type *Ty, bool HandleUnknown){
llvm_unreachable("Unknown type!");
case Type::VoidTyID:
return MVT::isVoid;
+ case Type::ByteTyID:
+ return getIntegerVT(cast<ByteType>(Ty)->getBitWidth());
case Type::IntegerTyID:
return getIntegerVT(cast<IntegerType>(Ty)->getBitWidth());
case Type::HalfTyID: return MVT(MVT::f16);
@@ -304,6 +306,8 @@ EVT EVT::getEVT(Type *Ty, bool HandleUnknown){
return MVT::getVT(Ty, HandleUnknown);
case Type::TokenTyID:
return MVT::Untyped;
+ case Type::ByteTyID:
+ return getIntegerVT(Ty->getContext(), cast<ByteType>(Ty)->getBitWidth());
case Type::IntegerTyID:
return getIntegerVT(Ty->getContext(), cast<IntegerType>(Ty)->getBitWidth());
case Type::FixedVectorTyID:
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 82e4de6d07441..6a90f6748161a 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -669,6 +669,9 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
return;
case Type::X86_AMXTyID: OS << "x86_amx"; return;
case Type::TokenTyID: OS << "token"; return;
+ case Type::ByteTyID:
+ OS << 'b' << Ty->getByteBitWidth();
+ return;
case Type::IntegerTyID:
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
return;
@@ -1648,6 +1651,23 @@ static void writeConstantInternal(raw_ostream &Out, const Constant *CV,
return;
}
+ if (const auto *CB = dyn_cast<ConstantByte>(CV)) {
+ Type *Ty = CB->getType();
+
+ if (Ty->isVectorTy()) {
+ Out << "splat (";
+ WriterCtx.TypePrinter->print(Ty->getScalarType(), Out);
+ Out << " ";
+ }
+
+ Out << CB->getValue();
+
+ if (Ty->isVectorTy())
+ Out << ")";
+
+ return;
+ }
+
if (const auto *CFP = dyn_cast<ConstantFP>(CV)) {
Type *Ty = CFP->getType();
@@ -1773,7 +1793,8 @@ static void writeConstantInternal(raw_ostream &Out, const Constant *CV,
// TODO: Remove this block when the UseConstant{Int,FP}ForFixedLengthSplat
// options are removed.
if (auto *SplatVal = CV->getSplatValue()) {
- if (isa<ConstantInt>(SplatVal) || isa<ConstantFP>(SplatVal)) {
+ if (isa<ConstantInt>(SplatVal) || isa<ConstantFP>(SplatVal) ||
+ isa<ConstantByte>(SplatVal)) {
Out << "splat (";
writeAsOperandInternal(Out, SplatVal, WriterCtx, /*PrintType=*/true);
Out << ')';
@@ -1820,7 +1841,8 @@ static void writeConstantInternal(raw_ostream &Out, const Constant *CV,
// options are removed.
if (CE->getOpcode() == Instruction::ShuffleVector) {
if (auto *SplatVal = CE->getSplatValue()) {
- if (isa<ConstantInt>(SplatVal) || isa<ConstantFP>(SplatVal)) {
+ if (isa<ConstantInt>(SplatVal) || isa<ConstantFP>(SplatVal) ||
+ isa<ConstantByte>(SplatVal)) {
Out << "splat (";
writeAsOperandInternal(Out, SplatVal, WriterCtx, /*PrintType=*/true);
Out << ')';
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 726a3d8dd906f..265d7eed21a6c 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -2451,8 +2451,8 @@ AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
AttributeSafetyKind ASK) {
AttributeMask Incompatible;
- if (!Ty->isIntegerTy()) {
- // Attributes that only apply to integers.
+ if (!Ty->isIntegerTy() && !Ty->isByteTy()) {
+ // Attributes that only apply to integers and bytes.
if (ASK & ASK_SAFE_TO_DROP)
Incompatible.addAttribute(Attribute::AllocAlign);
if (ASK & ASK_UNSAFE_TO_DROP)
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 76152fe91a532..9f7342a7bc83b 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -39,12 +39,18 @@ using namespace PatternMatch;
static cl::opt<bool> UseConstantIntForFixedLengthSplat(
"use-constant-int-for-fixed-length-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantInt's native fixed-length vector splat support."));
+static cl::opt<bool> UseConstantByteForFixedLengthSplat(
+ "use-constant-byte-for-fixed-length-splat", cl::init(false), cl::Hidden,
+ cl::desc("Use ConstantByte's native fixed-length vector splat support."));
static cl::opt<bool> UseConstantFPForFixedLengthSplat(
"use-constant-fp-for-fixed-length-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantFP's native fixed-length vector splat support."));
static cl::opt<bool> UseConstantIntForScalableSplat(
"use-constant-int-for-scalable-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantInt's native scalable vector splat support."));
+static cl::opt<bool> UseConstantByteForScalableSplat(
+ "use-constant-byte-for-scalable-splat", cl::init(false), cl::Hidden,
+ cl::desc("Use ConstantByte's native scalable vector splat support."));
static cl::opt<bool> UseConstantFPForScalableSplat(
"use-constant-fp-for-scalable-splat", cl::init(false), cl::Hidden,
cl::desc("Use ConstantFP's native scalable vector splat support."));
@@ -92,6 +98,10 @@ bool Constant::isNullValue() const {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
return CI->isZero();
+ // 0 is null.
+ if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
+ return CB->isZero();
+
// +0.0 is null.
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
// ppc_fp128 determine isZero using high order double only
@@ -109,6 +119,10 @@ bool Constant::isAllOnesValue() const {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
return CI->isMinusOne();
+ // Check for MaxValue bytes
+ if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
+ return CB->isMinusOne();
+
// Check for FP which are bitcasted from -1 integers
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
return CFP->getValueAPF().bitcastToAPInt().isAllOnes();
@@ -126,6 +140,10 @@ bool Constant::isOneValue() const {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
return CI->isOne();
+ // Check for 1 bytes
+ if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
+ return CB->isOne();
+
// Check for FP which are bitcasted from 1 integers
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
return CFP->getValueAPF().bitcastToAPInt().isOne();
@@ -143,6 +161,10 @@ bool Constant::isNotOneValue() const {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
return !CI->isOneValue();
+ // Check for 1 bytes
+ if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
+ return !CB->isOneValue();
+
// Check for FP which are bitcasted from 1 integers
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
return !CFP->getValueAPF().bitcastToAPInt().isOne();
@@ -389,6 +411,8 @@ bool Constant::containsConstantExpression() const {
/// Constructor to create a '0' constant of arbitrary type.
Constant *Constant::getNullValue(Type *Ty) {
switch (Ty->getTypeID()) {
+ case Type::ByteTyID:
+ return ConstantByte::get(Ty, 0);
case Type::IntegerTyID:
return ConstantInt::get(Ty, 0);
case Type::HalfTyID:
@@ -427,6 +451,10 @@ Constant *Constant::getIntegerValue(Type *Ty, const APInt &V) {
if (PointerType *PTy = dyn_cast<PointerType>(ScalarTy))
C = ConstantExpr::getIntToPtr(C, PTy);
+ // Convert an integer to a byte, if necessary.
+ if (ByteType *BTy = dyn_cast<ByteType>(ScalarTy))
+ C = ConstantExpr::getBitCast(C, BTy);
+
// Broadcast a scalar to a vector, if necessary.
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
C = ConstantVector::getSplat(VTy->getElementCount(), C);
@@ -444,6 +472,10 @@ Constant *Constant::getAllOnesValue(Type *Ty) {
return ConstantFP::get(Ty->getContext(), FL);
}
+ if (ByteType *BTy = dyn_cast<ByteType>(Ty))
+ return ConstantByte::get(Ty->getContext(),
+ APInt::getAllOnes(BTy->getBitWidth()));
+
VectorType *VTy = cast<VectorType>(Ty);
return ConstantVector::getSplat(VTy->getElementCount(),
getAllOnesValue(VTy->getElementType()));
@@ -468,6 +500,13 @@ Constant *Constant::getAggregateElement(unsigned Elt) const {
? ConstantInt::get(getContext(), CI->getValue())
: nullptr;
+ if (const auto *CB = dyn_cast<ConstantByte>(this))
+ return Elt < cast<VectorType>(getType())
+ ->getElementCount()
+ .getKnownMinValue()
+ ? ConstantByte::get(getContext(), CB->getValue())
+ : nullptr;
+
if (const auto *CFP = dyn_cast<ConstantFP>(this))
return Elt < cast<VectorType>(getType())
->getElementCount()
@@ -548,6 +587,9 @@ void llvm::deleteConstant(Constant *C) {
case Constant::ConstantIntVal:
delete static_cast<ConstantInt *>(C);
break;
+ case Constant::ConstantByteVal:
+ delete static_cast<ConstantByte *>(C);
+ break;
case Constant::ConstantFPVal:
delete static_cast<ConstantFP *>(C);
break;
@@ -999,6 +1041,133 @@ void ConstantInt::destroyConstantImpl() {
llvm_unreachable("You can't ConstantInt->destroyConstantImpl()!");
}
+//===----------------------------------------------------------------------===//
+// ConstantByte
+//===----------------------------------------------------------------------===//
+
+ConstantByte::ConstantByte(Type *Ty, const APInt &V)
+ : ConstantData(Ty, ConstantByteVal), Val(V) {
+ assert(V.getBitWidth() ==
+ cast<ByteType>(Ty->getScalarType())->getBitWidth() &&
+ "Invalid constant for type");
+}
+
+ConstantByte *ConstantByte::getTrue(LLVMContext &Context) {
+ LLVMContextImpl *pImpl = Context.pImpl;
+ if (!pImpl->TheTrueByteVal)
+ pImpl->TheTrueByteVal = ConstantByte::get(Type::getByte1Ty(Context), 1);
+ return pImpl->TheTrueByteVal;
+}
+
+ConstantByte *ConstantByte::getFalse(LLVMContext &Context) {
+ LLVMContextImpl *pImpl = Context.pImpl;
+ if (!pImpl->TheFalseByteVal)
+ pImpl->TheFalseByteVal = ConstantByte::get(Type::getByte1Ty(Context), 0);
+ return pImpl->TheFalseByteVal;
+}
+
+ConstantByte *ConstantByte::getBool(LLVMContext &Context, bool V) {
+ return V ? getTrue(Context) : getFalse(Context);
+}
+
+Constant *ConstantByte::getTrue(Type *Ty) {
+ assert(Ty->isByteOrByteVectorTy(1) && "Type not i1 or vector of i1.");
+ ConstantByte *TrueC = ConstantByte::getTrue(Ty->getContext());
+ if (auto *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getElementCount(), TrueC);
+ return TrueC;
+}
+
+Constant *ConstantByte::getFalse(Type *Ty) {
+ assert(Ty->isByteOrByteVectorTy(1) && "Type not i1 or vector of i1.");
+ ConstantByte *FalseC = ConstantByte::getFalse(Ty->getContext());
+ if (auto *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getElementCount(), FalseC);
+ return FalseC;
+}
+
+Constant *ConstantByte::getBool(Type *Ty, bool V) {
+ return V ? getTrue(Ty) : getFalse(Ty);
+}
+
+// Get a ConstantByte from an APInt.
+ConstantByte *ConstantByte::get(LLVMContext &Context, const APInt &V) {
+ // get an existing value or the insertion position
+ LLVMContextImpl *pImpl = Context.pImpl;
+ std::unique_ptr<ConstantByte> &Slot =
+ V.isZero() ? pImpl->ByteZeroConstants[V.getBitWidth()]
+ : V.isOne() ? pImpl->ByteOneConstants[V.getBitWidth()]
+ : pImpl->ByteConstants[V];
+ if (!Slot) {
+ // Get the corresponding byte type for the bit width of the value.
+ ByteType *BTy = ByteType::get(Context, V.getBitWidth());
+ Slot.reset(new ConstantByte(BTy, V));
+ }
+ assert(Slot->getType() == ByteType::get(Context, V.getBitWidth()));
+ return Slot.get();
+}
+
+// Get a ConstantByte vector with each lane set to the same APInt.
+ConstantByte *ConstantByte::get(LLVMContext &Context, ElementCount EC,
+ const APInt &V) {
+ // Get an existing value or the insertion position.
+ std::unique_ptr<ConstantByte> &Slot =
+ Context.pImpl->ByteSplatConstants[std::make_pair(EC, V)];
+ if (!Slot) {
+ ByteType *BTy = ByteType::get(Context, V.getBitWidth());
+ VectorType *VTy = VectorType::get(BTy, EC);
+ Slot.reset(new ConstantByte(VTy, V));
+ }
+
+#ifndef NDEBUG
+ ByteType *BTy = ByteType::get(Context, V.getBitWidth());
+ VectorType *VTy = VectorType::get(BTy, EC);
+ assert(Slot->getType() == VTy);
+#endif
+ return Slot.get();
+}
+
+Constant *ConstantByte::get(Type *Ty, uint64_t V, bool isSigned,
+ bool ImplicitTrunc) {
+ Constant *C =
+ get(cast<ByteType>(Ty->getScalarType()), V, isSigned, ImplicitTrunc);
+
+ // For vectors, broadcast the value.
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getElementCount(), C);
+
+ return C;
+}
+
+ConstantByte *ConstantByte::get(ByteType *Ty, uint64_t V, bool isSigned,
+ bool ImplicitTrunc) {
+ // TODO: Avoid implicit trunc?
+ // See https://github.com/llvm/llvm-project/issues/112510.
+ return get(Ty->getContext(),
+ APInt(Ty->getBitWidth(), V, isSigned, ImplicitTrunc));
+}
+
+Constant *ConstantByte::get(Type *Ty, const APInt &V) {
+ ConstantByte *C = get(Ty->getContext(), V);
+ assert(C->getType() == Ty->getScalarType() &&
+ "ConstantByte type doesn't match the type implied by its value!");
+
+ // For vectors, broadcast the value.
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getElementCount(), C);
+
+ return C;
+}
+
+ConstantByte *ConstantByte::get(ByteType *Ty, StringRef Str, uint8_t radix) {
+ return get(Ty->getContext(), APInt(Ty->getBitWidth(), Str, radix));
+}
+
+/// Remove the constant from the constant table.
+void ConstantByte::destroyConstantImpl() {
+ llvm_unreachable("You can't ConstantByte->destroyConstantImpl()!");
+}
+
//===----------------------------------------------------------------------===//
// ConstantFP
//===----------------------------------------------------------------------===//
@@ -1269,6 +1438,19 @@ static Constant *getIntSequenceIfElementsMatch(ArrayRef<Constant *> V) {
return SequentialTy::get(V[0]->getContext(), Elts);
}
+template <typename SequentialTy, typename ElementTy>
+static Constant *getByteSequenceIfElementsMatch(ArrayRef<Constant *> V) {
+ assert(!V.empty() && "Cannot get empty int sequence.");
+
+ SmallVector<ElementTy, 16> Elts;
+ for (Constant *C : V)
+ if (auto *CI = dyn_cast<ConstantByte>(C))
+ Elts.push_back(CI->getZExtValue());
+ else
+ return nullptr;
+ return SequentialTy::getByte(V[0]->getType(), Elts);
+}
+
template <typename SequentialTy, typename ElementTy>
static Constant *getFPSequenceIfElementsMatch(ArrayRef<Constant *> V) {
assert(!V.empty() && "Cannot get empty FP sequence.");
@@ -1297,6 +1479,15 @@ static Constant *getSequenceIfElementsMatch(Constant *C,
return getIntSequenceIfElementsMatch<SequenceTy, uint32_t>(V);
else if (CI->getType()->isIntegerTy(64))
return getIntSequenceIfElementsMatch<SequenceTy, uint64_t>(V);
+ } else if (ConstantByte *CB = dyn_cast<ConstantByte>(C)) {
+ if (CB->getType()->isByteTy(8))
+ return getByteSequenceIfElementsMatch<SequenceTy, uint8_t>(V);
+ else if (CB->getType()->isByteTy(16))
+ return getByteSequenceIfElementsMatch<SequenceTy, uint16_t>(V);
+ else if (CB->getType()->isByteTy(32))
+ return getByteSequenceIfElementsMatch<SequenceTy, uint32_t>(V);
+ else if (CB->getType()->isByteTy(64))
+ return getByteSequenceIfElementsMatch<SequenceTy, uint64_t>(V);
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
if (CFP->getType()->isHalfTy() || CFP->getType()->isBFloatTy())
return getFPSequenceIfElementsMatch<SequenceTy, uint16_t>(V);
@@ -1362,8 +1553,9 @@ Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) {
if (C->isNullValue() && rangeOnlyContains(V.begin(), V.end(), C))
return ConstantAggregateZero::get(Ty);
- // Check to see if all of the elements are ConstantFP or ConstantInt and if
- // the element type is compatible with ConstantDataVector. If so, use it.
+ // Check to see if all of the elements are ConstantFP or ConstantInt or
+ // ConstantByte and if the element type is compatible with ConstantDataVector.
+ // If so, use it.
if (ConstantDataSequential::isElementTypeCompatible(C->getType()))
return getSequenceIfElementsMatch<ConstantDataArray>(C, V);
@@ -1460,11 +1652,13 @@ Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
bool isPoison = isa<PoisonValue>(C);
bool isSplatFP = UseConstantFPForFixedLengthSplat && isa<ConstantFP>(C);
bool isSplatInt = UseConstantIntForFixedLengthSplat && isa<ConstantInt>(C);
+ bool isSplatByte = UseConstantByteForFixedLengthSplat && isa<ConstantByte>(C);
- if (isZero || isUndef || isSplatFP || isSplatInt) {
+ if (isZero || isUndef || isSplatFP || isSplatInt || isSplatByte) {
for (unsigned i = 1, e = V.size(); i != e; ++i)
if (V[i] != C) {
- isZero = isUndef = isPoison = isSplatFP = isSplatInt = false;
+ isZero = isUndef = isPoison = isSplatFP = isSplatInt = isSplatByte =
+ false;
break;
}
}
@@ -1481,6 +1675,9 @@ Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
if (isSplatInt)
return ConstantInt::get(C->getContext(), T->getElementCount(),
cast<ConstantInt>(C)->getValue());
+ if (isSplatByte)
+ return ConstantByte::get(C->getContext(), T->getElementCount(),
+ cast<ConstantByte>(C)->getValue());
// Check to see if all of the elements are ConstantFP or ConstantInt and if
// the element type is compatible with ConstantDataVector. If so, use it.
@@ -1499,6 +1696,9 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
if (UseConstantIntForFixedLengthSplat && isa<ConstantInt>(V))
return ConstantInt::get(V->getContext(), EC,
cast<ConstantInt>(V)->getValue());
+ if (UseConstantByteForFixedLengthSplat && isa<ConstantByte>(V))
+ return ConstantByte::get(V->getContext(), EC,
+ cast<ConstantByte>(V)->getValue());
if (UseConstantFPForFixedLengthSplat && isa<ConstantFP>(V))
return ConstantFP::get(V->getContext(), EC,
cast<ConstantFP>(V)->getValue());
@@ -1506,7 +1706,7 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
// If this splat is compatible with ConstantDataVector, use it instead of
// ConstantVector.
- if ((isa<ConstantFP>(V) || isa<ConstantInt>(V)) &&
+ if ((isa<ConstantFP>(V) || isa<ConstantInt>(V) || isa<ConstantByte>(V)) &&
ConstantDataSequential::isElementTypeCompatible(V->getType()))
return ConstantDataVector::getSplat(EC.getKnownMinValue(), V);
@@ -1519,6 +1719,9 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
if (UseConstantIntForScalableSplat && isa<ConstantInt>(V))
return ConstantInt::get(V->getContext(), EC,
cast<ConstantInt>(V)->getValue());
+ if (UseConstantByteForScalableSplat && isa<ConstantByte>(V))
+ return ConstantByte::get(V->getContext(), EC,
+ cast<ConstantByte>(V)->getValue());
if (UseConstantFPForScalableSplat && isa<ConstantFP>(V))
return ConstantFP::get(V->getContext(), EC,
cast<ConstantFP>(V)->getValue());
@@ -1634,6 +1837,10 @@ bool ConstantInt::isValueValidForType(Type *Ty, int64_t Val) {
return isIntN(NumBits, Val);
}
+bool ConstantByte::isValueValidForType(Type *Ty, uint64_t Val) {
+ return isUIntN(Ty->getByteBitWidth(), Val);
+}
+
bool ConstantFP::isValueValidForType(Type *Ty, const APFloat& Val) {
// convert modifies in place, so make a copy.
APFloat Val2 = APFloat(Val);
@@ -1739,6 +1946,8 @@ Constant *Constant::getSplatValue(bool AllowPoison) const {
return getNullValue(cast<VectorType>(getType())->getElementType());
if (auto *CI = dyn_cast<ConstantInt>(this))
return ConstantInt::get(getContext(), CI->getValue());
+ if (auto *CB = dyn_cast<ConstantByte>(this))
+ return ConstantByte::get(getContext(), CB->getValue());
if (auto *CFP = dyn_cast<ConstantFP>(this))
return ConstantFP::get(getContext(), CFP->getValue());
if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this))
@@ -1798,6 +2007,8 @@ Constant *ConstantVector::getSplatValue(bool AllowPoison) const {
const APInt &Constant::getUniqueInteger() const {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
return CI->getValue();
+ if (const ConstantByte *CB = dyn_cast<ConstantByte>(this))
+ return CB->getValue();
// Scalable vectors can use a ConstantExpr to build a splat.
if (isa<ConstantExpr>(this))
return cast<ConstantInt>(this->getSplatValue())->getValue();
@@ -1821,6 +2032,10 @@ ConstantRange Constant::toConstantRange() const {
getSplatValue(/*AllowPoison=*/true)))
return ConstantRange(CI->getValue());
+ if (auto *CB =
+ dyn_cast_or_null<ConstantByte>(getSplatValue(/*AllowPoison=*/true)))
+ return ConstantRange(CB->getValue());
+
if (auto *CDV = dyn_cast<ConstantDataVector>(this)) {
ConstantRange CR = ConstantRange::getEmpty(BitWidth);
for (unsigned I = 0, E = CDV->getNumElements(); I < E; ++I)
@@ -1837,7 +2052,8 @@ ConstantRange Constant::toConstantRange() const {
if (isa<PoisonValue>(Elem))
continue;
auto *CI = dyn_cast<ConstantInt>(Elem);
- if (!CI)
+ auto *CB = dyn_cast<ConstantByte>(Elem);
+ if (!CI && !CB)
return ConstantRange::getFull(BitWidth);
CR = CR.unionWith(CI->getValue());
}
@@ -2884,6 +3100,17 @@ bool ConstantDataSequential::isElementTypeCompatible(Type *Ty) {
default: break;
}
}
+ if (auto *IT = dyn_cast<ByteType>(Ty)) {
+ switch (IT->getBitWidth()) {
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ return true;
+ default:
+ break;
+ }
+ }
return false;
}
@@ -3016,17 +3243,54 @@ Constant *ConstantDataArray::getFP(Type *ElementType, ArrayRef<uint64_t> Elts) {
return getImpl(StringRef(Data, Elts.size() * 8), Ty);
}
-Constant *ConstantDataArray::getString(LLVMContext &Context,
- StringRef Str, bool AddNull) {
+/// getByte() constructors - Return a constant of array type with a byte
+/// element type taken from argument `ElementType', and count taken from
+/// argument `Elts'. The amount of bits of the contained type must match the
+/// number of bits of the type contained in the passed in ArrayRef.
+/// Note that this can return a ConstantAggregateZero object.
+Constant *ConstantDataArray::getByte(Type *ElementType,
+ ArrayRef<uint8_t> Elts) {
+ assert(ElementType->isByteTy(8) && "Element type is not a 8-bit byte type");
+ Type *Ty = ArrayType::get(ElementType, Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(Data, Elts.size() * 1), Ty);
+}
+Constant *ConstantDataArray::getByte(Type *ElementType,
+ ArrayRef<uint16_t> Elts) {
+ assert(ElementType->isByteTy(16) && "Element type is not a 16-bit byte type");
+ Type *Ty = ArrayType::get(ElementType, Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(Data, Elts.size() * 2), Ty);
+}
+Constant *ConstantDataArray::getByte(Type *ElementType,
+ ArrayRef<uint32_t> Elts) {
+ assert(ElementType->isByteTy(32) && "Element type is not a 32-bit byte type");
+ Type *Ty = ArrayType::get(ElementType, Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(Data, Elts.size() * 4), Ty);
+}
+Constant *ConstantDataArray::getByte(Type *ElementType,
+ ArrayRef<uint64_t> Elts) {
+ assert(ElementType->isByteTy(64) && "Element type is not a 64-bit byte type");
+ Type *Ty = ArrayType::get(ElementType, Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(Data, Elts.size() * 8), Ty);
+}
+
+Constant *ConstantDataArray::getString(LLVMContext &Context, StringRef Str,
+ bool AddNull, bool ByteString) {
if (!AddNull) {
const uint8_t *Data = Str.bytes_begin();
- return get(Context, ArrayRef(Data, Str.size()));
+ return ByteString
+ ? getByte(Type::getByte8Ty(Context), ArrayRef(Data, Str.size()))
+ : get(Context, ArrayRef(Data, Str.size()));
}
SmallVector<uint8_t, 64> ElementVals;
ElementVals.append(Str.begin(), Str.end());
ElementVals.push_back(0);
- return get(Context, ElementVals);
+ return ByteString ? getByte(Type::getByte8Ty(Context), ElementVals)
+ : get(Context, ElementVals);
}
/// get() constructors - Return a constant with vector type with an element
@@ -3063,6 +3327,40 @@ Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<double> Elts) {
return getImpl(StringRef(Data, Elts.size() * 8), Ty);
}
+/// getByte() constructors - Return a constant of vector type with a byte
+/// element type taken from argument `ElementType', and count taken from
+/// argument `Elts'. The amount of bits of the contained type must match the
+/// number of bits of the type contained in the passed in ArrayRef.
+/// Note that this can return a ConstantAggregateZero object.
+Constant *ConstantDataVector::getByte(Type *ElementType,
+ ArrayRef<uint8_t> Elts) {
+ assert(ElementType->isByteTy(8) && "Element type is not a 8-bit byte");
+ auto *Ty = FixedVectorType::get(ElementType, Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(Data, Elts.size() * 1), Ty);
+}
+Constant *ConstantDataVector::getByte(Type *ElementType,
+ ArrayRef<uint16_t> Elts) {
+ assert(ElementType->isByteTy(16) && "Element type is not a 16-bit byte");
+ auto *Ty = FixedVectorType::get(ElementType, Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(Data, Elts.size() * 2), Ty);
+}
+Constant *ConstantDataVector::getByte(Type *ElementType,
+ ArrayRef<uint32_t> Elts) {
+ assert(ElementType->isByteTy(32) && "Element type is not a 32-bit byte");
+ auto *Ty = FixedVectorType::get(ElementType, Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(Data, Elts.size() * 4), Ty);
+}
+Constant *ConstantDataVector::getByte(Type *ElementType,
+ ArrayRef<uint64_t> Elts) {
+ assert(ElementType->isByteTy(64) && "Element type is not a 64-bit byte");
+ auto *Ty = FixedVectorType::get(ElementType, Elts.size());
+ const char *Data = reinterpret_cast<const char *>(Elts.data());
+ return getImpl(StringRef(Data, Elts.size() * 8), Ty);
+}
+
/// getFP() constructors - Return a constant of vector type with a float
/// element type taken from argument `ElementType', and count taken from
/// argument `Elts'. The amount of bits of the contained type must match the
@@ -3114,6 +3412,24 @@ Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) {
return get(V->getContext(), Elts);
}
+ if (ConstantByte *CB = dyn_cast<ConstantByte>(V)) {
+ if (CB->getType()->isByteTy(8)) {
+ SmallVector<uint8_t, 16> Elts(NumElts, CB->getZExtValue());
+ return getByte(V->getType(), Elts);
+ }
+ if (CB->getType()->isByteTy(16)) {
+ SmallVector<uint16_t, 16> Elts(NumElts, CB->getZExtValue());
+ return getByte(V->getType(), Elts);
+ }
+ if (CB->getType()->isByteTy(32)) {
+ SmallVector<uint32_t, 16> Elts(NumElts, CB->getZExtValue());
+ return getByte(V->getType(), Elts);
+ }
+ assert(CB->getType()->isByteTy(64) && "Unsupported ConstantData type");
+ SmallVector<uint64_t, 16> Elts(NumElts, CB->getZExtValue());
+ return getByte(V->getType(), Elts);
+ }
+
if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
if (CFP->getType()->isHalfTy()) {
SmallVector<uint16_t, 16> Elts(
@@ -3140,13 +3456,14 @@ Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) {
}
uint64_t ConstantDataSequential::getElementAsInteger(uint64_t Elt) const {
- assert(isa<IntegerType>(getElementType()) &&
- "Accessor can only be used when element is an integer");
+ assert(
+ (isa<IntegerType>(getElementType()) || isa<ByteType>(getElementType())) &&
+ "Accessor can only be used when element is an integer or byte");
const char *EltPtr = getElementPointer(Elt);
// The data is stored in host byte order, make sure to cast back to the right
// type to load with the right endianness.
- switch (getElementType()->getIntegerBitWidth()) {
+ switch (getElementType()->getScalarSizeInBits()) {
default: llvm_unreachable("Invalid bitwidth for CDS");
case 8:
return *reinterpret_cast<const uint8_t *>(EltPtr);
@@ -3160,13 +3477,14 @@ uint64_t ConstantDataSequential::getElementAsInteger(uint64_t Elt) const {
}
APInt ConstantDataSequential::getElementAsAPInt(uint64_t Elt) const {
- assert(isa<IntegerType>(getElementType()) &&
- "Accessor can only be used when element is an integer");
+ assert(
+ (isa<IntegerType>(getElementType()) || isa<ByteType>(getElementType())) &&
+ "Accessor can only be used when element is an integer or byte");
const char *EltPtr = getElementPointer(Elt);
// The data is stored in host byte order, make sure to cast back to the right
// type to load with the right endianness.
- switch (getElementType()->getIntegerBitWidth()) {
+ switch (getElementType()->getScalarSizeInBits()) {
default: llvm_unreachable("Invalid bitwidth for CDS");
case 8: {
auto EltVal = *reinterpret_cast<const uint8_t *>(EltPtr);
@@ -3229,11 +3547,16 @@ Constant *ConstantDataSequential::getElementAsConstant(uint64_t Elt) const {
getElementType()->isFloatTy() || getElementType()->isDoubleTy())
return ConstantFP::get(getContext(), getElementAsAPFloat(Elt));
+ if (getElementType()->isByteTy())
+ return ConstantByte::get(getElementType(), getElementAsInteger(Elt));
+
return ConstantInt::get(getElementType(), getElementAsInteger(Elt));
}
bool ConstantDataSequential::isString(unsigned CharSize) const {
- return isa<ArrayType>(getType()) && getElementType()->isIntegerTy(CharSize);
+ return isa<ArrayType>(getType()) &&
+ (getElementType()->isIntegerTy(CharSize) ||
+ getElementType()->isByteTy(CharSize));
}
bool ConstantDataSequential::isCString() const {
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index d31322a3013b6..0fd832ac5c99e 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -605,6 +605,8 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
return LLVMLabelTypeKind;
case Type::MetadataTyID:
return LLVMMetadataTypeKind;
+ case Type::ByteTyID:
+ return LLVMByteTypeKind;
case Type::IntegerTyID:
return LLVMIntegerTypeKind;
case Type::FunctionTyID:
@@ -656,6 +658,50 @@ char *LLVMPrintTypeToString(LLVMTypeRef Ty) {
return strdup(buf.c_str());
}
+/*--.. Operations on byte types ............................................--*/
+
+LLVMTypeRef LLVMByte8TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte8Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByte16TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte16Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByte32TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte32Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByte64TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte64Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByte128TypeInContext(LLVMContextRef C) {
+ return (LLVMTypeRef)Type::getByte128Ty(*unwrap(C));
+}
+LLVMTypeRef LLVMByteTypeInContext(LLVMContextRef C, unsigned NumBits) {
+ return wrap(ByteType::get(*unwrap(C), NumBits));
+}
+
+LLVMTypeRef LLVMByte8Type(void) {
+ return LLVMByte8TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByte16Type(void) {
+ return LLVMByte16TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByte32Type(void) {
+ return LLVMByte32TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByte64Type(void) {
+ return LLVMByte64TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByte128Type(void) {
+ return LLVMByte128TypeInContext(getGlobalContextForCAPI());
+}
+LLVMTypeRef LLVMByteType(unsigned NumBits) {
+ return LLVMByteTypeInContext(getGlobalContextForCAPI(), NumBits);
+}
+
+unsigned LLVMGetByteTypeWidth(LLVMTypeRef ByteTy) {
+ return unwrap<ByteType>(ByteTy)->getBitWidth();
+}
+
/*--.. Operations on integer types .........................................--*/
LLVMTypeRef LLVMInt1TypeInContext(LLVMContextRef C) {
@@ -1556,6 +1602,30 @@ LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy, const char Str[],
Radix));
}
+LLVMValueRef LLVMConstByte(LLVMTypeRef ByteTy, unsigned long long N) {
+ return wrap(ConstantByte::get(unwrap<ByteType>(ByteTy), N));
+}
+
+LLVMValueRef LLVMConstByteOfArbitraryPrecision(LLVMTypeRef ByteTy,
+ unsigned NumWords,
+ const uint64_t Words[]) {
+ ByteType *Ty = unwrap<ByteType>(ByteTy);
+ return wrap(ConstantByte::get(
+ Ty->getContext(), APInt(Ty->getBitWidth(), ArrayRef(Words, NumWords))));
+}
+
+LLVMValueRef LLVMConstByteOfString(LLVMTypeRef ByteTy, const char Str[],
+ uint8_t Radix) {
+ return wrap(
+ ConstantByte::get(unwrap<ByteType>(ByteTy), StringRef(Str), Radix));
+}
+
+LLVMValueRef LLVMConstByteOfStringAndSize(LLVMTypeRef ByteTy, const char Str[],
+ unsigned SLen, uint8_t Radix) {
+ return wrap(
+ ConstantByte::get(unwrap<ByteType>(ByteTy), StringRef(Str, SLen), Radix));
+}
+
LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N) {
return wrap(ConstantFP::get(unwrap(RealTy), N));
}
@@ -1585,6 +1655,14 @@ long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal) {
return unwrap<ConstantInt>(ConstantVal)->getSExtValue();
}
+unsigned long long LLVMConstByteGetZExtValue(LLVMValueRef ConstantVal) {
+ return unwrap<ConstantByte>(ConstantVal)->getZExtValue();
+}
+
+long long LLVMConstByteGetSExtValue(LLVMValueRef ConstantVal) {
+ return unwrap<ConstantByte>(ConstantVal)->getSExtValue();
+}
+
double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *LosesInfo) {
ConstantFP *cFP = unwrap<ConstantFP>(ConstantVal) ;
Type *Ty = cFP->getType();
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 05aa6c29c0e50..f7361f337af0d 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -872,6 +872,9 @@ Align DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
const Align Align = abi_or_pref ? StructABIAlignment : StructPrefAlignment;
return std::max(Align, Layout->getAlignment());
}
+ case Type::ByteTyID:
+ // The byte type has the same alignment as the equally sized integer type.
+ return getIntegerAlignment(Ty->getByteBitWidth(), abi_or_pref);
case Type::IntegerTyID:
return getIntegerAlignment(Ty->getIntegerBitWidth(), abi_or_pref);
case Type::HalfTyID:
@@ -983,6 +986,40 @@ Type *DataLayout::getIntPtrType(Type *Ty) const {
return IntTy;
}
+Type *DataLayout::getIntByteType(Type *Ty) const {
+ assert(Ty->isByteOrByteVectorTy() && "Expected a byte or byte vector type.");
+ unsigned NumBits = Ty->getScalarSizeInBits();
+ IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
+ if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
+ return VectorType::get(IntTy, VecTy);
+ return IntTy;
+}
+
+ByteType *DataLayout::getBytePtrType(LLVMContext &C,
+ unsigned AddressSpace) const {
+ return ByteType::get(C, getPointerSizeInBits(AddressSpace));
+}
+
+Type *DataLayout::getBytePtrType(Type *Ty) const {
+ assert(Ty->isPtrOrPtrVectorTy() &&
+ "Expected a pointer or pointer vector type.");
+ unsigned NumBits = getPointerTypeSizeInBits(Ty);
+ ByteType *ByteTy = ByteType::get(Ty->getContext(), NumBits);
+ if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
+ return VectorType::get(ByteTy, VecTy);
+ return ByteTy;
+}
+
+Type *DataLayout::getByteIntType(Type *Ty) const {
+ assert(!Ty->isPtrOrPtrVectorTy() &&
+ "Expected a non-pointer or non-pointer vector type.");
+ unsigned NumBits = Ty->getScalarSizeInBits();
+ ByteType *ByteTy = ByteType::get(Ty->getContext(), NumBits);
+ if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
+ return VectorType::get(ByteTy, VecTy);
+ return ByteTy;
+}
+
Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const {
for (unsigned LegalIntWidth : LegalIntWidths)
if (Width <= LegalIntWidth)
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index be307cf08ccc5..c57e56cf5c095 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -3183,6 +3183,9 @@ bool CastInst::isBitCastable(Type *SrcTy, Type *DestTy) {
if (SrcBits != DestBits)
return false;
+ if (SrcTy->isByteOrByteVectorTy() && !DestTy->isByteOrByteVectorTy())
+ return false;
+
return true;
}
@@ -3237,7 +3240,16 @@ CastInst::getCastOpcode(
DestTy->getPrimitiveSizeInBits().getFixedValue(); // 0 for ptr
// Run through the possibilities ...
- if (DestTy->isIntegerTy()) { // Casting to integral
+ if (DestTy->isByteTy()) { // Casting to byte
+ if (SrcTy->isIntegerTy()) { // Casting from integral
+ assert(DestBits == SrcBits && "Illegal cast from integer to byte type");
+ return BitCast;
+ } else if (SrcTy->isPointerTy()) { // Casting from pointer
+ assert(DestBits == SrcBits && "Illegal cast from pointer to byte type");
+ return BitCast;
+ }
+ llvm_unreachable("Illegal cast to byte type");
+ } else if (DestTy->isIntegerTy()) { // Casting to integral
if (SrcTy->isIntegerTy()) { // Casting from integral
if (DestBits < SrcBits)
return Trunc; // int -> smaller int
@@ -3368,8 +3380,14 @@ CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
+ // Bytes can only be cast to bytes.
+ if (SrcTy->isByteOrByteVectorTy() && !DstTy->isByteOrByteVectorTy())
+ return false;
+
// BitCast implies a no-op cast of type only. No bits change.
- // However, you can't cast pointers to anything but pointers.
+ // However, you can't cast pointers to anything but pointers/bytes.
+ if (SrcPtrTy && DstTy->isByteOrByteVectorTy())
+ return true;
if (!SrcPtrTy != !DstPtrTy)
return false;
@@ -3382,6 +3400,10 @@ CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
if (SrcPtrTy->getAddressSpace() != DstPtrTy->getAddressSpace())
return false;
+ // Integers can be cast to bytes of the same size.
+ if (SrcTy->isIntOrIntVectorTy() && DstTy->isByteOrByteVectorTy())
+ return SrcScalarBitSize == DstScalarBitSize;
+
// A vector of pointers must have the same number of elements.
if (SrcIsVec && DstIsVec)
return SrcEC == DstEC;
diff --git a/llvm/lib/IR/Intrinsics.cpp b/llvm/lib/IR/Intrinsics.cpp
index f46d3e5063e43..49a0816eeb345 100644
--- a/llvm/lib/IR/Intrinsics.cpp
+++ b/llvm/lib/IR/Intrinsics.cpp
@@ -147,6 +147,9 @@ static std::string getMangledTypeStr(Type *Ty, bool &HasUnnamedType) {
case Type::IntegerTyID:
Result += "i" + utostr(cast<IntegerType>(Ty)->getBitWidth());
break;
+ case Type::ByteTyID:
+ Result += "b" + utostr(cast<IntegerType>(Ty)->getBitWidth());
+ break;
}
}
return Result;
diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index 8f79398b086eb..9bb14178234db 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -37,7 +37,8 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
X86_FP80Ty(C, Type::X86_FP80TyID), FP128Ty(C, Type::FP128TyID),
PPC_FP128Ty(C, Type::PPC_FP128TyID), X86_AMXTy(C, Type::X86_AMXTyID),
Int1Ty(C, 1), Int8Ty(C, 8), Int16Ty(C, 16), Int32Ty(C, 32),
- Int64Ty(C, 64), Int128Ty(C, 128) {}
+ Int64Ty(C, 64), Int128Ty(C, 128), Byte1Ty(C, 1), Byte8Ty(C, 8),
+ Byte16Ty(C, 16), Byte32Ty(C, 32), Byte64Ty(C, 64), Byte128Ty(C, 128) {}
LLVMContextImpl::~LLVMContextImpl() {
#ifndef NDEBUG
@@ -119,6 +120,10 @@ LLVMContextImpl::~LLVMContextImpl() {
IntOneConstants.clear();
IntConstants.clear();
IntSplatConstants.clear();
+ ByteZeroConstants.clear();
+ ByteOneConstants.clear();
+ ByteConstants.clear();
+ ByteSplatConstants.clear();
FPConstants.clear();
FPSplatConstants.clear();
CDSConstants.clear();
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 2c9921df0422e..85aaecede4795 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1674,6 +1674,12 @@ class LLVMContextImpl {
DenseMap<std::pair<ElementCount, APInt>, std::unique_ptr<ConstantInt>>
IntSplatConstants;
+ DenseMap<unsigned, std::unique_ptr<ConstantByte>> ByteZeroConstants;
+ DenseMap<unsigned, std::unique_ptr<ConstantByte>> ByteOneConstants;
+ DenseMap<APInt, std::unique_ptr<ConstantByte>> ByteConstants;
+ DenseMap<std::pair<ElementCount, APInt>, std::unique_ptr<ConstantByte>>
+ ByteSplatConstants;
+
DenseMap<APFloat, std::unique_ptr<ConstantFP>> FPConstants;
DenseMap<std::pair<ElementCount, APFloat>, std::unique_ptr<ConstantFP>>
FPSplatConstants;
@@ -1743,11 +1749,15 @@ class LLVMContextImpl {
ConstantInt *TheTrueVal = nullptr;
ConstantInt *TheFalseVal = nullptr;
+ ConstantByte *TheTrueByteVal = nullptr;
+ ConstantByte *TheFalseByteVal = nullptr;
+
// Basic type instances.
Type VoidTy, LabelTy, HalfTy, BFloatTy, FloatTy, DoubleTy, MetadataTy,
TokenTy;
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_AMXTy;
IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty;
+ ByteType Byte1Ty, Byte8Ty, Byte16Ty, Byte32Ty, Byte64Ty, Byte128Ty;
std::unique_ptr<ConstantTokenNone> TheNoneToken;
@@ -1756,6 +1766,7 @@ class LLVMContextImpl {
SpecificBumpPtrAllocator<ConstantRangeAttributeImpl>
ConstantRangeAttributeAlloc;
+ DenseMap<unsigned, ByteType *> ByteTypes;
DenseMap<unsigned, IntegerType *> IntegerTypes;
using FunctionTypeSet = DenseSet<FunctionType *, FunctionTypeKeyInfo>;
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 299d07b81837b..585c9c45c3524 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -54,6 +54,10 @@ Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
}
}
+bool Type::isByteTy(unsigned BitWidth) const {
+ return isByteTy() && cast<ByteType>(this)->getBitWidth() == BitWidth;
+}
+
bool Type::isIntegerTy(unsigned Bitwidth) const {
return isIntegerTy() && cast<IntegerType>(this)->getBitWidth() == Bitwidth;
}
@@ -212,6 +216,8 @@ TypeSize Type::getPrimitiveSizeInBits() const {
return TypeSize::getFixed(128);
case Type::X86_AMXTyID:
return TypeSize::getFixed(8192);
+ case Type::ByteTyID:
+ return TypeSize::getFixed(cast<ByteType>(this)->getBitWidth());
case Type::IntegerTyID:
return TypeSize::getFixed(cast<IntegerType>(this)->getBitWidth());
case Type::FixedVectorTyID:
@@ -290,6 +296,17 @@ Type *Type::getFP128Ty(LLVMContext &C) { return &C.pImpl->FP128Ty; }
Type *Type::getPPC_FP128Ty(LLVMContext &C) { return &C.pImpl->PPC_FP128Ty; }
Type *Type::getX86_AMXTy(LLVMContext &C) { return &C.pImpl->X86_AMXTy; }
+ByteType *Type::getByte1Ty(LLVMContext &C) { return &C.pImpl->Byte1Ty; }
+ByteType *Type::getByte8Ty(LLVMContext &C) { return &C.pImpl->Byte8Ty; }
+ByteType *Type::getByte16Ty(LLVMContext &C) { return &C.pImpl->Byte16Ty; }
+ByteType *Type::getByte32Ty(LLVMContext &C) { return &C.pImpl->Byte32Ty; }
+ByteType *Type::getByte64Ty(LLVMContext &C) { return &C.pImpl->Byte64Ty; }
+ByteType *Type::getByte128Ty(LLVMContext &C) { return &C.pImpl->Byte128Ty; }
+
+ByteType *Type::getByteNTy(LLVMContext &C, unsigned N) {
+ return ByteType::get(C, N);
+}
+
IntegerType *Type::getInt1Ty(LLVMContext &C) { return &C.pImpl->Int1Ty; }
IntegerType *Type::getInt8Ty(LLVMContext &C) { return &C.pImpl->Int8Ty; }
IntegerType *Type::getInt16Ty(LLVMContext &C) { return &C.pImpl->Int16Ty; }
@@ -341,6 +358,40 @@ IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) {
APInt IntegerType::getMask() const { return APInt::getAllOnes(getBitWidth()); }
+//===----------------------------------------------------------------------===//
+// ByteType Implementation
+//===----------------------------------------------------------------------===//
+
+ByteType *ByteType::get(LLVMContext &C, unsigned NumBits) {
+ assert(NumBits >= MIN_BYTE_BITS && "bitwidth too small");
+ assert(NumBits <= MAX_BYTE_BITS && "bitwidth too large");
+
+ // Check for the built-in byte types
+ switch (NumBits) {
+ case 8:
+ return cast<ByteType>(Type::getByte8Ty(C));
+ case 16:
+ return cast<ByteType>(Type::getByte16Ty(C));
+ case 32:
+ return cast<ByteType>(Type::getByte32Ty(C));
+ case 64:
+ return cast<ByteType>(Type::getByte64Ty(C));
+ case 128:
+ return cast<ByteType>(Type::getByte128Ty(C));
+ default:
+ break;
+ }
+
+ ByteType *&Entry = C.pImpl->ByteTypes[NumBits];
+
+ if (!Entry)
+ Entry = new (C.pImpl->Alloc) ByteType(C, NumBits);
+
+ return Entry;
+}
+
+APInt ByteType::getMask() const { return APInt::getAllOnes(getBitWidth()); }
+
//===----------------------------------------------------------------------===//
// FunctionType Implementation
//===----------------------------------------------------------------------===//
@@ -788,7 +839,8 @@ VectorType *VectorType::get(Type *ElementType, ElementCount EC) {
bool VectorType::isValidElementType(Type *ElemTy) {
if (ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() ||
- ElemTy->isPointerTy() || ElemTy->getTypeID() == TypedPointerTyID)
+ ElemTy->isPointerTy() || ElemTy->getTypeID() == TypedPointerTyID ||
+ ElemTy->isByteTy())
return true;
if (auto *TTy = dyn_cast<TargetExtType>(ElemTy))
return TTy->hasProperty(TargetExtType::CanBeVectorElement);
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 3d44d1317ecc7..a9962aed295b0 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4619,9 +4619,10 @@ void Verifier::visitLoadInst(LoadInst &LI) {
LI.getOrdering() != AtomicOrdering::AcquireRelease,
"Load cannot have Release ordering", &LI);
Check(ElTy->getScalarType()->isIntOrPtrTy() ||
+ ElTy->getScalarType()->isByteTy() ||
ElTy->getScalarType()->isFloatingPointTy(),
- "atomic load operand must have integer, pointer, floating point, "
- "or vector type!",
+ "atomic load operand must have integer, byte, pointer, floating "
+ "point, or vector type!",
ElTy, &LI);
checkAtomicMemAccessSize(ElTy, &LI);
@@ -4647,9 +4648,10 @@ void Verifier::visitStoreInst(StoreInst &SI) {
SI.getOrdering() != AtomicOrdering::AcquireRelease,
"Store cannot have Acquire ordering", &SI);
Check(ElTy->getScalarType()->isIntOrPtrTy() ||
+ ElTy->getScalarType()->isByteTy() ||
ElTy->getScalarType()->isFloatingPointTy(),
- "atomic store operand must have integer, pointer, floating point, "
- "or vector type!",
+ "atomic store operand must have integer, byte, pointer, floating "
+ "point, or vector type!",
ElTy, &SI);
checkAtomicMemAccessSize(ElTy, &SI);
} else {
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index 48a9085820471..0d87385b44d8f 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -77,6 +77,7 @@ class DXILBitcodeWriter {
// CONSTANTS_BLOCK abbrev id's.
CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV,
CONSTANTS_INTEGER_ABBREV,
+ CONSTANTS_BYTE_ABBREV,
CONSTANTS_CE_CAST_Abbrev,
CONSTANTS_NULL_Abbrev,
@@ -2014,6 +2015,24 @@ void DXILBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
}
Code = bitc::CST_CODE_WIDE_INTEGER;
}
+ } else if (const ConstantByte *BV = dyn_cast<ConstantByte>(C)) {
+ if (BV->getBitWidth() <= 64) {
+ uint64_t V = BV->getZExtValue();
+ emitSignedInt64(Record, V);
+ Code = bitc::CST_CODE_BYTE;
+ AbbrevToUse = CONSTANTS_BYTE_ABBREV;
+ } else { // Wide bytes, > 64 bits in size.
+ // We have an arbitrary precision byte value to write whose
+ // bit width is > 64. However, in canonical unsigned integer
+ // format it is likely that the high bits are going to be zero.
+ // So, we only write the number of active words.
+ unsigned NWords = BV->getValue().getActiveWords();
+ const uint64_t *RawWords = BV->getValue().getRawData();
+ for (unsigned i = 0; i != NWords; ++i) {
+ emitSignedInt64(Record, V);
+ }
+ Code = bitc::CST_CODE_WIDE_BYTE;
+ }
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
Code = bitc::CST_CODE_FLOAT;
Type *Ty = CFP->getType();
diff --git a/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt b/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
index d62b0dd157b0b..12d1567466b1b 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
@@ -73,6 +73,7 @@ Key: MetadataTy: [ 3.50 4.00 ]
Key: VectorTy: [ 11.50 12.00 ]
Key: TokenTy: [ 5.50 6.00 ]
Key: IntegerTy: [ 6.50 7.00 ]
+Key: ByteTy: [ 0.00 0.00 ]
Key: FunctionTy: [ 7.50 8.00 ]
Key: PointerTy: [ 8.50 9.00 ]
Key: StructTy: [ 9.50 10.00 ]
diff --git a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
index e443adb17ac78..cb775622dc722 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
@@ -73,6 +73,7 @@ Key: MetadataTy: [ 3.50 4.00 ]
Key: VectorTy: [ 11.50 12.00 ]
Key: TokenTy: [ 5.50 6.00 ]
Key: IntegerTy: [ 6.50 7.00 ]
+Key: ByteTy: [ 0.00 0.00 ]
Key: FunctionTy: [ 7.50 8.00 ]
Key: PointerTy: [ 8.50 9.00 ]
Key: StructTy: [ 9.50 10.00 ]
diff --git a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
index 7fb6043552f7b..cafc8eb1b7e23 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
@@ -73,6 +73,7 @@ Key: MetadataTy: [ 0.00 0.00 ]
Key: VectorTy: [ 0.00 0.00 ]
Key: TokenTy: [ 0.00 0.00 ]
Key: IntegerTy: [ 0.00 0.00 ]
+Key: ByteTy: [ 0.00 0.00 ]
Key: FunctionTy: [ 0.00 0.00 ]
Key: PointerTy: [ 0.00 0.00 ]
Key: StructTy: [ 0.00 0.00 ]
diff --git a/llvm/test/Assembler/2008-02-18-IntPointerCrash.ll b/llvm/test/Assembler/2008-02-18-IntPointerCrash.ll
index 0d8fbc08917a0..82818adfec309 100644
--- a/llvm/test/Assembler/2008-02-18-IntPointerCrash.ll
+++ b/llvm/test/Assembler/2008-02-18-IntPointerCrash.ll
@@ -1,7 +1,7 @@
; RUN: not llvm-as %s 2>&1 | FileCheck %s
; PR2060
-; CHECK: integer constant must have integer type
+; CHECK: integer/byte constant must have integer/byte type
define ptr @foo() {
ret ptr 0
diff --git a/llvm/test/Assembler/byte-invalid-cast-1.ll b/llvm/test/Assembler/byte-invalid-cast-1.ll
new file mode 100644
index 0000000000000..793a8c25ea3f1
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-1.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'b8' to 'i32'
+define void @invalid_zext(b8 %b) {
+ %t = zext b8 %b to i32
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-2.ll b/llvm/test/Assembler/byte-invalid-cast-2.ll
new file mode 100644
index 0000000000000..fa2cee7f11005
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-2.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'b8' to 'i32'
+define void @invalid_sext(b8 %b) {
+ %t = sext b8 %b to i32
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-3.ll b/llvm/test/Assembler/byte-invalid-cast-3.ll
new file mode 100644
index 0000000000000..edad062e0cbcd
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-3.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'b32' to 'i8'
+define void @invalid_trunc(b32 %b) {
+ %t = trunc b32 %b to i8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-4.ll b/llvm/test/Assembler/byte-invalid-cast-4.ll
new file mode 100644
index 0000000000000..878cdd8e27425
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-4.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'i8' to 'b32'
+define void @invalid_zext(i8 %v) {
+ %t = zext i8 %v to b32
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-5.ll b/llvm/test/Assembler/byte-invalid-cast-5.ll
new file mode 100644
index 0000000000000..bb569ff9c6064
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-5.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'i8' to 'b32'
+define void @invalid_sext(i8 %v) {
+ %t = sext i8 %v to b32
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-6.ll b/llvm/test/Assembler/byte-invalid-cast-6.ll
new file mode 100644
index 0000000000000..fcfb00383ce3e
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-6.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'i32' to 'b8'
+define void @invalid_trunc(i32 %v) {
+ %t = trunc i32 %v to b8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-7.ll b/llvm/test/Assembler/byte-invalid-cast-7.ll
new file mode 100644
index 0000000000000..d1e90960d4a02
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-7.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'b8' to 'i8'
+define void @invalid_bitcast(b8 %b) {
+ %t = bitcast b8 %b to i8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cmp.ll b/llvm/test/Assembler/byte-invalid-cmp.ll
new file mode 100644
index 0000000000000..8206b037ea911
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cmp.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: icmp requires integer operands
+define void @byte_compare(b8 %b1, b8 %b2) {
+ %cmp = icmp eq b8 %b1, %b2
+ ret void
+}
diff --git a/llvm/test/Assembler/byte.ll b/llvm/test/Assembler/byte.ll
new file mode 100644
index 0000000000000..d62d6cd9b5fc3
--- /dev/null
+++ b/llvm/test/Assembler/byte.ll
@@ -0,0 +1,79 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+
+; CHECK: common global [32 x b8] zeroinitializer
+; CHECK: constant [1 x b8] zeroinitializer
+; CHECK: constant [15 x b8] c"Hello, World!\0A\00"
+; CHECK: constant [15 x b8] c"Hello, World!\0A\00"
+ at a = common global [32 x b8] zeroinitializer, align 1
+ at b = constant [1 x b8] zeroinitializer
+ at c = constant [15 x b8] [b8 72, b8 101, b8 108, b8 108, b8 111, b8 44, b8 32, b8 87, b8 111, b8 114, b8 108, b8 100, b8 33, b8 10, b8 0]
+ at d = constant [15 x b8] c"Hello, World!\0A\00"
+
+define void @bytes(b1 %a, b3 %b, b5 %c, b8 %d, b16 %e, b32 %f, b64 %g, b128 %h, <8 x b5> %i, <2 x b64> %j) {
+; CHECK-LABEL: define void @bytes(
+; CHECK-SAME: b1 [[A:%.*]], b3 [[B:%.*]], b5 [[C:%.*]], b8 [[D:%.*]], b16 [[E:%.*]], b32 [[F:%.*]], b64 [[G:%.*]], b128 [[H:%.*]], <8 x b5> [[I:%.*]], <2 x b64> [[J:%.*]]) {
+; CHECK-NEXT: ret void
+;
+ ret void
+}
+
+define void @byte_alloca() {
+; CHECK-LABEL: define void @byte_alloca() {
+; CHECK-NEXT: [[B1:%.*]] = alloca b8, align 1
+; CHECK-NEXT: [[B8:%.*]] = alloca b64, align 8
+; CHECK-NEXT: [[V:%.*]] = alloca <4 x b64>, align 32
+; CHECK-NEXT: [[A:%.*]] = alloca [4 x b64], align 8
+; CHECK-NEXT: ret void
+;
+ %b1 = alloca b8
+ %b8 = alloca b64
+ %v = alloca <4 x b64>
+ %a = alloca [4 x b64]
+ ret void
+}
+
+define void @byte_load_store(ptr %ptr) {
+; CHECK-LABEL: define void @byte_load_store(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[B:%.*]] = load b8, ptr [[PTR]], align 1
+; CHECK-NEXT: store b8 [[B]], ptr [[PTR]], align 1
+; CHECK-NEXT: store b8 0, ptr [[PTR]], align 1
+; CHECK-NEXT: [[V:%.*]] = load <4 x b64>, ptr [[PTR]], align 32
+; CHECK-NEXT: store <4 x b64> [[V]], ptr [[PTR]], align 32
+; CHECK-NEXT: store <4 x b64> <b64 0, b64 1, b64 2, b64 3>, ptr [[PTR]], align 32
+; CHECK-NEXT: [[A:%.*]] = load [4 x b8], ptr [[PTR]], align 1
+; CHECK-NEXT: store [4 x b8] [[A]], ptr [[PTR]], align 1
+; CHECK-NEXT: store [4 x b8] c"\00\01\02\03", ptr [[PTR]], align 1
+; CHECK-NEXT: ret void
+;
+ %b = load b8, ptr %ptr
+ store b8 %b, ptr %ptr
+ store b8 0, ptr %ptr
+ %v = load <4 x b64>, ptr %ptr
+ store <4 x b64> %v, ptr %ptr
+ store <4 x b64> <b64 0, b64 1, b64 2, b64 3>, ptr %ptr
+ %a = load [4 x b8], ptr %ptr
+ store [4 x b8] %a, ptr %ptr
+ store [4 x b8] [b8 0, b8 1, b8 2, b8 3], ptr %ptr
+ ret void
+}
+
+define void @bitcasts(i64 %i, b64 %b, ptr %p) {
+; CHECK-LABEL: define void @bitcasts(
+; CHECK-SAME: i64 [[I:%.*]], b64 [[B:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast ptr [[P]] to b64
+; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64 [[I]] to b64
+; CHECK-NEXT: [[TMP3:%.*]] = bitcast b64 [[B]] to <8 x b8>
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast <8 x b8> [[TMP3]] to <2 x b32>
+; CHECK-NEXT: [[TMP5:%.*]] = bitcast <2 x b32> [[TMP4]] to b64
+; CHECK-NEXT: [[TMP6:%.*]] = bitcast <2 x b32> splat (b32 1) to b64
+; CHECK-NEXT: ret void
+;
+ %1 = bitcast ptr %p to b64
+ %2 = bitcast i64 %i to b64
+ %3 = bitcast b64 %b to <8 x b8>
+ %4 = bitcast <8 x b8> %3 to <2 x b32>
+ %5 = bitcast <2 x b32> %4 to b64
+ %6 = bitcast <2 x b32> <b32 1, b32 1> to b64
+ ret void
+}
diff --git a/llvm/test/Assembler/invalid-inttype.ll b/llvm/test/Assembler/invalid-inttype.ll
index 9e3c31148af2d..ef050d599875e 100644
--- a/llvm/test/Assembler/invalid-inttype.ll
+++ b/llvm/test/Assembler/invalid-inttype.ll
@@ -1,5 +1,5 @@
; RUN: not llvm-as --disable-output %s 2>&1 | FileCheck -DFILE=%s %s
; i8388609 is the smallest integer type that can't be represented in LLVM IR
-; CHECK: [[FILE]]:[[@LINE+1]]:21: error: bitwidth for integer type out of range
+; CHECK: [[FILE]]:[[@LINE+1]]:21: error: bitwidth for integer or byte type out of range
@i2 = common global i8388609 0, align 4
diff --git a/llvm/test/Bindings/llvm-c/byte.ll b/llvm/test/Bindings/llvm-c/byte.ll
new file mode 100644
index 0000000000000..93b9819c3c9b9
--- /dev/null
+++ b/llvm/test/Bindings/llvm-c/byte.ll
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | llvm-dis > %t.orig
+; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo
+; RUN: diff -w %t.orig %t.echo
+
+define void @foo(b8 %a, b16 %b, b64 %c) {
+ %1 = alloca b16, align 2
+ store b16 %b, ptr %1, align 2
+ %2 = load b16, ptr %1, align 2
+ %3 = bitcast b16 %2 to <2 x b8>
+ ret void
+}
diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll
index ab1771d1f879f..0202990018045 100644
--- a/llvm/test/Bindings/llvm-c/echo.ll
+++ b/llvm/test/Bindings/llvm-c/echo.ll
@@ -72,6 +72,7 @@ define void @types() {
%10 = alloca ptr addrspace(5), align 8
%11 = alloca <5 x ptr>, align 64
%12 = alloca <1 x i64>, align 8
+ %13 = alloca b8, align 1
ret void
}
diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index 53cbe2d6ffd37..1510d6275c56f 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -1270,6 +1270,8 @@ define void @typesystem() {
; CHECK: %t9 = alloca <4 x i32>
%t10 = alloca <vscale x 4 x i32>
; CHECK: %t10 = alloca <vscale x 4 x i32>
+ %t11 = alloca b8
+ ; CHECK: %t11 = alloca b8
ret void
}
diff --git a/llvm/test/Verifier/atomics.ll b/llvm/test/Verifier/atomics.ll
index 17bf5a0528d73..2b1f971e6e91f 100644
--- a/llvm/test/Verifier/atomics.ll
+++ b/llvm/test/Verifier/atomics.ll
@@ -1,6 +1,6 @@
; RUN: not opt -passes=verify < %s 2>&1 | FileCheck %s
-; CHECK: atomic store operand must have integer, pointer, floating point, or vector type!
-; CHECK: atomic load operand must have integer, pointer, floating point, or vector type!
+; CHECK: atomic store operand must have integer, byte, pointer, floating point, or vector type!
+; CHECK: atomic load operand must have integer, byte, pointer, floating point, or vector type!
%ty = type { i32 };
diff --git a/llvm/test/tools/llvm-ir2vec/entities.ll b/llvm/test/tools/llvm-ir2vec/entities.ll
index 8dbce57302f6f..58c2d74036783 100644
--- a/llvm/test/tools/llvm-ir2vec/entities.ll
+++ b/llvm/test/tools/llvm-ir2vec/entities.ll
@@ -1,6 +1,6 @@
; RUN: llvm-ir2vec entities | FileCheck %s
-CHECK: 110
+CHECK: 111
CHECK-NEXT: Ret 0
CHECK-NEXT: Br 1
CHECK-NEXT: Switch 2
@@ -76,38 +76,39 @@ CHECK-NEXT: MetadataTy 71
CHECK-NEXT: VectorTy 72
CHECK-NEXT: TokenTy 73
CHECK-NEXT: IntegerTy 74
-CHECK-NEXT: FunctionTy 75
-CHECK-NEXT: PointerTy 76
-CHECK-NEXT: StructTy 77
-CHECK-NEXT: ArrayTy 78
-CHECK-NEXT: UnknownTy 79
-CHECK-NEXT: Function 80
-CHECK-NEXT: Pointer 81
-CHECK-NEXT: Constant 82
-CHECK-NEXT: Variable 83
-CHECK-NEXT: FCMP_false 84
-CHECK-NEXT: FCMP_oeq 85
-CHECK-NEXT: FCMP_ogt 86
-CHECK-NEXT: FCMP_oge 87
-CHECK-NEXT: FCMP_olt 88
-CHECK-NEXT: FCMP_ole 89
-CHECK-NEXT: FCMP_one 90
-CHECK-NEXT: FCMP_ord 91
-CHECK-NEXT: FCMP_uno 92
-CHECK-NEXT: FCMP_ueq 93
-CHECK-NEXT: FCMP_ugt 94
-CHECK-NEXT: FCMP_uge 95
-CHECK-NEXT: FCMP_ult 96
-CHECK-NEXT: FCMP_ule 97
-CHECK-NEXT: FCMP_une 98
-CHECK-NEXT: FCMP_true 99
-CHECK-NEXT: ICMP_eq 100
-CHECK-NEXT: ICMP_ne 101
-CHECK-NEXT: ICMP_ugt 102
-CHECK-NEXT: ICMP_uge 103
-CHECK-NEXT: ICMP_ult 104
-CHECK-NEXT: ICMP_ule 105
-CHECK-NEXT: ICMP_sgt 106
-CHECK-NEXT: ICMP_sge 107
-CHECK-NEXT: ICMP_slt 108
-CHECK-NEXT: ICMP_sle 109
+CHECK-NEXT: ByteTy 75
+CHECK-NEXT: FunctionTy 76
+CHECK-NEXT: PointerTy 77
+CHECK-NEXT: StructTy 78
+CHECK-NEXT: ArrayTy 79
+CHECK-NEXT: UnknownTy 80
+CHECK-NEXT: Function 81
+CHECK-NEXT: Pointer 82
+CHECK-NEXT: Constant 83
+CHECK-NEXT: Variable 84
+CHECK-NEXT: FCMP_false 85
+CHECK-NEXT: FCMP_oeq 86
+CHECK-NEXT: FCMP_ogt 87
+CHECK-NEXT: FCMP_oge 88
+CHECK-NEXT: FCMP_olt 89
+CHECK-NEXT: FCMP_ole 90
+CHECK-NEXT: FCMP_one 91
+CHECK-NEXT: FCMP_ord 92
+CHECK-NEXT: FCMP_uno 93
+CHECK-NEXT: FCMP_ueq 94
+CHECK-NEXT: FCMP_ugt 95
+CHECK-NEXT: FCMP_uge 96
+CHECK-NEXT: FCMP_ult 97
+CHECK-NEXT: FCMP_ule 98
+CHECK-NEXT: FCMP_une 99
+CHECK-NEXT: FCMP_true 100
+CHECK-NEXT: ICMP_eq 101
+CHECK-NEXT: ICMP_ne 102
+CHECK-NEXT: ICMP_ugt 103
+CHECK-NEXT: ICMP_uge 104
+CHECK-NEXT: ICMP_ult 105
+CHECK-NEXT: ICMP_ule 106
+CHECK-NEXT: ICMP_sgt 107
+CHECK-NEXT: ICMP_sge 108
+CHECK-NEXT: ICMP_slt 109
+CHECK-NEXT: ICMP_sle 110
diff --git a/llvm/test/tools/llvm-ir2vec/triplets.ll b/llvm/test/tools/llvm-ir2vec/triplets.ll
index 7b476f60a07b3..1a7220cc9c3c5 100644
--- a/llvm/test/tools/llvm-ir2vec/triplets.ll
+++ b/llvm/test/tools/llvm-ir2vec/triplets.ll
@@ -26,40 +26,40 @@ entry:
; TRIPLETS: MAX_RELATION=3
; TRIPLETS-NEXT: 12 74 0
-; TRIPLETS-NEXT: 12 83 2
-; TRIPLETS-NEXT: 12 83 3
+; TRIPLETS-NEXT: 12 84 2
+; TRIPLETS-NEXT: 12 84 3
; TRIPLETS-NEXT: 12 0 1
; TRIPLETS-NEXT: 0 69 0
-; TRIPLETS-NEXT: 0 83 2
+; TRIPLETS-NEXT: 0 84 2
; TRIPLETS-NEXT: 16 74 0
-; TRIPLETS-NEXT: 16 83 2
-; TRIPLETS-NEXT: 16 83 3
+; TRIPLETS-NEXT: 16 84 2
+; TRIPLETS-NEXT: 16 84 3
; TRIPLETS-NEXT: 16 0 1
; TRIPLETS-NEXT: 0 69 0
-; TRIPLETS-NEXT: 0 83 2
-; TRIPLETS-NEXT: 30 76 0
-; TRIPLETS-NEXT: 30 82 2
+; TRIPLETS-NEXT: 0 84 2
+; TRIPLETS-NEXT: 30 77 0
+; TRIPLETS-NEXT: 30 83 2
; TRIPLETS-NEXT: 30 30 1
-; TRIPLETS-NEXT: 30 76 0
-; TRIPLETS-NEXT: 30 82 2
+; TRIPLETS-NEXT: 30 77 0
+; TRIPLETS-NEXT: 30 83 2
; TRIPLETS-NEXT: 30 32 1
; TRIPLETS-NEXT: 32 69 0
-; TRIPLETS-NEXT: 32 83 2
-; TRIPLETS-NEXT: 32 81 3
+; TRIPLETS-NEXT: 32 84 2
+; TRIPLETS-NEXT: 32 82 3
; TRIPLETS-NEXT: 32 32 1
; TRIPLETS-NEXT: 32 69 0
-; TRIPLETS-NEXT: 32 83 2
-; TRIPLETS-NEXT: 32 81 3
+; TRIPLETS-NEXT: 32 84 2
+; TRIPLETS-NEXT: 32 82 3
; TRIPLETS-NEXT: 32 31 1
; TRIPLETS-NEXT: 31 74 0
-; TRIPLETS-NEXT: 31 81 2
+; TRIPLETS-NEXT: 31 82 2
; TRIPLETS-NEXT: 31 31 1
; TRIPLETS-NEXT: 31 74 0
-; TRIPLETS-NEXT: 31 81 2
+; TRIPLETS-NEXT: 31 82 2
; TRIPLETS-NEXT: 31 12 1
; TRIPLETS-NEXT: 12 74 0
-; TRIPLETS-NEXT: 12 83 2
-; TRIPLETS-NEXT: 12 83 3
+; TRIPLETS-NEXT: 12 84 2
+; TRIPLETS-NEXT: 12 84 3
; TRIPLETS-NEXT: 12 0 1
; TRIPLETS-NEXT: 0 69 0
-; TRIPLETS-NEXT: 0 83 2
\ No newline at end of file
+; TRIPLETS-NEXT: 0 84 2
\ No newline at end of file
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index bd640cd8d85ec..e5add4430e5a5 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -89,6 +89,8 @@ struct TypeCloner {
return LLVMPPCFP128TypeInContext(Ctx);
case LLVMLabelTypeKind:
return LLVMLabelTypeInContext(Ctx);
+ case LLVMByteTypeKind:
+ return LLVMByteTypeInContext(Ctx, LLVMGetByteTypeWidth(Src));
case LLVMIntegerTypeKind:
return LLVMIntTypeInContext(Ctx, LLVMGetIntTypeWidth(Src));
case LLVMFunctionTypeKind: {
diff --git a/llvm/unittests/Analysis/IR2VecTest.cpp b/llvm/unittests/Analysis/IR2VecTest.cpp
index e085568a135fe..a095761bc246a 100644
--- a/llvm/unittests/Analysis/IR2VecTest.cpp
+++ b/llvm/unittests/Analysis/IR2VecTest.cpp
@@ -333,8 +333,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_Symbolic) {
EXPECT_EQ(AddEmb.size(), 2u);
EXPECT_EQ(RetEmb.size(), 2u);
- EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.5)));
- EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 15.5)));
+ EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.7)));
+ EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 15.6)));
}
TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
@@ -346,8 +346,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
EXPECT_EQ(AddEmb.size(), 2u);
EXPECT_EQ(RetEmb.size(), 2u);
- EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.5)));
- EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 32.6)));
+ EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.7)));
+ EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 32.8)));
}
TEST_F(IR2VecTestFixture, GetBBVector_Symbolic) {
@@ -357,9 +357,9 @@ TEST_F(IR2VecTestFixture, GetBBVector_Symbolic) {
const auto &BBVec = Emb->getBBVector(*BB);
EXPECT_EQ(BBVec.size(), 2u);
- // BB vector should be sum of add and ret: {25.5, 25.5} + {15.5, 15.5} =
- // {41.0, 41.0}
- EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 41.0)));
+ // BB vector should be sum of add and ret: {25.7, 25.7} + {15.6, 15.6} =
+ // {41.3, 41.3}
+ EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 41.3)));
}
TEST_F(IR2VecTestFixture, GetBBVector_FlowAware) {
@@ -369,9 +369,9 @@ TEST_F(IR2VecTestFixture, GetBBVector_FlowAware) {
const auto &BBVec = Emb->getBBVector(*BB);
EXPECT_EQ(BBVec.size(), 2u);
- // BB vector should be sum of add and ret: {25.5, 25.5} + {32.6, 32.6} =
- // {58.1, 58.1}
- EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 58.1)));
+ // BB vector should be sum of add and ret: {25.7, 25.7} + {32.8, 32.8} =
+ // {58.5, 58.5}
+ EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 58.5)));
}
TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
@@ -382,8 +382,8 @@ TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
EXPECT_EQ(FuncVec.size(), 2u);
- // Function vector should match BB vector (only one BB): {41.0, 41.0}
- EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 41.0)));
+ // Function vector should match BB vector (only one BB): {41.3, 41.3}
+ EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 41.3)));
}
TEST_F(IR2VecTestFixture, GetFunctionVector_FlowAware) {
@@ -393,8 +393,8 @@ TEST_F(IR2VecTestFixture, GetFunctionVector_FlowAware) {
const auto &FuncVec = Emb->getFunctionVector();
EXPECT_EQ(FuncVec.size(), 2u);
- // Function vector should match BB vector (only one BB): {58.1, 58.1}
- EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 58.1)));
+ // Function vector should match BB vector (only one BB): {58.5, 58.5}
+ EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 58.5)));
}
TEST_F(IR2VecTestFixture, MultipleComputeEmbeddingsConsistency_Symbolic) {
@@ -450,6 +450,7 @@ static constexpr unsigned MaxPredicateKinds = Vocabulary::MaxPredicateKinds;
// names and their canonical string keys.
#define IR2VEC_HANDLE_TYPE_BIMAP(X) \
X(VoidTyID, VoidTy, "VoidTy") \
+ X(ByteTyID, ByteTy, "ByteTy") \
X(IntegerTyID, IntegerTy, "IntegerTy") \
X(FloatTyID, FloatTy, "FloatTy") \
X(PointerTyID, PointerTy, "PointerTy") \
>From dd7f2c053c57c9a9c76d21d18480fd914a31969a Mon Sep 17 00:00:00 2001
From: George Mitenkov <georgemitenk0v at gmail.com>
Date: Fri, 23 Jul 2021 11:20:49 +0300
Subject: [PATCH 02/15] [IR] Introduce the `bytecast` instruction
- Adds the `bytecast` instruction
- Fixes IR2Vec and IRNormalizer tests
---
llvm/include/llvm-c/Core.h | 5 +
llvm/include/llvm/AsmParser/LLToken.h | 1 +
llvm/include/llvm/Bitcode/LLVMBitCodes.h | 1 +
.../llvm/CodeGen/GlobalISel/IRTranslator.h | 3 +
llvm/include/llvm/IR/Constants.h | 2 +
llvm/include/llvm/IR/IRBuilder.h | 46 +++++++
llvm/include/llvm/IR/InstVisitor.h | 1 +
llvm/include/llvm/IR/Instruction.def | 45 +++----
llvm/include/llvm/IR/Instructions.h | 32 +++++
llvm/lib/AsmParser/LLLexer.cpp | 1 +
llvm/lib/AsmParser/LLParser.cpp | 5 +-
llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 3 +
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 +
.../SelectionDAG/SelectionDAGBuilder.cpp | 21 +++
.../SelectionDAG/SelectionDAGBuilder.h | 1 +
llvm/lib/CodeGen/TargetLoweringBase.cpp | 3 +
llvm/lib/IR/Constants.cpp | 13 ++
llvm/lib/IR/Core.cpp | 5 +
llvm/lib/IR/Instruction.cpp | 3 +
llvm/lib/IR/Instructions.cpp | 88 +++++++++----
llvm/lib/IR/Verifier.cpp | 8 ++
.../Inputs/reference_default_vocab_print.txt | 1 +
.../Inputs/reference_wtd1_vocab_print.txt | 1 +
.../Inputs/reference_wtd2_vocab_print.txt | 1 +
llvm/test/Assembler/byte-invalid-cast-10.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-8.ll | 7 +
llvm/test/Assembler/byte-invalid-cast-9.ll | 7 +
llvm/test/Assembler/byte.ll | 48 +++++++
llvm/test/Bindings/llvm-c/byte.ll | 1 +
llvm/test/Bitcode/compatibility.ll | 4 +
.../regression-convergence-tokens.ll | 6 +-
.../IRNormalizer/regression-infinite-loop.ll | 44 +++----
.../IRNormalizer/reordering-basic.ll | 14 +-
.../Transforms/IRNormalizer/reordering.ll | 8 +-
llvm/test/tools/llvm-ir2vec/entities.ll | 123 +++++++++---------
llvm/test/tools/llvm-ir2vec/triplets.ll | 58 ++++-----
llvm/tools/llvm-c-test/echo.cpp | 5 +
llvm/unittests/Analysis/IR2VecTest.cpp | 28 ++--
38 files changed, 465 insertions(+), 188 deletions(-)
create mode 100644 llvm/test/Assembler/byte-invalid-cast-10.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-8.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-9.ll
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 23f94408b86b5..1c19194021c11 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -58,6 +58,7 @@ LLVM_C_EXTERN_C_BEGIN
/// External users depend on the following values being stable. It is not safe
/// to reorder them.
+// clang-format off
typedef enum {
/* Terminator Instructions */
LLVMRet = 1,
@@ -115,6 +116,7 @@ typedef enum {
LLVMIntToPtr = 40,
LLVMBitCast = 41,
LLVMAddrSpaceCast = 60,
+ LLVMByteCast = 70,
/* Other Operators */
LLVMICmp = 42,
@@ -146,6 +148,7 @@ typedef enum {
LLVMCleanupPad = 64,
LLVMCatchSwitch = 65
} LLVMOpcode;
+// clang-format on
typedef enum {
LLVMVoidTypeKind = 0, /**< type with no size */
@@ -5043,6 +5046,8 @@ LLVM_C_ABI LLVMValueRef LLVMBuildIntToPtr(LLVMBuilderRef, LLVMValueRef Val,
LLVMTypeRef DestTy, const char *Name);
LLVM_C_ABI LLVMValueRef LLVMBuildBitCast(LLVMBuilderRef, LLVMValueRef Val,
LLVMTypeRef DestTy, const char *Name);
+LLVM_C_ABI LLVMValueRef LLVMBuildByteCast(LLVMBuilderRef, LLVMValueRef Val,
+ LLVMTypeRef DestTy, const char *Name);
LLVM_C_ABI LLVMValueRef LLVMBuildAddrSpaceCast(LLVMBuilderRef, LLVMValueRef Val,
LLVMTypeRef DestTy,
const char *Name);
diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index 24f84cfa09e34..377eb68596002 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -328,6 +328,7 @@ enum Kind {
kw_ptrtoint,
kw_bitcast,
kw_addrspacecast,
+ kw_bytecast,
kw_select,
kw_va_arg,
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 592bdf3a34949..be6a71c35900b 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -465,6 +465,7 @@ enum CastOpcodes {
CAST_BITCAST = 11,
CAST_ADDRSPACECAST = 12,
CAST_PTRTOADDR = 13,
+ CAST_BYTECAST = 14
};
/// UnaryOpcodes - These are values used in the bitcode files to encode which
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 3828d859212cb..14cc9ec0f3d8d 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -585,6 +585,9 @@ class IRTranslator : public MachineFunctionPass {
bool translateAddrSpaceCast(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_ADDRSPACE_CAST, U, MIRBuilder);
}
+ bool translateByteCast(const User &U, MachineIRBuilder &MIRBuilder) {
+ return false;
+ }
bool translateCleanupPad(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 53d1b1ca9b059..9c00b55140fc6 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -1394,6 +1394,8 @@ class ConstantExpr : public Constant {
bool OnlyIfReduced = false);
LLVM_ABI static Constant *getAddrSpaceCast(Constant *C, Type *Ty,
bool OnlyIfReduced = false);
+ LLVM_ABI static Constant *getByteCast(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
static Constant *getNSWNeg(Constant *C) { return getNeg(C, /*HasNSW=*/true); }
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index ddf0538e0a30e..f005b0fc75ee3 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2204,6 +2204,45 @@ class IRBuilderBase {
return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name);
}
+ Value *CreateByteCast(Value *V, Type *DestTy, const Twine &Name = "") {
+ if (Value *Folded = Folder.FoldCast(Instruction::ByteCast, V, DestTy))
+ return Folded;
+ Instruction *I = CastInst::Create(Instruction::ByteCast, V, DestTy);
+ return Insert(I, Name);
+ }
+
+ Value *CreateByteCastToInt(Value *V, const Twine &Name = "") {
+ if (auto *VTy = dyn_cast<VectorType>(V->getType())) {
+ unsigned NumEls = VTy->getElementCount().getKnownMinValue();
+ unsigned BitWidth = VTy->getElementType()->getPrimitiveSizeInBits();
+
+ Type *DestElTy = getIntNTy(BitWidth);
+ VectorType *DestTy =
+ VectorType::get(DestElTy, NumEls, VTy->isScalableTy());
+
+ return CreateByteCast(V, DestTy, Name);
+ }
+
+ Type *DestTy = getIntNTy(V->getType()->getByteBitWidth());
+ return CreateByteCast(V, DestTy, Name);
+ }
+
+ Value *CreateByteCastToPtr(Value *V, unsigned AddrSpace = 0,
+ const Twine &Name = "") {
+ if (auto *VTy = dyn_cast<VectorType>(V->getType())) {
+ unsigned NumEls = VTy->getElementCount().getKnownMinValue();
+
+ Type *DestElTy = getPtrTy(AddrSpace);
+ VectorType *DestTy =
+ VectorType::get(DestElTy, NumEls, VTy->isScalableTy());
+
+ return CreateByteCast(V, DestTy, Name);
+ }
+
+ Type *DestTy = getPtrTy(AddrSpace);
+ return CreateByteCast(V, DestTy, Name);
+ }
+
Value *CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") {
Instruction::CastOps CastOp =
V->getType()->getScalarSizeInBits() == DestTy->getScalarSizeInBits()
@@ -2228,6 +2267,13 @@ class IRBuilderBase {
return CreateCast(CastOp, V, DestTy, Name);
}
+ Value *CreateBitOrByteCast(Value *V, Type *DestTy, const Twine &Name = "") {
+ Instruction::CastOps CastOp = V->getType()->isByteOrByteVectorTy()
+ ? Instruction::ByteCast
+ : Instruction::BitCast;
+ return CreateCast(CastOp, V, DestTy, Name);
+ }
+
Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy,
const Twine &Name = "", MDNode *FPMathTag = nullptr,
FMFSource FMFSource = {}) {
diff --git a/llvm/include/llvm/IR/InstVisitor.h b/llvm/include/llvm/IR/InstVisitor.h
index 8e4dc647e5230..ff3eff9506f95 100644
--- a/llvm/include/llvm/IR/InstVisitor.h
+++ b/llvm/include/llvm/IR/InstVisitor.h
@@ -187,6 +187,7 @@ class InstVisitor {
RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst);}
RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst);}
RetTy visitAddrSpaceCastInst(AddrSpaceCastInst &I) { DELEGATE(CastInst);}
+ RetTy visitByteCastInst(ByteCastInst &I) { DELEGATE(CastInst); }
RetTy visitSelectInst(SelectInst &I) { DELEGATE(Instruction);}
RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(UnaryInstruction);}
RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);}
diff --git a/llvm/include/llvm/IR/Instruction.def b/llvm/include/llvm/IR/Instruction.def
index face6a93ec7d5..bc0f22892e13f 100644
--- a/llvm/include/llvm/IR/Instruction.def
+++ b/llvm/include/llvm/IR/Instruction.def
@@ -195,31 +195,32 @@ 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)
+HANDLE_CAST_INST(52, ByteCast , ByteCastInst ) // Byte cast
+ LAST_CAST_INST(52)
- FIRST_FUNCLETPAD_INST(52)
-HANDLE_FUNCLETPAD_INST(52, CleanupPad, CleanupPadInst)
-HANDLE_FUNCLETPAD_INST(53, CatchPad , CatchPadInst)
- LAST_FUNCLETPAD_INST(53)
+ FIRST_FUNCLETPAD_INST(53)
+HANDLE_FUNCLETPAD_INST(53, CleanupPad, CleanupPadInst)
+HANDLE_FUNCLETPAD_INST(54, CatchPad , CatchPadInst)
+ LAST_FUNCLETPAD_INST(54)
// Other operators...
- 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)
+ FIRST_OTHER_INST(55)
+HANDLE_OTHER_INST(55, ICmp , ICmpInst ) // Integer comparison instruction
+HANDLE_OTHER_INST(56, FCmp , FCmpInst ) // Floating point comparison instr.
+HANDLE_OTHER_INST(57, PHI , PHINode ) // PHI node instruction
+HANDLE_OTHER_INST(58, Call , CallInst ) // Call a function
+HANDLE_OTHER_INST(59, Select , SelectInst ) // select instruction
+HANDLE_USER_INST (60, UserOp1, Instruction) // May be used internally in a pass
+HANDLE_USER_INST (61, UserOp2, Instruction) // Internal to passes only
+HANDLE_OTHER_INST(62, VAArg , VAArgInst ) // vaarg instruction
+HANDLE_OTHER_INST(63, ExtractElement, ExtractElementInst)// extract from vector
+HANDLE_OTHER_INST(64, InsertElement, InsertElementInst) // insert into vector
+HANDLE_OTHER_INST(65, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
+HANDLE_OTHER_INST(66, ExtractValue, ExtractValueInst)// extract from aggregate
+HANDLE_OTHER_INST(67, InsertValue, InsertValueInst) // insert into aggregate
+HANDLE_OTHER_INST(68, LandingPad, LandingPadInst) // Landing pad instruction.
+HANDLE_OTHER_INST(69, Freeze, FreezeInst) // Freeze instruction.
+ LAST_OTHER_INST(69)
#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index d4ea74c05ae62..e1009322c61c3 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -5198,6 +5198,38 @@ inline void setAtomicSyncScopeID(Instruction *I, SyncScope::ID SSID) {
llvm_unreachable("unhandled atomic operation");
}
+//===----------------------------------------------------------------------===//
+// ByteCastInst Class
+//===----------------------------------------------------------------------===//
+
+/// This class represents a cast for byte types.
+class ByteCastInst : public CastInst {
+protected:
+ // Note: Instruction needs to be a friend here to call cloneImpl.
+ friend class Instruction;
+
+ /// Clone an identical ByteCastInst.
+ LLVM_ABI ByteCastInst *cloneImpl() const;
+
+public:
+ /// Constructor with insert-before-instruction semantics
+ LLVM_ABI
+ ByteCastInst(Value *S, ///< The value to be casted
+ Type *Ty, ///< The type to casted to
+ const Twine &NameStr = "", ///< A name for the new instruction
+ InsertPosition InsertBefore =
+ nullptr ///< Where to insert the new instruction
+ );
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static bool classof(const Instruction *I) {
+ return I->getOpcode() == ByteCast;
+ }
+ static bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+};
+
//===----------------------------------------------------------------------===//
// FreezeInst Class
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index e5de7daa78aa0..828cd20104284 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -953,6 +953,7 @@ lltok::Kind LLLexer::LexIdentifier() {
INSTKEYWORD(ptrtoint, PtrToInt);
INSTKEYWORD(bitcast, BitCast);
INSTKEYWORD(addrspacecast, AddrSpaceCast);
+ INSTKEYWORD(bytecast, ByteCast);
INSTKEYWORD(select, Select);
INSTKEYWORD(va_arg, VAArg);
INSTKEYWORD(ret, Ret);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 1965efd37b968..9ce92d042e712 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4345,6 +4345,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
case lltok::kw_trunc:
case lltok::kw_bitcast:
+ case lltok::kw_bytecast:
case lltok::kw_addrspacecast:
case lltok::kw_inttoptr:
case lltok::kw_ptrtoaddr:
@@ -7448,6 +7449,7 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
case lltok::kw_inttoptr:
case lltok::kw_ptrtoaddr:
case lltok::kw_ptrtoint:
+ case lltok::kw_bytecast:
return parseCast(Inst, PFS, KeywordVal);
case lltok::kw_fptrunc:
case lltok::kw_fpext: {
@@ -8033,7 +8035,8 @@ bool LLParser::parseUnaryOp(Instruction *&Inst, PerFunctionState &PFS,
return true;
bool Valid = IsFP ? LHS->getType()->isFPOrFPVectorTy()
- : LHS->getType()->isIntOrIntVectorTy();
+ : (LHS->getType()->isIntOrIntVectorTy() ||
+ LHS->getType()->isByteOrByteVectorTy());
if (!Valid)
return error(Loc, "invalid operand type for instruction");
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 550972a252e90..5569ddb965673 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1272,6 +1272,7 @@ static GlobalVariable::UnnamedAddr getDecodedUnnamedAddrType(unsigned Val) {
}
}
+// clang-format off
static int getDecodedCastOpcode(unsigned Val) {
switch (Val) {
default: return -1;
@@ -1288,9 +1289,11 @@ static int getDecodedCastOpcode(unsigned Val) {
case bitc::CAST_PTRTOINT: return Instruction::PtrToInt;
case bitc::CAST_INTTOPTR: return Instruction::IntToPtr;
case bitc::CAST_BITCAST : return Instruction::BitCast;
+ case bitc::CAST_BYTECAST: return Instruction::ByteCast;
case bitc::CAST_ADDRSPACECAST: return Instruction::AddrSpaceCast;
}
}
+// clang-format on
static int getDecodedUnaryOpcode(unsigned Val, Type *Ty) {
bool IsFP = Ty->isFPOrFPVectorTy();
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 1e9058b9939b7..4a3d19cdc5adb 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -639,6 +639,7 @@ class IndexBitcodeWriter : public BitcodeWriterBase {
} // end anonymous namespace
+// clang-format off
static unsigned getEncodedCastOpcode(unsigned Opcode) {
switch (Opcode) {
default: llvm_unreachable("Unknown cast instruction!");
@@ -655,9 +656,11 @@ static unsigned getEncodedCastOpcode(unsigned Opcode) {
case Instruction::PtrToInt: return bitc::CAST_PTRTOINT;
case Instruction::IntToPtr: return bitc::CAST_INTTOPTR;
case Instruction::BitCast : return bitc::CAST_BITCAST;
+ case Instruction::ByteCast: return bitc::CAST_BYTECAST;
case Instruction::AddrSpaceCast: return bitc::CAST_ADDRSPACECAST;
}
}
+// clang-format on
static unsigned getEncodedUnaryOpcode(unsigned Opcode) {
switch (Opcode) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 2cbf2ae8105b7..5d97b7e73c673 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4132,6 +4132,27 @@ void SelectionDAGBuilder::visitAddrSpaceCast(const User &I) {
setValue(&I, N);
}
+void SelectionDAGBuilder::visitByteCast(const User &I) {
+ SDValue N = getValue(I.getOperand(0));
+ SDLoc dl = getCurSDLoc();
+ EVT DestVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
+ I.getType());
+
+ if (DestVT != N.getValueType())
+ // Convert vector types.
+ setValue(&I, DAG.getNode(ISD::BITCAST, dl, DestVT, N));
+ // Check if the original LLVM IR Operand was a ConstantByte, because
+ // getValue() might fold any kind of constant expression to an byte constant
+ // and that is not what we are looking for. Only recognize a bytecast of a
+ // genuine constant byte as an opaque constant.
+ else if (ConstantByte *C = dyn_cast<ConstantByte>(I.getOperand(0)))
+ setValue(&I, DAG.getConstant(C->getValue(), dl, DestVT, /*isTarget=*/false,
+ /*isOpaque*/ true));
+ else
+ // No-op cast.
+ setValue(&I, N);
+}
+
void SelectionDAGBuilder::visitInsertElement(const User &I) {
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
SDValue InVec = getValue(I.getOperand(0));
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index f8aecea25b3d6..ab8368e705e8b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -602,6 +602,7 @@ class SelectionDAGBuilder {
void visitIntToPtr(const User &I);
void visitBitCast(const User &I);
void visitAddrSpaceCast(const User &I);
+ void visitByteCast(const User &I);
void visitExtractElement(const User &I);
void visitInsertElement(const User &I);
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 922b3fa40518d..839e3c962b053 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -2163,6 +2163,7 @@ unsigned TargetLoweringBase::getMaxStoresPerMemmove(bool OptSize) const {
// TargetTransformInfo Helpers
//===----------------------------------------------------------------------===//
+// clang-format off
int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
enum InstructionOpcodes {
#define HANDLE_INST(NUM, OPCODE, CLASS) OPCODE = NUM,
@@ -2222,6 +2223,7 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
case PtrToInt: return ISD::BITCAST;
case IntToPtr: return ISD::BITCAST;
case BitCast: return ISD::BITCAST;
+ case ByteCast: return ISD::BITCAST;
case AddrSpaceCast: return ISD::ADDRSPACECAST;
case ICmp: return ISD::SETCC;
case FCmp: return ISD::SETCC;
@@ -2242,6 +2244,7 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
llvm_unreachable("Unknown instruction type encountered!");
}
+// clang-format on
int TargetLoweringBase::IntrinsicIDToISD(Intrinsic::ID ID) const {
switch (ID) {
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 9f7342a7bc83b..06f312434003f 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -1795,6 +1795,7 @@ Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty,
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
+ case Instruction::ByteCast:
case Instruction::AddrSpaceCast:
return ConstantExpr::getCast(getOpcode(), Ops[0], Ty, OnlyIfReduced);
case Instruction::InsertElement:
@@ -2478,6 +2479,8 @@ Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty,
return getIntToPtr(C, Ty, OnlyIfReduced);
case Instruction::BitCast:
return getBitCast(C, Ty, OnlyIfReduced);
+ case Instruction::ByteCast:
+ return getByteCast(C, Ty, OnlyIfReduced);
case Instruction::AddrSpaceCast:
return getAddrSpaceCast(C, Ty, OnlyIfReduced);
}
@@ -2583,6 +2586,13 @@ Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy,
return getFoldedCast(Instruction::BitCast, C, DstTy, OnlyIfReduced);
}
+Constant *ConstantExpr::getByteCast(Constant *C, Type *DstTy,
+ bool OnlyIfReduced) {
+ assert(CastInst::castIsValid(Instruction::ByteCast, C, DstTy) &&
+ "Invalid constantexpr bitcast!");
+ return getFoldedCast(Instruction::ByteCast, C, DstTy, OnlyIfReduced);
+}
+
Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy,
bool OnlyIfReduced) {
assert(CastInst::castIsValid(Instruction::AddrSpaceCast, C, DstTy) &&
@@ -2702,6 +2712,7 @@ bool ConstantExpr::isDesirableCastOp(unsigned Opcode) {
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
+ case Instruction::ByteCast:
case Instruction::AddrSpaceCast:
return true;
default:
@@ -2725,6 +2736,7 @@ bool ConstantExpr::isSupportedCastOp(unsigned Opcode) {
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
+ case Instruction::ByteCast:
case Instruction::AddrSpaceCast:
return true;
default:
@@ -3777,6 +3789,7 @@ Instruction *ConstantExpr::getAsInstruction() const {
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
+ case Instruction::ByteCast:
case Instruction::AddrSpaceCast:
return CastInst::Create((Instruction::CastOps)getOpcode(), Ops[0],
getType(), "");
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 0fd832ac5c99e..d1414469091ed 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -4351,6 +4351,11 @@ LLVMValueRef LLVMBuildAddrSpaceCast(LLVMBuilderRef B, LLVMValueRef Val,
return wrap(unwrap(B)->CreateAddrSpaceCast(unwrap(Val), unwrap(DestTy), Name));
}
+LLVMValueRef LLVMBuildByteCast(LLVMBuilderRef B, LLVMValueRef Val,
+ LLVMTypeRef DestTy, const char *Name) {
+ return wrap(unwrap(B)->CreateByteCast(unwrap(Val), unwrap(DestTy), Name));
+}
+
LLVMValueRef LLVMBuildZExtOrBitCast(LLVMBuilderRef B, LLVMValueRef Val,
LLVMTypeRef DestTy, const char *Name) {
return wrap(unwrap(B)->CreateZExtOrBitCast(unwrap(Val), unwrap(DestTy),
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index 3c35c656dca84..1a88891e2634d 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -791,6 +791,7 @@ void Instruction::andIRFlags(const Value *V) {
DestICmp->setSameSign(DestICmp->hasSameSign() && SrcICmp->hasSameSign());
}
+// clang-format off
const char *Instruction::getOpcodeName(unsigned OpCode) {
switch (OpCode) {
// Terminators
@@ -853,6 +854,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case PtrToInt: return "ptrtoint";
case BitCast: return "bitcast";
case AddrSpaceCast: return "addrspacecast";
+ case ByteCast: return "bytecast";
// Other instructions...
case ICmp: return "icmp";
@@ -876,6 +878,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
default: return "<Invalid operator> ";
}
}
+// clang-format on
/// This must be kept in sync with FunctionComparator::cmpOperations in
/// lib/Transforms/Utils/FunctionComparator.cpp.
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index c57e56cf5c095..b61cf86e6834b 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -2791,6 +2791,7 @@ bool CastInst::isNoopCast(Instruction::CastOps Opcode,
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
+ case Instruction::ByteCast:
case Instruction::AddrSpaceCast:
// TODO: Target informations may give a more accurate answer here.
return false;
@@ -2822,7 +2823,7 @@ unsigned CastInst::isEliminableCastPair(Instruction::CastOps firstOp,
Instruction::CastOps secondOp,
Type *SrcTy, Type *MidTy, Type *DstTy,
const DataLayout *DL) {
- // Define the 144 possibilities for these two cast instructions. The values
+ // Define the 225 possibilities for these two cast instructions. The values
// in this matrix determine what to do in a given situation and select the
// case in the switch below. The rows correspond to firstOp, the columns
// correspond to secondOp. In looking at the table below, keep in mind
@@ -2845,6 +2846,7 @@ unsigned CastInst::isEliminableCastPair(Instruction::CastOps firstOp,
// INTTOPTR n/a Integral Unsigned Pointer n/a
// BITCAST = FirstClass n/a FirstClass n/a
// ADDRSPCST n/a Pointer n/a Pointer n/a
+ // BYTECAST = Byte Unsigned FirstClass n/a
//
// NOTE: some transforms are safe, but we consider them to be non-profitable.
// For example, we could merge "fptoui double to i32" + "zext i32 to i64",
@@ -2857,25 +2859,26 @@ unsigned CastInst::isEliminableCastPair(Instruction::CastOps firstOp,
Instruction::CastOpsEnd - Instruction::CastOpsBegin;
// clang-format off
static const uint8_t CastResults[numCastOps][numCastOps] = {
- // T F F U S F F P P I B A -+
- // R Z S P P I I T P 2 2 N T S |
- // U E E 2 2 2 2 R E I A T C C +- secondOp
- // N X X U S F F N X N D 2 V V |
- // C T T I I P P C T T R P T T -+
- { 1, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // Trunc -+
- { 8, 1, 9,99,99, 2,17,99,99,99,99, 2, 3, 0}, // ZExt |
- { 8, 0, 1,99,99, 0, 2,99,99,99,99, 0, 3, 0}, // SExt |
- { 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // FPToUI |
- { 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // FPToSI |
- { 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0}, // UIToFP +- firstOp
- { 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0}, // SIToFP |
- { 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0}, // FPTrunc |
- { 99,99,99, 2, 2,99,99, 8, 2,99,99,99, 4, 0}, // FPExt |
- { 1, 0, 0,99,99, 0, 0,99,99,99,99, 7, 3, 0}, // PtrToInt |
- { 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // PtrToAddr |
- { 99,99,99,99,99,99,99,99,99,11,11,99,15, 0}, // IntToPtr |
- { 5, 5, 5, 0, 0, 5, 5, 0, 0,16,16, 5, 1,14}, // BitCast |
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,13,12}, // AddrSpaceCast -+
+ // T F F U S F F P P I B A B -+
+ // R Z S P P I I T P 2 2 N T S Y |
+ // U E E 2 2 2 2 R E I A T C C T +- secondOp
+ // N X X U S F F N X N D 2 V V C |
+ // C T T I I P P C T T R P T T T -+
+ { 1, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0, 0}, // Trunc -+
+ { 8, 1, 9,99,99, 2,17,99,99,99,99, 2, 3, 0, 0}, // ZExt |
+ { 8, 0, 1,99,99, 0, 2,99,99,99,99, 0, 3, 0, 0}, // SExt |
+ { 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0, 0}, // FPToUI |
+ { 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0, 0}, // FPToSI |
+ { 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0, 0}, // UIToFP +- firstOp
+ { 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0, 0}, // SIToFP |
+ { 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0, 0}, // FPTrunc |
+ { 99,99,99, 2, 2,99,99, 8, 2,99,99,99, 4, 0, 0}, // FPExt |
+ { 1, 0, 0,99,99, 0, 0,99,99,99,99, 7, 3, 0, 0}, // PtrToInt |
+ { 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0, 0}, // PtrToAddr |
+ { 99,99,99,99,99,99,99,99,99,11,11,99,15, 0, 0}, // IntToPtr |
+ { 5, 5, 5, 0, 0, 5, 5, 0, 0,16,16, 5, 1,14, 0}, // BitCast |
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,13,12, 0}, // AddrSpaceCast -+
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,99}, // ByteCast -+
};
// clang-format on
@@ -3056,6 +3059,8 @@ CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
return new BitCastInst(S, Ty, Name, InsertBefore);
case AddrSpaceCast:
return new AddrSpaceCastInst(S, Ty, Name, InsertBefore);
+ case ByteCast:
+ return new ByteCastInst(S, Ty, Name, InsertBefore);
default:
llvm_unreachable("Invalid opcode provided");
}
@@ -3249,8 +3254,12 @@ CastInst::getCastOpcode(
return BitCast;
}
llvm_unreachable("Illegal cast to byte type");
- } else if (DestTy->isIntegerTy()) { // Casting to integral
- if (SrcTy->isIntegerTy()) { // Casting from integral
+ } else if (DestTy->isIntegerTy()) {
+ if (SrcTy->isByteTy()) { // Casting from byte
+ assert(DestBits == SrcBits &&
+ "Casting byte to integer of different width");
+ return ByteCast;
+ } else if (SrcTy->isIntegerTy()) { // Casting from integral
if (DestBits < SrcBits)
return Trunc; // int -> smaller int
else if (DestBits > SrcBits) { // its an extension
@@ -3261,7 +3270,7 @@ CastInst::getCastOpcode(
} else {
return BitCast; // Same size, No-op cast
}
- } else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt
+ } else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt
if (DestIsSigned)
return FPToSI; // FP -> sint
else
@@ -3289,12 +3298,16 @@ CastInst::getCastOpcode(
} else {
return BitCast; // same size, no-op cast
}
+ } else if (SrcTy->isByteTy()) {
+ assert(DestBits == SrcBits &&
+ "Casting byte to floating point of different width");
+ return ByteCast;
} else if (SrcTy->isVectorTy()) {
assert(DestBits == SrcBits &&
"Casting vector to floating point of different width");
return BitCast; // same size, no-op cast
}
- llvm_unreachable("Casting pointer or non-first class to float");
+ llvm_unreachable("Casting pointer or non-first class to float or byte");
} else if (DestTy->isVectorTy()) {
assert(DestBits == SrcBits &&
"Illegal cast to vector (wrong type or size)");
@@ -3306,8 +3319,11 @@ CastInst::getCastOpcode(
return BitCast; // ptr -> ptr
} else if (SrcTy->isIntegerTy()) {
return IntToPtr; // int -> ptr
+ } else if (SrcTy->isByteTy()) {
+ assert(SrcBits <= 64 && "Casting byte to pointer of greater width");
+ return ByteCast; // byte -> ptr
}
- llvm_unreachable("Casting pointer to other than pointer or int");
+ llvm_unreachable("Casting pointer to other than pointer, int or byte");
}
llvm_unreachable("Casting to type that is not first-class");
}
@@ -3414,6 +3430,18 @@ CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
return true;
}
+ case Instruction::ByteCast: {
+ if (!SrcTy->isByteOrByteVectorTy())
+ return false;
+ if (DstTy->isByteOrByteVectorTy())
+ return false;
+
+ PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
+ if (!DstPtrTy)
+ return SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits();
+
+ return true;
+ }
case Instruction::AddrSpaceCast: {
PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
if (!SrcPtrTy)
@@ -3515,6 +3543,12 @@ AddrSpaceCastInst::AddrSpaceCastInst(Value *S, Type *Ty, const Twine &Name,
assert(castIsValid(getOpcode(), S, Ty) && "Illegal AddrSpaceCast");
}
+ByteCastInst::ByteCastInst(Value *S, Type *Ty, const Twine &Name,
+ InsertPosition InsertBefore)
+ : CastInst(Ty, ByteCast, S, Name, InsertBefore) {
+ assert(castIsValid(getOpcode(), S, Ty) && "Illegal ByteCast");
+}
+
//===----------------------------------------------------------------------===//
// CmpInst Classes
//===----------------------------------------------------------------------===//
@@ -4476,6 +4510,10 @@ AddrSpaceCastInst *AddrSpaceCastInst::cloneImpl() const {
return new AddrSpaceCastInst(getOperand(0), getType());
}
+ByteCastInst *ByteCastInst::cloneImpl() const {
+ return new ByteCastInst(getOperand(0), getType());
+}
+
CallInst *CallInst::cloneImpl() const {
if (hasOperandBundles()) {
IntrusiveOperandsAndDescriptorAllocMarker AllocMarker{
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index a9962aed295b0..a7f1dd006768e 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -579,6 +579,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
void visitPtrToIntInst(PtrToIntInst &I);
void visitBitCastInst(BitCastInst &I);
void visitAddrSpaceCastInst(AddrSpaceCastInst &I);
+ void visitByteCastInst(ByteCastInst &I);
void visitPHINode(PHINode &PN);
void visitCallBase(CallBase &Call);
void visitUnaryOperator(UnaryOperator &U);
@@ -3811,6 +3812,13 @@ void Verifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) {
visitInstruction(I);
}
+void Verifier::visitByteCastInst(ByteCastInst &I) {
+ Check(CastInst::castIsValid(Instruction::ByteCast, I.getOperand(0),
+ I.getType()),
+ "Invalid bytecast", &I);
+ visitInstruction(I);
+}
+
/// visitPHINode - Ensure that a PHI node is well formed.
///
void Verifier::visitPHINode(PHINode &PN) {
diff --git a/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt b/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
index 12d1567466b1b..cec613f2a5c5c 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
@@ -49,6 +49,7 @@ Key: PtrToAddr: [ 135.00 136.00 ]
Key: IntToPtr: [ 95.00 96.00 ]
Key: BitCast: [ 97.00 98.00 ]
Key: AddrSpaceCast: [ 99.00 100.00 ]
+Key: ByteCast: [ 0.00 0.00 ]
Key: CleanupPad: [ 101.00 102.00 ]
Key: CatchPad: [ 103.00 104.00 ]
Key: ICmp: [ 105.00 106.00 ]
diff --git a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
index cb775622dc722..c49a11caa3fa0 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
@@ -49,6 +49,7 @@ Key: PtrToAddr: [ 67.50 68.00 ]
Key: IntToPtr: [ 47.50 48.00 ]
Key: BitCast: [ 48.50 49.00 ]
Key: AddrSpaceCast: [ 49.50 50.00 ]
+Key: ByteCast: [ 0.00 0.00 ]
Key: CleanupPad: [ 50.50 51.00 ]
Key: CatchPad: [ 51.50 52.00 ]
Key: ICmp: [ 52.50 53.00 ]
diff --git a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
index cafc8eb1b7e23..632f1440dde61 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
@@ -49,6 +49,7 @@ Key: PtrToAddr: [ 13.50 13.60 ]
Key: IntToPtr: [ 9.50 9.60 ]
Key: BitCast: [ 9.70 9.80 ]
Key: AddrSpaceCast: [ 9.90 10.00 ]
+Key: ByteCast: [ 0.00 0.00 ]
Key: CleanupPad: [ 10.10 10.20 ]
Key: CatchPad: [ 10.30 10.40 ]
Key: ICmp: [ 10.50 10.60 ]
diff --git a/llvm/test/Assembler/byte-invalid-cast-10.ll b/llvm/test/Assembler/byte-invalid-cast-10.ll
new file mode 100644
index 0000000000000..9daadb4eed49e
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-10.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'b8' to 'b8'
+define void @invalid_bytcast(b8 %b) {
+ %t = bytecast b8 %b to b8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-8.ll b/llvm/test/Assembler/byte-invalid-cast-8.ll
new file mode 100644
index 0000000000000..904fa3de2a9f5
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-8.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from 'i8' to 'b8'
+define void @invalid_bytcast(i8 %b) {
+ %t = bytecast i8 %b to b8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-9.ll b/llvm/test/Assembler/byte-invalid-cast-9.ll
new file mode 100644
index 0000000000000..cbe36638884ba
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-9.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: invalid cast opcode for cast from '<4 x b32>' to '<6 x i16>'
+define void @invalid_bytcast(<4 x b32> %b) {
+ %t = bytecast <4 x b32> %b to <6 x i16>
+ ret void
+}
diff --git a/llvm/test/Assembler/byte.ll b/llvm/test/Assembler/byte.ll
index d62d6cd9b5fc3..671d2ca0ecb8c 100644
--- a/llvm/test/Assembler/byte.ll
+++ b/llvm/test/Assembler/byte.ll
@@ -77,3 +77,51 @@ define void @bitcasts(i64 %i, b64 %b, ptr %p) {
%6 = bitcast <2 x b32> <b32 1, b32 1> to b64
ret void
}
+
+define void @bytecasts(b8 %b1, b16 %b2, b32 %b3, b64 %b4, b128 %b5) {
+; CHECK-LABEL: define void @bytecasts(
+; CHECK-SAME: b8 [[B1:%.*]], b16 [[B2:%.*]], b32 [[B3:%.*]], b64 [[B4:%.*]], b128 [[B5:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = bytecast b8 [[B1]] to i8
+; CHECK-NEXT: [[TMP2:%.*]] = bytecast b16 [[B2]] to i16
+; CHECK-NEXT: [[TMP3:%.*]] = bytecast b32 [[B3]] to i32
+; CHECK-NEXT: [[TMP4:%.*]] = bytecast b64 [[B4]] to i64
+; CHECK-NEXT: [[TMP5:%.*]] = bytecast b64 [[B4]] to ptr
+; CHECK-NEXT: [[TMP6:%.*]] = bytecast b16 [[B2]] to half
+; CHECK-NEXT: [[TMP7:%.*]] = bytecast b32 [[B3]] to float
+; CHECK-NEXT: [[TMP8:%.*]] = bytecast b64 [[B4]] to double
+; CHECK-NEXT: ret void
+;
+ %1 = bytecast b8 %b1 to i8
+ %2 = bytecast b16 %b2 to i16
+ %3 = bytecast b32 %b3 to i32
+ %4 = bytecast b64 %b4 to i64
+ %5 = bytecast b64 %b4 to ptr
+ %6 = bytecast b16 %b2 to half
+ %7 = bytecast b32 %b3 to float
+ %8 = bytecast b64 %b4 to double
+ ret void
+}
+
+define void @vector_bytecasts(<2 x b64> %b1, <2 x b128> %b2, b64 %b3) {
+; CHECK-LABEL: define void @vector_bytecasts(
+; CHECK-SAME: <2 x b64> [[B1:%.*]], <2 x b128> [[B2:%.*]], b64 [[B3:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = bytecast <2 x b64> [[B1]] to <2 x i64>
+; CHECK-NEXT: [[TMP2:%.*]] = bytecast <2 x b64> [[B1]] to <2 x double>
+; CHECK-NEXT: [[TMP3:%.*]] = bytecast <2 x b64> [[B1]] to <2 x ptr>
+; CHECK-NEXT: [[TMP4:%.*]] = bytecast b64 [[B3]] to <2 x i32>
+; CHECK-NEXT: [[TMP5:%.*]] = bytecast b64 [[B3]] to <1 x ptr>
+; CHECK-NEXT: [[TMP6:%.*]] = bytecast <2 x b64> [[B1]] to i128
+; CHECK-NEXT: [[TMP7:%.*]] = bytecast <2 x b64> [[B1]] to <4 x i32>
+; CHECK-NEXT: [[TMP8:%.*]] = bytecast <2 x b128> [[B2]] to <4 x ptr>
+; CHECK-NEXT: ret void
+;
+ %1 = bytecast <2 x b64> %b1 to <2 x i64>
+ %2 = bytecast <2 x b64> %b1 to <2 x double>
+ %3 = bytecast <2 x b64> %b1 to <2 x ptr>
+ %4 = bytecast b64 %b3 to <2 x i32>
+ %5 = bytecast b64 %b3 to <1 x ptr>
+ %6 = bytecast <2 x b64> %b1 to i128
+ %7 = bytecast <2 x b64> %b1 to <4 x i32>
+ %8 = bytecast <2 x b128> %b2 to <4 x ptr>
+ ret void
+}
diff --git a/llvm/test/Bindings/llvm-c/byte.ll b/llvm/test/Bindings/llvm-c/byte.ll
index 93b9819c3c9b9..ac7217fb0ab54 100644
--- a/llvm/test/Bindings/llvm-c/byte.ll
+++ b/llvm/test/Bindings/llvm-c/byte.ll
@@ -7,5 +7,6 @@ define void @foo(b8 %a, b16 %b, b64 %c) {
store b16 %b, ptr %1, align 2
%2 = load b16, ptr %1, align 2
%3 = bitcast b16 %2 to <2 x b8>
+ %4 = bytecast <2 x b8> %3 to <2 x i8>
ret void
}
diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index 1510d6275c56f..0a93de3a3e81a 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -1646,6 +1646,10 @@ define void @instructions.conversions() {
; CHECK: bitcast i32 0 to i32
addrspacecast ptr null to ptr addrspace(1)
; CHECK: addrspacecast ptr null to ptr addrspace(1)
+ %im = bitcast i32 0 to b32
+ ; CHECK: bitcast i32 0 to b32
+ bytecast b32 %im to i32
+ ; CHECK: bytecast b32 %{{.*}} to i32
ret void
}
diff --git a/llvm/test/Transforms/IRNormalizer/regression-convergence-tokens.ll b/llvm/test/Transforms/IRNormalizer/regression-convergence-tokens.ll
index 0c2db4a2862b2..2db29cdc1db2a 100644
--- a/llvm/test/Transforms/IRNormalizer/regression-convergence-tokens.ll
+++ b/llvm/test/Transforms/IRNormalizer/regression-convergence-tokens.ll
@@ -7,9 +7,9 @@ define i32 @nested(i32 %src) #0 {
; CHECK-SAME: i32 [[A0:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[BB15160:.*:]]
; CHECK-NEXT: [[T1:%.*]] = call token @llvm.experimental.convergence.entry()
-; CHECK-NEXT: %"vl14659llvm.experimental.convergence.anchor()" = call token @llvm.experimental.convergence.anchor()
-; CHECK-NEXT: %"op15516(vl14659)" = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[A0]]) [ "convergencectrl"(token %"vl14659llvm.experimental.convergence.anchor()") ]
-; CHECK-NEXT: ret i32 %"op15516(vl14659)"
+; CHECK-NEXT: %"vl55087llvm.experimental.convergence.anchor()" = call token @llvm.experimental.convergence.anchor()
+; CHECK-NEXT: %"op11958(vl55087)" = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[A0]]) [ "convergencectrl"(token %"vl55087llvm.experimental.convergence.anchor()") ]
+; CHECK-NEXT: ret i32 %"op11958(vl55087)"
;
%t1 = call token @llvm.experimental.convergence.entry()
%t2 = call token @llvm.experimental.convergence.anchor()
diff --git a/llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll b/llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll
index b9be105bcda48..686fc46e6db2b 100644
--- a/llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll
+++ b/llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll
@@ -8,18 +8,18 @@ define void @test(ptr, i32) {
; CHECK-NEXT: %"vl72693([[A1]], 1)" = add i32 [[A1]], 1
; CHECK-NEXT: br label %[[BB16110:.*]]
; CHECK: [[BB16110]]:
-; CHECK-NEXT: %"op81283(op18080, vl72693)" = phi i32 [ %"op18080(op10412, op18131)", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
-; CHECK-NEXT: %"op81283(op18131, vl72693)" = phi i32 [ %"op18131(op81283)70", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
-; CHECK-NEXT: %"op13219(op81283)" = mul i32 %"op81283(op18080, vl72693)", undef
-; CHECK-NEXT: %"op16562(op13219)" = xor i32 -1, %"op13219(op81283)"
-; CHECK-NEXT: %"op12556(op16562, op81283)" = add i32 %"op16562(op13219)", %"op81283(op18080, vl72693)"
-; CHECK-NEXT: %"op18131(op81283)" = add i32 -1, %"op81283(op18131, vl72693)"
-; CHECK-NEXT: %"op18080(op12556, op18131)" = add i32 %"op12556(op16562, op81283)", %"op18131(op81283)"
-; CHECK-NEXT: %"op17720(op13219, op18080)" = mul i32 %"op13219(op81283)", %"op18080(op12556, op18131)"
-; CHECK-NEXT: %"op16562(op17720)" = xor i32 -1, %"op17720(op13219, op18080)"
-; CHECK-NEXT: %"op17430(op16562, op18080)" = add i32 %"op16562(op17720)", %"op18080(op12556, op18131)"
+; CHECK-NEXT: %"op26813(op18080, vl72693)" = phi i32 [ %"op18080(op10412, op11773)", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
+; CHECK-NEXT: %"op26813(op11773, vl72693)" = phi i32 [ %"op11773(op26813)70", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
+; CHECK-NEXT: %"op71272(op26813)" = mul i32 %"op26813(op18080, vl72693)", undef
+; CHECK-NEXT: %"op16562(op71272)" = xor i32 -1, %"op71272(op26813)"
+; CHECK-NEXT: %"op75661(op16562, op26813)" = add i32 %"op16562(op71272)", %"op26813(op18080, vl72693)"
+; CHECK-NEXT: %"op11773(op26813)" = add i32 -1, %"op26813(op11773, vl72693)"
+; CHECK-NEXT: %"op18080(op11773, op75661)" = add i32 %"op11773(op26813)", %"op75661(op16562, op26813)"
+; CHECK-NEXT: %"op17720(op18080, op71272)" = mul i32 %"op18080(op11773, op75661)", %"op71272(op26813)"
+; CHECK-NEXT: %"op16562(op17720)" = xor i32 -1, %"op17720(op18080, op71272)"
+; CHECK-NEXT: %"op17430(op16562, op18080)" = add i32 %"op16562(op17720)", %"op18080(op11773, op75661)"
; CHECK-NEXT: %"op10412(op17430)" = add i32 %"op17430(op16562, op18080)", undef
-; CHECK-NEXT: %"op17720(op10412, op17720)" = mul i32 %"op10412(op17430)", %"op17720(op13219, op18080)"
+; CHECK-NEXT: %"op17720(op10412, op17720)" = mul i32 %"op10412(op17430)", %"op17720(op18080, op71272)"
; CHECK-NEXT: %"op16562(op17720)1" = xor i32 -1, %"op17720(op10412, op17720)"
; CHECK-NEXT: %"op17430(op10412, op16562)" = add i32 %"op10412(op17430)", %"op16562(op17720)1"
; CHECK-NEXT: %"op10412(op17430)2" = add i32 %"op17430(op10412, op16562)", undef
@@ -45,11 +45,11 @@ define void @test(ptr, i32) {
; CHECK-NEXT: %"op17720(op10412, op17720)21" = mul i32 %"op10412(op17430)20", %"op17720(op10412, op17720)17"
; CHECK-NEXT: %"op16562(op17720)22" = xor i32 -1, %"op17720(op10412, op17720)21"
; CHECK-NEXT: %"op17430(op10412, op16562)23" = add i32 %"op10412(op17430)20", %"op16562(op17720)22"
-; CHECK-NEXT: %"op18131(op81283)24" = add i32 -9, %"op81283(op18131, vl72693)"
-; CHECK-NEXT: %"op18080(op17430, op18131)" = add i32 %"op17430(op10412, op16562)23", %"op18131(op81283)24"
-; CHECK-NEXT: %"op17720(op17720, op18080)" = mul i32 %"op17720(op10412, op17720)21", %"op18080(op17430, op18131)"
+; CHECK-NEXT: %"op11773(op26813)24" = add i32 -9, %"op26813(op11773, vl72693)"
+; CHECK-NEXT: %"op18080(op11773, op17430)" = add i32 %"op11773(op26813)24", %"op17430(op10412, op16562)23"
+; CHECK-NEXT: %"op17720(op17720, op18080)" = mul i32 %"op17720(op10412, op17720)21", %"op18080(op11773, op17430)"
; CHECK-NEXT: %"op16562(op17720)25" = xor i32 -1, %"op17720(op17720, op18080)"
-; CHECK-NEXT: %"op17430(op16562, op18080)26" = add i32 %"op16562(op17720)25", %"op18080(op17430, op18131)"
+; CHECK-NEXT: %"op17430(op16562, op18080)26" = add i32 %"op16562(op17720)25", %"op18080(op11773, op17430)"
; CHECK-NEXT: %"op10412(op17430)27" = add i32 %"op17430(op16562, op18080)26", undef
; CHECK-NEXT: %"op17720(op10412, op17720)28" = mul i32 %"op10412(op17430)27", %"op17720(op17720, op18080)"
; CHECK-NEXT: %"op16562(op17720)29" = xor i32 -1, %"op17720(op10412, op17720)28"
@@ -66,11 +66,11 @@ define void @test(ptr, i32) {
; CHECK-NEXT: %"op17720(op10412, op17720)40" = mul i32 %"op10412(op17430)39", %"op17720(op10412, op17720)36"
; CHECK-NEXT: %"op16562(op17720)41" = xor i32 -1, %"op17720(op10412, op17720)40"
; CHECK-NEXT: %"op17430(op10412, op16562)42" = add i32 %"op10412(op17430)39", %"op16562(op17720)41"
-; CHECK-NEXT: %"op18131(op81283)43" = add i32 -14, %"op81283(op18131, vl72693)"
-; CHECK-NEXT: %"op18080(op17430, op18131)44" = add i32 %"op17430(op10412, op16562)42", %"op18131(op81283)43"
-; CHECK-NEXT: %"op17720(op17720, op18080)45" = mul i32 %"op17720(op10412, op17720)40", %"op18080(op17430, op18131)44"
+; CHECK-NEXT: %"op11773(op26813)43" = add i32 -14, %"op26813(op11773, vl72693)"
+; CHECK-NEXT: %"op18080(op11773, op17430)44" = add i32 %"op11773(op26813)43", %"op17430(op10412, op16562)42"
+; CHECK-NEXT: %"op17720(op17720, op18080)45" = mul i32 %"op17720(op10412, op17720)40", %"op18080(op11773, op17430)44"
; CHECK-NEXT: %"op16562(op17720)46" = xor i32 -1, %"op17720(op17720, op18080)45"
-; CHECK-NEXT: %"op17430(op16562, op18080)47" = add i32 %"op16562(op17720)46", %"op18080(op17430, op18131)44"
+; CHECK-NEXT: %"op17430(op16562, op18080)47" = add i32 %"op16562(op17720)46", %"op18080(op11773, op17430)44"
; CHECK-NEXT: %"op10412(op17430)48" = add i32 %"op17430(op16562, op18080)47", undef
; CHECK-NEXT: %"op17720(op10412, op17720)49" = mul i32 %"op10412(op17430)48", %"op17720(op17720, op18080)45"
; CHECK-NEXT: %"op16562(op17720)50" = xor i32 -1, %"op17720(op10412, op17720)49"
@@ -93,9 +93,9 @@ define void @test(ptr, i32) {
; CHECK-NEXT: %"op17430(op10412, op16562)67" = add i32 %"op10412(op17430)64", %"op16562(op17720)66"
; CHECK-NEXT: %"op10412(op17430)68" = add i32 %"op17430(op10412, op16562)67", undef
; CHECK-NEXT: %"op10412(op10412)69" = add i32 %"op10412(op17430)68", undef
-; CHECK-NEXT: %"op18131(op81283)70" = add i32 -21, %"op81283(op18131, vl72693)"
-; CHECK-NEXT: %"op18080(op10412, op18131)" = add i32 %"op10412(op10412)69", %"op18131(op81283)70"
-; CHECK-NEXT: store i32 %"op18080(op10412, op18131)", ptr [[A0]], align 4
+; CHECK-NEXT: %"op11773(op26813)70" = add i32 -21, %"op26813(op11773, vl72693)"
+; CHECK-NEXT: %"op18080(op10412, op11773)" = add i32 %"op10412(op10412)69", %"op11773(op26813)70"
+; CHECK-NEXT: store i32 %"op18080(op10412, op11773)", ptr [[A0]], align 4
; CHECK-NEXT: br label %[[BB16110]]
;
bb:
diff --git a/llvm/test/Transforms/IRNormalizer/reordering-basic.ll b/llvm/test/Transforms/IRNormalizer/reordering-basic.ll
index 06e67e0feb7e4..87cd59f5c8c70 100644
--- a/llvm/test/Transforms/IRNormalizer/reordering-basic.ll
+++ b/llvm/test/Transforms/IRNormalizer/reordering-basic.ll
@@ -28,16 +28,16 @@ define double @baz(double %x) {
; CHECK-SAME: double [[A0:%.*]]) {
; CHECK-NEXT: [[BB76951:.*:]]
; CHECK-NEXT: [[IFCOND:%.*]] = fcmp one double [[A0]], 0.000000e+00
-; CHECK-NEXT: br i1 [[IFCOND]], label %[[BB47054:.*]], label %[[BB470541:.*]]
-; CHECK: [[BB47054]]:
-; CHECK-NEXT: %"vl16994bir()" = call double @bir()
+; CHECK-NEXT: br i1 [[IFCOND]], label %[[BB57091:.*]], label %[[BB570911:.*]]
+; CHECK: [[BB57091]]:
+; CHECK-NEXT: %"vl12417bir()" = call double @bir()
; CHECK-NEXT: br label %[[BB17254:.*]]
-; CHECK: [[BB470541]]:
-; CHECK-NEXT: %"vl88592bar()" = call double @bar()
+; CHECK: [[BB570911]]:
+; CHECK-NEXT: %"vl26594bar()" = call double @bar()
; CHECK-NEXT: br label %[[BB17254]]
; CHECK: [[BB17254]]:
-; CHECK-NEXT: %"op16411(vl16994, vl88592)" = phi double [ %"vl16994bir()", %[[BB47054]] ], [ %"vl88592bar()", %[[BB470541]] ]
-; CHECK-NEXT: ret double %"op16411(vl16994, vl88592)"
+; CHECK-NEXT: %"op24395(vl12417, vl26594)" = phi double [ %"vl12417bir()", %[[BB57091]] ], [ %"vl26594bar()", %[[BB570911]] ]
+; CHECK-NEXT: ret double %"op24395(vl12417, vl26594)"
;
entry:
%ifcond = fcmp one double %x, 0.000000e+00
diff --git a/llvm/test/Transforms/IRNormalizer/reordering.ll b/llvm/test/Transforms/IRNormalizer/reordering.ll
index a3dbcb5494875..80ab28db62ba0 100644
--- a/llvm/test/Transforms/IRNormalizer/reordering.ll
+++ b/llvm/test/Transforms/IRNormalizer/reordering.ll
@@ -23,7 +23,7 @@ declare void @effecting()
; Place dead instruction(s) before the terminator
define void @call_effecting() {
; CHECK-LABEL: define void @call_effecting() {
-; CHECK-NEXT: bb14885:
+; CHECK-NEXT: bb72598:
; CHECK-NEXT: call void @effecting()
; CHECK-NEXT: [[TMP0:%.*]] = add i32 0, 1
; CHECK-NEXT: ret void
@@ -51,7 +51,7 @@ exit:
define void @dont_move_above_alloca() {
; CHECK-LABEL: define void @dont_move_above_alloca() {
-; CHECK-NEXT: bb14885:
+; CHECK-NEXT: bb72598:
; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
; CHECK-NEXT: call void @effecting()
; CHECK-NEXT: ret void
@@ -65,7 +65,7 @@ declare void @effecting1()
define void @dont_reorder_effecting() {
; CHECK-LABEL: define void @dont_reorder_effecting() {
-; CHECK-NEXT: bb45003:
+; CHECK-NEXT: bb86996:
; CHECK-NEXT: call void @effecting()
; CHECK-NEXT: call void @effecting1()
; CHECK-NEXT: ret void
@@ -79,7 +79,7 @@ declare void @effecting2(i32)
define void @dont_reorder_effecting1() {
; CHECK-LABEL: define void @dont_reorder_effecting1() {
-; CHECK-NEXT: bb45003:
+; CHECK-NEXT: bb86996:
; CHECK-NEXT: [[ONE:%.*]] = add i32 1, 1
; CHECK-NEXT: call void @effecting2(i32 [[ONE]])
; CHECK-NEXT: [[TWO:%.*]] = add i32 2, 2
diff --git a/llvm/test/tools/llvm-ir2vec/entities.ll b/llvm/test/tools/llvm-ir2vec/entities.ll
index 58c2d74036783..c2d416a1f8b7c 100644
--- a/llvm/test/tools/llvm-ir2vec/entities.ll
+++ b/llvm/test/tools/llvm-ir2vec/entities.ll
@@ -1,6 +1,6 @@
; RUN: llvm-ir2vec entities | FileCheck %s
-CHECK: 111
+CHECK: 112
CHECK-NEXT: Ret 0
CHECK-NEXT: Br 1
CHECK-NEXT: Switch 2
@@ -52,63 +52,64 @@ CHECK-NEXT: PtrToAddr 47
CHECK-NEXT: IntToPtr 48
CHECK-NEXT: BitCast 49
CHECK-NEXT: AddrSpaceCast 50
-CHECK-NEXT: CleanupPad 51
-CHECK-NEXT: CatchPad 52
-CHECK-NEXT: ICmp 53
-CHECK-NEXT: FCmp 54
-CHECK-NEXT: PHI 55
-CHECK-NEXT: Call 56
-CHECK-NEXT: Select 57
-CHECK-NEXT: UserOp1 58
-CHECK-NEXT: UserOp2 59
-CHECK-NEXT: VAArg 60
-CHECK-NEXT: ExtractElement 61
-CHECK-NEXT: InsertElement 62
-CHECK-NEXT: ShuffleVector 63
-CHECK-NEXT: ExtractValue 64
-CHECK-NEXT: InsertValue 65
-CHECK-NEXT: LandingPad 66
-CHECK-NEXT: Freeze 67
-CHECK-NEXT: FloatTy 68
-CHECK-NEXT: VoidTy 69
-CHECK-NEXT: LabelTy 70
-CHECK-NEXT: MetadataTy 71
-CHECK-NEXT: VectorTy 72
-CHECK-NEXT: TokenTy 73
-CHECK-NEXT: IntegerTy 74
-CHECK-NEXT: ByteTy 75
-CHECK-NEXT: FunctionTy 76
-CHECK-NEXT: PointerTy 77
-CHECK-NEXT: StructTy 78
-CHECK-NEXT: ArrayTy 79
-CHECK-NEXT: UnknownTy 80
-CHECK-NEXT: Function 81
-CHECK-NEXT: Pointer 82
-CHECK-NEXT: Constant 83
-CHECK-NEXT: Variable 84
-CHECK-NEXT: FCMP_false 85
-CHECK-NEXT: FCMP_oeq 86
-CHECK-NEXT: FCMP_ogt 87
-CHECK-NEXT: FCMP_oge 88
-CHECK-NEXT: FCMP_olt 89
-CHECK-NEXT: FCMP_ole 90
-CHECK-NEXT: FCMP_one 91
-CHECK-NEXT: FCMP_ord 92
-CHECK-NEXT: FCMP_uno 93
-CHECK-NEXT: FCMP_ueq 94
-CHECK-NEXT: FCMP_ugt 95
-CHECK-NEXT: FCMP_uge 96
-CHECK-NEXT: FCMP_ult 97
-CHECK-NEXT: FCMP_ule 98
-CHECK-NEXT: FCMP_une 99
-CHECK-NEXT: FCMP_true 100
-CHECK-NEXT: ICMP_eq 101
-CHECK-NEXT: ICMP_ne 102
-CHECK-NEXT: ICMP_ugt 103
-CHECK-NEXT: ICMP_uge 104
-CHECK-NEXT: ICMP_ult 105
-CHECK-NEXT: ICMP_ule 106
-CHECK-NEXT: ICMP_sgt 107
-CHECK-NEXT: ICMP_sge 108
-CHECK-NEXT: ICMP_slt 109
-CHECK-NEXT: ICMP_sle 110
+CHECK-NEXT: ByteCast 51
+CHECK-NEXT: CleanupPad 52
+CHECK-NEXT: CatchPad 53
+CHECK-NEXT: ICmp 54
+CHECK-NEXT: FCmp 55
+CHECK-NEXT: PHI 56
+CHECK-NEXT: Call 57
+CHECK-NEXT: Select 58
+CHECK-NEXT: UserOp1 59
+CHECK-NEXT: UserOp2 60
+CHECK-NEXT: VAArg 61
+CHECK-NEXT: ExtractElement 62
+CHECK-NEXT: InsertElement 63
+CHECK-NEXT: ShuffleVector 64
+CHECK-NEXT: ExtractValue 65
+CHECK-NEXT: InsertValue 66
+CHECK-NEXT: LandingPad 67
+CHECK-NEXT: Freeze 68
+CHECK-NEXT: FloatTy 69
+CHECK-NEXT: VoidTy 70
+CHECK-NEXT: LabelTy 71
+CHECK-NEXT: MetadataTy 72
+CHECK-NEXT: VectorTy 73
+CHECK-NEXT: TokenTy 74
+CHECK-NEXT: IntegerTy 75
+CHECK-NEXT: ByteTy 76
+CHECK-NEXT: FunctionTy 77
+CHECK-NEXT: PointerTy 78
+CHECK-NEXT: StructTy 79
+CHECK-NEXT: ArrayTy 80
+CHECK-NEXT: UnknownTy 81
+CHECK-NEXT: Function 82
+CHECK-NEXT: Pointer 83
+CHECK-NEXT: Constant 84
+CHECK-NEXT: Variable 85
+CHECK-NEXT: FCMP_false 86
+CHECK-NEXT: FCMP_oeq 87
+CHECK-NEXT: FCMP_ogt 88
+CHECK-NEXT: FCMP_oge 89
+CHECK-NEXT: FCMP_olt 90
+CHECK-NEXT: FCMP_ole 91
+CHECK-NEXT: FCMP_one 92
+CHECK-NEXT: FCMP_ord 93
+CHECK-NEXT: FCMP_uno 94
+CHECK-NEXT: FCMP_ueq 95
+CHECK-NEXT: FCMP_ugt 96
+CHECK-NEXT: FCMP_uge 97
+CHECK-NEXT: FCMP_ult 98
+CHECK-NEXT: FCMP_ule 99
+CHECK-NEXT: FCMP_une 100
+CHECK-NEXT: FCMP_true 101
+CHECK-NEXT: ICMP_eq 102
+CHECK-NEXT: ICMP_ne 103
+CHECK-NEXT: ICMP_ugt 104
+CHECK-NEXT: ICMP_uge 105
+CHECK-NEXT: ICMP_ult 106
+CHECK-NEXT: ICMP_ule 107
+CHECK-NEXT: ICMP_sgt 108
+CHECK-NEXT: ICMP_sge 109
+CHECK-NEXT: ICMP_slt 110
+CHECK-NEXT: ICMP_sle 111
diff --git a/llvm/test/tools/llvm-ir2vec/triplets.ll b/llvm/test/tools/llvm-ir2vec/triplets.ll
index 1a7220cc9c3c5..c34370a37e595 100644
--- a/llvm/test/tools/llvm-ir2vec/triplets.ll
+++ b/llvm/test/tools/llvm-ir2vec/triplets.ll
@@ -25,41 +25,41 @@ entry:
}
; TRIPLETS: MAX_RELATION=3
-; TRIPLETS-NEXT: 12 74 0
-; TRIPLETS-NEXT: 12 84 2
-; TRIPLETS-NEXT: 12 84 3
+; TRIPLETS-NEXT: 12 75 0
+; TRIPLETS-NEXT: 12 85 2
+; TRIPLETS-NEXT: 12 85 3
; TRIPLETS-NEXT: 12 0 1
-; TRIPLETS-NEXT: 0 69 0
-; TRIPLETS-NEXT: 0 84 2
-; TRIPLETS-NEXT: 16 74 0
-; TRIPLETS-NEXT: 16 84 2
-; TRIPLETS-NEXT: 16 84 3
+; TRIPLETS-NEXT: 0 70 0
+; TRIPLETS-NEXT: 0 85 2
+; TRIPLETS-NEXT: 16 75 0
+; TRIPLETS-NEXT: 16 85 2
+; TRIPLETS-NEXT: 16 85 3
; TRIPLETS-NEXT: 16 0 1
-; TRIPLETS-NEXT: 0 69 0
-; TRIPLETS-NEXT: 0 84 2
-; TRIPLETS-NEXT: 30 77 0
-; TRIPLETS-NEXT: 30 83 2
+; TRIPLETS-NEXT: 0 70 0
+; TRIPLETS-NEXT: 0 85 2
+; TRIPLETS-NEXT: 30 78 0
+; TRIPLETS-NEXT: 30 84 2
; TRIPLETS-NEXT: 30 30 1
-; TRIPLETS-NEXT: 30 77 0
-; TRIPLETS-NEXT: 30 83 2
+; TRIPLETS-NEXT: 30 78 0
+; TRIPLETS-NEXT: 30 84 2
; TRIPLETS-NEXT: 30 32 1
-; TRIPLETS-NEXT: 32 69 0
-; TRIPLETS-NEXT: 32 84 2
-; TRIPLETS-NEXT: 32 82 3
+; TRIPLETS-NEXT: 32 70 0
+; TRIPLETS-NEXT: 32 85 2
+; TRIPLETS-NEXT: 32 83 3
; TRIPLETS-NEXT: 32 32 1
-; TRIPLETS-NEXT: 32 69 0
-; TRIPLETS-NEXT: 32 84 2
-; TRIPLETS-NEXT: 32 82 3
+; TRIPLETS-NEXT: 32 70 0
+; TRIPLETS-NEXT: 32 85 2
+; TRIPLETS-NEXT: 32 83 3
; TRIPLETS-NEXT: 32 31 1
-; TRIPLETS-NEXT: 31 74 0
-; TRIPLETS-NEXT: 31 82 2
+; TRIPLETS-NEXT: 31 75 0
+; TRIPLETS-NEXT: 31 83 2
; TRIPLETS-NEXT: 31 31 1
-; TRIPLETS-NEXT: 31 74 0
-; TRIPLETS-NEXT: 31 82 2
+; TRIPLETS-NEXT: 31 75 0
+; TRIPLETS-NEXT: 31 83 2
; TRIPLETS-NEXT: 31 12 1
-; TRIPLETS-NEXT: 12 74 0
-; TRIPLETS-NEXT: 12 84 2
-; TRIPLETS-NEXT: 12 84 3
+; TRIPLETS-NEXT: 12 75 0
+; TRIPLETS-NEXT: 12 85 2
+; TRIPLETS-NEXT: 12 85 3
; TRIPLETS-NEXT: 12 0 1
-; TRIPLETS-NEXT: 0 69 0
-; TRIPLETS-NEXT: 0 84 2
\ No newline at end of file
+; TRIPLETS-NEXT: 0 70 0
+; TRIPLETS-NEXT: 0 85 2
\ No newline at end of file
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index e5add4430e5a5..9b629f9913ddd 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -823,6 +823,11 @@ struct FunCloner {
Dst = LLVMBuildBitCast(Builder, V, CloneType(Src), Name);
break;
}
+ case LLVMByteCast: {
+ LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 0));
+ Dst = LLVMBuildByteCast(Builder, V, CloneType(Src), Name);
+ break;
+ }
case LLVMICmp: {
LLVMIntPredicate Pred = LLVMGetICmpPredicate(Src);
LLVMBool IsSameSign = LLVMGetICmpSameSign(Src);
diff --git a/llvm/unittests/Analysis/IR2VecTest.cpp b/llvm/unittests/Analysis/IR2VecTest.cpp
index a095761bc246a..d1a14cda168e9 100644
--- a/llvm/unittests/Analysis/IR2VecTest.cpp
+++ b/llvm/unittests/Analysis/IR2VecTest.cpp
@@ -333,8 +333,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_Symbolic) {
EXPECT_EQ(AddEmb.size(), 2u);
EXPECT_EQ(RetEmb.size(), 2u);
- EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.7)));
- EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 15.6)));
+ EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 26.0)));
+ EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 15.8)));
}
TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
@@ -346,8 +346,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
EXPECT_EQ(AddEmb.size(), 2u);
EXPECT_EQ(RetEmb.size(), 2u);
- EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 25.7)));
- EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 32.8)));
+ EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 26.0)));
+ EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 33.2)));
}
TEST_F(IR2VecTestFixture, GetBBVector_Symbolic) {
@@ -357,9 +357,9 @@ TEST_F(IR2VecTestFixture, GetBBVector_Symbolic) {
const auto &BBVec = Emb->getBBVector(*BB);
EXPECT_EQ(BBVec.size(), 2u);
- // BB vector should be sum of add and ret: {25.7, 25.7} + {15.6, 15.6} =
- // {41.3, 41.3}
- EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 41.3)));
+ // BB vector should be sum of add and ret: {26.0, 26.0} + {15.8, 15.8} =
+ // {41.8, 41.8}
+ EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 41.8)));
}
TEST_F(IR2VecTestFixture, GetBBVector_FlowAware) {
@@ -369,9 +369,9 @@ TEST_F(IR2VecTestFixture, GetBBVector_FlowAware) {
const auto &BBVec = Emb->getBBVector(*BB);
EXPECT_EQ(BBVec.size(), 2u);
- // BB vector should be sum of add and ret: {25.7, 25.7} + {32.8, 32.8} =
- // {58.5, 58.5}
- EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 58.5)));
+ // BB vector should be sum of add and ret: {26.0, 26.0} + {33.2, 33.2} =
+ // {59.2, 59.2}
+ EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 59.2)));
}
TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
@@ -382,8 +382,8 @@ TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
EXPECT_EQ(FuncVec.size(), 2u);
- // Function vector should match BB vector (only one BB): {41.3, 41.3}
- EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 41.3)));
+ // Function vector should match BB vector (only one BB): {41.8, 41.8}
+ EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 41.8)));
}
TEST_F(IR2VecTestFixture, GetFunctionVector_FlowAware) {
@@ -393,8 +393,8 @@ TEST_F(IR2VecTestFixture, GetFunctionVector_FlowAware) {
const auto &FuncVec = Emb->getFunctionVector();
EXPECT_EQ(FuncVec.size(), 2u);
- // Function vector should match BB vector (only one BB): {58.5, 58.5}
- EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 58.5)));
+ // Function vector should match BB vector (only one BB): {59.2, 59.2}
+ EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 59.2)));
}
TEST_F(IR2VecTestFixture, MultipleComputeEmbeddingsConsistency_Symbolic) {
>From 802a679dfb05ab3c4923fa14d2ae8d1dcbaba3e8 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Fri, 21 Feb 2025 12:14:12 +0000
Subject: [PATCH 03/15] [IR] Support bytes operands in the `trunc` instruction
---
llvm/lib/IR/Instructions.cpp | 3 ++-
llvm/lib/IR/Verifier.cpp | 9 +++++++--
llvm/test/Assembler/byte.ll | 16 ++++++++++++++++
3 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index b61cf86e6834b..fce3934c10a1a 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -3361,7 +3361,8 @@ CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
switch (op) {
default: return false; // This is an input error
case Instruction::Trunc:
- return SrcTy->isIntOrIntVectorTy() && DstTy->isIntOrIntVectorTy() &&
+ return ((SrcTy->isIntOrIntVectorTy() && DstTy->isIntOrIntVectorTy()) ||
+ (SrcTy->isByteOrByteVectorTy() && DstTy->isByteOrByteVectorTy())) &&
SrcEC == DstEC && SrcScalarBitSize > DstScalarBitSize;
case Instruction::ZExt:
return SrcTy->isIntOrIntVectorTy() && DstTy->isIntOrIntVectorTy() &&
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index a7f1dd006768e..6581466357385 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3556,8 +3556,13 @@ void Verifier::visitTruncInst(TruncInst &I) {
unsigned SrcBitSize = SrcTy->getScalarSizeInBits();
unsigned DestBitSize = DestTy->getScalarSizeInBits();
- Check(SrcTy->isIntOrIntVectorTy(), "Trunc only operates on integer", &I);
- Check(DestTy->isIntOrIntVectorTy(), "Trunc only produces integer", &I);
+ Check(SrcTy->isIntOrIntVectorTy() || SrcTy->isByteOrByteVectorTy(),
+ "Trunc only operates on integer or byte", &I);
+ Check(DestTy->isIntOrIntVectorTy() || DestTy->isByteOrByteVectorTy(),
+ "Trunc only produces integer or byte", &I);
+ Check(SrcTy->isIntOrIntVectorTy() == DestTy->isIntOrIntVectorTy() &&
+ SrcTy->isByteOrByteVectorTy() == DestTy->isByteOrByteVectorTy(),
+ "Trunc only operates on operands of the same base type", &I);
Check(SrcTy->isVectorTy() == DestTy->isVectorTy(),
"trunc source and destination must both be a vector or neither", &I);
Check(SrcBitSize > DestBitSize, "DestTy too big for Trunc", &I);
diff --git a/llvm/test/Assembler/byte.ll b/llvm/test/Assembler/byte.ll
index 671d2ca0ecb8c..5e1fd41254f31 100644
--- a/llvm/test/Assembler/byte.ll
+++ b/llvm/test/Assembler/byte.ll
@@ -125,3 +125,19 @@ define void @vector_bytecasts(<2 x b64> %b1, <2 x b128> %b2, b64 %b3) {
%8 = bytecast <2 x b128> %b2 to <4 x ptr>
ret void
}
+
+define void @trunc(b16 %b, <2 x b16> %v) {
+; CHECK-LABEL: define void @trunc(
+; CHECK-SAME: b16 [[B:%.*]], <2 x b16> [[V:%.*]]) {
+; CHECK-NEXT: [[T1:%.*]] = trunc b16 [[B]] to b8
+; CHECK-NEXT: [[T2:%.*]] = trunc <2 x b16> [[V]] to <2 x b8>
+; CHECK-NEXT: [[T3:%.*]] = trunc b16 0 to b8
+; CHECK-NEXT: [[T4:%.*]] = trunc <2 x b16> zeroinitializer to <2 x b8>
+; CHECK-NEXT: ret void
+;
+ %t1 = trunc b16 %b to b8
+ %t2 = trunc <2 x b16> %v to <2 x b8>
+ %t3 = trunc b16 0 to b8
+ %t4 = trunc <2 x b16> <b16 0, b16 0> to <2 x b8>
+ ret void
+}
>From fe0b5b64b9caece908d580b2f3068e11cb58d1d8 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Tue, 27 Jan 2026 23:01:47 +0000
Subject: [PATCH 04/15] [IR] Support bytes operands in the `lshr` instruction
---
llvm/include/llvm/IR/IRBuilder.h | 10 ++++++++--
llvm/lib/AsmParser/LLParser.cpp | 4 +++-
llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 4 ++--
llvm/lib/IR/Instructions.cpp | 8 +++++++-
llvm/lib/IR/Verifier.cpp | 8 +++++++-
llvm/test/Assembler/byte-invalid-cast-11.ll | 7 +++++++
llvm/test/Assembler/byte-invalid-cast-12.ll | 7 +++++++
llvm/test/Assembler/byte.ll | 16 ++++++++++++++++
8 files changed, 57 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/Assembler/byte-invalid-cast-11.ll
create mode 100644 llvm/test/Assembler/byte-invalid-cast-12.ll
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index f005b0fc75ee3..1482035c02de8 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -1545,12 +1545,18 @@ class IRBuilderBase {
Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "",
bool isExact = false) {
- return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
+ Constant *RHSC = LHS->getType()->isByteTy()
+ ? ConstantByte::get(LHS->getType(), RHS)
+ : ConstantInt::get(LHS->getType(), RHS);
+ return CreateLShr(LHS, RHSC, Name, isExact);
}
Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "",
bool isExact = false) {
- return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
+ Constant *RHSC = LHS->getType()->isByteTy()
+ ? ConstantByte::get(LHS->getType(), RHS)
+ : ConstantInt::get(LHS->getType(), RHS);
+ return CreateLShr(LHS, RHSC, Name, isExact);
}
Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "",
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 9ce92d042e712..2e22dc9997f7b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -8166,7 +8166,9 @@ bool LLParser::parseArithmetic(Instruction *&Inst, PerFunctionState &PFS,
return true;
bool Valid = IsFP ? LHS->getType()->isFPOrFPVectorTy()
- : LHS->getType()->isIntOrIntVectorTy();
+ : (LHS->getType()->isIntOrIntVectorTy() ||
+ (LHS->getType()->isByteOrByteVectorTy() &&
+ Opc == Instruction::LShr));
if (!Valid)
return error(Loc, "invalid operand type for instruction");
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 5569ddb965673..1ef53c7432ff8 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1311,8 +1311,8 @@ static int getDecodedUnaryOpcode(unsigned Val, Type *Ty) {
static int getDecodedBinaryOpcode(unsigned Val, Type *Ty) {
bool IsFP = Ty->isFPOrFPVectorTy();
- // BinOps are only valid for int/fp or vector of int/fp types
- if (!IsFP && !Ty->isIntOrIntVectorTy())
+ // BinOps are only valid for int/fp/byte or vector of int/fp/byte types
+ if (!IsFP && !Ty->isIntOrIntVectorTy() && !Ty->isByteOrByteVectorTy())
return -1;
switch (Val) {
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index fce3934c10a1a..332f2b4b20057 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -2678,8 +2678,14 @@ void BinaryOperator::AssertOK() {
assert(getType()->isFPOrFPVectorTy() &&
"Incorrect operand type (not floating point) for FREM");
break;
- case Shl:
case LShr:
+ assert(getType() == LHS->getType() &&
+ "Lshr operation should return same type as operands!");
+ assert((getType()->isIntOrIntVectorTy() ||
+ getType()->isByteOrByteVectorTy()) &&
+ "Tried to create a lshr operation on a non-integral/byte type!");
+ break;
+ case Shl:
case AShr:
assert(getType() == LHS->getType() &&
"Shift operation should return same type as operands!");
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 6581466357385..bb6fdad4482e7 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4381,8 +4381,14 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) {
Check(B.getType() == B.getOperand(0)->getType(),
"Logical operators must have same type for operands and result!", &B);
break;
- case Instruction::Shl:
case Instruction::LShr:
+ Check(B.getType()->isIntOrIntVectorTy() ||
+ B.getType()->isByteOrByteVectorTy(),
+ "Lshr only work with integral/byte types!", &B);
+ Check(B.getType() == B.getOperand(0)->getType(),
+ "Lshr return type must be same as operands!", &B);
+ break;
+ case Instruction::Shl:
case Instruction::AShr:
Check(B.getType()->isIntOrIntVectorTy(),
"Shifts only work with integral types!", &B);
diff --git a/llvm/test/Assembler/byte-invalid-cast-11.ll b/llvm/test/Assembler/byte-invalid-cast-11.ll
new file mode 100644
index 0000000000000..47d8f7d6e4aab
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-11.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: error: invalid operand type for instruction
+define void @invalid_shift(b32 %b) {
+ %s = shl b32 %b, 8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte-invalid-cast-12.ll b/llvm/test/Assembler/byte-invalid-cast-12.ll
new file mode 100644
index 0000000000000..f1fc7d3341410
--- /dev/null
+++ b/llvm/test/Assembler/byte-invalid-cast-12.ll
@@ -0,0 +1,7 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: error: invalid operand type for instruction
+define void @invalid_shift(b32 %b) {
+ %s = ashr b32 %b, 8
+ ret void
+}
diff --git a/llvm/test/Assembler/byte.ll b/llvm/test/Assembler/byte.ll
index 5e1fd41254f31..7ba2d3152fd61 100644
--- a/llvm/test/Assembler/byte.ll
+++ b/llvm/test/Assembler/byte.ll
@@ -141,3 +141,19 @@ define void @trunc(b16 %b, <2 x b16> %v) {
%t4 = trunc <2 x b16> <b16 0, b16 0> to <2 x b8>
ret void
}
+
+define void @lshr(b64 %b, <4 x b64> %v) {
+; CHECK-LABEL: define void @lshr(
+; CHECK-SAME: b64 [[B:%.*]], <4 x b64> [[V:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = lshr b64 [[B]], 32
+; CHECK-NEXT: [[TMP2:%.*]] = lshr <4 x b64> [[V]], splat (b64 8)
+; CHECK-NEXT: [[TMP3:%.*]] = lshr b64 64, 32
+; CHECK-NEXT: [[TMP4:%.*]] = lshr <4 x b64> zeroinitializer, splat (b64 8)
+; CHECK-NEXT: ret void
+;
+ %1 = lshr b64 %b, 32
+ %2 = lshr <4 x b64> %v, <b64 8, b64 8, b64 8, b64 8>
+ %3 = lshr b64 64, 32
+ %4 = lshr <4 x b64> <b64 0, b64 0, b64 0, b64 0>, <b64 8, b64 8, b64 8, b64 8>
+ ret void
+}
>From cbc81c4e862fc7ebeaaf15fde67afe813202ca90 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Wed, 28 Jan 2026 19:34:19 +0000
Subject: [PATCH 05/15] [LangRef] Add section on the byte type
---
llvm/docs/LangRef.rst | 104 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 100 insertions(+), 4 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 38f2ad8c166fd..b5d5c1639deb8 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -4432,6 +4432,40 @@ Examples:
| ``i1942652`` | a really big integer of over 1 million bits. |
+----------------+------------------------------------------------+
+.. _t_byte:
+
+Byte Type
+""""""""""""
+
+:Overview:
+
+The byte type represents raw memory data in SSA registers. Each bit can be:
+
+* An integer bit (0 or 1)
+* Part of a pointer value
+* ``poison``
+
+Any bit width from 1 bit to 2\ :sup:`23`\ (about 8 million) can be specified.
+
+:Syntax:
+
+::
+
+ bN
+
+The number of bits the byte occupies is specified by the ``N`` value.
+
+Examples:
+*********
+
++----------------+------------------------------------------------+
+| ``b1`` | a single-bit byte value. |
++----------------+------------------------------------------------+
+| ``b32`` | a 32-bit byte value. |
++----------------+------------------------------------------------+
+| ``b128`` | a 128-bit byte value. |
++----------------+------------------------------------------------+
+
.. _t_floating:
Floating-Point Types
@@ -4865,6 +4899,10 @@ Simple Constants
Note that hexadecimal integers are sign extended from the number
of active bits, i.e., the bit width minus the number of leading
zeros. So '``s0x0001``' of type '``i16``' will be -1, not 1.
+**Byte constants**
+ Byte constants are used to initialize global variables of the :ref:`byte
+ <t_byte>` type. These are strictly equivalent to integer constants:
+ ``store b8 42, ptr %p`` is equivalent to ``store i8 42, ptr %p``.
**Floating-point constants**
Floating-point constants use standard decimal notation (e.g.
123.421), exponential notation (e.g., 1.23421e+2), or a more precise
@@ -11005,7 +11043,7 @@ Arguments:
""""""""""
Both arguments to the '``lshr``' instruction must be the same
-:ref:`integer <t_integer>` or :ref:`vector <t_vector>` of integer type.
+:ref:`integer <t_integer>`, :ref:`byte <t_byte>`, or :ref:`vector <t_vector>` of integer or byte type.
'``op2``' is treated as an unsigned value.
Semantics:
@@ -11032,6 +11070,8 @@ Example:
<result> = lshr i8 -2, 1 ; yields i8:result = 0x7F
<result> = lshr i32 1, 32 ; undefined
<result> = lshr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 2> ; yields: result=<2 x i32> < i32 0x7FFFFFFF, i32 1>
+ <result> = lshr b32 4, 1 ; yields b32:result = 2
+ <result> = lshr <2 x b32> < b32 -2, b32 4>, < b32 1, b32 2> ; yields: result=<2 x b32> < b32 0x7FFFFFFF, b32 1>
.. _i_ashr:
@@ -12390,8 +12430,8 @@ Arguments:
""""""""""
The '``trunc``' instruction takes a value to trunc, and a type to trunc
-it to. Both types must be of :ref:`integer <t_integer>` types, or vectors
-of the same number of integers. The bit size of the ``value`` must be
+it to. Both types must be of :ref:`integer <t_integer>` or :ref:`byte <t_byte>` types, or vectors
+of the same number of integers or bytes. The bit size of the ``value`` must be
larger than the bit size of the destination type, ``ty2``. Equal sized
types are not allowed.
@@ -12417,6 +12457,8 @@ Example:
%Y = trunc i32 123 to i1 ; yields i1:true
%Z = trunc i32 122 to i1 ; yields i1:false
%W = trunc <2 x i16> <i16 8, i16 7> to <2 x i8> ; yields <i8 8, i8 7>
+ %X = trunc b32 257 to b8 ; yields b8:1
+ %W = trunc <2 x b16> <b16 8, b16 7> to <2 x b8> ; yields <b8 8, b8 7>
.. _i_zext:
@@ -12998,7 +13040,7 @@ is always a *no-op cast* because no bits change with this
conversion. The conversion is done as if the ``value`` had been stored
to memory and read back as type ``ty2``. Pointer (or vector of
pointers) types may only be converted to other pointer (or vector of
-pointers) types with the same address space through this instruction.
+pointers) types with the same address space or byte (or vector of bytes) types through this instruction.
To convert pointers to other types, use the :ref:`inttoptr <i_inttoptr>`
or :ref:`ptrtoint <i_ptrtoint>` instructions first.
@@ -13017,6 +13059,60 @@ Example:
%Z = bitcast <2 x i32> %V to i64; ; yields i64: %V (depends on endianness)
%Z = bitcast <2 x i32*> %V to <2 x i64*> ; yields <2 x i64*>
+.. _i_bytecast:
+
+'``bytecast .. to``' Instruction
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ <result> = bytecast <ty> <value> to <ty2> ; yields ty2
+
+Overview:
+"""""""""
+
+The '``bytecast``' instruction converts ``value``, of the byte type, to type
+``ty2`` performing type punning.
+
+Arguments:
+""""""""""
+
+The '``bytecast``' instruction takes a value to cast, which must be of the
+:ref:`byte type <t_byte>`, and a type to cast it to, which must be a
+non-aggregate :ref:`first class <t_firstclass>` type. The bit sizes of ``value``
+and the destination type, ``ty2``, must be identical. This instruction supports
+conversions from vectors of bytes to vector of other types (as long as they
+have the same size).
+
+Semantics:
+""""""""""
+
+The '``bytecast``' instruction converts the ``value`` of the :ref:`byte type
+<t_byte>` to type ``ty2``. If ``value`` holds a pointer and type ``ty2`` is not
+a pointer type, the address of the pointer is extracted without exposing its
+provenance, similarly to the :ref:`ptrtoaddr <i_ptrtoaddr>` instruction. If
+``value`` holds a non-pointer value and type ``ty2`` is a pointer type, the cast
+result is a pointer without provenance. This pointer cannot be dereferenced, but
+can be used in comparisons or :ref:`getelementptr <i_getelementptr>`
+instructions. Otherwise, the cast is a *no-op*.
+
+Example:
+""""""""
+
+.. code-block:: text
+
+ ; considering %bi to hold an integer and %bp to hold a pointer,
+ %a = bytecast b64 %bi to i64 ; returns an integer, no-op cast
+ %b = bytecast b64 %bp to i64 ; reinterprets the pointer as an integer, returning its address without exposing provenance
+ %c = bytecast b64 %bp to ptr ; returns a pointer, no-op cast
+ %d = bytecast b64 %bi to ptr ; reinterprets the integer as a pointer, returning a pointer with no provenance
+
+ %e = bytecast <2 x b32> %v to i64 ; reinterprets the raw bytes as an integer
+ %f = bytecast <2 x b32> %v to ptr ; reinterprets the raw bytes as a pointer
+
.. _i_addrspacecast:
'``addrspacecast .. to``' Instruction
>From 313cab865991b644bd0d55e86751095cbdfaa1c5 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Thu, 29 Jan 2026 14:56:54 +0000
Subject: [PATCH 06/15] fix langref
---
llvm/docs/LangRef.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index b5d5c1639deb8..9f4cdbba54ad7 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -13062,7 +13062,7 @@ Example:
.. _i_bytecast:
'``bytecast .. to``' Instruction
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
>From b15a56f8ab9ec31a413851c5aee3c430ea021368 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Thu, 29 Jan 2026 18:33:22 +0000
Subject: [PATCH 07/15] fix CI
---
llvm/include/llvm/SandboxIR/Instruction.h | 2 ++
llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp | 2 +-
llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp | 1 +
llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp | 1 +
4 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/SandboxIR/Instruction.h b/llvm/include/llvm/SandboxIR/Instruction.h
index 95e59a49125c5..13c3deb96f1cc 100644
--- a/llvm/include/llvm/SandboxIR/Instruction.h
+++ b/llvm/include/llvm/SandboxIR/Instruction.h
@@ -2365,6 +2365,8 @@ class CastInst : public UnaryInstruction {
return Opcode::FPTrunc;
case llvm::Instruction::BitCast:
return Opcode::BitCast;
+ case llvm::Instruction::ByteCast:
+ llvm_unreachable("Not implemented!");
case llvm::Instruction::AddrSpaceCast:
return Opcode::AddrSpaceCast;
case llvm::Instruction::CastOpsEnd:
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index 0d87385b44d8f..7feaf5a7bb68e 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -2029,7 +2029,7 @@ void DXILBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
unsigned NWords = BV->getValue().getActiveWords();
const uint64_t *RawWords = BV->getValue().getRawData();
for (unsigned i = 0; i != NWords; ++i) {
- emitSignedInt64(Record, V);
+ emitSignedInt64(Record, RawWords[i]);
}
Code = bitc::CST_CODE_WIDE_BYTE;
}
diff --git a/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp b/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
index 0c1b0aea41f41..0212dffa38645 100644
--- a/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
@@ -316,6 +316,7 @@ unsigned HexagonTargetObjectFile::getSmallestAddressableSize(const Type *Ty,
case Type::HalfTyID:
case Type::FloatTyID:
case Type::DoubleTyID:
+ case Type::ByteTyID:
case Type::IntegerTyID: {
const DataLayout &DL = GV->getDataLayout();
// It is unfortunate that DL's function take non-const Type*.
diff --git a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp
index 5d558c2f7a341..5dab775143bc6 100644
--- a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp
+++ b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp
@@ -273,6 +273,7 @@ static bool isShapePreserving(Value *V) {
case CastInst::PtrToInt:
case CastInst::IntToPtr:
return false;
+ case CastInst::ByteCast:
case CastInst::BitCast: {
if (auto *SrcVTy = dyn_cast<FixedVectorType>(Cast->getSrcTy()))
if (auto *DestVTy = dyn_cast<FixedVectorType>(Cast->getDestTy()))
>From 7a49e831de01d7b992ff20f1353edf2871b23d8e Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Thu, 29 Jan 2026 19:34:46 +0000
Subject: [PATCH 08/15] add codegen test for byte constants
---
llvm/lib/IR/Constants.cpp | 7 +++++--
llvm/test/CodeGen/X86/byte-constants.ll | 21 +++++++++++++++++++++
2 files changed, 26 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/byte-constants.ll
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 06f312434003f..f388069596679 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -2524,8 +2524,11 @@ Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) {
bool toVec = isa<VectorType>(Ty);
#endif
assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
- assert(C->getType()->isIntOrIntVectorTy() && "Trunc operand must be integer");
- assert(Ty->isIntOrIntVectorTy() && "Trunc produces only integral");
+ assert((C->getType()->isIntOrIntVectorTy() ||
+ C->getType()->isByteOrByteVectorTy()) &&
+ "Trunc operand must be integer or byte");
+ assert((Ty->isIntOrIntVectorTy() || Ty->isByteOrByteVectorTy()) &&
+ "Trunc produces only integral or byte");
assert(C->getType()->getScalarSizeInBits() > Ty->getScalarSizeInBits()&&
"SrcTy must be larger than DestTy for Trunc!");
diff --git a/llvm/test/CodeGen/X86/byte-constants.ll b/llvm/test/CodeGen/X86/byte-constants.ll
new file mode 100644
index 0000000000000..9077a6426c0a5
--- /dev/null
+++ b/llvm/test/CodeGen/X86/byte-constants.ll
@@ -0,0 +1,21 @@
+; RUN: llc < %s | FileCheck %s
+
+%union.x = type { b32 }
+
+; CHECK: .globl r
+; CHECK: r:
+; CHECK: .long 42
+
+ at r = global %union.x { b32 42 }, align 4
+
+; CHECK: .globl x
+; CHECK: x:
+; CHECK: .quad 10
+
+ at x = global b64 bitcast (i64 10 to b64)
+
+; CHECK: .globl y
+; CHECK: y:
+; CHECK: .byte 12
+
+ at y = global b8 trunc (b32 12 to b8)
>From c76bb74951970e2c7a5845571a4d76a5c4b7f7ad Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Thu, 29 Jan 2026 22:04:26 +0000
Subject: [PATCH 09/15] address reviews
---
llvm/docs/LangRef.rst | 18 +++++++++++-------
llvm/include/llvm/IR/Constants.h | 2 +-
llvm/include/llvm/IR/DerivedTypes.h | 6 +++---
llvm/include/llvm/IR/IRBuilder.h | 16 ----------------
llvm/include/llvm/IR/Type.h | 2 +-
.../SelectionDAG/SelectionDAGBuilder.cpp | 2 +-
6 files changed, 17 insertions(+), 29 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 9f4cdbba54ad7..ba2a87926bf7b 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -13091,13 +13091,17 @@ Semantics:
""""""""""
The '``bytecast``' instruction converts the ``value`` of the :ref:`byte type
-<t_byte>` to type ``ty2``. If ``value`` holds a pointer and type ``ty2`` is not
-a pointer type, the address of the pointer is extracted without exposing its
-provenance, similarly to the :ref:`ptrtoaddr <i_ptrtoaddr>` instruction. If
-``value`` holds a non-pointer value and type ``ty2`` is a pointer type, the cast
-result is a pointer without provenance. This pointer cannot be dereferenced, but
-can be used in comparisons or :ref:`getelementptr <i_getelementptr>`
-instructions. Otherwise, the cast is a *no-op*.
+<t_byte>` to type ``ty2``. If ``value`` holds a mix of pointer and non-pointer
+bits and type ``ty2`` is a non-pointer type, the provenance of the pointer bits
+is stripped without being exposed, similarly to the :ref:`ptrtoaddr
+<i_ptrtoaddr>` instruction. If ``value`` holds bits from different pointers, or
+a mix of pointer and non-pointer bits, and type ``ty2`` is a pointer type, the
+cast result is a pointer without provenance. This pointer cannot be
+dereferenced, but can be used in comparisons or :ref:`getelementptr
+<i_getelementptr>` instructions. If any of the bits of ``value`` is ``poison``,
+the cast result is also ``poison``. Casting a mix of pointer and non-pointer
+bits to a non-pointer type strips the pointer's provenance. Otherwise, the cast
+is a *no-op*.
Example:
""""""""
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 9c00b55140fc6..e40cbb4e2bd42 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -386,7 +386,7 @@ class ConstantByte final : public ConstantData {
/// Determine if this constant's value is same as an unsigned char.
bool equalsByte(uint64_t V) const { return Val == V; }
- /// Variant of the getType() method to always return an ByteType, which
+ /// Variant of the getType() method to always return a ByteType, which
/// reduces the amount of casting needed in parts of the compiler.
inline ByteType *getByteType() const {
return cast<ByteType>(Value::getType());
diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h
index 7c1fcb90952ec..876c4c8c871ce 100644
--- a/llvm/include/llvm/IR/DerivedTypes.h
+++ b/llvm/include/llvm/IR/DerivedTypes.h
@@ -124,11 +124,11 @@ class ByteType : public Type {
///< to the largest representable power of 2, 8388608.
};
- /// This static method is the primary way of constructing an ByteType.
- /// If an ByteType with the same NumBits value was previously instantiated,
+ /// This static method is the primary way of constructing a ByteType.
+ /// If a ByteType with the same NumBits value was previously instantiated,
/// that instance will be returned. Otherwise a new one will be created. Only
/// one instance with a given NumBits value is ever created.
- /// Get or create an ByteType instance.
+ /// Get or create a ByteType instance.
LLVM_ABI static ByteType *get(LLVMContext &C, unsigned NumBits);
/// Returns type twice as wide the input type.
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 1482035c02de8..3f326239808f7 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2233,22 +2233,6 @@ class IRBuilderBase {
return CreateByteCast(V, DestTy, Name);
}
- Value *CreateByteCastToPtr(Value *V, unsigned AddrSpace = 0,
- const Twine &Name = "") {
- if (auto *VTy = dyn_cast<VectorType>(V->getType())) {
- unsigned NumEls = VTy->getElementCount().getKnownMinValue();
-
- Type *DestElTy = getPtrTy(AddrSpace);
- VectorType *DestTy =
- VectorType::get(DestElTy, NumEls, VTy->isScalableTy());
-
- return CreateByteCast(V, DestTy, Name);
- }
-
- Type *DestTy = getPtrTy(AddrSpace);
- return CreateByteCast(V, DestTy, Name);
- }
-
Value *CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") {
Instruction::CastOps CastOp =
V->getType()->getScalarSizeInBits() == DestTy->getScalarSizeInBits()
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 1640de3b9fbd8..98d432ca243f3 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -241,7 +241,7 @@ class Type {
/// True if this is an instance of ByteType.
bool isByteTy() const { return getTypeID() == ByteTyID; }
- /// Return true if this is an ByteType of the given width.
+ /// Return true if this is a ByteType of the given width.
LLVM_ABI bool isByteTy(unsigned BitWidth) const;
/// Return true if this is a byte type or a vector of byte types.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 5d97b7e73c673..b10e69909d76f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4142,7 +4142,7 @@ void SelectionDAGBuilder::visitByteCast(const User &I) {
// Convert vector types.
setValue(&I, DAG.getNode(ISD::BITCAST, dl, DestVT, N));
// Check if the original LLVM IR Operand was a ConstantByte, because
- // getValue() might fold any kind of constant expression to an byte constant
+ // getValue() might fold any kind of constant expression to a byte constant
// and that is not what we are looking for. Only recognize a bytecast of a
// genuine constant byte as an opaque constant.
else if (ConstantByte *C = dyn_cast<ConstantByte>(I.getOperand(0)))
>From bddbfc0d76d3731a412fd9f37b39b4205b6e48bb Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Fri, 30 Jan 2026 19:44:37 +0000
Subject: [PATCH 10/15] add wide bytes and vectors to codegen test
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 81 ++++++++++++++++++++++
llvm/test/CodeGen/X86/byte-constants.ll | 58 ++++++++++++++--
2 files changed, 134 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index c0b284ec865f6..715b3c353eeba 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -4131,6 +4131,66 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
emitGlobalConstantFP(CFP->getValueAPF(), CFP->getType(), AP);
}
+static void emitGlobalConstantLargeByte(const ConstantByte *CB,
+ AsmPrinter &AP) {
+ const DataLayout &DL = AP.getDataLayout();
+ unsigned BitWidth = CB->getBitWidth();
+
+ // Copy the value as we may massage the layout for constants whose bit width
+ // is not a multiple of 64-bits.
+ APInt Realigned(CB->getValue());
+ uint64_t ExtraBits = 0;
+ unsigned ExtraBitsSize = BitWidth & 63;
+
+ if (ExtraBitsSize) {
+ // The bit width of the data is not a multiple of 64-bits.
+ // The extra bits are expected to be at the end of the chunk of the memory.
+ // Little endian:
+ // * Nothing to be done, just record the extra bits to emit.
+ // Big endian:
+ // * Record the extra bits to emit.
+ // * Realign the raw data to emit the chunks of 64-bits.
+ if (DL.isBigEndian()) {
+ // Basically the structure of the raw data is a chunk of 64-bits cells:
+ // 0 1 BitWidth / 64
+ // [chunk1][chunk2] ... [chunkN].
+ // The most significant chunk is chunkN and it should be emitted first.
+ // However, due to the alignment issue chunkN contains useless bits.
+ // Realign the chunks so that they contain only useful information:
+ // ExtraBits 0 1 (BitWidth / 64) - 1
+ // chu[nk1 chu][nk2 chu] ... [nkN-1 chunkN]
+ ExtraBitsSize = alignTo(ExtraBitsSize, 8);
+ ExtraBits =
+ Realigned.getRawData()[0] & (((uint64_t)-1) >> (64 - ExtraBitsSize));
+ if (BitWidth >= 64)
+ Realigned.lshrInPlace(ExtraBitsSize);
+ } else
+ ExtraBits = Realigned.getRawData()[BitWidth / 64];
+ }
+
+ // We don't expect assemblers to support integer data directives
+ // for more than 64 bits, so we emit the data in at most 64-bit
+ // quantities at a time.
+ const uint64_t *RawData = Realigned.getRawData();
+ for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
+ uint64_t Val = DL.isBigEndian() ? RawData[e - i - 1] : RawData[i];
+ AP.OutStreamer->emitIntValue(Val, 8);
+ }
+
+ if (ExtraBitsSize) {
+ // Emit the extra bits after the 64-bits chunks.
+
+ // Emit a directive that fills the expected size.
+ uint64_t Size = AP.getDataLayout().getTypeStoreSize(CB->getType());
+ Size -= (BitWidth / 64) * 8;
+ assert(Size && Size * 8 >= ExtraBitsSize &&
+ (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize))) ==
+ ExtraBits &&
+ "Directive too small for extra bits.");
+ AP.OutStreamer->emitIntValue(ExtraBits, Size);
+ }
+}
+
static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
const DataLayout &DL = AP.getDataLayout();
unsigned BitWidth = CI->getBitWidth();
@@ -4334,6 +4394,27 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
return;
}
+ if (const ConstantByte *CB = dyn_cast<ConstantByte>(CV)) {
+ if (isa<VectorType>(CV->getType()))
+ return emitGlobalConstantVector(DL, CV, AP, AliasList);
+
+ const uint64_t StoreSize = DL.getTypeStoreSize(CV->getType());
+ if (StoreSize <= 8) {
+ if (AP.isVerbose())
+ AP.OutStreamer->getCommentOS()
+ << format("0x%" PRIx64 "\n", CB->getZExtValue());
+ AP.OutStreamer->emitIntValue(CB->getZExtValue(), StoreSize);
+ } else {
+ emitGlobalConstantLargeByte(CB, AP);
+ }
+
+ // Emit tail padding if needed
+ if (Size != StoreSize)
+ AP.OutStreamer->emitZeros(Size - StoreSize);
+
+ return;
+ }
+
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
if (isa<VectorType>(CV->getType()))
return emitGlobalConstantVector(DL, CV, AP, AliasList);
diff --git a/llvm/test/CodeGen/X86/byte-constants.ll b/llvm/test/CodeGen/X86/byte-constants.ll
index 9077a6426c0a5..5b6cd7ae1f166 100644
--- a/llvm/test/CodeGen/X86/byte-constants.ll
+++ b/llvm/test/CodeGen/X86/byte-constants.ll
@@ -1,12 +1,10 @@
; RUN: llc < %s | FileCheck %s
-%union.x = type { b32 }
-
; CHECK: .globl r
; CHECK: r:
; CHECK: .long 42
- at r = global %union.x { b32 42 }, align 4
+ at r = global b32 42
; CHECK: .globl x
; CHECK: x:
@@ -16,6 +14,56 @@
; CHECK: .globl y
; CHECK: y:
-; CHECK: .byte 12
+; CHECK: .byte 4
+
+ at y = global b8 trunc (b32 4 to b8)
+
+; CHECK: .globl b
+; CHECK: b:
+; CHECK: .byte 1
+
+ at b = global b1 1
+
+; CHECK: .globl f
+; CHECK: f:
+; CHECK: .byte 31
+
+ at f = global b5 31
+
+; CHECK: .globl w
+; CHECK: w:
+; CHECK: .quad -1
+; CHECK: .quad -1
+
+ at w = global b128 -1
+
+; CHECK: .globl uw
+; CHECK: uw:
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
+
+ at uw = global b256 -1
+
+; CHECK: .globl v
+; CHECK: v:
+; CHECK: .byte 1
+; CHECK: .byte 2
+; CHECK: .byte 3
+; CHECK: .byte 4
+
+ at v = global <4 x b8> <b8 1, b8 2, b8 3, b8 4>
+
+; CHECK: .globl uv
+; CHECK: uv:
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
+; CHECK: .quad -1
- at y = global b8 trunc (b32 12 to b8)
+ at uv = global <4 x b128> <b128 -1, b128 -1, b128 -1, b128 -1>
>From 18dd04961c4e2f8d63641abd95e548520a82ad6b Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Fri, 30 Jan 2026 20:00:29 +0000
Subject: [PATCH 11/15] update langref
---
llvm/docs/LangRef.rst | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index ba2a87926bf7b..7886713836602 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -13091,17 +13091,18 @@ Semantics:
""""""""""
The '``bytecast``' instruction converts the ``value`` of the :ref:`byte type
-<t_byte>` to type ``ty2``. If ``value`` holds a mix of pointer and non-pointer
-bits and type ``ty2`` is a non-pointer type, the provenance of the pointer bits
-is stripped without being exposed, similarly to the :ref:`ptrtoaddr
-<i_ptrtoaddr>` instruction. If ``value`` holds bits from different pointers, or
-a mix of pointer and non-pointer bits, and type ``ty2`` is a pointer type, the
-cast result is a pointer without provenance. This pointer cannot be
-dereferenced, but can be used in comparisons or :ref:`getelementptr
-<i_getelementptr>` instructions. If any of the bits of ``value`` is ``poison``,
-the cast result is also ``poison``. Casting a mix of pointer and non-pointer
-bits to a non-pointer type strips the pointer's provenance. Otherwise, the cast
-is a *no-op*.
+<t_byte>` to type ``ty2``. If ``value`` contains at least one ``poison`` bit,
+the cast result is ``poison``. Otherwise, if ``value`` is any mix of
+(non-``poison``) pointer and non-pointer bits:
+
+* If ``ty2`` is a non-pointer type, the provenance of the pointer bits is
+ stripped without being exposed, similarly to the
+ :ref:`ptrtoaddr <i_ptrtoaddr>` instruction.
+* If ``ty2`` is a pointer type, the cast result is a pointer without provenance.
+ This pointer cannot be dereferenced, but can be used in comparisons or
+ :ref:`getelementptr <i_getelementptr>` instructions.
+
+Otherwise, the cast is a *no-op*.
Example:
""""""""
>From 14dceb6c38f7c6d89a29933e2b058b17711ef14d Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Fri, 30 Jan 2026 20:03:31 +0000
Subject: [PATCH 12/15] ir builder review
---
llvm/include/llvm/IR/IRBuilder.h | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 3f326239808f7..48d82b09f222a 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2219,13 +2219,7 @@ class IRBuilderBase {
Value *CreateByteCastToInt(Value *V, const Twine &Name = "") {
if (auto *VTy = dyn_cast<VectorType>(V->getType())) {
- unsigned NumEls = VTy->getElementCount().getKnownMinValue();
- unsigned BitWidth = VTy->getElementType()->getPrimitiveSizeInBits();
-
- Type *DestElTy = getIntNTy(BitWidth);
- VectorType *DestTy =
- VectorType::get(DestElTy, NumEls, VTy->isScalableTy());
-
+ VectorType *DestTy = VectorType::getInteger(VTy);
return CreateByteCast(V, DestTy, Name);
}
@@ -2258,9 +2252,10 @@ class IRBuilderBase {
}
Value *CreateBitOrByteCast(Value *V, Type *DestTy, const Twine &Name = "") {
- Instruction::CastOps CastOp = V->getType()->isByteOrByteVectorTy()
- ? Instruction::ByteCast
- : Instruction::BitCast;
+ Instruction::CastOps CastOp =
+ V->getType()->isByteOrByteVectorTy() && !DestTy->isByteOrByteVectorTy()
+ ? Instruction::ByteCast
+ : Instruction::BitCast;
return CreateCast(CastOp, V, DestTy, Name);
}
>From 358734298206bbf480314ae39a031fcbe3e30842 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Fri, 30 Jan 2026 21:42:52 +0000
Subject: [PATCH 13/15] update langref
---
llvm/docs/LangRef.rst | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 7886713836602..119a81cd0c6f9 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -13098,9 +13098,11 @@ the cast result is ``poison``. Otherwise, if ``value`` is any mix of
* If ``ty2`` is a non-pointer type, the provenance of the pointer bits is
stripped without being exposed, similarly to the
:ref:`ptrtoaddr <i_ptrtoaddr>` instruction.
-* If ``ty2`` is a pointer type, the cast result is a pointer without provenance.
- This pointer cannot be dereferenced, but can be used in comparisons or
- :ref:`getelementptr <i_getelementptr>` instructions.
+* If ``ty2`` is a pointer type, then if all bits of ``value`` are from the same
+ pointer, the cast result is that pointer. If ``value`` is a mix of bits from
+ different pointers or a mix of pointer and non-pointer bits, the result is a
+ pointer without provenance. This pointer cannot be dereferenced, but can be
+ used in comparisons or :ref:`getelementptr <i_getelementptr>` instructions.
Otherwise, the cast is a *no-op*.
>From 84e24c4dd85d972945338d32f187b525eb5de871 Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Sat, 31 Jan 2026 19:26:05 +0000
Subject: [PATCH 14/15] update docs
---
llvm/docs/Frontend/PerformanceTips.rst | 13 +++++++++++++
llvm/docs/LangRef.rst | 6 ++++--
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/llvm/docs/Frontend/PerformanceTips.rst b/llvm/docs/Frontend/PerformanceTips.rst
index b81df707a31a6..5a32499cd5700 100644
--- a/llvm/docs/Frontend/PerformanceTips.rst
+++ b/llvm/docs/Frontend/PerformanceTips.rst
@@ -95,6 +95,19 @@ For example, when working with boolean values, store them by zero-extending
If you do use loads/stores on non-byte-sized types, make sure that you *always*
use those types. For example, do not first store ``i8`` and then load ``i1``.
+Use byte types when manipulating raw memory
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The byte type represents raw memory values in SSA registers. Loads and stores of
+byte types should be used when performing raw memory copies (such as ``memmove``
+and ``memcpy``). Using integer types to represent raw memory introduces type
+punning, which discards the provenance of pointers being copied.
+
+Use a byte type if a value may hold either a pointer or any other type at run
+time (and you don't know which one). For instance, if a union may hold a pointer
+or another type, use byte types to load and store the value. Otherwise, use the
+specific type.
+
Prefer zext over sext when legal
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 119a81cd0c6f9..e46442f58450b 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -4439,7 +4439,9 @@ Byte Type
:Overview:
-The byte type represents raw memory data in SSA registers. Each bit can be:
+The byte type represents raw memory data in SSA registers. It should be used
+when it cannot be determined whether a value holds a pointer or another type at
+run time. Otherwise, the specific type should be used. Each bit can be:
* An integer bit (0 or 1)
* Part of a pointer value
@@ -13109,7 +13111,7 @@ Otherwise, the cast is a *no-op*.
Example:
""""""""
-.. code-block:: text
+.. code-block:: llvm
; considering %bi to hold an integer and %bp to hold a pointer,
%a = bytecast b64 %bi to i64 ; returns an integer, no-op cast
>From f0f6c95c4e7017ce2cd606f94bba5970707761cd Mon Sep 17 00:00:00 2001
From: Pedro Lobo <pedro.lobo at tecnico.ulisboa.pt>
Date: Sat, 31 Jan 2026 20:15:57 +0000
Subject: [PATCH 15/15] fix IR2Vec type order
---
llvm/include/llvm/Analysis/IR2Vec.h | 2 +-
llvm/include/llvm/IR/Type.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/Analysis/IR2Vec.h b/llvm/include/llvm/Analysis/IR2Vec.h
index e728e76fcc058..e795e3b86f20f 100644
--- a/llvm/include/llvm/Analysis/IR2Vec.h
+++ b/llvm/include/llvm/Analysis/IR2Vec.h
@@ -489,8 +489,8 @@ class Vocabulary {
CanonicalTypeID::MetadataTy, // MetadataTyID
CanonicalTypeID::VectorTy, // X86_AMXTyID
CanonicalTypeID::TokenTy, // TokenTyID
- CanonicalTypeID::ByteTy, // ByteTyID
CanonicalTypeID::IntegerTy, // IntegerTyID
+ CanonicalTypeID::ByteTy, // ByteTyID
CanonicalTypeID::FunctionTy, // FunctionTyID
CanonicalTypeID::PointerTy, // PointerTyID
CanonicalTypeID::StructTy, // StructTyID
diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h
index 98d432ca243f3..56417ee14796f 100644
--- a/llvm/include/llvm/IR/Type.h
+++ b/llvm/include/llvm/IR/Type.h
@@ -68,8 +68,8 @@ class Type {
TokenTyID, ///< Tokens
// Derived types... see DerivedTypes.h file.
- ByteTyID, ///< Arbitrary bit width bytes
IntegerTyID, ///< Arbitrary bit width integers
+ ByteTyID, ///< Arbitrary bit width bytes
FunctionTyID, ///< Functions
PointerTyID, ///< Pointers
StructTyID, ///< Structures
More information about the llvm-commits
mailing list