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 <[email protected]> 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 <[email protected]> --- 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 } _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
