Skip to content

Commit ce71cf8

Browse files
committed
Thumb support for ucmp
there is no real good way to do scmp sadly
1 parent dd3d30a commit ce71cf8

File tree

2 files changed

+57
-31
lines changed

2 files changed

+57
-31
lines changed

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -802,10 +802,9 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
802802
setOperationAction(ISD::BSWAP, VT, Expand);
803803
}
804804

805-
if (!Subtarget->isThumb()) {
805+
if (!Subtarget->isThumb())
806806
setOperationAction(ISD::SCMP, MVT::i32, Custom);
807-
setOperationAction(ISD::UCMP, MVT::i32, Custom);
808-
}
807+
setOperationAction(ISD::UCMP, MVT::i32, Custom);
809808

810809
setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
811810
setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
@@ -10693,6 +10692,45 @@ SDValue ARMTargetLowering::LowerUCMP(SDValue Op, SelectionDAG &DAG) const {
1069310692
SDValue LHS = Op.getOperand(0);
1069410693
SDValue RHS = Op.getOperand(1);
1069510694

10695+
if (Subtarget->isThumb()) {
10696+
// For Thumb unsigned comparison, use this sequence:
10697+
// subs r2, r0, r1 ; r2 = LHS - RHS, sets flags
10698+
// sbc r2, r2 ; r2 = r2 - r2 - !carry
10699+
// cmp r1, r0 ; compare RHS with LHS
10700+
// sbc r1, r1 ; r1 = r1 - r1 - !carry
10701+
// subs r0, r2, r1 ; r0 = r2 - r1 (final result)
10702+
10703+
// First subtraction: LHS - RHS
10704+
SDValue Sub1WithFlags = DAG.getNode(
10705+
ARMISD::SUBC, dl, DAG.getVTList(MVT::i32, FlagsVT), LHS, RHS);
10706+
SDValue Sub1Result = Sub1WithFlags.getValue(0);
10707+
SDValue Flags1 = Sub1WithFlags.getValue(1);
10708+
10709+
// SUBE: Sub1Result - Sub1Result - !carry
10710+
// This gives 0 if LHS >= RHS (unsigned), -1 if LHS < RHS (unsigned)
10711+
SDValue Sbc1 =
10712+
DAG.getNode(ARMISD::SUBE, dl, DAG.getVTList(MVT::i32, FlagsVT),
10713+
Sub1Result, Sub1Result, Flags1);
10714+
SDValue Sbc1Result = Sbc1.getValue(0);
10715+
10716+
// Second comparison: RHS vs LHS (reverse comparison)
10717+
SDValue CmpFlags = DAG.getNode(ARMISD::CMP, dl, FlagsVT, RHS, LHS);
10718+
10719+
// SUBE: RHS - RHS - !carry
10720+
// This gives 0 if RHS <= LHS (unsigned), -1 if RHS > LHS (unsigned)
10721+
SDValue Sbc2 = DAG.getNode(
10722+
ARMISD::SUBE, dl, DAG.getVTList(MVT::i32, FlagsVT), RHS, RHS, CmpFlags);
10723+
SDValue Sbc2Result = Sbc2.getValue(0);
10724+
10725+
// Final subtraction: Sbc1Result - Sbc2Result (no flags needed)
10726+
SDValue Result =
10727+
DAG.getNode(ISD::SUB, dl, MVT::i32, Sbc1Result, Sbc2Result);
10728+
if (Op.getValueType() != MVT::i32)
10729+
Result = DAG.getSExtOrTrunc(Result, dl, Op.getValueType());
10730+
10731+
return Result;
10732+
}
10733+
1069610734
// For the ARM assembly pattern (unsigned version):
1069710735
// subs r0, r0, r1 ; subtract RHS from LHS and set flags
1069810736
// movhi r0, #1 ; if LHS > RHS (unsigned), set result to 1

llvm/test/CodeGen/Thumb/ucmp.ll

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,10 @@
44
define i8 @ucmp_8_8(i8 zeroext %x, i8 zeroext %y) nounwind {
55
; CHECK-LABEL: ucmp_8_8:
66
; CHECK: @ %bb.0:
7-
; CHECK-NEXT: cmp r0, r1
8-
; CHECK-NEXT: mov.w r0, #0
9-
; CHECK-NEXT: mov.w r2, #0
10-
; CHECK-NEXT: it lo
11-
; CHECK-NEXT: movlo r0, #1
12-
; CHECK-NEXT: it hi
13-
; CHECK-NEXT: movhi r2, #1
7+
; CHECK-NEXT: subs r2, r0, r1
8+
; CHECK-NEXT: sbcs r2, r2
9+
; CHECK-NEXT: cmp r1, r0
10+
; CHECK-NEXT: sbc.w r0, r1, r1
1411
; CHECK-NEXT: subs r0, r2, r0
1512
; CHECK-NEXT: bx lr
1613
%1 = call i8 @llvm.ucmp(i8 %x, i8 %y)
@@ -20,13 +17,10 @@ define i8 @ucmp_8_8(i8 zeroext %x, i8 zeroext %y) nounwind {
2017
define i8 @ucmp_8_16(i16 zeroext %x, i16 zeroext %y) nounwind {
2118
; CHECK-LABEL: ucmp_8_16:
2219
; CHECK: @ %bb.0:
23-
; CHECK-NEXT: cmp r0, r1
24-
; CHECK-NEXT: mov.w r0, #0
25-
; CHECK-NEXT: mov.w r2, #0
26-
; CHECK-NEXT: it lo
27-
; CHECK-NEXT: movlo r0, #1
28-
; CHECK-NEXT: it hi
29-
; CHECK-NEXT: movhi r2, #1
20+
; CHECK-NEXT: subs r2, r0, r1
21+
; CHECK-NEXT: sbcs r2, r2
22+
; CHECK-NEXT: cmp r1, r0
23+
; CHECK-NEXT: sbc.w r0, r1, r1
3024
; CHECK-NEXT: subs r0, r2, r0
3125
; CHECK-NEXT: bx lr
3226
%1 = call i8 @llvm.ucmp(i16 %x, i16 %y)
@@ -36,13 +30,10 @@ define i8 @ucmp_8_16(i16 zeroext %x, i16 zeroext %y) nounwind {
3630
define i8 @ucmp_8_32(i32 %x, i32 %y) nounwind {
3731
; CHECK-LABEL: ucmp_8_32:
3832
; CHECK: @ %bb.0:
39-
; CHECK-NEXT: cmp r0, r1
40-
; CHECK-NEXT: mov.w r0, #0
41-
; CHECK-NEXT: mov.w r2, #0
42-
; CHECK-NEXT: it lo
43-
; CHECK-NEXT: movlo r0, #1
44-
; CHECK-NEXT: it hi
45-
; CHECK-NEXT: movhi r2, #1
33+
; CHECK-NEXT: subs r2, r0, r1
34+
; CHECK-NEXT: sbcs r2, r2
35+
; CHECK-NEXT: cmp r1, r0
36+
; CHECK-NEXT: sbc.w r0, r1, r1
4637
; CHECK-NEXT: subs r0, r2, r0
4738
; CHECK-NEXT: bx lr
4839
%1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
@@ -98,13 +89,10 @@ define i8 @ucmp_8_128(i128 %x, i128 %y) nounwind {
9889
define i32 @ucmp_32_32(i32 %x, i32 %y) nounwind {
9990
; CHECK-LABEL: ucmp_32_32:
10091
; CHECK: @ %bb.0:
101-
; CHECK-NEXT: cmp r0, r1
102-
; CHECK-NEXT: mov.w r0, #0
103-
; CHECK-NEXT: mov.w r2, #0
104-
; CHECK-NEXT: it lo
105-
; CHECK-NEXT: movlo r0, #1
106-
; CHECK-NEXT: it hi
107-
; CHECK-NEXT: movhi r2, #1
92+
; CHECK-NEXT: subs r2, r0, r1
93+
; CHECK-NEXT: sbcs r2, r2
94+
; CHECK-NEXT: cmp r1, r0
95+
; CHECK-NEXT: sbc.w r0, r1, r1
10896
; CHECK-NEXT: subs r0, r2, r0
10997
; CHECK-NEXT: bx lr
11098
%1 = call i32 @llvm.ucmp(i32 %x, i32 %y)

0 commit comments

Comments
 (0)