[llvm] 57bf08d - [PowerPC] simplify the asm of scmp builtin (#200024)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 11 06:20:22 PDT 2026
Author: zhijian lin
Date: 2026-09-11T09:20:18-04:00
New Revision: 57bf08dc0f318ce50e6c9fdc0d7c9e770f247ee8
URL: https://github.com/llvm/llvm-project/commit/57bf08dc0f318ce50e6c9fdc0d7c9e770f247ee8
DIFF: https://github.com/llvm/llvm-project/commit/57bf08dc0f318ce50e6c9fdc0d7c9e770f247ee8.diff
LOG: [PowerPC] simplify the asm of scmp builtin (#200024)
for the IR
```
define noundef signext range(i32 -1, 2) i32 @test_scmp(i64 noundef %a, i64 noundef %b) local_unnamed_addr #0 {
entry:
%cond2 = tail call i32 @llvm.scmp.i32.i64(i64 %a, i64 %b)
ret i32 %cond2
}
```
when compile -mcpu=pwr8 and 64bit
it generated as asm following orginal
sradi 5, 4, 63
rldicl 6, 3, 1, 63
subc 7, 4, 3
adde 5, 6, 5
cmpd 3, 4
li 3, -1
xori 5, 5, 1
isellt 3, 3, 5
extsw 3, 3
blr
the patch will let it generate as
```
cmpd 7, 3, 4
mfocrf 3, 1
rlwinm 4, 3, 30, 31, 31
rlwinm 3, 3, 29, 31, 31
sub 3, 4, 3
blr
```
Added:
Modified:
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
llvm/lib/Target/PowerPC/PPCISelLowering.h
llvm/test/CodeGen/PowerPC/scmp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 07f018baed2ce..b012e6c6093ae 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -605,11 +605,13 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
// We cannot sextinreg(i1). Expand to shifts.
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
- // Custom handling for PowerPC ucmp instruction
+ // Custom handling for PowerPC ucmp and scmp instructions
setOperationAction(ISD::UCMP, MVT::i32, Custom);
setOperationAction(ISD::UCMP, MVT::i64, isPPC64 ? Custom : Expand);
setOperationAction(ISD::ABDU, MVT::i32, Custom);
setOperationAction(ISD::ABDU, MVT::i64, isPPC64 ? Custom : Expand);
+ setOperationAction(ISD::SCMP, MVT::i32, Custom);
+ setOperationAction(ISD::SCMP, MVT::i64, isPPC64 ? Custom : Expand);
// NOTE: EH_SJLJ_SETJMP/_LONGJMP supported here is NOT intended to support
// SjLj exception handling but a light-weight setjmp/longjmp replacement to
@@ -12890,6 +12892,87 @@ SDValue PPCTargetLowering::LowerUCMP(SDValue Op, SelectionDAG &DAG) const {
return DAG.getSExtOrTrunc(ResPair.getValue(0), DL, ResVT);
}
+// Lower signed 3-way compare producing -1/0/1.
+// For PowerPC with SETB (P9+), use the default expansion.
+// For pre-P9, we generate a custom sequence using comparison and bit
+// extraction.
+// cmpw cr7, LHS, RHS
+// mfocrf r, CR7
+// rlwinm LT, r, 29, 31, 31 (extract LT bit from CR7)
+// rlwinm GT, r, 30, 31, 31 (extract GT bit from CR7)
+// subf result, LT, GT (GT - LT = -1/0/1)
+SDValue PPCTargetLowering::LowerSCMP(SDValue Op, SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ EVT VT = LHS.getValueType();
+ EVT ResVT = Op.getValueType();
+
+ // For P9+, use the default expansion which will use SETB instruction
+ if (Subtarget.isISA3_0())
+ return SDValue();
+
+ // For pre-P9, generate custom sequence without SETB
+ bool Is64BitCmp = (VT == MVT::i64);
+
+ // On PPC64, always use 64-bit operations to avoid extra sign-extension
+ // Even if result type is i32, it will likely be extended to i64 by calling
+ // convention
+ bool Use64BitOps = Subtarget.isPPC64();
+
+ // Perform comparison
+ unsigned CmpOpc = Is64BitCmp ? PPC::CMPD : PPC::CMPW;
+ SDValue Cmp = SDValue(DAG.getMachineNode(CmpOpc, DL, MVT::i32, LHS, RHS), 0);
+
+ // Move comparison result to CR7 to have known bit positions
+ SDValue CR7Reg = DAG.getRegister(PPC::CR7, MVT::i32);
+ SDValue InGlue; // Null incoming glue
+ SDValue CopyToReg =
+ DAG.getCopyToReg(DAG.getEntryNode(), DL, CR7Reg, Cmp, InGlue);
+ SDValue Glue = CopyToReg.getValue(1);
+
+ // Use MFOCRF to read CR7
+ unsigned MFOCRFOpc = Use64BitOps ? PPC::MFOCRF8 : PPC::MFOCRF;
+ EVT MFVT = Use64BitOps ? MVT::i64 : MVT::i32;
+ SDValue MFOCRF =
+ SDValue(DAG.getMachineNode(MFOCRFOpc, DL, MFVT, CR7Reg, Glue), 0);
+
+ // CR7 bits in the result (after MFOCRF):
+ // Bit 28: LT
+ // Bit 29: GT
+ // Bit 30: EQ
+ // Bit 31: SO
+
+ // Extract LT and GT bits using RLWINM
+ unsigned RLWinmOpc = Use64BitOps ? PPC::RLWINM8 : PPC::RLWINM;
+
+ // Extract LT bit (Bit 28 -> Rotate Left 29 to move to bit 31, then mask)
+ SDValue LTOps[] = {MFOCRF, DAG.getTargetConstant(29, DL, MVT::i32),
+ DAG.getTargetConstant(31, DL, MVT::i32),
+ DAG.getTargetConstant(31, DL, MVT::i32)};
+ SDValue LTBit = SDValue(DAG.getMachineNode(RLWinmOpc, DL, MFVT, LTOps), 0);
+
+ // Extract GT bit (Bit 29 -> Rotate Left 30 to move to bit 31, then mask)
+ SDValue GTOps[] = {MFOCRF, DAG.getTargetConstant(30, DL, MVT::i32),
+ DAG.getTargetConstant(31, DL, MVT::i32),
+ DAG.getTargetConstant(31, DL, MVT::i32)};
+ SDValue GTBit = SDValue(DAG.getMachineNode(RLWinmOpc, DL, MFVT, GTOps), 0);
+
+ // Compute result: GT - LT
+ // If LT: 0 - 1 = -1
+ // If GT: 1 - 0 = 1
+ // If EQ: 0 - 0 = 0
+ unsigned SubOpc = Use64BitOps ? PPC::SUBF8 : PPC::SUBF;
+ SDValue Result =
+ SDValue(DAG.getMachineNode(SubOpc, DL, MFVT, LTBit, GTBit), 0);
+
+ if (ResVT == MFVT)
+ return Result;
+
+ // Adjust result to match expected type (sign-extend or truncate as needed)
+ return DAG.getSExtOrTrunc(Result, DL, ResVT);
+}
+
/// LowerOperation - Provide custom lowering hooks for some operations.
///
SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
@@ -13002,6 +13085,8 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
return LowerUCMP(Op, DAG);
case ISD::ABDU:
return LowerABDU(Op, DAG);
+ case ISD::SCMP:
+ return LowerSCMP(Op, DAG);
case ISD::STRICT_LRINT:
case ISD::STRICT_LLRINT:
case ISD::STRICT_LROUND:
@@ -17902,10 +17987,26 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
return N->getOperand(0);
}
break;
- case ISD::SIGN_EXTEND:
+ case ISD::SIGN_EXTEND: {
+ // Optimize: sign_extend(scmp) -> scmp with i64 result (on PPC64)
+ // This eliminates the sign_extend when scmp result is being extended to i64
+ // Pattern: t6: i64 = sign_extend t5:i32
+ // t5: i32 = scmp t2, t4
+ // Result: t5: i64 = scmp t2, t4
+ SDValue N0 = N->getOperand(0);
+ if (Subtarget.isPPC64() && N0.getOpcode() == ISD::SCMP &&
+ N->getValueType(0) == MVT::i64 && N0.getValueType() == MVT::i32 &&
+ N0.hasOneUse()) {
+ // Recreate the SCMP with i64 result type directly
+ SDValue LHS = N0.getOperand(0);
+ SDValue RHS = N0.getOperand(1);
+ return DAG.getNode(ISD::SCMP, dl, MVT::i64, LHS, RHS);
+ }
+
if (SDValue SECC = combineSignExtendSetCC(N, DCI))
return SECC;
[[fallthrough]];
+ }
case ISD::ZERO_EXTEND:
if (SDValue RetV = combineZextSetccWithZero(N, DCI.DAG))
return RetV;
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index ee1277eab14ee..fc0e776521e08 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -745,6 +745,7 @@ namespace llvm {
SDValue LowerADDSUBO(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerABDU(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerUCMP(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSCMP(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerToLibCall(const char *LibCallName, SDValue Op,
SelectionDAG &DAG) const;
SDValue lowerLibCallBasedOnType(const char *LibCallFloatName,
diff --git a/llvm/test/CodeGen/PowerPC/scmp.ll b/llvm/test/CodeGen/PowerPC/scmp.ll
index 107137c0bea7c..e1cc5bbef6cf0 100644
--- a/llvm/test/CodeGen/PowerPC/scmp.ll
+++ b/llvm/test/CodeGen/PowerPC/scmp.ll
@@ -1,15 +1,63 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=ppc64le-unknown-unknown %s -o - | FileCheck %s
+
+; RUN: llc -mtriple=ppc64le-unknown-unknown -mcpu=pwr8 %s -o - | FileCheck %s
+; RUN: llc -mtriple=powerpc-ibm-aix7.2.0.0 -mcpu=pwr8 %s -o - | FileCheck --check-prefix=AIX32 %s
+; RUN: llc -mtriple=powerpc64-ibm-aix7.2.0.0 -mcpu=pwr8 %s -o - | FileCheck --check-prefix=AIX64 %s
+
+; RUN: llc -mtriple=ppc64le-unknown-unknown -mcpu=pwr9 %s -o - | FileCheck --check-prefix=CHECK-PWR9 %s
+; RUN: llc -mtriple=powerpc-ibm-aix7.2.0.0 -mcpu=pwr9 %s -o - | FileCheck --check-prefix=AIX32-PWR9 %s
+; RUN: llc -mtriple=powerpc64-ibm-aix7.2.0.0 -mcpu=pwr9 %s -o - | FileCheck --check-prefix=AIX64-PWR9 %s
+
define i8 @scmp_8_8(i8 signext %x, i8 signext %y) nounwind {
; CHECK-LABEL: scmp_8_8:
; CHECK: # %bb.0:
-; CHECK-NEXT: cmpw 3, 4
-; CHECK-NEXT: sub 5, 4, 3
-; CHECK-NEXT: li 3, -1
-; CHECK-NEXT: rldicl 5, 5, 1, 63
-; CHECK-NEXT: isellt 3, 3, 5
+; CHECK-NEXT: cmpw 7, 3, 4
+; CHECK-NEXT: mfocrf 3, 1
+; CHECK-NEXT: rlwinm 4, 3, 30, 31, 31
+; CHECK-NEXT: rlwinm 3, 3, 29, 31, 31
+; CHECK-NEXT: sub 3, 4, 3
; CHECK-NEXT: blr
+;
+; AIX32-LABEL: scmp_8_8:
+; AIX32: # %bb.0:
+; AIX32-NEXT: cmpw 7, 3, 4
+; AIX32-NEXT: mfocrf 3, 1
+; AIX32-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX32-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX32-NEXT: sub 3, 4, 3
+; AIX32-NEXT: blr
+;
+; AIX64-LABEL: scmp_8_8:
+; AIX64: # %bb.0:
+; AIX64-NEXT: cmpw 7, 3, 4
+; AIX64-NEXT: mfocrf 3, 1
+; AIX64-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX64-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX64-NEXT: sub 3, 4, 3
+; AIX64-NEXT: blr
+;
+; CHECK-PWR9-LABEL: scmp_8_8:
+; CHECK-PWR9: # %bb.0:
+; CHECK-PWR9-NEXT: cmpw 3, 4
+; CHECK-PWR9-NEXT: setb 3, 0
+; CHECK-PWR9-NEXT: blr
+;
+; AIX32-PWR9-LABEL: scmp_8_8:
+; AIX32-PWR9: # %bb.0:
+; AIX32-PWR9-NEXT: cmpw 3, 4
+; AIX32-PWR9-NEXT: li 3, 0
+; AIX32-PWR9-NEXT: li 4, 1
+; AIX32-PWR9-NEXT: iselgt 3, 4, 3
+; AIX32-PWR9-NEXT: li 4, -1
+; AIX32-PWR9-NEXT: isellt 3, 4, 3
+; AIX32-PWR9-NEXT: blr
+;
+; AIX64-PWR9-LABEL: scmp_8_8:
+; AIX64-PWR9: # %bb.0:
+; AIX64-PWR9-NEXT: cmpw 3, 4
+; AIX64-PWR9-NEXT: setb 3, 0
+; AIX64-PWR9-NEXT: blr
%1 = call i8 @llvm.scmp(i8 %x, i8 %y)
ret i8 %1
}
@@ -17,12 +65,52 @@ define i8 @scmp_8_8(i8 signext %x, i8 signext %y) nounwind {
define i8 @scmp_8_16(i16 signext %x, i16 signext %y) nounwind {
; CHECK-LABEL: scmp_8_16:
; CHECK: # %bb.0:
-; CHECK-NEXT: cmpw 3, 4
-; CHECK-NEXT: sub 5, 4, 3
-; CHECK-NEXT: li 3, -1
-; CHECK-NEXT: rldicl 5, 5, 1, 63
-; CHECK-NEXT: isellt 3, 3, 5
+; CHECK-NEXT: cmpw 7, 3, 4
+; CHECK-NEXT: mfocrf 3, 1
+; CHECK-NEXT: rlwinm 4, 3, 30, 31, 31
+; CHECK-NEXT: rlwinm 3, 3, 29, 31, 31
+; CHECK-NEXT: sub 3, 4, 3
; CHECK-NEXT: blr
+;
+; AIX32-LABEL: scmp_8_16:
+; AIX32: # %bb.0:
+; AIX32-NEXT: cmpw 7, 3, 4
+; AIX32-NEXT: mfocrf 3, 1
+; AIX32-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX32-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX32-NEXT: sub 3, 4, 3
+; AIX32-NEXT: blr
+;
+; AIX64-LABEL: scmp_8_16:
+; AIX64: # %bb.0:
+; AIX64-NEXT: cmpw 7, 3, 4
+; AIX64-NEXT: mfocrf 3, 1
+; AIX64-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX64-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX64-NEXT: sub 3, 4, 3
+; AIX64-NEXT: blr
+;
+; CHECK-PWR9-LABEL: scmp_8_16:
+; CHECK-PWR9: # %bb.0:
+; CHECK-PWR9-NEXT: cmpw 3, 4
+; CHECK-PWR9-NEXT: setb 3, 0
+; CHECK-PWR9-NEXT: blr
+;
+; AIX32-PWR9-LABEL: scmp_8_16:
+; AIX32-PWR9: # %bb.0:
+; AIX32-PWR9-NEXT: cmpw 3, 4
+; AIX32-PWR9-NEXT: li 3, 0
+; AIX32-PWR9-NEXT: li 4, 1
+; AIX32-PWR9-NEXT: iselgt 3, 4, 3
+; AIX32-PWR9-NEXT: li 4, -1
+; AIX32-PWR9-NEXT: isellt 3, 4, 3
+; AIX32-PWR9-NEXT: blr
+;
+; AIX64-PWR9-LABEL: scmp_8_16:
+; AIX64-PWR9: # %bb.0:
+; AIX64-PWR9-NEXT: cmpw 3, 4
+; AIX64-PWR9-NEXT: setb 3, 0
+; AIX64-PWR9-NEXT: blr
%1 = call i8 @llvm.scmp(i16 %x, i16 %y)
ret i8 %1
}
@@ -30,14 +118,52 @@ define i8 @scmp_8_16(i16 signext %x, i16 signext %y) nounwind {
define i8 @scmp_8_32(i32 %x, i32 %y) nounwind {
; CHECK-LABEL: scmp_8_32:
; CHECK: # %bb.0:
-; CHECK-NEXT: extsw 4, 4
-; CHECK-NEXT: extsw 3, 3
-; CHECK-NEXT: cmpw 3, 4
+; CHECK-NEXT: cmpw 7, 3, 4
+; CHECK-NEXT: mfocrf 3, 1
+; CHECK-NEXT: rlwinm 4, 3, 30, 31, 31
+; CHECK-NEXT: rlwinm 3, 3, 29, 31, 31
; CHECK-NEXT: sub 3, 4, 3
-; CHECK-NEXT: li 4, -1
-; CHECK-NEXT: rldicl 3, 3, 1, 63
-; CHECK-NEXT: isellt 3, 4, 3
; CHECK-NEXT: blr
+;
+; AIX32-LABEL: scmp_8_32:
+; AIX32: # %bb.0:
+; AIX32-NEXT: cmpw 7, 3, 4
+; AIX32-NEXT: mfocrf 3, 1
+; AIX32-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX32-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX32-NEXT: sub 3, 4, 3
+; AIX32-NEXT: blr
+;
+; AIX64-LABEL: scmp_8_32:
+; AIX64: # %bb.0:
+; AIX64-NEXT: cmpw 7, 3, 4
+; AIX64-NEXT: mfocrf 3, 1
+; AIX64-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX64-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX64-NEXT: sub 3, 4, 3
+; AIX64-NEXT: blr
+;
+; CHECK-PWR9-LABEL: scmp_8_32:
+; CHECK-PWR9: # %bb.0:
+; CHECK-PWR9-NEXT: cmpw 3, 4
+; CHECK-PWR9-NEXT: setb 3, 0
+; CHECK-PWR9-NEXT: blr
+;
+; AIX32-PWR9-LABEL: scmp_8_32:
+; AIX32-PWR9: # %bb.0:
+; AIX32-PWR9-NEXT: cmpw 3, 4
+; AIX32-PWR9-NEXT: li 3, 0
+; AIX32-PWR9-NEXT: li 4, 1
+; AIX32-PWR9-NEXT: iselgt 3, 4, 3
+; AIX32-PWR9-NEXT: li 4, -1
+; AIX32-PWR9-NEXT: isellt 3, 4, 3
+; AIX32-PWR9-NEXT: blr
+;
+; AIX64-PWR9-LABEL: scmp_8_32:
+; AIX64-PWR9: # %bb.0:
+; AIX64-PWR9-NEXT: cmpw 3, 4
+; AIX64-PWR9-NEXT: setb 3, 0
+; AIX64-PWR9-NEXT: blr
%1 = call i8 @llvm.scmp(i32 %x, i32 %y)
ret i8 %1
}
@@ -45,15 +171,67 @@ define i8 @scmp_8_32(i32 %x, i32 %y) nounwind {
define i8 @scmp_8_64(i64 %x, i64 %y) nounwind {
; CHECK-LABEL: scmp_8_64:
; CHECK: # %bb.0:
-; CHECK-NEXT: sradi 5, 4, 63
-; CHECK-NEXT: rldicl 6, 3, 1, 63
-; CHECK-NEXT: subc 7, 4, 3
-; CHECK-NEXT: adde 5, 6, 5
-; CHECK-NEXT: cmpd 3, 4
-; CHECK-NEXT: li 3, -1
-; CHECK-NEXT: xori 5, 5, 1
-; CHECK-NEXT: isellt 3, 3, 5
+; CHECK-NEXT: cmpd 7, 3, 4
+; CHECK-NEXT: mfocrf 3, 1
+; CHECK-NEXT: rlwinm 4, 3, 30, 31, 31
+; CHECK-NEXT: rlwinm 3, 3, 29, 31, 31
+; CHECK-NEXT: sub 3, 4, 3
; CHECK-NEXT: blr
+;
+; AIX32-LABEL: scmp_8_64:
+; AIX32: # %bb.0:
+; AIX32-NEXT: cmplw 3, 5
+; AIX32-NEXT: cmpw 1, 3, 5
+; AIX32-NEXT: li 3, 1
+; AIX32-NEXT: cmplw 5, 4, 6
+; AIX32-NEXT: li 4, -1
+; AIX32-NEXT: crandc 22, 5, 2
+; AIX32-NEXT: crand 21, 2, 21
+; AIX32-NEXT: crand 20, 2, 20
+; AIX32-NEXT: crnor 21, 21, 22
+; AIX32-NEXT: isel 3, 0, 3, 21
+; AIX32-NEXT: crandc 21, 4, 2
+; AIX32-NEXT: cror 20, 20, 21
+; AIX32-NEXT: isel 3, 4, 3, 20
+; AIX32-NEXT: blr
+;
+; AIX64-LABEL: scmp_8_64:
+; AIX64: # %bb.0:
+; AIX64-NEXT: cmpd 7, 3, 4
+; AIX64-NEXT: mfocrf 3, 1
+; AIX64-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX64-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX64-NEXT: sub 3, 4, 3
+; AIX64-NEXT: blr
+;
+; CHECK-PWR9-LABEL: scmp_8_64:
+; CHECK-PWR9: # %bb.0:
+; CHECK-PWR9-NEXT: cmpd 3, 4
+; CHECK-PWR9-NEXT: setb 3, 0
+; CHECK-PWR9-NEXT: blr
+;
+; AIX32-PWR9-LABEL: scmp_8_64:
+; AIX32-PWR9: # %bb.0:
+; AIX32-PWR9-NEXT: cmplw 3, 5
+; AIX32-PWR9-NEXT: cmpw 1, 3, 5
+; AIX32-PWR9-NEXT: cmplw 6, 4, 6
+; AIX32-PWR9-NEXT: li 3, 1
+; AIX32-PWR9-NEXT: li 4, -1
+; AIX32-PWR9-NEXT: crandc 20, 5, 2
+; AIX32-PWR9-NEXT: crand 21, 2, 25
+; AIX32-PWR9-NEXT: crnor 20, 21, 20
+; AIX32-PWR9-NEXT: crand 21, 2, 24
+; AIX32-PWR9-NEXT: isel 3, 0, 3, 20
+; AIX32-PWR9-NEXT: crandc 20, 4, 2
+; AIX32-PWR9-NEXT: cror 20, 21, 20
+; AIX32-PWR9-NEXT: isel 3, 4, 3, 20
+; AIX32-PWR9-NEXT: blr
+;
+; AIX64-PWR9-LABEL: scmp_8_64:
+; AIX64-PWR9: # %bb.0:
+; AIX64-PWR9-NEXT: cmpd 3, 4
+; AIX64-PWR9-NEXT: setb 3, 0
+; AIX64-PWR9-NEXT: blr
%1 = call i8 @llvm.scmp(i64 %x, i64 %y)
ret i8 %1
}
@@ -75,6 +253,135 @@ define i8 @scmp_8_128(i128 %x, i128 %y) nounwind {
; CHECK-NEXT: cror 20, 20, 21
; CHECK-NEXT: isel 3, 4, 3, 20
; CHECK-NEXT: blr
+;
+; AIX32-LABEL: scmp_8_128:
+; AIX32: # %bb.0:
+; AIX32-NEXT: cmplw 3, 7
+; AIX32-NEXT: cmpw 1, 3, 7
+; AIX32-NEXT: mfcr 12
+; AIX32-NEXT: stw 12, 4(1)
+; AIX32-NEXT: cmplw 6, 4, 8
+; AIX32-NEXT: xor 3, 3, 7
+; AIX32-NEXT: crandc 20, 5, 2
+; AIX32-NEXT: xor 4, 4, 8
+; AIX32-NEXT: crand 21, 2, 25
+; AIX32-NEXT: or 3, 4, 3
+; AIX32-NEXT: cmplw 7, 5, 9
+; AIX32-NEXT: cmplw 2, 6, 10
+; AIX32-NEXT: li 4, -1
+; AIX32-NEXT: lwz 12, 4(1)
+; AIX32-NEXT: cror 25, 21, 20
+; AIX32-NEXT: cmplwi 5, 3, 0
+; AIX32-NEXT: crandc 21, 29, 30
+; AIX32-NEXT: crand 23, 30, 9
+; AIX32-NEXT: cror 21, 23, 21
+; AIX32-NEXT: li 3, 1
+; AIX32-NEXT: crand 23, 30, 8
+; AIX32-NEXT: mtocrf 32, 12
+; AIX32-NEXT: crandc 20, 25, 22
+; AIX32-NEXT: crand 21, 22, 21
+; AIX32-NEXT: crnor 20, 21, 20
+; AIX32-NEXT: crand 21, 2, 24
+; AIX32-NEXT: isel 3, 0, 3, 20
+; AIX32-NEXT: crandc 20, 4, 2
+; AIX32-NEXT: cror 20, 21, 20
+; AIX32-NEXT: crandc 21, 28, 30
+; AIX32-NEXT: cror 21, 23, 21
+; AIX32-NEXT: crandc 20, 20, 22
+; AIX32-NEXT: crand 21, 22, 21
+; AIX32-NEXT: cror 20, 21, 20
+; AIX32-NEXT: isel 3, 4, 3, 20
+; AIX32-NEXT: blr
+;
+; AIX64-LABEL: scmp_8_128:
+; AIX64: # %bb.0:
+; AIX64-NEXT: cmpld 3, 5
+; AIX64-NEXT: cmpd 1, 3, 5
+; AIX64-NEXT: li 3, 1
+; AIX64-NEXT: cmpld 5, 4, 6
+; AIX64-NEXT: li 4, -1
+; AIX64-NEXT: crandc 22, 5, 2
+; AIX64-NEXT: crand 21, 2, 21
+; AIX64-NEXT: crand 20, 2, 20
+; AIX64-NEXT: crnor 21, 21, 22
+; AIX64-NEXT: isel 3, 0, 3, 21
+; AIX64-NEXT: crandc 21, 4, 2
+; AIX64-NEXT: cror 20, 20, 21
+; AIX64-NEXT: isel 3, 4, 3, 20
+; AIX64-NEXT: blr
+;
+; CHECK-PWR9-LABEL: scmp_8_128:
+; CHECK-PWR9: # %bb.0:
+; CHECK-PWR9-NEXT: cmpld 4, 6
+; CHECK-PWR9-NEXT: cmpd 1, 4, 6
+; CHECK-PWR9-NEXT: cmpld 6, 3, 5
+; CHECK-PWR9-NEXT: li 3, 1
+; CHECK-PWR9-NEXT: li 4, -1
+; CHECK-PWR9-NEXT: crandc 20, 5, 2
+; CHECK-PWR9-NEXT: crand 21, 2, 25
+; CHECK-PWR9-NEXT: crnor 20, 21, 20
+; CHECK-PWR9-NEXT: crand 21, 2, 24
+; CHECK-PWR9-NEXT: isel 3, 0, 3, 20
+; CHECK-PWR9-NEXT: crandc 20, 4, 2
+; CHECK-PWR9-NEXT: cror 20, 21, 20
+; CHECK-PWR9-NEXT: isel 3, 4, 3, 20
+; CHECK-PWR9-NEXT: blr
+;
+; AIX32-PWR9-LABEL: scmp_8_128:
+; AIX32-PWR9: # %bb.0:
+; AIX32-PWR9-NEXT: cmplw 3, 7
+; AIX32-PWR9-NEXT: cmpw 1, 3, 7
+; AIX32-PWR9-NEXT: cmplw 6, 4, 8
+; AIX32-PWR9-NEXT: xor 3, 3, 7
+; AIX32-PWR9-NEXT: xor 4, 4, 8
+; AIX32-PWR9-NEXT: cmplw 7, 5, 9
+; AIX32-PWR9-NEXT: crandc 20, 5, 2
+; AIX32-PWR9-NEXT: crand 21, 2, 25
+; AIX32-PWR9-NEXT: mfcr 12
+; AIX32-PWR9-NEXT: or 3, 4, 3
+; AIX32-PWR9-NEXT: cmplw 2, 6, 10
+; AIX32-PWR9-NEXT: li 4, -1
+; AIX32-PWR9-NEXT: cror 25, 21, 20
+; AIX32-PWR9-NEXT: cmplwi 5, 3, 0
+; AIX32-PWR9-NEXT: crandc 21, 29, 30
+; AIX32-PWR9-NEXT: li 3, 1
+; AIX32-PWR9-NEXT: crand 23, 30, 9
+; AIX32-PWR9-NEXT: cror 21, 23, 21
+; AIX32-PWR9-NEXT: crandc 20, 25, 22
+; AIX32-PWR9-NEXT: crand 23, 30, 8
+; AIX32-PWR9-NEXT: stw 12, 4(1)
+; AIX32-PWR9-NEXT: lwz 12, 4(1)
+; AIX32-PWR9-NEXT: crand 21, 22, 21
+; AIX32-PWR9-NEXT: crnor 20, 21, 20
+; AIX32-PWR9-NEXT: crand 21, 2, 24
+; AIX32-PWR9-NEXT: mtocrf 32, 12
+; AIX32-PWR9-NEXT: isel 3, 0, 3, 20
+; AIX32-PWR9-NEXT: crandc 20, 4, 2
+; AIX32-PWR9-NEXT: cror 20, 21, 20
+; AIX32-PWR9-NEXT: crandc 21, 28, 30
+; AIX32-PWR9-NEXT: cror 21, 23, 21
+; AIX32-PWR9-NEXT: crandc 20, 20, 22
+; AIX32-PWR9-NEXT: crand 21, 22, 21
+; AIX32-PWR9-NEXT: cror 20, 21, 20
+; AIX32-PWR9-NEXT: isel 3, 4, 3, 20
+; AIX32-PWR9-NEXT: blr
+;
+; AIX64-PWR9-LABEL: scmp_8_128:
+; AIX64-PWR9: # %bb.0:
+; AIX64-PWR9-NEXT: cmpld 3, 5
+; AIX64-PWR9-NEXT: cmpd 1, 3, 5
+; AIX64-PWR9-NEXT: cmpld 6, 4, 6
+; AIX64-PWR9-NEXT: li 3, 1
+; AIX64-PWR9-NEXT: li 4, -1
+; AIX64-PWR9-NEXT: crandc 20, 5, 2
+; AIX64-PWR9-NEXT: crand 21, 2, 25
+; AIX64-PWR9-NEXT: crnor 20, 21, 20
+; AIX64-PWR9-NEXT: crand 21, 2, 24
+; AIX64-PWR9-NEXT: isel 3, 0, 3, 20
+; AIX64-PWR9-NEXT: crandc 20, 4, 2
+; AIX64-PWR9-NEXT: cror 20, 21, 20
+; AIX64-PWR9-NEXT: isel 3, 4, 3, 20
+; AIX64-PWR9-NEXT: blr
%1 = call i8 @llvm.scmp(i128 %x, i128 %y)
ret i8 %1
}
@@ -82,14 +389,52 @@ define i8 @scmp_8_128(i128 %x, i128 %y) nounwind {
define i32 @scmp_32_32(i32 %x, i32 %y) nounwind {
; CHECK-LABEL: scmp_32_32:
; CHECK: # %bb.0:
-; CHECK-NEXT: extsw 4, 4
-; CHECK-NEXT: extsw 3, 3
-; CHECK-NEXT: cmpw 3, 4
+; CHECK-NEXT: cmpw 7, 3, 4
+; CHECK-NEXT: mfocrf 3, 1
+; CHECK-NEXT: rlwinm 4, 3, 30, 31, 31
+; CHECK-NEXT: rlwinm 3, 3, 29, 31, 31
; CHECK-NEXT: sub 3, 4, 3
-; CHECK-NEXT: li 4, -1
-; CHECK-NEXT: rldicl 3, 3, 1, 63
-; CHECK-NEXT: isellt 3, 4, 3
; CHECK-NEXT: blr
+;
+; AIX32-LABEL: scmp_32_32:
+; AIX32: # %bb.0:
+; AIX32-NEXT: cmpw 7, 3, 4
+; AIX32-NEXT: mfocrf 3, 1
+; AIX32-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX32-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX32-NEXT: sub 3, 4, 3
+; AIX32-NEXT: blr
+;
+; AIX64-LABEL: scmp_32_32:
+; AIX64: # %bb.0:
+; AIX64-NEXT: cmpw 7, 3, 4
+; AIX64-NEXT: mfocrf 3, 1
+; AIX64-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX64-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX64-NEXT: sub 3, 4, 3
+; AIX64-NEXT: blr
+;
+; CHECK-PWR9-LABEL: scmp_32_32:
+; CHECK-PWR9: # %bb.0:
+; CHECK-PWR9-NEXT: cmpw 3, 4
+; CHECK-PWR9-NEXT: setb 3, 0
+; CHECK-PWR9-NEXT: blr
+;
+; AIX32-PWR9-LABEL: scmp_32_32:
+; AIX32-PWR9: # %bb.0:
+; AIX32-PWR9-NEXT: cmpw 3, 4
+; AIX32-PWR9-NEXT: li 3, 0
+; AIX32-PWR9-NEXT: li 4, 1
+; AIX32-PWR9-NEXT: iselgt 3, 4, 3
+; AIX32-PWR9-NEXT: li 4, -1
+; AIX32-PWR9-NEXT: isellt 3, 4, 3
+; AIX32-PWR9-NEXT: blr
+;
+; AIX64-PWR9-LABEL: scmp_32_32:
+; AIX64-PWR9: # %bb.0:
+; AIX64-PWR9-NEXT: cmpw 3, 4
+; AIX64-PWR9-NEXT: setb 3, 0
+; AIX64-PWR9-NEXT: blr
%1 = call i32 @llvm.scmp(i32 %x, i32 %y)
ret i32 %1
}
@@ -97,15 +442,67 @@ define i32 @scmp_32_32(i32 %x, i32 %y) nounwind {
define i32 @scmp_32_64(i64 %x, i64 %y) nounwind {
; CHECK-LABEL: scmp_32_64:
; CHECK: # %bb.0:
-; CHECK-NEXT: sradi 5, 4, 63
-; CHECK-NEXT: rldicl 6, 3, 1, 63
-; CHECK-NEXT: subc 7, 4, 3
-; CHECK-NEXT: adde 5, 6, 5
-; CHECK-NEXT: cmpd 3, 4
-; CHECK-NEXT: li 3, -1
-; CHECK-NEXT: xori 5, 5, 1
-; CHECK-NEXT: isellt 3, 3, 5
+; CHECK-NEXT: cmpd 7, 3, 4
+; CHECK-NEXT: mfocrf 3, 1
+; CHECK-NEXT: rlwinm 4, 3, 30, 31, 31
+; CHECK-NEXT: rlwinm 3, 3, 29, 31, 31
+; CHECK-NEXT: sub 3, 4, 3
; CHECK-NEXT: blr
+;
+; AIX32-LABEL: scmp_32_64:
+; AIX32: # %bb.0:
+; AIX32-NEXT: cmplw 3, 5
+; AIX32-NEXT: cmpw 1, 3, 5
+; AIX32-NEXT: li 3, 1
+; AIX32-NEXT: cmplw 5, 4, 6
+; AIX32-NEXT: li 4, -1
+; AIX32-NEXT: crandc 22, 5, 2
+; AIX32-NEXT: crand 21, 2, 21
+; AIX32-NEXT: crand 20, 2, 20
+; AIX32-NEXT: crnor 21, 21, 22
+; AIX32-NEXT: isel 3, 0, 3, 21
+; AIX32-NEXT: crandc 21, 4, 2
+; AIX32-NEXT: cror 20, 20, 21
+; AIX32-NEXT: isel 3, 4, 3, 20
+; AIX32-NEXT: blr
+;
+; AIX64-LABEL: scmp_32_64:
+; AIX64: # %bb.0:
+; AIX64-NEXT: cmpd 7, 3, 4
+; AIX64-NEXT: mfocrf 3, 1
+; AIX64-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX64-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX64-NEXT: sub 3, 4, 3
+; AIX64-NEXT: blr
+;
+; CHECK-PWR9-LABEL: scmp_32_64:
+; CHECK-PWR9: # %bb.0:
+; CHECK-PWR9-NEXT: cmpd 3, 4
+; CHECK-PWR9-NEXT: setb 3, 0
+; CHECK-PWR9-NEXT: blr
+;
+; AIX32-PWR9-LABEL: scmp_32_64:
+; AIX32-PWR9: # %bb.0:
+; AIX32-PWR9-NEXT: cmplw 3, 5
+; AIX32-PWR9-NEXT: cmpw 1, 3, 5
+; AIX32-PWR9-NEXT: cmplw 6, 4, 6
+; AIX32-PWR9-NEXT: li 3, 1
+; AIX32-PWR9-NEXT: li 4, -1
+; AIX32-PWR9-NEXT: crandc 20, 5, 2
+; AIX32-PWR9-NEXT: crand 21, 2, 25
+; AIX32-PWR9-NEXT: crnor 20, 21, 20
+; AIX32-PWR9-NEXT: crand 21, 2, 24
+; AIX32-PWR9-NEXT: isel 3, 0, 3, 20
+; AIX32-PWR9-NEXT: crandc 20, 4, 2
+; AIX32-PWR9-NEXT: cror 20, 21, 20
+; AIX32-PWR9-NEXT: isel 3, 4, 3, 20
+; AIX32-PWR9-NEXT: blr
+;
+; AIX64-PWR9-LABEL: scmp_32_64:
+; AIX64-PWR9: # %bb.0:
+; AIX64-PWR9-NEXT: cmpd 3, 4
+; AIX64-PWR9-NEXT: setb 3, 0
+; AIX64-PWR9-NEXT: blr
%1 = call i32 @llvm.scmp(i64 %x, i64 %y)
ret i32 %1
}
@@ -113,15 +510,140 @@ define i32 @scmp_32_64(i64 %x, i64 %y) nounwind {
define i64 @scmp_64_64(i64 %x, i64 %y) nounwind {
; CHECK-LABEL: scmp_64_64:
; CHECK: # %bb.0:
-; CHECK-NEXT: sradi 5, 4, 63
-; CHECK-NEXT: rldicl 6, 3, 1, 63
-; CHECK-NEXT: subc 7, 4, 3
-; CHECK-NEXT: adde 5, 6, 5
-; CHECK-NEXT: cmpd 3, 4
-; CHECK-NEXT: li 3, -1
-; CHECK-NEXT: xori 5, 5, 1
-; CHECK-NEXT: isellt 3, 3, 5
+; CHECK-NEXT: cmpd 7, 3, 4
+; CHECK-NEXT: mfocrf 3, 1
+; CHECK-NEXT: rlwinm 4, 3, 30, 31, 31
+; CHECK-NEXT: rlwinm 3, 3, 29, 31, 31
+; CHECK-NEXT: sub 3, 4, 3
; CHECK-NEXT: blr
+;
+; AIX32-LABEL: scmp_64_64:
+; AIX32: # %bb.0:
+; AIX32-NEXT: cmplw 3, 5
+; AIX32-NEXT: cmpw 1, 3, 5
+; AIX32-NEXT: li 3, 1
+; AIX32-NEXT: li 5, 0
+; AIX32-NEXT: cmplw 6, 4, 6
+; AIX32-NEXT: li 6, -1
+; AIX32-NEXT: crandc 20, 5, 2
+; AIX32-NEXT: crand 21, 2, 25
+; AIX32-NEXT: crnor 20, 21, 20
+; AIX32-NEXT: crand 21, 2, 24
+; AIX32-NEXT: isel 3, 0, 3, 20
+; AIX32-NEXT: crandc 20, 4, 2
+; AIX32-NEXT: cror 20, 21, 20
+; AIX32-NEXT: isel 4, 6, 3, 20
+; AIX32-NEXT: isel 3, 6, 5, 20
+; AIX32-NEXT: blr
+;
+; AIX64-LABEL: scmp_64_64:
+; AIX64: # %bb.0:
+; AIX64-NEXT: cmpd 7, 3, 4
+; AIX64-NEXT: mfocrf 3, 1
+; AIX64-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX64-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX64-NEXT: sub 3, 4, 3
+; AIX64-NEXT: blr
+;
+; CHECK-PWR9-LABEL: scmp_64_64:
+; CHECK-PWR9: # %bb.0:
+; CHECK-PWR9-NEXT: cmpd 3, 4
+; CHECK-PWR9-NEXT: setb 3, 0
+; CHECK-PWR9-NEXT: blr
+;
+; AIX32-PWR9-LABEL: scmp_64_64:
+; AIX32-PWR9: # %bb.0:
+; AIX32-PWR9-NEXT: cmplw 3, 5
+; AIX32-PWR9-NEXT: cmpw 1, 3, 5
+; AIX32-PWR9-NEXT: cmplw 6, 4, 6
+; AIX32-PWR9-NEXT: li 3, 1
+; AIX32-PWR9-NEXT: li 5, 0
+; AIX32-PWR9-NEXT: li 6, -1
+; AIX32-PWR9-NEXT: crandc 20, 5, 2
+; AIX32-PWR9-NEXT: crand 21, 2, 25
+; AIX32-PWR9-NEXT: crnor 20, 21, 20
+; AIX32-PWR9-NEXT: crand 21, 2, 24
+; AIX32-PWR9-NEXT: isel 3, 0, 3, 20
+; AIX32-PWR9-NEXT: crandc 20, 4, 2
+; AIX32-PWR9-NEXT: cror 20, 21, 20
+; AIX32-PWR9-NEXT: isel 4, 6, 3, 20
+; AIX32-PWR9-NEXT: isel 3, 6, 5, 20
+; AIX32-PWR9-NEXT: blr
+;
+; AIX64-PWR9-LABEL: scmp_64_64:
+; AIX64-PWR9: # %bb.0:
+; AIX64-PWR9-NEXT: cmpd 3, 4
+; AIX64-PWR9-NEXT: setb 3, 0
+; AIX64-PWR9-NEXT: blr
%1 = call i64 @llvm.scmp(i64 %x, i64 %y)
ret i64 %1
}
+
+define noundef signext range(i32 -1, 2) i32 @test_scmp(i64 noundef %a, i64 noundef %b) {
+; CHECK-LABEL: test_scmp:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cmpd 7, 3, 4
+; CHECK-NEXT: mfocrf 3, 1
+; CHECK-NEXT: rlwinm 4, 3, 30, 31, 31
+; CHECK-NEXT: rlwinm 3, 3, 29, 31, 31
+; CHECK-NEXT: sub 3, 4, 3
+; CHECK-NEXT: blr
+;
+; AIX32-LABEL: test_scmp:
+; AIX32: # %bb.0: # %entry
+; AIX32-NEXT: cmplw 3, 5
+; AIX32-NEXT: cmpw 1, 3, 5
+; AIX32-NEXT: li 3, 1
+; AIX32-NEXT: cmplw 5, 4, 6
+; AIX32-NEXT: li 4, -1
+; AIX32-NEXT: crandc 22, 5, 2
+; AIX32-NEXT: crand 21, 2, 21
+; AIX32-NEXT: crand 20, 2, 20
+; AIX32-NEXT: crnor 21, 21, 22
+; AIX32-NEXT: isel 3, 0, 3, 21
+; AIX32-NEXT: crandc 21, 4, 2
+; AIX32-NEXT: cror 20, 20, 21
+; AIX32-NEXT: isel 3, 4, 3, 20
+; AIX32-NEXT: blr
+;
+; AIX64-LABEL: test_scmp:
+; AIX64: # %bb.0: # %entry
+; AIX64-NEXT: cmpd 7, 3, 4
+; AIX64-NEXT: mfocrf 3, 1
+; AIX64-NEXT: rlwinm 4, 3, 30, 31, 31
+; AIX64-NEXT: rlwinm 3, 3, 29, 31, 31
+; AIX64-NEXT: sub 3, 4, 3
+; AIX64-NEXT: blr
+;
+; CHECK-PWR9-LABEL: test_scmp:
+; CHECK-PWR9: # %bb.0: # %entry
+; CHECK-PWR9-NEXT: cmpd 3, 4
+; CHECK-PWR9-NEXT: setb 3, 0
+; CHECK-PWR9-NEXT: blr
+;
+; AIX32-PWR9-LABEL: test_scmp:
+; AIX32-PWR9: # %bb.0: # %entry
+; AIX32-PWR9-NEXT: cmplw 3, 5
+; AIX32-PWR9-NEXT: cmpw 1, 3, 5
+; AIX32-PWR9-NEXT: cmplw 6, 4, 6
+; AIX32-PWR9-NEXT: li 3, 1
+; AIX32-PWR9-NEXT: li 4, -1
+; AIX32-PWR9-NEXT: crandc 20, 5, 2
+; AIX32-PWR9-NEXT: crand 21, 2, 25
+; AIX32-PWR9-NEXT: crnor 20, 21, 20
+; AIX32-PWR9-NEXT: crand 21, 2, 24
+; AIX32-PWR9-NEXT: isel 3, 0, 3, 20
+; AIX32-PWR9-NEXT: crandc 20, 4, 2
+; AIX32-PWR9-NEXT: cror 20, 21, 20
+; AIX32-PWR9-NEXT: isel 3, 4, 3, 20
+; AIX32-PWR9-NEXT: blr
+;
+; AIX64-PWR9-LABEL: test_scmp:
+; AIX64-PWR9: # %bb.0: # %entry
+; AIX64-PWR9-NEXT: cmpd 3, 4
+; AIX64-PWR9-NEXT: setb 3, 0
+; AIX64-PWR9-NEXT: blr
+entry:
+ %cond2 = tail call i32 @llvm.scmp.i32.i64(i64 %a, i64 %b)
+ ret i32 %cond2
+}
More information about the llvm-commits
mailing list