[llvm] [PowerPC] Fix crash when promoting smaller types to 64 bit ucmp (PR #203399)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 12 09:22:36 PDT 2026


https://github.com/mike-goutokuji updated https://github.com/llvm/llvm-project/pull/203399

>From 8975c1af654e819fa7818cf7e6e60e7c9cdaadc7 Mon Sep 17 00:00:00 2001
From: Mike-Goutokuji <83477269+mike-goutokuji at users.noreply.github.com>
Date: Thu, 11 Jun 2026 16:07:13 -0400
Subject: [PATCH] [PowerPC] Fix crash when promoting smaller types to 64 bit
 ucmp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

i64 @llvm.ucmp(i8, …) bypasses UCMP i32→i64 promotion; widen operands in LowerUCMP before carry lowering.
---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 11 ++++++++-
 llvm/test/CodeGen/PowerPC/ucmp.ll           | 27 +++++++++++++++++++++
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index e43021b1f5379..eaf95cbd2d023 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -606,7 +606,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
   // Custom handling for PowerPC ucmp instruction
   if (isPPC64) {
     // UCMP involves using carries, which only works in 64-bit
-    setOperationAction(ISD::UCMP, MVT::i32, Promote);
+    setOperationPromotedToType(ISD::UCMP, MVT::i32, MVT::i64);
     setOperationAction(ISD::UCMP, MVT::i64, Custom);
   } else {
     setOperationAction(ISD::UCMP, MVT::i32, Custom);
@@ -12802,6 +12802,15 @@ SDValue PPCTargetLowering::LowerUCMP(SDValue Op, SelectionDAG &DAG) const {
   EVT OpVT = A.getValueType();
   EVT ResVT = Op.getValueType();
 
+  // On PPC64, carry ops use the full 64-bit register. UCMP i32 is promoted to
+  // i64 by the legalizer; this only runs for UCMP i64 with operands still
+  // narrower than i64 (e.g. i64 @llvm.ucmp(i8, i8)).
+  if (Subtarget.isPPC64() && OpVT != MVT::i64) {
+    A = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, A);
+    B = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, B);
+    OpVT = MVT::i64;
+  }
+
   // First compute diff = A - B.
   SDValue Diff = DAG.getNode(ISD::SUB, DL, OpVT, A, B);
 
diff --git a/llvm/test/CodeGen/PowerPC/ucmp.ll b/llvm/test/CodeGen/PowerPC/ucmp.ll
index e371776d82604..66387f979cae3 100644
--- a/llvm/test/CodeGen/PowerPC/ucmp.ll
+++ b/llvm/test/CodeGen/PowerPC/ucmp.ll
@@ -108,3 +108,30 @@ define i64 @ucmp_64_64(i64 %x, i64 %y) nounwind {
   %1 = call i64 @llvm.ucmp(i64 %x, i64 %y)
   ret i64 %1
 }
+
+define i64 @ucmp_64_8_zero(i8 %x) nounwind {
+; CHECK-LABEL: ucmp_64_8_zero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    clrldi 3, 3, 56
+; CHECK-NEXT:    subfic 4, 3, 0
+; CHECK-NEXT:    li 4, 0
+; CHECK-NEXT:    subfe 4, 4, 3
+; CHECK-NEXT:    subfe 3, 4, 3
+; CHECK-NEXT:    blr
+  %1 = call i64 @llvm.ucmp(i8 %x, i8 0)
+  ret i64 %1
+}
+
+define i64 @ucmp_64_8(i8 %x, i8 %y) nounwind {
+; CHECK-LABEL: ucmp_64_8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    clrldi 3, 3, 56
+; CHECK-NEXT:    clrldi 4, 4, 56
+; CHECK-NEXT:    sub 5, 3, 4
+; CHECK-NEXT:    subc 6, 4, 3
+; CHECK-NEXT:    subfe 3, 4, 3
+; CHECK-NEXT:    subfe 3, 3, 5
+; CHECK-NEXT:    blr
+  %1 = call i64 @llvm.ucmp(i8 %x, i8 %y)
+  ret i64 %1
+}



More information about the llvm-commits mailing list