@@ -802,6 +802,11 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
802
802
setOperationAction(ISD::BSWAP, VT, Expand);
803
803
}
804
804
805
+ if (!Subtarget->isThumb()) {
806
+ setOperationAction(ISD::SCMP, MVT::i32, Custom);
807
+ setOperationAction(ISD::UCMP, MVT::i32, Custom);
808
+ }
809
+
805
810
setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
806
811
setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
807
812
@@ -10614,6 +10619,142 @@ SDValue ARMTargetLowering::LowerFP_TO_BF16(SDValue Op,
10614
10619
return DAG.getBitcast(MVT::i32, Res);
10615
10620
}
10616
10621
10622
+ SDValue ARMTargetLowering::LowerSCMP(SDValue Op, SelectionDAG &DAG) const {
10623
+ SDLoc dl(Op);
10624
+ SDValue LHS = Op.getOperand(0);
10625
+ SDValue RHS = Op.getOperand(1);
10626
+
10627
+ // For the ARM assembly pattern:
10628
+ // subs r0, r0, r1 ; subtract RHS from LHS and set flags
10629
+ // movgt r0, #1 ; if LHS > RHS, set result to 1
10630
+ // mvnlt r0, #0 ; if LHS < RHS, set result to -1 (mvn #0 = -1)
10631
+ // ; if LHS == RHS, result remains 0 from the subs
10632
+
10633
+ // Optimization: if RHS is a subtraction against 0, use ADDC instead of SUBC
10634
+ // Check if RHS is (0 - something), and if so use ADDC with LHS + something
10635
+ SDValue SubResult, Flags;
10636
+ bool CanUseAdd = false;
10637
+ SDValue AddOperand;
10638
+
10639
+ // Check if RHS is a subtraction against 0: (0 - X)
10640
+ if (RHS.getOpcode() == ISD::SUB) {
10641
+ SDValue SubLHS = RHS.getOperand(0);
10642
+ SDValue SubRHS = RHS.getOperand(1);
10643
+
10644
+ // Check if it's 0 - X
10645
+ if (isNullConstant(SubLHS)) {
10646
+ // For SCMP: only if X is known to never be INT_MIN (to avoid overflow)
10647
+ if (RHS->getFlags().hasNoSignedWrap() || !DAG.computeKnownBits(SubRHS)
10648
+ .getSignedMinValue()
10649
+ .isMinSignedValue()) {
10650
+ CanUseAdd = true;
10651
+ AddOperand = SubRHS; // Replace RHS with X, so we do LHS + X instead of
10652
+ // LHS - (0 - X)
10653
+ }
10654
+ }
10655
+ }
10656
+
10657
+ if (CanUseAdd) {
10658
+ // Use ADDC: LHS + AddOperand (where RHS was 0 - AddOperand)
10659
+ SDValue AddWithFlags = DAG.getNode(
10660
+ ARMISD::ADDC, dl, DAG.getVTList(MVT::i32, FlagsVT), LHS, AddOperand);
10661
+ SubResult = AddWithFlags.getValue(0); // The addition result
10662
+ Flags = AddWithFlags.getValue(1); // The flags from ADDS
10663
+ } else {
10664
+ // Use ARMISD::SUBC to generate SUBS instruction (subtract with flags)
10665
+ SDValue SubWithFlags = DAG.getNode(
10666
+ ARMISD::SUBC, dl, DAG.getVTList(MVT::i32, FlagsVT), LHS, RHS);
10667
+ SubResult = SubWithFlags.getValue(0); // The subtraction result
10668
+ Flags = SubWithFlags.getValue(1); // The flags from SUBS
10669
+ }
10670
+
10671
+ // Constants for conditional moves
10672
+ SDValue One = DAG.getConstant(1, dl, MVT::i32);
10673
+ SDValue MinusOne = DAG.getConstant(0xFFFFFFFF, dl, MVT::i32);
10674
+
10675
+ // movgt: if greater than, set to 1
10676
+ SDValue GTCond = DAG.getConstant(ARMCC::GT, dl, MVT::i32);
10677
+ SDValue Result1 =
10678
+ DAG.getNode(ARMISD::CMOV, dl, MVT::i32, SubResult, One, GTCond, Flags);
10679
+
10680
+ // mvnlt: if less than, set to -1 (equivalent to mvn #0)
10681
+ SDValue LTCond = DAG.getConstant(ARMCC::LT, dl, MVT::i32);
10682
+ SDValue Result2 =
10683
+ DAG.getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne, LTCond, Flags);
10684
+
10685
+ if (Op.getValueType() != MVT::i32)
10686
+ Result2 = DAG.getSExtOrTrunc(Result2, dl, Op.getValueType());
10687
+
10688
+ return Result2;
10689
+ }
10690
+
10691
+ SDValue ARMTargetLowering::LowerUCMP(SDValue Op, SelectionDAG &DAG) const {
10692
+ SDLoc dl(Op);
10693
+ SDValue LHS = Op.getOperand(0);
10694
+ SDValue RHS = Op.getOperand(1);
10695
+
10696
+ // For the ARM assembly pattern (unsigned version):
10697
+ // subs r0, r0, r1 ; subtract RHS from LHS and set flags
10698
+ // movhi r0, #1 ; if LHS > RHS (unsigned), set result to 1
10699
+ // mvnlo r0, #0 ; if LHS < RHS (unsigned), set result to -1
10700
+ // ; if LHS == RHS, result remains 0 from the subs
10701
+
10702
+ // Optimization: if RHS is a subtraction against 0, use ADDC instead of SUBC
10703
+ // Check if RHS is (0 - something), and if so use ADDC with LHS + something
10704
+ SDValue SubResult, Flags;
10705
+ bool CanUseAdd = false;
10706
+ SDValue AddOperand;
10707
+
10708
+ // Check if RHS is a subtraction against 0: (0 - X)
10709
+ if (RHS.getOpcode() == ISD::SUB) {
10710
+ SDValue SubLHS = RHS.getOperand(0);
10711
+ SDValue SubRHS = RHS.getOperand(1);
10712
+
10713
+ // Check if it's 0 - X
10714
+ if (isNullConstant(SubLHS)) {
10715
+ // For UCMP: only if X is known to never be zero
10716
+ if (DAG.isKnownNeverZero(SubRHS)) {
10717
+ CanUseAdd = true;
10718
+ AddOperand = SubRHS; // Replace RHS with X, so we do LHS + X instead of
10719
+ // LHS - (0 - X)
10720
+ }
10721
+ }
10722
+ }
10723
+
10724
+ if (CanUseAdd) {
10725
+ // Use ADDC: LHS + AddOperand (where RHS was 0 - AddOperand)
10726
+ SDValue AddWithFlags = DAG.getNode(
10727
+ ARMISD::ADDC, dl, DAG.getVTList(MVT::i32, FlagsVT), LHS, AddOperand);
10728
+ SubResult = AddWithFlags.getValue(0); // The addition result
10729
+ Flags = AddWithFlags.getValue(1); // The flags from ADDS
10730
+ } else {
10731
+ // Use ARMISD::SUBC to generate SUBS instruction (subtract with flags)
10732
+ SDValue SubWithFlags = DAG.getNode(
10733
+ ARMISD::SUBC, dl, DAG.getVTList(MVT::i32, FlagsVT), LHS, RHS);
10734
+ SubResult = SubWithFlags.getValue(0); // The subtraction result
10735
+ Flags = SubWithFlags.getValue(1); // The flags from SUBS
10736
+ }
10737
+
10738
+ // Constants for conditional moves
10739
+ SDValue One = DAG.getConstant(1, dl, MVT::i32);
10740
+ SDValue MinusOne = DAG.getConstant(0xFFFFFFFF, dl, MVT::i32);
10741
+
10742
+ // movhi: if higher (unsigned greater than), set to 1
10743
+ SDValue HICond = DAG.getConstant(ARMCC::HI, dl, MVT::i32);
10744
+ SDValue Result1 =
10745
+ DAG.getNode(ARMISD::CMOV, dl, MVT::i32, SubResult, One, HICond, Flags);
10746
+
10747
+ // mvnlo: if lower (unsigned less than), set to -1
10748
+ SDValue LOCond = DAG.getConstant(ARMCC::LO, dl, MVT::i32);
10749
+ SDValue Result2 =
10750
+ DAG.getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne, LOCond, Flags);
10751
+
10752
+ if (Op.getValueType() != MVT::i32)
10753
+ Result2 = DAG.getSExtOrTrunc(Result2, dl, Op.getValueType());
10754
+
10755
+ return Result2;
10756
+ }
10757
+
10617
10758
SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
10618
10759
LLVM_DEBUG(dbgs() << "Lowering node: "; Op.dump());
10619
10760
switch (Op.getOpcode()) {
@@ -10742,6 +10883,10 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
10742
10883
case ISD::FP_TO_BF16:
10743
10884
return LowerFP_TO_BF16(Op, DAG);
10744
10885
case ARMISD::WIN__DBZCHK: return SDValue();
10886
+ case ISD::SCMP:
10887
+ return LowerSCMP(Op, DAG);
10888
+ case ISD::UCMP:
10889
+ return LowerUCMP(Op, DAG);
10745
10890
}
10746
10891
}
10747
10892
0 commit comments