[llvm-branch-commits] [llvm] [GlobalISel] Lower bytecast in IRTranslator (PR #221887)

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


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

## Summary
- Add `translateByteCast` in GlobalISel IRTranslator with proper lowering for byte↔pointer boundary crossings (`G_INTTOPTR`/`G_PTRTOINT`) and `G_BITCAST` for same-class reinterprets.
- Update `amdgpu-irtranslator.ll` to use `bytecast` syntax and verify the new lowering paths.

## Test plan
- [x] `ninja check-llvm` passes on this branch
- [x] `llvm/test/CodeGen/AMDGPU/GlobalISel/amdgpu-irtranslator.ll` passes

Depends on #221884


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

>From c14dc03d81182d712afa7bb76df864e0b2fb4866 Mon Sep 17 00:00:00 2001
From: Anshil Gandhi <Anshil.Gandhi at amd.com>
Date: Mon, 7 Sep 2026 07:45:49 -0500
Subject: [PATCH] [GlobalISel] Lower bytecast in IRTranslator

Add translateByteCast and move byte-specific cast lowering out of
translateBitCast. Byte-pointer crossings use G_INTTOPTR/G_PTRTOINT; other
byte casts reuse the existing G_BITCAST/COPY paths.

Co-authored-by: Cursor <cursoragent at cursor.com>
---
 llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp  | 27 ++++++++++-----
 .../AMDGPU/GlobalISel/amdgpu-irtranslator.ll  | 34 +++++++++----------
 2 files changed, 36 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 534848466b643..ef144eee8aa47 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -2357,12 +2357,28 @@ bool IRTranslatorImpl::translateBitCast(const User &U,
     return translateCopy(U, *U.getOperand(0), MIRBuilder);
   }
 
+  return translateCast(TargetOpcode::G_BITCAST, U, MIRBuilder);
+}
+
+bool IRTranslatorImpl::translateByteCast(const User &U,
+                                         MachineIRBuilder &MIRBuilder) {
+  Type *SrcTy = U.getOperand(0)->getType();
+  Type *DstTy = U.getType();
+
+  // If we're casting to the source type, we can reuse the source vreg.
+  if (getLLTForType(*SrcTy, *DL) == getLLTForType(*DstTy, *DL)) {
+    if (isa<ConstantInt>(U.getOperand(0)))
+      return translateCast(TargetOpcode::G_CONSTANT_FOLD_BARRIER, U,
+                           MIRBuilder);
+    return translateCopy(U, *U.getOperand(0), MIRBuilder);
+  }
+
   // Only the scalar byte<->ptr crossing is redirected to G_INTTOPTR/G_PTRTOINT,
   // which is the well-typed MIR shape for that boundary. Vector byte<->ptr
   // (e.g. <N x b32> -> ptr produced by mixed-type load coalescing) and other
-  // legacy ptr/non-ptr IR bitcasts (AMDGPU iN<->p3 kernarg packing, etc.)
-  // keep their historical G_BITCAST lowering — G_INTTOPTR has no vector-src
-  // -> scalar-ptr form, and downstream passes already handle G_BITCAST.
+  // legacy ptr/non-ptr IR bytecasts keep their historical G_BITCAST lowering —
+  // G_INTTOPTR has no vector-src -> scalar-ptr form, and downstream passes
+  // already handle G_BITCAST.
   if (DstTy->isPointerTy() && SrcTy->isByteTy())
     return translateCast(TargetOpcode::G_INTTOPTR, U, MIRBuilder);
   if (SrcTy->isPointerTy() && DstTy->isByteTy())
@@ -2371,11 +2387,6 @@ 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/test/CodeGen/AMDGPU/GlobalISel/amdgpu-irtranslator.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/amdgpu-irtranslator.ll
index 672aec2551c03..41dbc1990f91f 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/amdgpu-irtranslator.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/amdgpu-irtranslator.ll
@@ -37,10 +37,10 @@ define void @byte_constant(ptr addrspace(1) %p) {
   ret void
 }
 
-; bitcast b64 -> ptr crosses the pointer/non-pointer boundary, which
+; bytecast b64 -> ptr crosses the pointer/non-pointer boundary, which
 ; G_BITCAST cannot express; lower it as G_INTTOPTR.
-define void @bitcast_b64_to_p1(b64 %b) {
-  ; CHECK-LABEL: name: bitcast_b64_to_p1
+define void @bytecast_b64_to_p1(b64 %b) {
+  ; CHECK-LABEL: name: bytecast_b64_to_p1
   ; CHECK: bb.1 (%ir-block.0):
   ; CHECK-NEXT:   liveins: $vgpr0, $vgpr1
   ; CHECK-NEXT: {{  $}}
@@ -51,14 +51,14 @@ define void @bitcast_b64_to_p1(b64 %b) {
   ; CHECK-NEXT:   [[INTTOPTR:%[0-9]+]]:_(p1) = G_INTTOPTR [[MV]](i64)
   ; CHECK-NEXT:   G_STORE [[C]](i64), [[INTTOPTR]](p1) :: (store (i64) into %ir.p, addrspace 1)
   ; CHECK-NEXT:   SI_RETURN
-  %p = bitcast b64 %b to ptr addrspace(1)
+  %p = bytecast b64 %b to ptr addrspace(1)
   store i64 0, ptr addrspace(1) %p
   ret void
 }
 
 ; Inverse direction lowers to G_PTRTOINT.
-define void @bitcast_p1_to_b64(ptr addrspace(1) %p) {
-  ; CHECK-LABEL: name: bitcast_p1_to_b64
+define void @bytecast_p1_to_b64(ptr addrspace(1) %p) {
+  ; CHECK-LABEL: name: bytecast_p1_to_b64
   ; CHECK: bb.1 (%ir-block.0):
   ; CHECK-NEXT:   liveins: $vgpr0, $vgpr1
   ; CHECK-NEXT: {{  $}}
@@ -69,14 +69,14 @@ define void @bitcast_p1_to_b64(ptr addrspace(1) %p) {
   ; CHECK-NEXT:   [[PTRTOINT:%[0-9]+]]:_(i64) = G_PTRTOINT [[MV]](p1)
   ; CHECK-NEXT:   G_STORE [[PTRTOINT]](i64), [[DEF]](p0) :: (store (i64) into `ptr poison`)
   ; CHECK-NEXT:   SI_RETURN
-  %b = bitcast ptr addrspace(1) %p to b64
+  %b = bytecast ptr addrspace(1) %p to b64
   store b64 %b, ptr poison
   ret void
 }
 
-; Byte and same-sized integer share an LLT, so this bitcast collapses to a copy.
-define void @bitcast_b64_to_i64(b64 %b, ptr addrspace(1) %p) {
-  ; CHECK-LABEL: name: bitcast_b64_to_i64
+; Byte and same-sized integer share an LLT, so this bytecast collapses to a copy.
+define void @bytecast_b64_to_i64(b64 %b, ptr addrspace(1) %p) {
+  ; CHECK-LABEL: name: bytecast_b64_to_i64
   ; CHECK: bb.1 (%ir-block.0):
   ; CHECK-NEXT:   liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3
   ; CHECK-NEXT: {{  $}}
@@ -88,14 +88,14 @@ define void @bitcast_b64_to_i64(b64 %b, ptr addrspace(1) %p) {
   ; CHECK-NEXT:   [[MV1:%[0-9]+]]:_(p1) = G_MERGE_VALUES [[COPY2]](i32), [[COPY3]](i32)
   ; CHECK-NEXT:   G_STORE [[MV]](i64), [[MV1]](p1) :: (store (i64) into %ir.p, addrspace 1)
   ; CHECK-NEXT:   SI_RETURN
-  %i = bitcast b64 %b to i64
+  %i = bytecast b64 %b to i64
   store i64 %i, ptr addrspace(1) %p
   ret void
 }
 
 ; Same-LLT direction: integer to byte is also a copy.
-define void @bitcast_i64_to_b64(i64 %i, ptr addrspace(1) %p) {
-  ; CHECK-LABEL: name: bitcast_i64_to_b64
+define void @bytecast_i64_to_b64(i64 %i, ptr addrspace(1) %p) {
+  ; CHECK-LABEL: name: bytecast_i64_to_b64
   ; CHECK: bb.1 (%ir-block.0):
   ; CHECK-NEXT:   liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3
   ; CHECK-NEXT: {{  $}}
@@ -107,15 +107,15 @@ define void @bitcast_i64_to_b64(i64 %i, ptr addrspace(1) %p) {
   ; CHECK-NEXT:   [[MV1:%[0-9]+]]:_(p1) = G_MERGE_VALUES [[COPY2]](i32), [[COPY3]](i32)
   ; CHECK-NEXT:   G_STORE [[MV]](i64), [[MV1]](p1) :: (store (i64) into %ir.p, addrspace 1)
   ; CHECK-NEXT:   SI_RETURN
-  %b = bitcast i64 %i to b64
+  %b = bytecast i64 %i to b64
   store b64 %b, ptr addrspace(1) %p
   ret void
 }
 
 ; Byte to floating point: distinct LLTs in extended mode, equal in default mode.
 ; AMDGPU runs in default mode, so this collapses to a copy.
-define void @bitcast_b64_to_double(b64 %b, ptr addrspace(1) %p) {
-  ; CHECK-LABEL: name: bitcast_b64_to_double
+define void @bytecast_b64_to_double(b64 %b, ptr addrspace(1) %p) {
+  ; CHECK-LABEL: name: bytecast_b64_to_double
   ; CHECK: bb.1 (%ir-block.0):
   ; CHECK-NEXT:   liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3
   ; CHECK-NEXT: {{  $}}
@@ -128,7 +128,7 @@ define void @bitcast_b64_to_double(b64 %b, ptr addrspace(1) %p) {
   ; CHECK-NEXT:   [[BITCAST:%[0-9]+]]:_(f64) = G_BITCAST [[MV]](i64)
   ; CHECK-NEXT:   G_STORE [[BITCAST]](f64), [[MV1]](p1) :: (store (f64) into %ir.p, addrspace 1)
   ; CHECK-NEXT:   SI_RETURN
-  %d = bitcast b64 %b to double
+  %d = bytecast b64 %b to double
   store double %d, ptr addrspace(1) %p
   ret void
 }



More information about the llvm-branch-commits mailing list