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

Anshil Gandhi via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 7 23:04:41 PDT 2026


https://github.com/gandhi56 created https://github.com/llvm/llvm-project/pull/221884

## Summary
- Add a dedicated `bytecast` instruction (opcode 70) for reinterpretation involving byte types (`b8`, `b16`, `b32`, `b64`), separate from `bitcast`.
- Wire up IR support: `ByteCastInst`, verifier, constant folding, asm parser/lexer, visitor, and minimal CodeGen stubs (SelectionDAG/GlobalISel delegate to bitcast for now).
- Update llubi and IR2Vec tests for the new opcode and migrated byte-related casts.

## Test plan
- [x] `ninja check-llvm` passes on this branch
- [ ] Review IR2Vec embedding/index updates
- [ ] Confirm backward compatibility for legacy byte-related `bitcast` in text IR


Made with [Cursor](https://cursor.com)

>From be70468b11b517cfdca424acc00b50ffe4caf286 Mon Sep 17 00:00:00 2001
From: Anshil Gandhi <Anshil.Gandhi at amd.com>
Date: Mon, 7 Sep 2026 07:45:40 -0500
Subject: [PATCH] [IR] Add ByteCast opcode and ByteCastInst

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.

Co-authored-by: Cursor <cursoragent at cursor.com>
---
 llvm/include/llvm-c/Core.h                    |  1 +
 llvm/include/llvm/Analysis/IR2Vec.h           |  4 +-
 llvm/include/llvm/AsmParser/LLToken.h         |  1 +
 llvm/include/llvm/IR/Constants.h              |  2 +
 llvm/include/llvm/IR/InstVisitor.h            |  1 +
 llvm/include/llvm/IR/InstrTypes.h             |  2 +-
 llvm/include/llvm/IR/Instruction.def          |  3 +
 llvm/include/llvm/IR/Instruction.h            |  3 +-
 llvm/include/llvm/IR/Instructions.h           | 28 ++++++
 llvm/include/llvm/IR/Operator.h               | 24 +++++
 llvm/lib/AsmParser/LLLexer.cpp                |  1 +
 llvm/lib/AsmParser/LLParser.cpp               |  3 +
 llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp  |  8 ++
 .../SelectionDAG/SelectionDAGBuilder.cpp      |  4 +
 .../SelectionDAG/SelectionDAGBuilder.h        |  1 +
 llvm/lib/IR/ConstantFold.cpp                  |  2 +
 llvm/lib/IR/Constants.cpp                     | 17 ++++
 llvm/lib/IR/Instruction.cpp                   |  1 +
 llvm/lib/IR/Instructions.cpp                  | 95 ++++++++++++++++---
 llvm/lib/IR/Verifier.cpp                      | 12 +++
 .../Inputs/reference_default_vocab_print.txt  |  1 +
 .../Inputs/reference_wtd1_vocab_print.txt     |  1 +
 .../Inputs/reference_wtd2_vocab_print.txt     |  1 +
 llvm/test/tools/llubi/bitcast_be.ll           | 12 +--
 llvm/test/tools/llubi/bitcast_le.ll           | 12 +--
 llvm/test/tools/llubi/bytes_undef.ll          |  8 +-
 llvm/test/tools/llubi/freeze.ll               |  4 +-
 llvm/test/tools/llubi/loadstore_be.ll         | 12 +--
 llvm/test/tools/llubi/loadstore_le.ll         | 12 +--
 llvm/test/tools/llvm-ir2vec/entities.ll       | 89 ++++++++---------
 llvm/test/tools/llvm-ir2vec/triplets.ll       | 58 +++++------
 llvm/tools/llubi/lib/Context.cpp              |  3 +-
 llvm/tools/llubi/lib/Interpreter.cpp          | 13 ++-
 llvm/unittests/Analysis/IR2VecTest.cpp        | 28 +++---
 34 files changed, 327 insertions(+), 140 deletions(-)

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");
@@ -3355,18 +3400,18 @@ CastInst::getCastOpcode(
       } else if (DestBits > SrcBits) {
         return FPExt;                               // FP -> larger FP
       } else  {
-        return BitCast;                             // same size, no-op cast
+        return getNoopCastOpcode(SrcTy, DestTy);  // same size, no-op cast
       }
     } else if (SrcTy->isVectorTy()) {
       assert(DestBits == SrcBits &&
              "Casting vector to floating point of different width");
-      return BitCast;                             // same size, no-op cast
+      return getNoopCastOpcode(SrcTy, DestTy);  // same size, no-op cast
     }
     llvm_unreachable("Casting pointer or non-first class to float");
   } else if (DestTy->isVectorTy()) {
     assert(DestBits == SrcBits &&
            "Illegal cast to vector (wrong type or size)");
-    return BitCast;
+    return getNoopCastOpcode(SrcTy, DestTy);
   } else if (DestTy->isPointerTy()) {
     if (SrcTy->isPointerTy()) {
       if (DestTy->getPointerAddressSpace() != SrcTy->getPointerAddressSpace())
@@ -3448,8 +3493,8 @@ CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
     PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
     PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
 
-    // BitCast implies a no-op cast of type only. No bits change.
-    // However, you can't cast pointers to anything but pointers/bytes.
+    // Keep accepting legacy bitcasts involving byte types while producers and
+    // tests migrate to the dedicated ByteCast opcode.
     if ((SrcPtrTy && DstTy->isByteOrByteVectorTy()) ||
         (SrcTy->isByteOrByteVectorTy() && DstPtrTy))
       return true;
@@ -3475,6 +3520,22 @@ CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
 
     return true;
   }
+  case Instruction::ByteCast: {
+    bool SrcHasByte = SrcTy->isByteOrByteVectorTy();
+    bool DstHasByte = DstTy->isByteOrByteVectorTy();
+    if (!SrcHasByte && !DstHasByte)
+      return false;
+
+    PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
+    PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
+
+    // As with legacy byte-related bitcasts, opaque pointers do not provide
+    // enough type information to compare widths here.
+    if ((SrcPtrTy && DstHasByte) || (SrcHasByte && DstPtrTy))
+      return true;
+
+    return SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits();
+  }
   case Instruction::AddrSpaceCast: {
     PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
     if (!SrcPtrTy)
@@ -3570,6 +3631,12 @@ BitCastInst::BitCastInst(Value *S, Type *Ty, const Twine &Name,
   assert(castIsValid(getOpcode(), S, Ty) && "Illegal BitCast");
 }
 
+ByteCastInst::ByteCastInst(Value *S, Type *Ty, const Twine &Name,
+                           InsertPosition InsertBefore)
+    : CastInst(Ty, ByteCast, S, Name, InsertBefore) {
+  assert(castIsValid(getOpcode(), S, Ty) && "Illegal ByteCast");
+}
+
 AddrSpaceCastInst::AddrSpaceCastInst(Value *S, Type *Ty, const Twine &Name,
                                      InsertPosition InsertBefore)
     : CastInst(Ty, AddrSpaceCast, S, Name, InsertBefore) {
@@ -4545,6 +4612,10 @@ BitCastInst *BitCastInst::cloneImpl() const {
   return new BitCastInst(getOperand(0), getType());
 }
 
+ByteCastInst *ByteCastInst::cloneImpl() const {
+  return new ByteCastInst(getOperand(0), getType());
+}
+
 AddrSpaceCastInst *AddrSpaceCastInst::cloneImpl() const {
   return new AddrSpaceCastInst(getOperand(0), getType());
 }
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 20df60ed61da3..88ee0bf692e05 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -418,6 +418,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
   void visitPtrToAddrInst(PtrToAddrInst &I);
   void visitPtrToIntInst(PtrToIntInst &I);
   void visitBitCastInst(BitCastInst &I);
+  void visitByteCastInst(ByteCastInst &I);
   void visitAddrSpaceCastInst(AddrSpaceCastInst &I);
   void visitPHINode(PHINode &PN);
   void visitCallBase(CallBase &Call);
@@ -2879,6 +2880,10 @@ void Verifier::visitConstantExpr(const ConstantExpr *CE) {
     Check(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0),
                                 CE->getType()),
           "Invalid bitcast", CE);
+  else if (CE->getOpcode() == Instruction::ByteCast)
+    Check(CastInst::castIsValid(Instruction::ByteCast, CE->getOperand(0),
+                                CE->getType()),
+          "Invalid bytecast", CE);
   else if (CE->getOpcode() == Instruction::PtrToAddr)
     checkPtrToAddr(CE->getOperand(0)->getType(), CE->getType(), *CE);
 }
@@ -3907,6 +3912,13 @@ void Verifier::visitBitCastInst(BitCastInst &I) {
   visitInstruction(I);
 }
 
+void Verifier::visitByteCastInst(ByteCastInst &I) {
+  Check(CastInst::castIsValid(Instruction::ByteCast, I.getOperand(0),
+                              I.getType()),
+        "Invalid bytecast", &I);
+  visitInstruction(I);
+}
+
 void Verifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) {
   Type *SrcTy = I.getOperand(0)->getType();
   Type *DestTy = I.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 cc36415abb00b..f8c852019e3ab 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_default_vocab_print.txt
@@ -67,6 +67,7 @@ Key: ExtractValue:  [ 127.00  128.00 ]
 Key: InsertValue:  [ 129.00  130.00 ]
 Key: LandingPad:  [ 131.00  132.00 ]
 Key: Freeze:  [ 133.00  134.00 ]
+Key: ByteCast:  [ 0.00  0.00 ]
 Key: FloatTy:  [ 0.50  1.00 ]
 Key: VoidTy:  [ 1.50  2.00 ]
 Key: LabelTy:  [ 2.50  3.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 8d837e9502739..c6bbcd833e92d 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd1_vocab_print.txt
@@ -67,6 +67,7 @@ Key: ExtractValue:  [ 63.50  64.00 ]
 Key: InsertValue:  [ 64.50  65.00 ]
 Key: LandingPad:  [ 65.50  66.00 ]
 Key: Freeze:  [ 66.50  67.00 ]
+Key: ByteCast:  [ 0.00  0.00 ]
 Key: FloatTy:  [ 0.50  1.00 ]
 Key: VoidTy:  [ 1.50  2.00 ]
 Key: LabelTy:  [ 2.50  3.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 3d31b9d9db315..6af5772992ac9 100644
--- a/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
+++ b/llvm/test/Analysis/IR2Vec/Inputs/reference_wtd2_vocab_print.txt
@@ -67,6 +67,7 @@ Key: ExtractValue:  [ 12.70  12.80 ]
 Key: InsertValue:  [ 12.90  13.00 ]
 Key: LandingPad:  [ 13.10  13.20 ]
 Key: Freeze:  [ 13.30  13.40 ]
+Key: ByteCast:  [ 0.00  0.00 ]
 Key: FloatTy:  [ 0.00  0.00 ]
 Key: VoidTy:  [ 0.00  0.00 ]
 Key: LabelTy:  [ 0.00  0.00 ]
diff --git a/llvm/test/tools/llubi/bitcast_be.ll b/llvm/test/tools/llubi/bitcast_be.ll
index d0b3163669c40..20010d095fa00 100644
--- a/llvm/test/tools/llubi/bitcast_be.ll
+++ b/llvm/test/tools/llubi/bitcast_be.ll
@@ -30,9 +30,9 @@ entry:
   %bitcast_intvec2floatvec = bitcast <2 x i32> <i32 1, i32 2> to <4 x half>
   %bitcast_floatvec2int = bitcast <4 x half> <half 1.0, half 2.0, half 3.0, half 4.0> to i64
 
-  %bitcast_ptr2b64 = bitcast ptr %ptr to b64
-  %bitcast_b642i64 = bitcast b64 %bitcast_ptr2b64 to i64
-  %bitcast_b642ptr = bitcast b64 %bitcast_ptr2b64 to ptr
+  %bitcast_ptr2b64 = bytecast ptr %ptr to b64
+  %bitcast_b642i64 = bytecast b64 %bitcast_ptr2b64 to i64
+  %bitcast_b642ptr = bytecast b64 %bitcast_ptr2b64 to ptr
   ret void
 }
 ; CHECK: Entering function: main
@@ -58,8 +58,8 @@ entry:
 ; CHECK-NEXT:   %bitcast_vec2vec_weird = bitcast <8 x i3> <i3 0, i3 1, i3 2, i3 3, i3 -4, i3 -3, i3 -2, i3 -1> to <3 x i8> => { i8 5, i8 57, i8 119 }
 ; CHECK-NEXT:   %bitcast_intvec2floatvec = bitcast <2 x i32> <i32 1, i32 2> to <4 x half> => { half 0.000000e+00, half 5.960460e-08, half 0.000000e+00, half 1.192090e-07 }
 ; CHECK-NEXT:   %bitcast_floatvec2int = bitcast <4 x half> <half 1.000000e+00, half 2.000000e+00, half 3.000000e+00, half 4.000000e+00> to i64 => i64 4323526012127167488
-; CHECK-NEXT:   %bitcast_ptr2b64 = bitcast ptr %ptr to b64 => b64 ptr 0x8 [ptr]
-; CHECK-NEXT:   %bitcast_b642i64 = bitcast b64 %bitcast_ptr2b64 to i64 => i64 8
-; CHECK-NEXT:   %bitcast_b642ptr = bitcast b64 %bitcast_ptr2b64 to ptr => ptr 0x8 [ptr]
+; CHECK-NEXT:   %bitcast_ptr2b64 = bytecast ptr %ptr to b64 => b64 ptr 0x8 [ptr]
+; CHECK-NEXT:   %bitcast_b642i64 = bytecast b64 %bitcast_ptr2b64 to i64 => i64 8
+; CHECK-NEXT:   %bitcast_b642ptr = bytecast b64 %bitcast_ptr2b64 to ptr => ptr 0x8 [ptr]
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: Exiting function: main
diff --git a/llvm/test/tools/llubi/bitcast_le.ll b/llvm/test/tools/llubi/bitcast_le.ll
index acb4af6dd73d9..b2888c66560d9 100644
--- a/llvm/test/tools/llubi/bitcast_le.ll
+++ b/llvm/test/tools/llubi/bitcast_le.ll
@@ -30,9 +30,9 @@ entry:
   %bitcast_intvec2floatvec = bitcast <2 x i32> <i32 1, i32 2> to <4 x half>
   %bitcast_floatvec2int = bitcast <4 x half> <half 1.0, half 2.0, half 3.0, half 4.0> to i64
 
-  %bitcast_ptr2b64 = bitcast ptr %ptr to b64
-  %bitcast_b642i64 = bitcast b64 %bitcast_ptr2b64 to i64
-  %bitcast_b642ptr = bitcast b64 %bitcast_ptr2b64 to ptr
+  %bitcast_ptr2b64 = bytecast ptr %ptr to b64
+  %bitcast_b642i64 = bytecast b64 %bitcast_ptr2b64 to i64
+  %bitcast_b642ptr = bytecast b64 %bitcast_ptr2b64 to ptr
   ret void
 }
 ; CHECK: Entering function: main
@@ -58,8 +58,8 @@ entry:
 ; CHECK-NEXT:   %bitcast_vec2vec_weird = bitcast <8 x i3> <i3 0, i3 1, i3 2, i3 3, i3 -4, i3 -3, i3 -2, i3 -1> to <3 x i8> => { i8 -120, i8 -58, i8 -6 }
 ; CHECK-NEXT:   %bitcast_intvec2floatvec = bitcast <2 x i32> <i32 1, i32 2> to <4 x half> => { half 5.960460e-08, half 0.000000e+00, half 1.192090e-07, half 0.000000e+00 }
 ; CHECK-NEXT:   %bitcast_floatvec2int = bitcast <4 x half> <half 1.000000e+00, half 2.000000e+00, half 3.000000e+00, half 4.000000e+00> to i64 => i64 4899988963420290048
-; CHECK-NEXT:   %bitcast_ptr2b64 = bitcast ptr %ptr to b64 => b64 ptr 0x8 [ptr]
-; CHECK-NEXT:   %bitcast_b642i64 = bitcast b64 %bitcast_ptr2b64 to i64 => i64 8
-; CHECK-NEXT:   %bitcast_b642ptr = bitcast b64 %bitcast_ptr2b64 to ptr => ptr 0x8 [ptr]
+; CHECK-NEXT:   %bitcast_ptr2b64 = bytecast ptr %ptr to b64 => b64 ptr 0x8 [ptr]
+; CHECK-NEXT:   %bitcast_b642i64 = bytecast b64 %bitcast_ptr2b64 to i64 => i64 8
+; CHECK-NEXT:   %bitcast_b642ptr = bytecast b64 %bitcast_ptr2b64 to ptr => ptr 0x8 [ptr]
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: Exiting function: main
diff --git a/llvm/test/tools/llubi/bytes_undef.ll b/llvm/test/tools/llubi/bytes_undef.ll
index bd0d07a59abc8..7ed590340a0c1 100644
--- a/llvm/test/tools/llubi/bytes_undef.ll
+++ b/llvm/test/tools/llubi/bytes_undef.ll
@@ -7,15 +7,15 @@ define void @main() {
   %undef = alloca b8
   %load_undef1 = load b8, ptr %undef
   %load_undef2 = load b8, ptr %undef
-  %bitcast_undef1 = bitcast b8 %load_undef1 to i8
-  %bitcast_undef2 = bitcast b8 %load_undef1 to i8
+  %bitcast_undef1 = bytecast b8 %load_undef1 to i8
+  %bitcast_undef2 = bytecast b8 %load_undef1 to i8
   ret void
 }
 ; CHECK: Entering function: main
 ; CHECK-NEXT:   %undef = alloca b8, align 1 => ptr 0x8 [undef]
 ; CHECK-NEXT:   %load_undef1 = load b8, ptr %undef, align 1 => b8 0x!! 
 ; CHECK-NEXT:   %load_undef2 = load b8, ptr %undef, align 1 => b8 0x!! 
-; CHECK-NEXT:   %bitcast_undef1 = bitcast b8 %load_undef1 to i8 => poison
-; CHECK-NEXT:   %bitcast_undef2 = bitcast b8 %load_undef1 to i8 => poison
+; CHECK-NEXT:   %bitcast_undef1 = bytecast b8 %load_undef1 to i8 => poison
+; CHECK-NEXT:   %bitcast_undef2 = bytecast b8 %load_undef1 to i8 => poison
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: Exiting function: main
diff --git a/llvm/test/tools/llubi/freeze.ll b/llvm/test/tools/llubi/freeze.ll
index a5b21682a32f8..d842d09282324 100644
--- a/llvm/test/tools/llubi/freeze.ll
+++ b/llvm/test/tools/llubi/freeze.ll
@@ -23,7 +23,7 @@ define void @main() {
   %byte_with_provenance = load b8, ptr %alloca
   %vec_bytes1 = insertelement <4 x b8> <b8 0, b8 poison, b8 poison, b8 poison>, b8 %byte_undef, i32 2
   %vec_bytes2 = insertelement <4 x b8> %vec_bytes1, b8 %byte_with_provenance, i32 3
-  %bytes = bitcast <4 x b8> %vec_bytes2 to b32
+  %bytes = bytecast <4 x b8> %vec_bytes2 to b32
   %bytes_freeze = freeze b32 %bytes
   ret void
 }
@@ -45,7 +45,7 @@ define void @main() {
 ; CHECK-NEXT:   %byte_with_provenance = load b8, ptr %alloca, align 1 => b8 00001000(00011001) 
 ; CHECK-NEXT:   %vec_bytes1 = insertelement <4 x b8> <b8 0, b8 poison, b8 poison, b8 poison>, b8 %byte_undef, i32 2 => { b8 0x00 , b8 0x!! , b8 0x!! , b8 0x!!  }
 ; CHECK-NEXT:   %vec_bytes2 = insertelement <4 x b8> %vec_bytes1, b8 %byte_with_provenance, i32 3 => { b8 0x00 , b8 0x!! , b8 0x!! , b8 00001000(00011001)  }
-; CHECK-NEXT:   %bytes = bitcast <4 x b8> %vec_bytes2 to b32 => b32 0x00 0x!! 0x!! 00001000(00011001) 
+; CHECK-NEXT:   %bytes = bytecast <4 x b8> %vec_bytes2 to b32 => b32 0x00 0x!! 0x!! 00001000(00011001) 
 ; CHECK-NEXT:   %bytes_freeze = freeze b32 %bytes => b32 0x00 0x13 0xF8 00001000(00011001) 
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: Exiting function: main
diff --git a/llvm/test/tools/llubi/loadstore_be.ll b/llvm/test/tools/llubi/loadstore_be.ll
index fe2733dc8149c..be40bff06db4f 100644
--- a/llvm/test/tools/llubi/loadstore_be.ll
+++ b/llvm/test/tools/llubi/loadstore_be.ll
@@ -123,7 +123,7 @@ define void @main() {
   store b64 %bytes, ptr %alloc_ptr
   ; It should recover the provenance.
   %ptr_with_provenance2 = load ptr, ptr %alloc_ptr
-  %bv64b1 = bitcast b64 %bytes to <64 x b1>
+  %bv64b1 = bytecast b64 %bytes to <64 x b1>
   %bv64b1_reversed = call <64 x b1> @llvm.vector.reverse(<64 x b1> %bv64b1)
   store <64 x b1> %bv64b1_reversed, ptr %alloc_ptr
   ; The bit order is incorrect. We cannot recover the provenance.
@@ -133,9 +133,9 @@ define void @main() {
   %bytes_tainted = load b64, ptr %alloc_ptr
   ; The first byte is tainted. We cannot recover the provenance.
   %ptr_without_provenance3 = load ptr, ptr %alloc_ptr
-  %bv8b8_reversed = bitcast <64 x b1> %bv64b1_reversed to <8 x b8>
+  %bv8b8_reversed = bytecast <64 x b1> %bv64b1_reversed to <8 x b8>
   %first_byte_with_provenance_reversed = extractelement <8 x b8> %bv8b8_reversed, i32 7
-  %first_byte_with_provenance_reversed_v8b1 = bitcast b8 %first_byte_with_provenance_reversed to <8 x b1>
+  %first_byte_with_provenance_reversed_v8b1 = bytecast b8 %first_byte_with_provenance_reversed to <8 x b1>
   %first_byte_with_provenance_v8b1 = call <8 x b1> @llvm.vector.reverse(<8 x b1> %first_byte_with_provenance_reversed_v8b1)
   store <8 x b1> %first_byte_with_provenance_v8b1, ptr %alloc_ptr
   %bytes_recovered = load b64, ptr %alloc_ptr
@@ -258,7 +258,7 @@ define void @main() {
 ; CHECK-NEXT:   %ptr_without_provenance = load ptr, ptr %alloc_ptr, align 8 => ptr 0xC0 [nullary]
 ; CHECK-NEXT:   store b64 %bytes, ptr %alloc_ptr, align 8
 ; CHECK-NEXT:   %ptr_with_provenance2 = load ptr, ptr %alloc_ptr, align 8 => ptr 0xC0 [alloc_ptr]
-; CHECK-NEXT:   %bv64b1 = bitcast b64 %bytes to <64 x b1> => { b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 1(0) , b1 1(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0)  }
+; CHECK-NEXT:   %bv64b1 = bytecast b64 %bytes to <64 x b1> => { b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 1(0) , b1 1(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0)  }
 ; CHECK-NEXT:   %bv64b1_reversed = call <64 x b1> @llvm.vector.reverse.v64b1(<64 x b1> %bv64b1) => { b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(1) , b1 1(0) , b1 1(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0)  }
 ; CHECK-NEXT:   store <64 x b1> %bv64b1_reversed, ptr %alloc_ptr, align 8
 ; CHECK-NEXT:   %ptr_without_provenance2 = load ptr, ptr %alloc_ptr, align 8 => ptr 0x300000000000000 [nullary]
@@ -266,9 +266,9 @@ define void @main() {
 ; CHECK-NEXT:   store <2 x b4> <b4 0, b4 poison>, ptr %alloc_ptr, align 1
 ; CHECK-NEXT:   %bytes_tainted = load b64, ptr %alloc_ptr, align 8 => b64 0000!!!! 00000000(01110001) 00000000(00111100) 00000000(00111001) 00000000(10001010) 00000000(10010101) 00000000(00001000) 11000000(00101100) 
 ; CHECK-NEXT:   %ptr_without_provenance3 = load ptr, ptr %alloc_ptr, align 8 => poison
-; CHECK-NEXT:   %bv8b8_reversed = bitcast <64 x b1> %bv64b1_reversed to <8 x b8> => { b8 00000011(00110100) , b8 00000000(00010000) , b8 00000000(10101001) , b8 00000000(01010001) , b8 00000000(10011100) , b8 00000000(00111100) , b8 00000000(10001110) , b8 00000000(01100100)  }
+; CHECK-NEXT:   %bv8b8_reversed = bytecast <64 x b1> %bv64b1_reversed to <8 x b8> => { b8 00000011(00110100) , b8 00000000(00010000) , b8 00000000(10101001) , b8 00000000(01010001) , b8 00000000(10011100) , b8 00000000(00111100) , b8 00000000(10001110) , b8 00000000(01100100)  }
 ; CHECK-NEXT:   %first_byte_with_provenance_reversed = extractelement <8 x b8> %bv8b8_reversed, i32 7 => b8 00000000(01100100) 
-; CHECK-NEXT:   %first_byte_with_provenance_reversed_v8b1 = bitcast b8 %first_byte_with_provenance_reversed to <8 x b1> => { b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0)  }
+; CHECK-NEXT:   %first_byte_with_provenance_reversed_v8b1 = bytecast b8 %first_byte_with_provenance_reversed to <8 x b1> => { b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0)  }
 ; CHECK-NEXT:   %first_byte_with_provenance_v8b1 = call <8 x b1> @llvm.vector.reverse.v8b1(<8 x b1> %first_byte_with_provenance_reversed_v8b1) => { b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0)  }
 ; CHECK-NEXT:   store <8 x b1> %first_byte_with_provenance_v8b1, ptr %alloc_ptr, align 1
 ; CHECK-NEXT:   %bytes_recovered = load b64, ptr %alloc_ptr, align 8 => b64 ptr 0xC0 [alloc_ptr] 
diff --git a/llvm/test/tools/llubi/loadstore_le.ll b/llvm/test/tools/llubi/loadstore_le.ll
index 9c434461380cc..3703a44da4fa8 100644
--- a/llvm/test/tools/llubi/loadstore_le.ll
+++ b/llvm/test/tools/llubi/loadstore_le.ll
@@ -124,7 +124,7 @@ define void @main() {
   store b64 %bytes, ptr %alloc_ptr
   ; It should recover the provenance.
   %ptr_with_provenance2 = load ptr, ptr %alloc_ptr
-  %bv64b1 = bitcast b64 %bytes to <64 x b1>
+  %bv64b1 = bytecast b64 %bytes to <64 x b1>
   %bv64b1_reversed = call <64 x b1> @llvm.vector.reverse(<64 x b1> %bv64b1)
   store <64 x b1> %bv64b1_reversed, ptr %alloc_ptr
   ; The bit order is incorrect. We cannot recover the provenance.
@@ -134,9 +134,9 @@ define void @main() {
   %bytes_tainted = load b64, ptr %alloc_ptr
   ; The first byte is tainted. We cannot recover the provenance.
   %ptr_without_provenance3 = load ptr, ptr %alloc_ptr
-  %bv8b8_reversed = bitcast <64 x b1> %bv64b1_reversed to <8 x b8>
+  %bv8b8_reversed = bytecast <64 x b1> %bv64b1_reversed to <8 x b8>
   %first_byte_with_provenance_reversed = extractelement <8 x b8> %bv8b8_reversed, i32 7
-  %first_byte_with_provenance_reversed_v8b1 = bitcast b8 %first_byte_with_provenance_reversed to <8 x b1>
+  %first_byte_with_provenance_reversed_v8b1 = bytecast b8 %first_byte_with_provenance_reversed to <8 x b1>
   %first_byte_with_provenance_v8b1 = call <8 x b1> @llvm.vector.reverse(<8 x b1> %first_byte_with_provenance_reversed_v8b1)
   store <8 x b1> %first_byte_with_provenance_v8b1, ptr %alloc_ptr
   %bytes_recovered = load b64, ptr %alloc_ptr
@@ -260,7 +260,7 @@ define void @main() {
 ; CHECK-NEXT:   %ptr_without_provenance = load ptr, ptr %alloc_ptr, align 8 => ptr 0xC0 [nullary]
 ; CHECK-NEXT:   store b64 %bytes, ptr %alloc_ptr, align 8
 ; CHECK-NEXT:   %ptr_with_provenance2 = load ptr, ptr %alloc_ptr, align 8 => ptr 0xC0 [alloc_ptr]
-; CHECK-NEXT:   %bv64b1 = bitcast b64 %bytes to <64 x b1> => { b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(1) , b1 1(0) , b1 1(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0)  }
+; CHECK-NEXT:   %bv64b1 = bytecast b64 %bytes to <64 x b1> => { b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(1) , b1 1(0) , b1 1(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0)  }
 ; CHECK-NEXT:   %bv64b1_reversed = call <64 x b1> @llvm.vector.reverse.v64b1(<64 x b1> %bv64b1) => { b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(0) , b1 0(1) , b1 0(0) , b1 0(0) , b1 0(0) , b1 1(0) , b1 1(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0)  }
 ; CHECK-NEXT:   store <64 x b1> %bv64b1_reversed, ptr %alloc_ptr, align 8
 ; CHECK-NEXT:   %ptr_without_provenance2 = load ptr, ptr %alloc_ptr, align 8 => ptr 0x300000000000000 [nullary]
@@ -268,9 +268,9 @@ define void @main() {
 ; CHECK-NEXT:   store <2 x b4> <b4 0, b4 poison>, ptr %alloc_ptr, align 1
 ; CHECK-NEXT:   %bytes_tainted = load b64, ptr %alloc_ptr, align 8 => b64 !!!!0000 00000000(00001000) 00000000(10010101) 00000000(10001010) 00000000(00111001) 00000000(00111100) 00000000(01110001) 00000000(00100110) 
 ; CHECK-NEXT:   %ptr_without_provenance3 = load ptr, ptr %alloc_ptr, align 8 => poison
-; CHECK-NEXT:   %bv8b8_reversed = bitcast <64 x b1> %bv64b1_reversed to <8 x b8> => { b8 00000000(01100100) , b8 00000000(10001110) , b8 00000000(00111100) , b8 00000000(10011100) , b8 00000000(01010001) , b8 00000000(10101001) , b8 00000000(00010000) , b8 00000011(00110100)  }
+; CHECK-NEXT:   %bv8b8_reversed = bytecast <64 x b1> %bv64b1_reversed to <8 x b8> => { b8 00000000(01100100) , b8 00000000(10001110) , b8 00000000(00111100) , b8 00000000(10011100) , b8 00000000(01010001) , b8 00000000(10101001) , b8 00000000(00010000) , b8 00000011(00110100)  }
 ; CHECK-NEXT:   %first_byte_with_provenance_reversed = extractelement <8 x b8> %bv8b8_reversed, i32 7 => b8 00000011(00110100) 
-; CHECK-NEXT:   %first_byte_with_provenance_reversed_v8b1 = bitcast b8 %first_byte_with_provenance_reversed to <8 x b1> => { b1 1(0) , b1 1(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0)  }
+; CHECK-NEXT:   %first_byte_with_provenance_reversed_v8b1 = bytecast b8 %first_byte_with_provenance_reversed to <8 x b1> => { b1 1(0) , b1 1(0) , b1 0(1) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(0)  }
 ; CHECK-NEXT:   %first_byte_with_provenance_v8b1 = call <8 x b1> @llvm.vector.reverse.v8b1(<8 x b1> %first_byte_with_provenance_reversed_v8b1) => { b1 0(0) , b1 0(0) , b1 0(1) , b1 0(1) , b1 0(0) , b1 0(1) , b1 1(0) , b1 1(0)  }
 ; CHECK-NEXT:   store <8 x b1> %first_byte_with_provenance_v8b1, ptr %alloc_ptr, align 1
 ; CHECK-NEXT:   %bytes_recovered = load b64, ptr %alloc_ptr, align 8 => b64 ptr 0xC0 [alloc_ptr] 
diff --git a/llvm/test/tools/llvm-ir2vec/entities.ll b/llvm/test/tools/llvm-ir2vec/entities.ll
index 002614164c128..41615682397b1 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: 112
+CHECK: 113
 CHECK-NEXT: Ret	0
 CHECK-NEXT: UncondBr	1
 CHECK-NEXT: CondBr	2
@@ -70,46 +70,47 @@ 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
+CHECK-NEXT: ByteCast	69
+CHECK-NEXT: FloatTy	70
+CHECK-NEXT: VoidTy	71
+CHECK-NEXT: LabelTy	72
+CHECK-NEXT: MetadataTy	73
+CHECK-NEXT: VectorTy	74
+CHECK-NEXT: TokenTy	75
+CHECK-NEXT: IntegerTy	76
+CHECK-NEXT: ByteTy	77
+CHECK-NEXT: FunctionTy	78
+CHECK-NEXT: PointerTy	79
+CHECK-NEXT: StructTy	80
+CHECK-NEXT: ArrayTy	81
+CHECK-NEXT: UnknownTy	82
+CHECK-NEXT: Function	83
+CHECK-NEXT: Pointer	84
+CHECK-NEXT: Constant	85
+CHECK-NEXT: Variable	86
+CHECK-NEXT: FCMP_false	87
+CHECK-NEXT: FCMP_oeq	88
+CHECK-NEXT: FCMP_ogt	89
+CHECK-NEXT: FCMP_oge	90
+CHECK-NEXT: FCMP_olt	91
+CHECK-NEXT: FCMP_ole	92
+CHECK-NEXT: FCMP_one	93
+CHECK-NEXT: FCMP_ord	94
+CHECK-NEXT: FCMP_uno	95
+CHECK-NEXT: FCMP_ueq	96
+CHECK-NEXT: FCMP_ugt	97
+CHECK-NEXT: FCMP_uge	98
+CHECK-NEXT: FCMP_ult	99
+CHECK-NEXT: FCMP_ule	100
+CHECK-NEXT: FCMP_une	101
+CHECK-NEXT: FCMP_true	102
+CHECK-NEXT: ICMP_eq	103
+CHECK-NEXT: ICMP_ne	104
+CHECK-NEXT: ICMP_ugt	105
+CHECK-NEXT: ICMP_uge	106
+CHECK-NEXT: ICMP_ult	107
+CHECK-NEXT: ICMP_ule	108
+CHECK-NEXT: ICMP_sgt	109
+CHECK-NEXT: ICMP_sge	110
+CHECK-NEXT: ICMP_slt	111
+CHECK-NEXT: ICMP_sle	112
diff --git a/llvm/test/tools/llvm-ir2vec/triplets.ll b/llvm/test/tools/llvm-ir2vec/triplets.ll
index 45a158c926900..23366e90f129b 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: 13	75	0
-; TRIPLETS-NEXT: 13	85	2
-; TRIPLETS-NEXT: 13	85	3
+; TRIPLETS-NEXT: 13	76	0
+; TRIPLETS-NEXT: 13	86	2
+; TRIPLETS-NEXT: 13	86	3
 ; TRIPLETS-NEXT: 13	0	1
-; TRIPLETS-NEXT: 0	70	0
-; TRIPLETS-NEXT: 0	85	2
-; TRIPLETS-NEXT: 17	75	0
-; TRIPLETS-NEXT: 17	85	2
-; TRIPLETS-NEXT: 17	85	3
+; TRIPLETS-NEXT: 0	71	0
+; TRIPLETS-NEXT: 0	86	2
+; TRIPLETS-NEXT: 17	76	0
+; TRIPLETS-NEXT: 17	86	2
+; TRIPLETS-NEXT: 17	86	3
 ; TRIPLETS-NEXT: 17	0	1
-; TRIPLETS-NEXT: 0	70	0
-; TRIPLETS-NEXT: 0	85	2
-; TRIPLETS-NEXT: 31	78	0
-; TRIPLETS-NEXT: 31	84	2
+; TRIPLETS-NEXT: 0	71	0
+; TRIPLETS-NEXT: 0	86	2
+; TRIPLETS-NEXT: 31	79	0
+; TRIPLETS-NEXT: 31	85	2
 ; TRIPLETS-NEXT: 31	31	1
-; TRIPLETS-NEXT: 31	78	0
-; TRIPLETS-NEXT: 31	84	2
+; TRIPLETS-NEXT: 31	79	0
+; TRIPLETS-NEXT: 31	85	2
 ; TRIPLETS-NEXT: 31	33	1
-; TRIPLETS-NEXT: 33	70	0
-; TRIPLETS-NEXT: 33	85	2
-; TRIPLETS-NEXT: 33	83	3
+; TRIPLETS-NEXT: 33	71	0
+; TRIPLETS-NEXT: 33	86	2
+; TRIPLETS-NEXT: 33	84	3
 ; TRIPLETS-NEXT: 33	33	1
-; TRIPLETS-NEXT: 33	70	0
-; TRIPLETS-NEXT: 33	85	2
-; TRIPLETS-NEXT: 33	83	3
+; TRIPLETS-NEXT: 33	71	0
+; TRIPLETS-NEXT: 33	86	2
+; TRIPLETS-NEXT: 33	84	3
 ; TRIPLETS-NEXT: 33	32	1
-; TRIPLETS-NEXT: 32	75	0
-; TRIPLETS-NEXT: 32	83	2
+; TRIPLETS-NEXT: 32	76	0
+; TRIPLETS-NEXT: 32	84	2
 ; TRIPLETS-NEXT: 32	32	1
-; TRIPLETS-NEXT: 32	75	0
-; TRIPLETS-NEXT: 32	83	2
+; TRIPLETS-NEXT: 32	76	0
+; TRIPLETS-NEXT: 32	84	2
 ; TRIPLETS-NEXT: 32	13	1
-; TRIPLETS-NEXT: 13	75	0
-; TRIPLETS-NEXT: 13	85	2
-; TRIPLETS-NEXT: 13	85	3
+; TRIPLETS-NEXT: 13	76	0
+; TRIPLETS-NEXT: 13	86	2
+; TRIPLETS-NEXT: 13	86	3
 ; TRIPLETS-NEXT: 13	0	1
-; TRIPLETS-NEXT: 0	70	0
-; TRIPLETS-NEXT: 0	85	2
+; TRIPLETS-NEXT: 0	71	0
+; TRIPLETS-NEXT: 0	86	2
diff --git a/llvm/tools/llubi/lib/Context.cpp b/llvm/tools/llubi/lib/Context.cpp
index 048eec8e8c52d..c4d97f10ab555 100644
--- a/llvm/tools/llubi/lib/Context.cpp
+++ b/llvm/tools/llubi/lib/Context.cpp
@@ -201,7 +201,8 @@ MaterializedConstant Context::evaluateConstantExpression(ConstantExpr *CE) {
     }
     return MaterializedConstant(std::move(Vec), Src->isCacheable());
   }
-  case Instruction::BitCast: {
+  case Instruction::BitCast:
+  case Instruction::ByteCast: {
     Constant *SrcOp = CE->getOperand(0);
     const auto *Src = getConstantValue(SrcOp);
     if (!Src)
diff --git a/llvm/tools/llubi/lib/Interpreter.cpp b/llvm/tools/llubi/lib/Interpreter.cpp
index 77b7fae4c4ab3..b2be6dbc0db90 100644
--- a/llvm/tools/llubi/lib/Interpreter.cpp
+++ b/llvm/tools/llubi/lib/Interpreter.cpp
@@ -2799,17 +2799,20 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
     setResult(SVI, std::move(Res));
   }
 
-  void visitBitCastInst(BitCastInst &BCI) {
+  void visitBitCastLike(CastInst &CI) {
     // The conversion is done as if the value had been stored to memory and read
     // back as the target type.
     SmallVector<Byte> Bytes;
-    Bytes.resize(Ctx.getEffectiveTypeStoreSize(BCI.getType()),
+    Bytes.resize(Ctx.getEffectiveTypeStoreSize(CI.getType()),
                  Byte::concrete(0));
-    Ctx.toBytes(getValue(BCI.getOperand(0)), BCI.getOperand(0)->getType(),
-                Bytes);
-    setResult(BCI, Ctx.fromBytes(Bytes, BCI.getType()));
+    Ctx.toBytes(getValue(CI.getOperand(0)), CI.getOperand(0)->getType(), Bytes);
+    setResult(CI, Ctx.fromBytes(Bytes, CI.getType()));
   }
 
+  void visitBitCastInst(BitCastInst &BCI) { visitBitCastLike(BCI); }
+
+  void visitByteCastInst(ByteCastInst &BCI) { visitBitCastLike(BCI); }
+
   void visitFreezeInst(FreezeInst &FI) {
     AnyValue Val = getValue(FI.getOperand(0));
     Ctx.freeze(Val, FI.getType());
diff --git a/llvm/unittests/Analysis/IR2VecTest.cpp b/llvm/unittests/Analysis/IR2VecTest.cpp
index fe67442da0f90..4678c6ef25722 100644
--- a/llvm/unittests/Analysis/IR2VecTest.cpp
+++ b/llvm/unittests/Analysis/IR2VecTest.cpp
@@ -363,8 +363,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_Symbolic) {
   EXPECT_EQ(AddEmb.size(), 2u);
   EXPECT_EQ(RetEmb.size(), 2u);
 
-  EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 26.1)));
-  EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 15.8)));
+  EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 26.4)));
+  EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 16.0)));
 }
 
 TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
