[llvm] [IR] Add ByteCast opcode and ByteCastInst (PR #221882)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 7 23:00:53 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-selectiondag

Author: Anshil Gandhi (gandhi56)

<details>
<summary>Changes</summary>

Introduce a dedicated bytecast instruction for casts involving byte types. Split byte cast validation out of bitcast, add ByteCastInst, constant folding, and verifier support. Renumber subsequent opcodes to keep Instruction.def unique.

Add LLVMByteCast to the C API opcode enum for Core.cpp mapping tables, minimal codegen stubs, assembler/llubi support, and bitcast-to-bytecast fallback in the parser so existing IR text continues to assemble.

---

Patch is 54.69 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/221882.diff


34 Files Affected:

- (modified) llvm/include/llvm-c/Core.h (+1) 
- (modified) llvm/include/llvm/Analysis/IR2Vec.h (+1-3) 
- (modified) llvm/include/llvm/AsmParser/LLToken.h (+1) 
- (modified) llvm/include/llvm/IR/Constants.h (+2) 
- (modified) llvm/include/llvm/IR/InstVisitor.h (+1) 
- (modified) llvm/include/llvm/IR/InstrTypes.h (+1-1) 
- (modified) llvm/include/llvm/IR/Instruction.def (+3) 
- (modified) llvm/include/llvm/IR/Instruction.h (+2-1) 
- (modified) llvm/include/llvm/IR/Instructions.h (+28) 
- (modified) llvm/include/llvm/IR/Operator.h (+24) 
- (modified) llvm/lib/AsmParser/LLLexer.cpp (+1) 
- (modified) llvm/lib/AsmParser/LLParser.cpp (+3) 
- (modified) llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (+8) 
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+4) 
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h (+1) 
- (modified) llvm/lib/IR/ConstantFold.cpp (+2) 
- (modified) llvm/lib/IR/Constants.cpp (+17) 
- (modified) llvm/lib/IR/Instruction.cpp (+1) 
- (modified) llvm/lib/IR/Instructions.cpp (+83-12) 
- (modified) llvm/lib/IR/Verifier.cpp (+12) 
- (modified) llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt (+1) 
- (modified) llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt (+1) 
- (modified) llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt (+1) 
- (modified) llvm/test/tools/llubi/bitcast_be.ll (+6-6) 
- (modified) llvm/test/tools/llubi/bitcast_le.ll (+6-6) 
- (modified) llvm/test/tools/llubi/bytes_undef.ll (+4-4) 
- (modified) llvm/test/tools/llubi/freeze.ll (+2-2) 
- (modified) llvm/test/tools/llubi/loadstore_be.ll (+6-6) 
- (modified) llvm/test/tools/llubi/loadstore_le.ll (+6-6) 
- (modified) llvm/test/tools/llvm-ir2vec/entities.ll (+45-44) 
- (modified) llvm/test/tools/llvm-ir2vec/triplets.ll (+29-29) 
- (modified) llvm/tools/llubi/lib/Context.cpp (+2-1) 
- (modified) llvm/tools/llubi/lib/Interpreter.cpp (+8-5) 
- (modified) llvm/unittests/Analysis/IR2VecTest.cpp (+14-14) 


