[llvm] [PowerPC] Legalize i8 for rea/write global name registers (PR #180805)

Lei Huang via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 11 08:30:20 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/6] 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/6] 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"}

>From 9dd6aef2c4bf2fc58458a9873142483d9a6e659b Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Wed, 11 Feb 2026 10:20:51 -0500
Subject: [PATCH 3/6] allow i8 promotion for ppc target

---
 .../SelectionDAG/LegalizeIntegerTypes.cpp     | 53 +++++++++++++++----
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   | 48 +++--------------
 llvm/lib/Target/PowerPC/PPCISelLowering.h     |  2 -
 .../CodeGen/PowerPC/named-reg-alloc-i8.ll     | 15 ++----
 4 files changed, 51 insertions(+), 67 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 58ef691a0249d..936619badf5b5 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -2926,11 +2926,25 @@ SDValue DAGTypeLegalizer::PromoteIntOp_PATCHPOINT(SDNode *N, unsigned OpNo) {
 
 SDValue DAGTypeLegalizer::PromoteIntOp_WRITE_REGISTER(SDNode *N,
                                                       unsigned OpNo) {
-  const Function &Fn = DAG.getMachineFunction().getFunction();
-  Fn.getContext().diagnose(DiagnosticInfoLegalizationFailure(
-      "cannot use llvm.write_register with illegal type", Fn,
-      N->getDebugLoc()));
-  return N->getOperand(0);
+  assert(OpNo == 2 && "Unexpected operand number");
+  EVT VT = N->getOperand(2).getValueType();
+
+  // Check if target has set Promote action for this type.
+  // We check the action directly since isOperationLegalOrPromote requires
+  // the type to be legal, but we're specifically handling illegal types here.
+  if (!VT.isSimple() ||
+      TLI.getOperationAction(ISD::WRITE_REGISTER, VT.getSimpleVT()) !=
+          TargetLowering::Promote) {
+    const Function &Fn = DAG.getMachineFunction().getFunction();
+    Fn.getContext().diagnose(DiagnosticInfoLegalizationFailure(
+        "cannot use llvm.write_register with illegal type", Fn,
+        N->getDebugLoc()));
+    return N->getOperand(0);
+  }
+
+  SDValue Val = GetPromotedInteger(N->getOperand(2));
+  SmallVector<SDValue, 3> Ops = {N->getOperand(0), N->getOperand(1), Val};
+  return SDValue(DAG.UpdateNodeOperands(N, Ops), 0);
 }
 
 SDValue DAGTypeLegalizer::PromoteIntOp_VP_STRIDED(SDNode *N, unsigned OpNo) {
@@ -6372,13 +6386,30 @@ SDValue DAGTypeLegalizer::PromoteIntRes_PATCHPOINT(SDNode *N) {
 }
 
 SDValue DAGTypeLegalizer::PromoteIntRes_READ_REGISTER(SDNode *N) {
-  const Function &Fn = DAG.getMachineFunction().getFunction();
-  Fn.getContext().diagnose(DiagnosticInfoLegalizationFailure(
-      "cannot use llvm.read_register with illegal type", Fn, N->getDebugLoc()));
+  EVT VT = N->getValueType(0);
 
-  EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
-  ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
-  return DAG.getPOISON(NVT);
+  // Check if target has set Promote action for this type.
+  // We check the action directly since isOperationLegalOrPromote requires
+  // the type to be legal, but we're specifically handling illegal types here.
+  if (!VT.isSimple() ||
+      TLI.getOperationAction(ISD::READ_REGISTER, VT.getSimpleVT()) !=
+          TargetLowering::Promote) {
+    const Function &Fn = DAG.getMachineFunction().getFunction();
+    Fn.getContext().diagnose(DiagnosticInfoLegalizationFailure(
+        "cannot use llvm.read_register with illegal type", Fn,
+        N->getDebugLoc()));
+    EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
+    ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
+    return DAG.getPOISON(NVT);
+  }
+
+  SDLoc dl(N);
+  EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
+  SDValue Res = DAG.getNode(ISD::READ_REGISTER, dl,
+                             DAG.getVTList(NVT, MVT::Other),
+                             N->getOperand(0), N->getOperand(1));
+  ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
+  return Res;
 }
 
 SDValue DAGTypeLegalizer::PromoteIntOp_EXTRACT_VECTOR_ELT(SDNode *N) {
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 6c5d63e4c2d02..7fc3119ec07f1 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -689,8 +689,11 @@ 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, Custom);
-  setOperationAction(ISD::READ_REGISTER, MVT::i8, Custom);
+  setOperationAction(ISD::WRITE_REGISTER, MVT::i8, Promote);
+  setOperationAction(ISD::READ_REGISTER, MVT::i8, Promote);
+  MVT PromoteToVT = Subtarget.isPPC64() ? MVT::i64 : MVT::i32;
+  AddPromotedToType(ISD::WRITE_REGISTER, MVT::i8, PromoteToVT);
+  AddPromotedToType(ISD::READ_REGISTER, MVT::i8, PromoteToVT);
 
   // Comparisons that require checking two conditions.
   if (Subtarget.hasSPE()) {
@@ -12761,10 +12764,6 @@ 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:
@@ -12794,18 +12793,6 @@ 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;
@@ -18588,29 +18575,6 @@ 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"
@@ -18620,7 +18584,7 @@ Register PPCTargetLowering::getRegisterByName(const char *RegName, LLT VT,
   bool IsPPC64 = Subtarget.isPPC64();
 
   bool Is64Bit = IsPPC64 && VT == LLT::scalar(64);
-  if (!Is64Bit && VT != LLT::scalar(32))
+  if (!Is64Bit && VT != LLT::scalar(32) && VT != LLT::scalar(8))
     report_fatal_error("Invalid register global variable type");
 
   Register Reg = MatchRegisterName(RegName);
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 8b06753fc4e22..c74f6a6db8a3c 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -697,8 +697,6 @@ 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
index 751d2755fca1c..5281de1bb8bee 100644
--- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll
+++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll
@@ -14,8 +14,6 @@ define dso_local void @testSetByteReg(i8 noundef signext %val) nounwind {
 ;
 ; 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:
@@ -41,8 +39,7 @@ define dso_local signext i8 @testGetByteReg() nounwind {
 ; 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:    extsb 3, 23
 ; PPC64-NEXT:    ld 23, -72(1) # 8-byte Folded Reload
 ; PPC64-NEXT:    blr
 entry:
@@ -66,13 +63,10 @@ define dso_local signext i32 @testCmpByteReg() nounwind {
 ;
 ; 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:    cmpwi 3, 15
 ; PPC64-NEXT:    crmove 20, 2
 ; PPC64-NEXT:    li 4, 0
 ; PPC64-NEXT:    li 3, 1
@@ -99,11 +93,8 @@ define dso_local zeroext i8 @testZextByteReg(i8 noundef zeroext %val) nounwind {
 ;
 ; 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:    clrldi 3, 5, 56
 ; PPC64-NEXT:    blr
 entry:
   tail call void @llvm.write_register.i8(metadata !0, i8 %val)

>From f92c982bdb2ec65e41694240b014477108b6e995 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Wed, 11 Feb 2026 10:26:48 -0500
Subject: [PATCH 4/6] update doc

---
 llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 936619badf5b5..36ceb00598f0d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -2930,8 +2930,6 @@ SDValue DAGTypeLegalizer::PromoteIntOp_WRITE_REGISTER(SDNode *N,
   EVT VT = N->getOperand(2).getValueType();
 
   // Check if target has set Promote action for this type.
-  // We check the action directly since isOperationLegalOrPromote requires
-  // the type to be legal, but we're specifically handling illegal types here.
   if (!VT.isSimple() ||
       TLI.getOperationAction(ISD::WRITE_REGISTER, VT.getSimpleVT()) !=
           TargetLowering::Promote) {
@@ -6389,8 +6387,6 @@ SDValue DAGTypeLegalizer::PromoteIntRes_READ_REGISTER(SDNode *N) {
   EVT VT = N->getValueType(0);
 
   // Check if target has set Promote action for this type.
-  // We check the action directly since isOperationLegalOrPromote requires
-  // the type to be legal, but we're specifically handling illegal types here.
   if (!VT.isSimple() ||
       TLI.getOperationAction(ISD::READ_REGISTER, VT.getSimpleVT()) !=
           TargetLowering::Promote) {

>From e61a5d6cbf4b61442dba9ca13695ff589a1abf57 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Wed, 11 Feb 2026 11:11:50 -0500
Subject: [PATCH 5/6] pull condition check out into a static function

---
 .../SelectionDAG/LegalizeIntegerTypes.cpp     | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 36ceb00598f0d..0e9eebe04dd48 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -2924,15 +2924,21 @@ SDValue DAGTypeLegalizer::PromoteIntOp_PATCHPOINT(SDNode *N, unsigned OpNo) {
   return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
 }
 
+/// Check if the target has set Promote action for the given register operation
+/// and type. Unlike isOperationLegalOrPromote, this works for illegal types.
+static bool hasPromoteActionForRegisterOp(const TargetLowering &TLI,
+                                           unsigned Opcode, EVT VT) {
+  return VT.isSimple() &&
+         TLI.getOperationAction(Opcode, VT.getSimpleVT()) ==
+             TargetLowering::Promote;
+}
+
 SDValue DAGTypeLegalizer::PromoteIntOp_WRITE_REGISTER(SDNode *N,
                                                       unsigned OpNo) {
   assert(OpNo == 2 && "Unexpected operand number");
   EVT VT = N->getOperand(2).getValueType();
 
-  // Check if target has set Promote action for this type.
-  if (!VT.isSimple() ||
-      TLI.getOperationAction(ISD::WRITE_REGISTER, VT.getSimpleVT()) !=
-          TargetLowering::Promote) {
+  if (!hasPromoteActionForRegisterOp(TLI, ISD::WRITE_REGISTER, VT)) {
     const Function &Fn = DAG.getMachineFunction().getFunction();
     Fn.getContext().diagnose(DiagnosticInfoLegalizationFailure(
         "cannot use llvm.write_register with illegal type", Fn,
@@ -6386,10 +6392,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_PATCHPOINT(SDNode *N) {
 SDValue DAGTypeLegalizer::PromoteIntRes_READ_REGISTER(SDNode *N) {
   EVT VT = N->getValueType(0);
 
-  // Check if target has set Promote action for this type.
-  if (!VT.isSimple() ||
-      TLI.getOperationAction(ISD::READ_REGISTER, VT.getSimpleVT()) !=
-          TargetLowering::Promote) {
+  if (!hasPromoteActionForRegisterOp(TLI, ISD::READ_REGISTER, VT)) {
     const Function &Fn = DAG.getMachineFunction().getFunction();
     Fn.getContext().diagnose(DiagnosticInfoLegalizationFailure(
         "cannot use llvm.read_register with illegal type", Fn,

>From fc6ccb71fc5f4254d58079dbd14fc98b83ec57f6 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Wed, 11 Feb 2026 11:29:22 -0500
Subject: [PATCH 6/6] remove unnecessary conditon

---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |  2 +-
 .../CodeGen/PowerPC/named-reg-alloc-i8.ll     | 28 ++++++++++++++-----
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 7fc3119ec07f1..8ef6edbcbba1e 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -18584,7 +18584,7 @@ Register PPCTargetLowering::getRegisterByName(const char *RegName, LLT VT,
   bool IsPPC64 = Subtarget.isPPC64();
 
   bool Is64Bit = IsPPC64 && VT == LLT::scalar(64);
-  if (!Is64Bit && VT != LLT::scalar(32) && VT != LLT::scalar(8))
+  if (!Is64Bit && VT != LLT::scalar(32))
     report_fatal_error("Invalid register global variable type");
 
   Register Reg = MatchRegisterName(RegName);
diff --git a/llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll b/llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll
index 5281de1bb8bee..e3bf063e04689 100644
--- a/llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll
+++ b/llvm/test/CodeGen/PowerPC/named-reg-alloc-i8.ll
@@ -1,5 +1,5 @@
 ; 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=powerpc-ibm-aix-xcoff | FileCheck %s
 ; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s --check-prefix=PPC64
 
 @byteVal = dso_local global i8 15, align 1
@@ -27,12 +27,26 @@ declare void @llvm.write_register.i8(metadata, i8)
 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:    stw 23, -36(1) # 4-byte Folded Spill
+; CHECK-NEXT:    stw 24, -32(1) # 4-byte Folded Spill
+; CHECK-NEXT:    stw 25, -28(1) # 4-byte Folded Spill
+; CHECK-NEXT:    stw 26, -24(1) # 4-byte Folded Spill
+; CHECK-NEXT:    stw 27, -20(1) # 4-byte Folded Spill
+; CHECK-NEXT:    stw 28, -16(1) # 4-byte Folded Spill
+; CHECK-NEXT:    stw 29, -12(1) # 4-byte Folded Spill
+; CHECK-NEXT:    stw 30, -8(1) # 4-byte Folded Spill
+; CHECK-NEXT:    stw 31, -4(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:    lwz 31, -4(1) # 4-byte Folded Reload
+; CHECK-NEXT:    lwz 30, -8(1) # 4-byte Folded Reload
+; CHECK-NEXT:    lwz 29, -12(1) # 4-byte Folded Reload
+; CHECK-NEXT:    lwz 28, -16(1) # 4-byte Folded Reload
+; CHECK-NEXT:    lwz 27, -20(1) # 4-byte Folded Reload
+; CHECK-NEXT:    lwz 26, -24(1) # 4-byte Folded Reload
+; CHECK-NEXT:    lwz 25, -28(1) # 4-byte Folded Reload
+; CHECK-NEXT:    lwz 24, -32(1) # 4-byte Folded Reload
+; CHECK-NEXT:    lwz 23, -36(1) # 4-byte Folded Reload
 ; CHECK-NEXT:    blr
 ;
 ; PPC64-LABEL: testGetByteReg:
@@ -54,8 +68,8 @@ declare i8 @llvm.read_register.i8(metadata)
 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:    lwz 3, L..C0(2) # @byteVal
+; CHECK-NEXT:    lbz 3, 0(3)
 ; CHECK-NEXT:    xori 3, 3, 15
 ; CHECK-NEXT:    cntlzw 3, 3
 ; CHECK-NEXT:    srwi 3, 3, 5



More information about the llvm-commits mailing list