@@ -376,8 +376,8 @@ TEST_F(IR2VecTestFixture, GetInstVec_FlowAware) {
   EXPECT_EQ(AddEmb.size(), 2u);
   EXPECT_EQ(RetEmb.size(), 2u);
 
-  EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 26.1)));
-  EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 33.3)));
+  EXPECT_TRUE(AddEmb.approximatelyEquals(Embedding(2, 26.4)));
+  EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(2, 33.7)));
 }
 
 TEST_F(IR2VecTestFixture, GetBBVector_Symbolic) {
@@ -387,9 +387,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: {26.1, 26.1} + {15.8, 15.8} =
-  // {41.9, 41.9}
-  EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 41.9)));
+  // BB vector should be sum of add and ret: {26.4, 26.4} + {16.0, 16.0} =
+  // {42.4, 42.4}
+  EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 42.4)));
 }
 
 TEST_F(IR2VecTestFixture, GetBBVector_FlowAware) {
@@ -399,9 +399,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: {26.1, 26.1} + {33.3, 33.3} =
-  // {59.4, 59.4}
-  EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 59.4)));
+  // BB vector should be sum of add and ret: {26.4, 26.4} + {33.7, 33.7} =
+  // {60.1, 60.1}
+  EXPECT_TRUE(BBVec.approximatelyEquals(Embedding(2, 60.1)));
 }
 
 TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
@@ -412,8 +412,8 @@ TEST_F(IR2VecTestFixture, GetFunctionVector_Symbolic) {
 
   EXPECT_EQ(FuncVec.size(), 2u);
 
-  // Function vector should match BB vector (only one BB): {41.9, 41.9}
-  EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 41.9)));
+  // Function vector should match BB vector (only one BB): {42.4, 42.4}
+  EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 42.4)));
 }
 
 TEST_F(IR2VecTestFixture, GetFunctionVector_FlowAware) {
@@ -423,8 +423,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): {59.4, 59.4}
-  EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 59.4)));
+  // Function vector should match BB vector (only one BB): {60.1, 60.1}
+  EXPECT_TRUE(FuncVec.approximatelyEquals(Embedding(2, 60.1)));
 }
 
 TEST_F(IR2VecTestFixture, MultipleComputeEmbeddingsConsistency_Symbolic) {



More information about the llvm-commits mailing list