``````````diff
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index f3b98a31c5bd7..f4431536dc481 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -116,6 +116,7 @@ typedef enum {
   LLVMPtrToAddr      = 69,
   LLVMIntToPtr       = 40,
   LLVMBitCast        = 41,
+  LLVMByteCast       = 72,
   LLVMAddrSpaceCast  = 60,
 
   /* Other Operators */
diff --git a/llvm/include/llvm/Analysis/IR2Vec.h b/llvm/include/llvm/Analysis/IR2Vec.h
index b89d52a002445..7f84538f93c08 100644
--- a/llvm/include/llvm/Analysis/IR2Vec.h
+++ b/llvm/include/llvm/Analysis/IR2Vec.h
@@ -311,9 +311,7 @@ class Vocabulary {
   };
 
   /// Vocabulary layout constants
-#define LAST_OTHER_INST(NUM) static constexpr unsigned MaxOpcodes = NUM;
-#include "llvm/IR/Instruction.def"
-#undef LAST_OTHER_INST
+  static constexpr unsigned MaxOpcodes = Instruction::ByteCast;
 
   static constexpr unsigned MaxTypeIDs = Type::TypeID::TargetExtTyID + 1;
   static constexpr unsigned MaxCanonicalTypeIDs =
diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index d2766a05ce9ba..9f400f5676040 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -338,6 +338,7 @@ enum Kind {
   kw_ptrtoaddr,
   kw_ptrtoint,
   kw_bitcast,
+  kw_bytecast,
   kw_addrspacecast,
   kw_select,
   kw_va_arg,
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index d5299aebd16fe..bd5cd93904d41 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -1362,6 +1362,8 @@ class ConstantExpr : public Constant {
                                         bool OnlyIfReduced = false);
   LLVM_ABI static Constant *getBitCast(Constant *C, Type *Ty,
                                        bool OnlyIfReduced = false);
+  LLVM_ABI static Constant *getByteCast(Constant *C, Type *Ty,
+                                        bool OnlyIfReduced = false);
   LLVM_ABI static Constant *getAddrSpaceCast(Constant *C, Type *Ty,
                                              bool OnlyIfReduced = false);
 
diff --git a/llvm/include/llvm/IR/InstVisitor.h b/llvm/include/llvm/IR/InstVisitor.h
index ecef7f50d98ce..2176743e0b855 100644
--- a/llvm/include/llvm/IR/InstVisitor.h
+++ b/llvm/include/llvm/IR/InstVisitor.h
@@ -186,6 +186,7 @@ class InstVisitor {
   RetTy visitPtrToAddrInst(PtrToAddrInst &I)      { DELEGATE(CastInst);}
   RetTy visitIntToPtrInst(IntToPtrInst &I)        { DELEGATE(CastInst);}
   RetTy visitBitCastInst(BitCastInst &I)          { DELEGATE(CastInst);}
+  RetTy visitByteCastInst(ByteCastInst &I)        { DELEGATE(CastInst);}
   RetTy visitAddrSpaceCastInst(AddrSpaceCastInst &I) { DELEGATE(CastInst);}
   RetTy visitSelectInst(SelectInst &I)            { DELEGATE(Instruction);}
   RetTy visitVAArgInst(VAArgInst   &I)            { DELEGATE(UnaryInstruction);}
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 5f7df6a4eb6f8..22ca047ecb22c 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -89,7 +89,7 @@ class UnaryInstruction : public Instruction {
            I->getOpcode() == Instruction::VAArg ||
            I->getOpcode() == Instruction::ExtractValue ||
            I->getOpcode() == Instruction::Freeze ||
-           (I->getOpcode() >= CastOpsBegin && I->getOpcode() < CastOpsEnd);
+           I->isCast();
   }
   static bool classof(const Value *V) {
     return isa<Instruction>(V) && classof(cast<Instruction>(V));
diff --git a/llvm/include/llvm/IR/Instruction.def b/llvm/include/llvm/IR/Instruction.def
index 949a9d0beecb4..b3ef4fed44d60 100644
--- a/llvm/include/llvm/IR/Instruction.def
+++ b/llvm/include/llvm/IR/Instruction.def
@@ -196,6 +196,9 @@ HANDLE_CAST_INST(49, PtrToAddr, PtrToAddrInst) // Pointer -> Address
 HANDLE_CAST_INST(50, IntToPtr, IntToPtrInst)  // Integer -> Pointer
 HANDLE_CAST_INST(51, BitCast , BitCastInst )  // Type cast
 HANDLE_CAST_INST(52, AddrSpaceCast, AddrSpaceCastInst)  // addrspace cast
+// ByteCast uses the terminal opcode so existing opcodes remain stable. It is
+// handled explicitly where code relies on the contiguous cast range.
+HANDLE_CAST_INST(70, ByteCast, ByteCastInst)  // Byte type cast
   LAST_CAST_INST(52)
 
  FIRST_FUNCLETPAD_INST(53)
diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index a6ef59c85265c..37919fced86cb 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -374,7 +374,8 @@ class Instruction : public User,
 
   /// Determine if the Opcode is one of the CastInst instructions.
   static inline bool isCast(unsigned Opcode) {
-    return Opcode >= CastOpsBegin && Opcode < CastOpsEnd;
+    return (Opcode >= CastOpsBegin && Opcode < CastOpsEnd) ||
+           Opcode == ByteCast;
   }
 
   /// Determine if the Opcode is one of the FuncletPadInst instructions.
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index 00d689283479f..445b682f5458b 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -5182,6 +5182,34 @@ class BitCastInst : public CastInst {
   }
 };
 
+//===----------------------------------------------------------------------===//
+//                           ByteCastInst Class
+//===----------------------------------------------------------------------===//
+
+/// This class represents a byte type cast instruction.
+class ByteCastInst : public CastInst {
+protected:
+  friend class Instruction;
+  LLVM_ABI ByteCastInst *cloneImpl() const;
+
+public:
+  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));
+  }
+};
+
 //===----------------------------------------------------------------------===//
 //                          AddrSpaceCastInst Class
 //===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h
