[llvm] [PowerPC] Legalize i8 for rea/write global name registers (PR #180805)
Lei Huang via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 10 12:53:39 PST 2026
https://github.com/lei137 updated https://github.com/llvm/llvm-project/pull/180805
>From 6465b27681485d99caf2c32fc2dc765b83a7b5c1 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Tue, 10 Feb 2026 13:33:28 -0500
Subject: [PATCH 1/2] Legalize i8 for rea/write global name registers
---
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 640b3b48e5707..2f03f792c9231 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -688,6 +688,12 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setOperationAction(ISD::INTRINSIC_VOID, MVT::i32, Custom);
setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
+ // Legalize i8 for read/write global named registers.
+ setOperationAction(ISD::WRITE_REGISTER, MVT::i8, Promote);
+ AddPromotedToType(ISD::WRITE_REGISTER, MVT::i8, isPPC64 ? MVT::i64 : MVT::i32);
+ setOperationAction(ISD::READ_REGISTER, MVT::i8, Promote);
+ AddPromotedToType(ISD::READ_REGISTER, MVT::i8, isPPC64 ? MVT::i64 : MVT::i32);
+
// Comparisons that require checking two conditions.
if (Subtarget.hasSPE()) {
setCondCodeAction(ISD::SETO, MVT::f32, Expand);
>From bad64f3002bf451363c1f8b45fabffc6280ec92e Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Tue, 10 Feb 2026 15:53:10 -0500
Subject: [PATCH 2/2] fix to use ppc specific lowering and add tests
---
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 45 ++++++-
llvm/lib/Target/PowerPC/PPCISelLowering.h | 2 +
.../CodeGen/PowerPC/named-reg-alloc-i8.ll | 115 ++++++++++++++++++
3 files changed, 158 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 2f03f792c9231..6c5d63e4c2d02 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -689,10 +689,8 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
// Legalize i8 for read/write global named registers.
- setOperationAction(ISD::WRITE_REGISTER, MVT::i8, Promote);
- AddPromotedToType(ISD::WRITE_REGISTER, MVT::i8, isPPC64 ? MVT::i64 : MVT::i32);
- setOperationAction(ISD::READ_REGISTER, MVT::i8, Promote);
- AddPromotedToType(ISD::READ_REGISTER, MVT::i8, isPPC64 ? MVT::i64 : MVT::i32);
+ setOperationAction(ISD::WRITE_REGISTER, MVT::i8, Custom);
+ setOperationAction(ISD::READ_REGISTER, MVT::i8, Custom);
// Comparisons that require checking two conditions.
if (Subtarget.hasSPE()) {
@@ -12763,6 +12761,10 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
if (Op->getFlags().hasNoFPExcept())
return Op;
return SDValue();
+ case ISD::READ_REGISTER:
+ return LowerREAD_REGISTER(Op, DAG);
+ case ISD::WRITE_REGISTER:
+ return LowerWRITE_REGISTER(Op, DAG);
case ISD::VP_LOAD:
return LowerVP_LOAD(Op, DAG);
case ISD::VP_STORE:
@@ -12792,6 +12794,18 @@ void PPCTargetLowering::ReplaceNodeResults(SDNode *N,
Results.push_back(RTB.getValue(2));
break;
}
+ case ISD::READ_REGISTER: {
+ // Promote to register width, then truncate back to original type
+ EVT VT = N->getValueType(0);
+ EVT RegVT = Subtarget.isPPC64() ? MVT::i64 : MVT::i32;
+ SDValue Res = DAG.getNode(ISD::READ_REGISTER, dl,
+ DAG.getVTList(RegVT, MVT::Other),
+ N->getOperand(0), N->getOperand(1));
+ SDValue Truncated = DAG.getNode(ISD::TRUNCATE, dl, VT, Res);
+ Results.push_back(Truncated);
+ Results.push_back(Res.getValue(1));
+ break;
+ }
case ISD::INTRINSIC_W_CHAIN: {
if (N->getConstantOperandVal(1) != Intrinsic::loop_decrement)
break;
@@ -18574,6 +18588,29 @@ SDValue PPCTargetLowering::LowerFRAMEADDR(SDValue Op,
FrameAddr, MachinePointerInfo());
return FrameAddr;
}
+SDValue PPCTargetLowering::LowerREAD_REGISTER(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc dl(Op);
+
+ // Promote to register width.
+ EVT RegVT = Subtarget.isPPC64() ? MVT::i64 : MVT::i32;
+ return DAG.getNode(ISD::READ_REGISTER, dl,
+ DAG.getVTList(RegVT, MVT::Other),
+ Op.getOperand(0), Op.getOperand(1));
+}
+
+SDValue PPCTargetLowering::LowerWRITE_REGISTER(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc dl(Op);
+ SDValue Val = Op.getOperand(2);
+
+ // Promote to register width.
+ EVT RegVT = Subtarget.isPPC64() ? MVT::i64 : MVT::i32;
+ SDValue Promoted = DAG.getNode(ISD::ANY_EXTEND, dl, RegVT, Val);
+ return DAG.getNode(ISD::WRITE_REGISTER, dl, MVT::Other,
+ Op.getOperand(0), Op.getOperand(1), Promoted);
+}
+
#define GET_REGISTER_MATCHER
#include "PPCGenAsmMatcher.inc"
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index c74f6a6db8a3c..8b06753fc4e22 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -697,6 +697,8 @@ namespace llvm {
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerREAD_REGISTER(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll
new file mode 100644
index 0000000000000..751d2755fca1c
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll
@@ -0,0 +1,115 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s
+; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s --check-prefix=PPC64
+
+ at byteVal = dso_local global i8 15, align 1
+
+; Test writing i8 value to a named register
+define dso_local void @testSetByteReg(i8 noundef signext %val) nounwind {
+; CHECK-LABEL: testSetByteReg:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mr 5, 3
+; CHECK-NEXT: # kill: def $r3 killed $r5
+; CHECK-NEXT: blr
+;
+; PPC64-LABEL: testSetByteReg:
+; PPC64: # %bb.0: # %entry
+; PPC64-NEXT: # kill: def $r3 killed $r3 killed $x3
+; PPC64-NEXT: # implicit-def: $x5
+; PPC64-NEXT: mr 5, 3
+; PPC64-NEXT: blr
+entry:
+ tail call void @llvm.write_register.i8(metadata !0, i8 %val)
+ ret void
+}
+
+declare void @llvm.write_register.i8(metadata, i8)
+
+; Test reading i8 value from a named register
+define dso_local signext i8 @testGetByteReg() nounwind {
+; CHECK-LABEL: testGetByteReg:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: stwu 1, -48(1)
+; CHECK-NEXT: stw 23, 12(1) # 4-byte Folded Spill
+; CHECK-NEXT: li 23, 42
+; CHECK-NEXT: extsb 3, 23
+; CHECK-NEXT: lwz 23, 12(1) # 4-byte Folded Reload
+; CHECK-NEXT: addi 1, 1, 48
+; CHECK-NEXT: blr
+;
+; PPC64-LABEL: testGetByteReg:
+; PPC64: # %bb.0: # %entry
+; PPC64-NEXT: std 23, -72(1) # 8-byte Folded Spill
+; PPC64-NEXT: li 23, 42
+; PPC64-NEXT: mr 3, 23
+; PPC64-NEXT: extsb 3, 3
+; PPC64-NEXT: ld 23, -72(1) # 8-byte Folded Reload
+; PPC64-NEXT: blr
+entry:
+ tail call void @llvm.write_register.i8(metadata !1, i8 42)
+ %0 = tail call i8 @llvm.read_register.i8(metadata !1)
+ ret i8 %0
+}
+
+declare i8 @llvm.read_register.i8(metadata)
+
+; Test comparing i8 value from register with memory
+define dso_local signext i32 @testCmpByteReg() nounwind {
+; CHECK-LABEL: testCmpByteReg:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis 3, byteVal at ha
+; CHECK-NEXT: lbz 3, byteVal at l(3)
+; CHECK-NEXT: xori 3, 3, 15
+; CHECK-NEXT: cntlzw 3, 3
+; CHECK-NEXT: srwi 3, 3, 5
+; CHECK-NEXT: blr
+;
+; PPC64-LABEL: testCmpByteReg:
+; PPC64: # %bb.0: # %entry
+; PPC64-NEXT: li 5, 15
+; PPC64-NEXT: addis 3, 2, byteVal at toc@ha
+; PPC64-NEXT: addi 3, 3, byteVal at toc@l
+; PPC64-NEXT: lbz 3, 0(3)
+; PPC64-NEXT: mr 4, 5
+; PPC64-NEXT: clrlwi 4, 4, 24
+; PPC64-NEXT: cmpw 3, 4
+; PPC64-NEXT: crmove 20, 2
+; PPC64-NEXT: li 4, 0
+; PPC64-NEXT: li 3, 1
+; PPC64-NEXT: isel 3, 3, 4, 20
+; PPC64-NEXT: extsw 3, 3
+; PPC64-NEXT: blr
+entry:
+ tail call void @llvm.write_register.i8(metadata !0, i8 15)
+ %0 = load i8, ptr @byteVal, align 1
+ %1 = tail call i8 @llvm.read_register.i8(metadata !0)
+ %cmp = icmp eq i8 %0, %1
+ %conv = zext i1 %cmp to i32
+ ret i32 %conv
+}
+
+; Test zero-extending i8 from register
+define dso_local zeroext i8 @testZextByteReg(i8 noundef zeroext %val) nounwind {
+; CHECK-LABEL: testZextByteReg:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mr 5, 3
+; CHECK-NEXT: # kill: def $r3 killed $r5
+; CHECK-NEXT: clrlwi 3, 5, 24
+; CHECK-NEXT: blr
+;
+; PPC64-LABEL: testZextByteReg:
+; PPC64: # %bb.0: # %entry
+; PPC64-NEXT: # kill: def $r3 killed $r3 killed $x3
+; PPC64-NEXT: # implicit-def: $x5
+; PPC64-NEXT: mr 5, 3
+; PPC64-NEXT: mr 3, 5
+; PPC64-NEXT: clrldi 3, 3, 56
+; PPC64-NEXT: blr
+entry:
+ tail call void @llvm.write_register.i8(metadata !0, i8 %val)
+ %0 = tail call i8 @llvm.read_register.i8(metadata !0)
+ ret i8 %0
+}
+
+!0 = !{!"r5"}
+!1 = !{!"r23"}
More information about the llvm-commits
mailing list