[llvm-branch-commits] [llvm] release/22.x: [PowerPC] Fix miscompilation when using 32-bit ucmp on 64-bit PowerPC (#178979) (PR #179181)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Feb 2 00:31:34 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-powerpc
Author: None (llvmbot)
<details>
<summary>Changes</summary>
Backport b4797d4
Requested by: @<!-- -->arsenm
---
Full diff: https://github.com/llvm/llvm-project/pull/179181.diff
2 Files Affected:
- (modified) llvm/lib/Target/PowerPC/PPCISelLowering.cpp (+13-4)
- (modified) llvm/test/CodeGen/PowerPC/ucmp.ll (+12-4)
``````````diff
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index ef211bf8c8982..640082153e57d 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -12574,10 +12574,19 @@ SDValue PPCTargetLowering::LowerUCMP(SDValue Op, SelectionDAG &DAG) const {
SDLoc DL(Op);
SDValue A = DAG.getFreeze(Op.getOperand(0));
SDValue B = DAG.getFreeze(Op.getOperand(1));
- EVT OpVT = A.getValueType(); // operand type
- EVT ResVT = Op.getValueType(); // result type
+ EVT OpVT = A.getValueType();
+ EVT ResVT = Op.getValueType();
+
+ // On PPC64, i32 carries are affected by the upper 32 bits of the registers.
+ // We must zero-extend to i64 to ensure the carry reflects the 32-bit unsigned
+ // comparison.
+ if (Subtarget.isPPC64() && OpVT == MVT::i32) {
+ 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 (will become subf).
+ // First compute diff = A - B.
SDValue Diff = DAG.getNode(ISD::SUB, DL, OpVT, A, B);
// Generate B - A using SUBC to capture carry.
@@ -12592,7 +12601,7 @@ SDValue PPCTargetLowering::LowerUCMP(SDValue Op, SelectionDAG &DAG) const {
// res = diff - t2 + CA1 using SUBE (produces desired -1/0/1).
SDValue ResPair = DAG.getNode(PPCISD::SUBE, DL, VTs, Diff, SubE1, CA1);
- // Extract the first result and truncate to result type if needed
+ // Extract the first result and truncate to result type if needed.
return DAG.getSExtOrTrunc(ResPair.getValue(0), DL, ResVT);
}
diff --git a/llvm/test/CodeGen/PowerPC/ucmp.ll b/llvm/test/CodeGen/PowerPC/ucmp.ll
index 4d393dd00e3db..6ece83c35e1fc 100644
--- a/llvm/test/CodeGen/PowerPC/ucmp.ll
+++ b/llvm/test/CodeGen/PowerPC/ucmp.ll
@@ -4,8 +4,10 @@
define i8 @ucmp_8_8(i8 zeroext %x, i8 zeroext %y) nounwind {
; CHECK-LABEL: ucmp_8_8:
; CHECK: # %bb.0:
-; CHECK-NEXT: subc 6, 4, 3
+; CHECK-NEXT: clrldi 3, 3, 32
+; CHECK-NEXT: clrldi 4, 4, 32
; 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
@@ -16,8 +18,10 @@ define i8 @ucmp_8_8(i8 zeroext %x, i8 zeroext %y) nounwind {
define i8 @ucmp_8_16(i16 zeroext %x, i16 zeroext %y) nounwind {
; CHECK-LABEL: ucmp_8_16:
; CHECK: # %bb.0:
-; CHECK-NEXT: subc 6, 4, 3
+; CHECK-NEXT: clrldi 3, 3, 32
+; CHECK-NEXT: clrldi 4, 4, 32
; 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
@@ -28,8 +32,10 @@ define i8 @ucmp_8_16(i16 zeroext %x, i16 zeroext %y) nounwind {
define i8 @ucmp_8_32(i32 %x, i32 %y) nounwind {
; CHECK-LABEL: ucmp_8_32:
; CHECK: # %bb.0:
-; CHECK-NEXT: subc 6, 4, 3
+; CHECK-NEXT: clrldi 3, 3, 32
+; CHECK-NEXT: clrldi 4, 4, 32
; 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
@@ -72,8 +78,10 @@ define i8 @ucmp_8_128(i128 %x, i128 %y) nounwind {
define i32 @ucmp_32_32(i32 %x, i32 %y) nounwind {
; CHECK-LABEL: ucmp_32_32:
; CHECK: # %bb.0:
-; CHECK-NEXT: subc 6, 4, 3
+; CHECK-NEXT: clrldi 3, 3, 32
+; CHECK-NEXT: clrldi 4, 4, 32
; 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
``````````
</details>
https://github.com/llvm/llvm-project/pull/179181
More information about the llvm-branch-commits
mailing list