index c44cddca93009..32482ac0c891e 100644
--- a/llvm/include/llvm/IR/Operator.h
+++ b/llvm/include/llvm/IR/Operator.h
@@ -610,6 +610,30 @@ struct OperandTraits<BitCastOperator>
 
 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BitCastOperator, Value)
 
+class ByteCastOperator
+    : public ConcreteOperator<Operator, Instruction::ByteCast> {
+  friend class ByteCastInst;
+  friend class ConstantExpr;
+
+public:
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+  Type *getSrcTy() const {
+    return getOperand(0)->getType();
+  }
+
+  Type *getDestTy() const {
+    return getType();
+  }
+};
+
+template <>
+struct OperandTraits<ByteCastOperator>
+    : public FixedNumOperandTraits<ByteCastOperator, 1> {};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ByteCastOperator, Value)
+
 class AddrSpaceCastOperator
     : public ConcreteOperator<Operator, Instruction::AddrSpaceCast> {
   friend class AddrSpaceCastInst;
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 069a180056488..0f2e348cf5294 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -963,6 +963,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   INSTKEYWORD(ptrtoaddr,   PtrToAddr);
   INSTKEYWORD(ptrtoint,    PtrToInt);
   INSTKEYWORD(bitcast,     BitCast);
+  INSTKEYWORD(bytecast,    ByteCast);
   INSTKEYWORD(addrspacecast, AddrSpaceCast);
   INSTKEYWORD(select,      Select);
   INSTKEYWORD(va_arg,      VAArg);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 477bcebccf2ad..5052bd07a7113 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1349,6 +1349,7 @@ bool LLParser::parseAliasOrIFunc(const std::string &Name, unsigned NameID,
   Constant *Aliasee;
   LocTy AliaseeLoc = Lex.getLoc();
   if (Lex.getKind() != lltok::kw_bitcast &&
+      Lex.getKind() != lltok::kw_bytecast &&
       Lex.getKind() != lltok::kw_getelementptr &&
       Lex.getKind() != lltok::kw_addrspacecast &&
       Lex.getKind() != lltok::kw_inttoptr) {
@@ -4684,6 +4685,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:
@@ -7880,6 +7882,7 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
   }
   case lltok::kw_sext:
   case lltok::kw_bitcast:
+  case lltok::kw_bytecast:
   case lltok::kw_fptoui:
   case lltok::kw_fptosi:
   case lltok::kw_inttoptr:
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 75f3023e479c5..534848466b643 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -272,6 +272,9 @@ class IRTranslatorImpl {
   /// emitted.
   bool translateBitCast(const User &U, MachineIRBuilder &MIRBuilder);
 
+  /// Translate an LLVM bytecast into generic IR.
+  bool translateByteCast(const User &U, MachineIRBuilder &MIRBuilder);
+
   /// Translate an LLVM load instruction into generic IR.
   bool translateLoad(const User &U, MachineIRBuilder &MIRBuilder);
 
@@ -2368,6 +2371,11 @@ bool IRTranslatorImpl::translateBitCast(const User &U,
   return translateCast(TargetOpcode::G_BITCAST, U, MIRBuilder);
 }
 
+bool IRTranslatorImpl::translateByteCast(const User &U,
+                                         MachineIRBuilder &MIRBuilder) {
+  return translateBitCast(U, MIRBuilder);
+}
+
 bool IRTranslatorImpl::translateCast(unsigned Opcode, const User &U,
                                      MachineIRBuilder &MIRBuilder) {
   if (!mayTranslateUserTypes(U))
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index f34f1c7e9c969..1216082cb337c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4167,6 +4167,10 @@ void SelectionDAGBuilder::visitBitCast(const User &I) {
     setValue(&I, N);            // noop cast.
 }
 
+void SelectionDAGBuilder::visitByteCast(const User &I) {
+  visitBitCast(I);
+}
+
 void SelectionDAGBuilder::visitAddrSpaceCast(const User &I) {
   const TargetLowering &TLI = DAG.getTargetLoweringInfo();
   const Value *SV = I.getOperand(0);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index e4e958cba5ac2..3cbcafe9b0769 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -604,6 +604,7 @@ class SelectionDAGBuilder {
   void visitPtrToInt(const User &I);
   void visitIntToPtr(const User &I);
   void visitBitCast(const User &I);
+  void visitByteCast(const User &I);
   void visitAddrSpaceCast(const User &I);
 
   void visitExtractElement(const User &I);
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index f8abd576f93c4..247284af781d4 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -284,6 +284,8 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
   }
   case Instruction::BitCast:
     return FoldBitCast(V, DestTy);
+  case Instruction::ByteCast:
+    return FoldBitCast(V, DestTy);
   case Instruction::AddrSpaceCast:
   case Instruction::IntToPtr:
   case Instruction::PtrToAddr:
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 675cdaf6f1689..c7e41cf10fc4b 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -1704,6 +1704,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:
@@ -2388,6 +2389,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);
   }
@@ -2493,6 +2496,17 @@ 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 bytecast!");
+
+  if (C->getType() == DstTy)
+    return C;
+
+  return getFoldedCast(Instruction::ByteCast, C, DstTy, OnlyIfReduced);
+}
+
 Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy,
                                          bool OnlyIfReduced) {
   assert(CastInst::castIsValid(Instruction::AddrSpaceCast, C, DstTy) &&
@@ -2612,6 +2626,7 @@ bool ConstantExpr::isDesirableCastOp(unsigned Opcode) {
   case Instruction::PtrToInt:
   case Instruction::IntToPtr:
   case Instruction::BitCast:
+  case Instruction::ByteCast:
   case Instruction::AddrSpaceCast:
     return true;
   default:
@@ -2635,6 +2650,7 @@ bool ConstantExpr::isSupportedCastOp(unsigned Opcode) {
   case Instruction::PtrToInt:
   case Instruction::IntToPtr:
   case Instruction::BitCast:
+  case Instruction::ByteCast:
   case Instruction::AddrSpaceCast:
     return true;
   default:
@@ -3687,6 +3703,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/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index 2cfd9fb902886..7139f91620f00 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -883,6 +883,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
   case PtrToAddr:     return "ptrtoaddr";
   case PtrToInt:      return "ptrtoint";
   case BitCast:       return "bitcast";
+  case ByteCast:      return "bytecast";
   case AddrSpaceCast: return "addrspacecast";
 
   // Other instructions...
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 325850b0a880d..f62bee8309a21 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -2859,6 +2859,8 @@ bool CastInst::isNoopCast(Instruction::CastOps Opcode,
       return false;
     case Instruction::BitCast:
       return true;  // BitCast never modifies bits.
+    case Instruction::ByteCast:
+      return true;  // ByteCast never modifies bits.
     case Instruction::PtrToAddr:
     case Instruction::PtrToInt:
       return DL.getIntPtrType(SrcTy)->getScalarSizeInBits() ==
@@ -2918,6 +2920,26 @@ unsigned CastInst::isEliminableCastPair(Instruction::CastOps firstOp,
   // same reason.
   const unsigned numCastOps =
     Instruction::CastOpsEnd - Instruction::CastOpsBegin;
+
+  // ByteCast deliberately has a non-contiguous opcode so introducing it does
+  // not renumber existing instructions. Handle combinations involving it
+  // conservatively before indexing the contiguous cast table.
+  if (firstOp == Instruction::ByteCast ||
+      secondOp == Instruction::ByteCast) {
+    bool FirstIsNoop = firstOp == Instruction::BitCast ||
+                       firstOp == Instruction::ByteCast;
+    bool SecondIsNoop = secondOp == Instruction::BitCast ||
+                        secondOp == Instruction::ByteCast;
+    if (!FirstIsNoop || !SecondIsNoop)
+      return 0;
+
+    Instruction::CastOps Result =
+        SrcTy->isByteOrByteVectorTy() || DstTy->isByteOrByteVectorTy()
+            ? Instruction::ByteCast
+            : Instruction::BitCast;
+    return castIsValid(Result, SrcTy, DstTy) ? Result : 0;
+  }
+
   // clang-format off
   static const uint8_t CastResults[numCastOps][numCastOps] = {
     // T        F  F  U  S  F  F  P  P  I  B  A  -+
@@ -3125,6 +3147,8 @@ CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
   case IntToPtr:      return new IntToPtrInst      (S, Ty, Name, InsertBefore);
   case BitCast:
     return new BitCastInst(S, Ty, Name, InsertBefore);
+  case ByteCast:
+    return new ByteCastInst(S, Ty, Name, InsertBefore);
   case AddrSpaceCast:
     return new AddrSpaceCastInst(S, Ty, Name, InsertBefore);
   default:
@@ -3272,6 +3296,12 @@ bool CastInst::isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy,
   return isBitCastable(SrcTy, DestTy);
 }
 
+static Instruction::CastOps getNoopCastOpcode(Type *SrcTy, Type *DestTy) {
+  if (SrcTy->isByteOrByteVectorTy() || DestTy->isByteOrByteVectorTy())
+    return Instruction::ByteCast;
+  return Instruction::BitCast;
+}
+
 // Provide a way to get a "cast" where the cast opcode is inferred from the
 // types and size of the operand. This, basically, is a parallel of the
 // logic in the castIsValid function below.  This axiom should hold:
@@ -3308,15 +3338,30 @@ CastInst::getCastOpcode(
       DestTy->getPrimitiveSizeInBits().getFixedValue(); // 0 for ptr
 
   // Run through the possibilities ...
-  if (DestTy->isByteTy()) {     // Casting to byte
-    if (SrcTy->isIntegerTy()) { // Casting from integral
-      assert(DestBits == SrcBits && "Illegal cast from integer to byte type");
-      return BitCast;
+  if (DestTy->isByteOrByteVectorTy()) { // Casting to byte
+    if (SrcTy->isIntegerTy() || SrcTy->isByteOrByteVectorTy()) {
+      assert(DestBits == SrcBits && "Illegal cast to byte type");
+      return ByteCast;
     } else if (SrcTy->isPointerTy()) { // Casting from pointer
       assert(DestBits == SrcBits && "Illegal cast from pointer to byte type");
-      return BitCast;
+      return ByteCast;
+    } else if (SrcTy->isFloatingPointTy()) {
+      assert(DestBits == SrcBits && "Illegal cast to byte type");
+      return ByteCast;
     }
     llvm_unreachable("Illegal cast to byte type");
+  } else if (SrcTy->isByteOrByteVectorTy()) { // Casting from byte
+    if (DestTy->isIntegerTy() || DestTy->isFloatingPointTy()) {
+      assert(DestBits == SrcBits && "Illegal cast from byte type");
+      return ByteCast;
+    } else if (DestTy->isPointerTy()) {
+      assert(DestBits == SrcBits && "Illegal cast from byte to pointer type");
+      return ByteCast;
+    } else if (DestTy->isVectorTy()) {
+      assert(DestBits == SrcBits && "Illegal cast from byte type");
+      return ByteCast;
+    }
+    llvm_unreachable("Illegal cast from byte type");
   } else if (DestTy->isIntegerTy()) {               // Casting to integral
     if (SrcTy->isIntegerTy()) {                     // Casting from integral
       if (DestBits < SrcBits)
@@ -3327,7 +3372,7 @@ CastInst::getCastOpcode(
         else
           return ZExt;                              // unsigned -> ZEXT
       } else {
-        return BitCast;                             // Same size, No-op cast
+        return getNoopCastOpcode(SrcTy, DestTy);  // Same size, No-op cast
       }
     } else if (SrcTy->isFloatingPointTy()) {        // Casting from floating pt
       if (DestIsSigned)
@@ -3337,7 +3382,7 @@ CastInst::getCastOpcode(
     } else if (SrcTy->isVectorTy()) {
       assert(DestBits == SrcBits &&
              "Casting vector to integer of different width");
-      return BitCast;                             // Same size, no-op cast
+      return getNoopCastOpcode(SrcTy, DestTy);    // Same size, no-op cast
     } else {
       assert(SrcTy->isPointerTy() &&
              "Casting from a value that is not first-class type");
@@ -33...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/221882


More information about the llvm-commits mailing list