[llvm] [Thumb] Custom lower abdu (PR #206291)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 27 16:00:18 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: AZero13 (AZero13)

<details>
<summary>Changes</summary>

For Thumb, we can use the negate if carry idiom using sbc directly for abdu.

---

Patch is 176.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/206291.diff


7 Files Affected:

- (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+57-1) 
- (modified) llvm/lib/Target/ARM/ARMISelLowering.h (+1) 
- (added) llvm/test/CodeGen/ARM/abds-neg.ll (+1380) 
- (added) llvm/test/CodeGen/ARM/abds.ll (+1528) 
- (added) llvm/test/CodeGen/ARM/abdu-neg.ll (+996) 
- (added) llvm/test/CodeGen/ARM/abdu.ll (+1054) 
- (modified) llvm/test/CodeGen/ARM/iabs.ll (+78-34) 


``````````diff
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 042ae5cc6b74c..a878118653cdb 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -596,8 +596,11 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
   if (!Subtarget->hasV8_1MMainlineOps())
     setOperationAction(ISD::UCMP, MVT::i32, Custom);
 
-  if (!Subtarget->isThumb1Only())
+  if (!Subtarget->isThumb1Only()) {
     setOperationAction(ISD::ABS, MVT::i32, Custom);
+  } else {
+    setOperationAction(ISD::ABDU, MVT::i32, Custom);
+  }
 
   setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
   setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
@@ -5366,6 +5369,57 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
   return Result;
 }
 
+SDValue ARMTargetLowering::LowerABDU(SDValue Op, SelectionDAG &DAG) const {
+  SDValue LHS = Op.getOperand(0);
+  SDValue RHS = Op.getOperand(1);
+  SDLoc DL(Op);
+  EVT VT = Op.getValueType();
+
+  bool IsNonNegative = DAG.SignBitIsZero(LHS) && DAG.SignBitIsZero(RHS);
+
+  // If the subtract doesn't overflow then just use abs(sub()).
+  if (DAG.willNotOverflowSub(IsNonNegative, LHS, RHS))
+    return DAG.getNode(ISD::ABS, DL, VT,
+                       DAG.getNode(ISD::SUB, DL, VT, LHS, RHS));
+
+  if (DAG.willNotOverflowSub(IsNonNegative, RHS, LHS))
+    return DAG.getNode(ISD::ABS, DL, VT,
+                       DAG.getNode(ISD::SUB, DL, VT, RHS, LHS));
+
+  // General path: use SUBC (or ADDC when RHS is 0-X) to get
+  // subtract-with-flags, then CMOV to select a-b or b-a. ADDC/SUBC produce the
+  // flags we need.
+  unsigned Opcode = ARMISD::SUBC;
+
+  // Check if RHS is a negation (0 - X). If so, we can use ADDC instead of SUBC:
+  //   a - (0 - x) = a + x (mod 2^n)
+  // Same semantics as in LowerCMP; apply same safety checks.
+  if (RHS.getOpcode() == ISD::SUB) {
+    SDValue SubLHS = RHS.getOperand(0);
+    SDValue SubRHS = RHS.getOperand(1);
+    if (isNullConstant(SubLHS) && DAG.isKnownNeverZero(SubRHS)) {
+      Opcode = ARMISD::ADDC;
+      RHS = SubRHS;
+    }
+  }
+
+  SDValue SubWithFlags =
+      DAG.getNode(Opcode, DL, DAG.getVTList(VT, FlagsVT), LHS, RHS);
+
+  // First subtraction: LHS - RHS
+  SDValue Flags1 = SubWithFlags.getValue(1);
+
+  // sbcs r1,r1,r1 (mask from borrow)
+  SDValue Sbc1 = DAG.getNode(ARMISD::SUBE, DL, DAG.getVTList(VT, FlagsVT), RHS,
+                             RHS, Flags1);
+
+  // eors (XOR)
+  SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, SubWithFlags, Sbc1.getValue(0));
+
+  // subs (final subtraction)
+  return DAG.getNode(ISD::SUB, DL, VT, Xor, Sbc1.getValue(0));
+}
+
 /// canChangeToInt - Given the fp compare operand, return true if it is suitable
 /// to morph to an integer compare sequence.
 static bool canChangeToInt(SDValue Op, bool &SeenZero,
@@ -10474,6 +10528,8 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
   case ISD::SELECT:        return LowerSELECT(Op, DAG);
   case ISD::SELECT_CC:     return LowerSELECT_CC(Op, DAG);
+  case ISD::ABDU:
+    return LowerABDU(Op, DAG);
   case ISD::BRCOND:        return LowerBRCOND(Op, DAG);
   case ISD::BR_CC:         return LowerBR_CC(Op, DAG);
   case ISD::BR_JT:         return LowerBR_JT(Op, DAG);
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index 10f5442d7429b..ba02344067843 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -575,6 +575,7 @@ class VectorType;
     SDValue LowerALUO(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
+    SDValue LowerABDU(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/test/CodeGen/ARM/abds-neg.ll b/llvm/test/CodeGen/ARM/abds-neg.ll
new file mode 100644
index 0000000000000..53bc719127019
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/abds-neg.ll
@@ -0,0 +1,1380 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=arm-eabi -mattr=+v4t %s -o - | FileCheck %s  --check-prefixes=CHECK,CHECK-ARM
+; RUN: llc -mtriple=thumbv6m-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-THUMB
+
+;
+; trunc(nabs(sub(sext(a),sext(b)))) -> nabds(a,b)
+;
+
+define i8 @abd_ext_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i8:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    lsl r0, r0, #24
+; CHECK-ARM-NEXT:    lsl r1, r1, #24
+; CHECK-ARM-NEXT:    asr r0, r0, #24
+; CHECK-ARM-NEXT:    sub r0, r0, r1, asr #24
+; CHECK-ARM-NEXT:    cmp r0, #0
+; CHECK-ARM-NEXT:    rsbpl r0, r0, #0
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i8:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    sxtb r1, r1
+; CHECK-THUMB-NEXT:    sxtb r0, r0
+; CHECK-THUMB-NEXT:    subs r0, r0, r1
+; CHECK-THUMB-NEXT:    asrs r1, r0, #31
+; CHECK-THUMB-NEXT:    eors r0, r1
+; CHECK-THUMB-NEXT:    subs r0, r1, r0
+; CHECK-THUMB-NEXT:    bx lr
+  %aext = sext i8 %a to i64
+  %bext = sext i8 %b to i64
+  %sub = sub i64 %aext, %bext
+  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+  %nabs = sub i64 0, %abs
+  %trunc = trunc i64 %nabs to i8
+  ret i8 %trunc
+}
+
+define i8 @abd_ext_i8_i16(i8 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i8_i16:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    lsl r0, r0, #24
+; CHECK-ARM-NEXT:    lsl r1, r1, #16
+; CHECK-ARM-NEXT:    asr r0, r0, #24
+; CHECK-ARM-NEXT:    sub r0, r0, r1, asr #16
+; CHECK-ARM-NEXT:    cmp r0, #0
+; CHECK-ARM-NEXT:    rsbpl r0, r0, #0
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i8_i16:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    sxth r1, r1
+; CHECK-THUMB-NEXT:    sxtb r0, r0
+; CHECK-THUMB-NEXT:    subs r0, r0, r1
+; CHECK-THUMB-NEXT:    asrs r1, r0, #31
+; CHECK-THUMB-NEXT:    eors r0, r1
+; CHECK-THUMB-NEXT:    subs r0, r1, r0
+; CHECK-THUMB-NEXT:    bx lr
+  %aext = sext i8 %a to i64
+  %bext = sext i16 %b to i64
+  %sub = sub i64 %aext, %bext
+  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+  %nabs = sub i64 0, %abs
+  %trunc = trunc i64 %nabs to i8
+  ret i8 %trunc
+}
+
+define i8 @abd_ext_i8_undef(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i8_undef:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    lsl r0, r0, #24
+; CHECK-ARM-NEXT:    lsl r1, r1, #24
+; CHECK-ARM-NEXT:    asr r0, r0, #24
+; CHECK-ARM-NEXT:    sub r0, r0, r1, asr #24
+; CHECK-ARM-NEXT:    cmp r0, #0
+; CHECK-ARM-NEXT:    rsbpl r0, r0, #0
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i8_undef:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    sxtb r1, r1
+; CHECK-THUMB-NEXT:    sxtb r0, r0
+; CHECK-THUMB-NEXT:    subs r0, r0, r1
+; CHECK-THUMB-NEXT:    asrs r1, r0, #31
+; CHECK-THUMB-NEXT:    eors r0, r1
+; CHECK-THUMB-NEXT:    subs r0, r1, r0
+; CHECK-THUMB-NEXT:    bx lr
+  %aext = sext i8 %a to i64
+  %bext = sext i8 %b to i64
+  %sub = sub i64 %aext, %bext
+  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
+  %nabs = sub i64 0, %abs
+  %trunc = trunc i64 %nabs to i8
+  ret i8 %trunc
+}
+
+define i16 @abd_ext_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i16:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    lsl r0, r0, #16
+; CHECK-ARM-NEXT:    lsl r1, r1, #16
+; CHECK-ARM-NEXT:    asr r0, r0, #16
+; CHECK-ARM-NEXT:    sub r0, r0, r1, asr #16
+; CHECK-ARM-NEXT:    cmp r0, #0
+; CHECK-ARM-NEXT:    rsbpl r0, r0, #0
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i16:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    sxth r1, r1
+; CHECK-THUMB-NEXT:    sxth r0, r0
+; CHECK-THUMB-NEXT:    subs r0, r0, r1
+; CHECK-THUMB-NEXT:    asrs r1, r0, #31
+; CHECK-THUMB-NEXT:    eors r0, r1
+; CHECK-THUMB-NEXT:    subs r0, r1, r0
+; CHECK-THUMB-NEXT:    bx lr
+  %aext = sext i16 %a to i64
+  %bext = sext i16 %b to i64
+  %sub = sub i64 %aext, %bext
+  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+  %nabs = sub i64 0, %abs
+  %trunc = trunc i64 %nabs to i16
+  ret i16 %trunc
+}
+
+define i16 @abd_ext_i16_i32(i16 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i16_i32:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    lsl r0, r0, #16
+; CHECK-ARM-NEXT:    sub r2, r1, r0, asr #16
+; CHECK-ARM-NEXT:    cmp r1, r0, asr #16
+; CHECK-ARM-NEXT:    rsblt r2, r1, r0, asr #16
+; CHECK-ARM-NEXT:    rsb r0, r2, #0
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i16_i32:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    sxth r2, r0
+; CHECK-THUMB-NEXT:    subs r0, r1, r2
+; CHECK-THUMB-NEXT:    bge .LBB4_2
+; CHECK-THUMB-NEXT:  @ %bb.1:
+; CHECK-THUMB-NEXT:    subs r0, r2, r1
+; CHECK-THUMB-NEXT:  .LBB4_2:
+; CHECK-THUMB-NEXT:    rsbs r0, r0, #0
+; CHECK-THUMB-NEXT:    bx lr
+  %aext = sext i16 %a to i64
+  %bext = sext i32 %b to i64
+  %sub = sub i64 %aext, %bext
+  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+  %nabs = sub i64 0, %abs
+  %trunc = trunc i64 %nabs to i16
+  ret i16 %trunc
+}
+
+define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i16_undef:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    lsl r0, r0, #16
+; CHECK-ARM-NEXT:    lsl r1, r1, #16
+; CHECK-ARM-NEXT:    asr r0, r0, #16
+; CHECK-ARM-NEXT:    sub r0, r0, r1, asr #16
+; CHECK-ARM-NEXT:    cmp r0, #0
+; CHECK-ARM-NEXT:    rsbpl r0, r0, #0
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i16_undef:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    sxth r1, r1
+; CHECK-THUMB-NEXT:    sxth r0, r0
+; CHECK-THUMB-NEXT:    subs r0, r0, r1
+; CHECK-THUMB-NEXT:    asrs r1, r0, #31
+; CHECK-THUMB-NEXT:    eors r0, r1
+; CHECK-THUMB-NEXT:    subs r0, r1, r0
+; CHECK-THUMB-NEXT:    bx lr
+  %aext = sext i16 %a to i64
+  %bext = sext i16 %b to i64
+  %sub = sub i64 %aext, %bext
+  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
+  %nabs = sub i64 0, %abs
+  %trunc = trunc i64 %nabs to i16
+  ret i16 %trunc
+}
+
+define i32 @abd_ext_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i32:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    subs r2, r1, r0
+; CHECK-ARM-NEXT:    sublt r2, r0, r1
+; CHECK-ARM-NEXT:    rsb r0, r2, #0
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i32:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    subs r2, r1, r0
+; CHECK-THUMB-NEXT:    bge .LBB6_2
+; CHECK-THUMB-NEXT:  @ %bb.1:
+; CHECK-THUMB-NEXT:    subs r2, r0, r1
+; CHECK-THUMB-NEXT:  .LBB6_2:
+; CHECK-THUMB-NEXT:    rsbs r0, r2, #0
+; CHECK-THUMB-NEXT:    bx lr
+  %aext = sext i32 %a to i64
+  %bext = sext i32 %b to i64
+  %sub = sub i64 %aext, %bext
+  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+  %nabs = sub i64 0, %abs
+  %trunc = trunc i64 %nabs to i32
+  ret i32 %trunc
+}
+
+define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i32_i16:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    lsl r1, r1, #16
+; CHECK-ARM-NEXT:    rsb r2, r0, r1, asr #16
+; CHECK-ARM-NEXT:    cmp r0, r1, asr #16
+; CHECK-ARM-NEXT:    subgt r2, r0, r1, asr #16
+; CHECK-ARM-NEXT:    rsb r0, r2, #0
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i32_i16:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    sxth r2, r1
+; CHECK-THUMB-NEXT:    subs r1, r2, r0
+; CHECK-THUMB-NEXT:    bge .LBB7_2
+; CHECK-THUMB-NEXT:  @ %bb.1:
+; CHECK-THUMB-NEXT:    subs r1, r0, r2
+; CHECK-THUMB-NEXT:  .LBB7_2:
+; CHECK-THUMB-NEXT:    rsbs r0, r1, #0
+; CHECK-THUMB-NEXT:    bx lr
+  %aext = sext i32 %a to i64
+  %bext = sext i16 %b to i64
+  %sub = sub i64 %aext, %bext
+  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+  %nabs = sub i64 0, %abs
+  %trunc = trunc i64 %nabs to i32
+  ret i32 %trunc
+}
+
+define i32 @abd_ext_i32_undef(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i32_undef:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    subs r2, r1, r0
+; CHECK-ARM-NEXT:    sublt r2, r0, r1
+; CHECK-ARM-NEXT:    rsb r0, r2, #0
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i32_undef:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    subs r2, r1, r0
+; CHECK-THUMB-NEXT:    bge .LBB8_2
+; CHECK-THUMB-NEXT:  @ %bb.1:
+; CHECK-THUMB-NEXT:    subs r2, r0, r1
+; CHECK-THUMB-NEXT:  .LBB8_2:
+; CHECK-THUMB-NEXT:    rsbs r0, r2, #0
+; CHECK-THUMB-NEXT:    bx lr
+  %aext = sext i32 %a to i64
+  %bext = sext i32 %b to i64
+  %sub = sub i64 %aext, %bext
+  %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
+  %nabs = sub i64 0, %abs
+  %trunc = trunc i64 %nabs to i32
+  ret i32 %trunc
+}
+
+define i64 @abd_ext_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i64:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    .save {r11, lr}
+; CHECK-ARM-NEXT:    push {r11, lr}
+; CHECK-ARM-NEXT:    subs r12, r0, r2
+; CHECK-ARM-NEXT:    sbc lr, r1, r3
+; CHECK-ARM-NEXT:    subs r0, r2, r0
+; CHECK-ARM-NEXT:    sbcs r1, r3, r1
+; CHECK-ARM-NEXT:    movlt r0, r12
+; CHECK-ARM-NEXT:    movlt r1, lr
+; CHECK-ARM-NEXT:    rsbs r0, r0, #0
+; CHECK-ARM-NEXT:    rsc r1, r1, #0
+; CHECK-ARM-NEXT:    pop {r11, lr}
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i64:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    .save {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT:    push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT:    subs r5, r0, r2
+; CHECK-THUMB-NEXT:    mov r4, r1
+; CHECK-THUMB-NEXT:    sbcs r4, r3
+; CHECK-THUMB-NEXT:    subs r0, r2, r0
+; CHECK-THUMB-NEXT:    sbcs r3, r1
+; CHECK-THUMB-NEXT:    blt .LBB9_2
+; CHECK-THUMB-NEXT:  @ %bb.1:
+; CHECK-THUMB-NEXT:    mov r4, r3
+; CHECK-THUMB-NEXT:  .LBB9_2:
+; CHECK-THUMB-NEXT:    blt .LBB9_4
+; CHECK-THUMB-NEXT:  @ %bb.3:
+; CHECK-THUMB-NEXT:    mov r5, r0
+; CHECK-THUMB-NEXT:  .LBB9_4:
+; CHECK-THUMB-NEXT:    movs r1, #0
+; CHECK-THUMB-NEXT:    rsbs r0, r5, #0
+; CHECK-THUMB-NEXT:    sbcs r1, r4
+; CHECK-THUMB-NEXT:    pop {r4, r5, r7, pc}
+  %aext = sext i64 %a to i128
+  %bext = sext i64 %b to i128
+  %sub = sub i128 %aext, %bext
+  %abs = call i128 @llvm.abs.i128(i128 %sub, i1 false)
+  %nabs = sub i128 0, %abs
+  %trunc = trunc i128 %nabs to i64
+  ret i64 %trunc
+}
+
+define i64 @abd_ext_i64_undef(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i64_undef:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    .save {r11, lr}
+; CHECK-ARM-NEXT:    push {r11, lr}
+; CHECK-ARM-NEXT:    subs r12, r0, r2
+; CHECK-ARM-NEXT:    sbc lr, r1, r3
+; CHECK-ARM-NEXT:    subs r0, r2, r0
+; CHECK-ARM-NEXT:    sbcs r1, r3, r1
+; CHECK-ARM-NEXT:    movlt r0, r12
+; CHECK-ARM-NEXT:    movlt r1, lr
+; CHECK-ARM-NEXT:    rsbs r0, r0, #0
+; CHECK-ARM-NEXT:    rsc r1, r1, #0
+; CHECK-ARM-NEXT:    pop {r11, lr}
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i64_undef:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    .save {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT:    push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT:    subs r5, r0, r2
+; CHECK-THUMB-NEXT:    mov r4, r1
+; CHECK-THUMB-NEXT:    sbcs r4, r3
+; CHECK-THUMB-NEXT:    subs r0, r2, r0
+; CHECK-THUMB-NEXT:    sbcs r3, r1
+; CHECK-THUMB-NEXT:    blt .LBB10_2
+; CHECK-THUMB-NEXT:  @ %bb.1:
+; CHECK-THUMB-NEXT:    mov r4, r3
+; CHECK-THUMB-NEXT:  .LBB10_2:
+; CHECK-THUMB-NEXT:    blt .LBB10_4
+; CHECK-THUMB-NEXT:  @ %bb.3:
+; CHECK-THUMB-NEXT:    mov r5, r0
+; CHECK-THUMB-NEXT:  .LBB10_4:
+; CHECK-THUMB-NEXT:    movs r1, #0
+; CHECK-THUMB-NEXT:    rsbs r0, r5, #0
+; CHECK-THUMB-NEXT:    sbcs r1, r4
+; CHECK-THUMB-NEXT:    pop {r4, r5, r7, pc}
+  %aext = sext i64 %a to i128
+  %bext = sext i64 %b to i128
+  %sub = sub i128 %aext, %bext
+  %abs = call i128 @llvm.abs.i128(i128 %sub, i1 true)
+  %nabs = sub i128 0, %abs
+  %trunc = trunc i128 %nabs to i64
+  ret i64 %trunc
+}
+
+define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i128:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    .save {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT:    push {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT:    ldr r9, [sp, #32]
+; CHECK-ARM-NEXT:    ldr r8, [sp, #36]
+; CHECK-ARM-NEXT:    subs r6, r0, r9
+; CHECK-ARM-NEXT:    ldr lr, [sp, #40]
+; CHECK-ARM-NEXT:    sbcs r7, r1, r8
+; CHECK-ARM-NEXT:    ldr r12, [sp, #44]
+; CHECK-ARM-NEXT:    sbcs r4, r2, lr
+; CHECK-ARM-NEXT:    sbc r5, r3, r12
+; CHECK-ARM-NEXT:    subs r0, r9, r0
+; CHECK-ARM-NEXT:    sbcs r1, r8, r1
+; CHECK-ARM-NEXT:    sbcs r2, lr, r2
+; CHECK-ARM-NEXT:    sbcs r3, r12, r3
+; CHECK-ARM-NEXT:    movlt r0, r6
+; CHECK-ARM-NEXT:    movlt r3, r5
+; CHECK-ARM-NEXT:    movlt r2, r4
+; CHECK-ARM-NEXT:    movlt r1, r7
+; CHECK-ARM-NEXT:    rsbs r0, r0, #0
+; CHECK-ARM-NEXT:    rscs r1, r1, #0
+; CHECK-ARM-NEXT:    rscs r2, r2, #0
+; CHECK-ARM-NEXT:    rsc r3, r3, #0
+; CHECK-ARM-NEXT:    pop {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT:    bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i128:
+; CHECK-THUMB:       @ %bb.0:
+; CHECK-THUMB-NEXT:    .save {r4, r5, r6, r7, lr}
+; CHECK-THUMB-NEXT:    push {r4, r5, r6, r7, lr}
+; CHECK-THUMB-NEXT:    .pad #28
+; CHECK-THUMB-NEXT:    sub sp, #28
+; CHECK-THUMB-NEXT:    str r3, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT:    mov r6, r2
+; CHECK-THUMB-NEXT:    mov r3, r1
+; CHECK-THUMB-NEXT:    str r1, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT:    ldr r4, [sp, #60]
+; CHECK-THUMB-NEXT:    ldr r5, [sp, #56]
+; CHECK-THUMB-NEXT:    ldr r1, [sp, #52]
+; CHECK-THUMB-NEXT:    ldr r7, [sp, #48]
+; CHECK-THUMB-NEXT:    subs r2, r0, r7
+; CHECK-THUMB-NEXT:    str r2, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT:    sbcs r3, r1
+; CHECK-THUMB-NEXT:    str r3, [sp, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT:    mov r3, r6
+; CHECK-THUMB-NEXT:    sbcs r3, r5
+; CHECK-THUMB-NEXT:    str r3, [sp, #20] @ 4-byte Spill
+; CHECK-THUMB-NEXT:    ldr r2, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT:    mov r3, r2
+; CHECK-THUMB-NEXT:    sbcs r3, r4
+; CHECK-THUMB-NEXT:    str r3, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT:    subs r0, r7, r0
+; CHECK-THUMB-NEXT:    ldr r3, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT:    sbcs r1, r3
+; CHECK-THUMB-NEXT:    sbcs r5, r6
+; CHECK-THUMB-NEXT:    sbcs r4, r2
+; CHECK-THUMB-NEXT:    blt .LBB11_2
+; CHECK-THUMB-NEXT:  @ %bb.1:
+; CHECK-THUMB-NEXT:    str r4, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT:  .LBB11_2:
+; CHECK-THUMB-NEXT:    ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT:    blt .LBB11_4
+; CHECK-THUMB-NEXT:  @ %bb.3:
+; CHECK-THUMB-NEXT:    mov r4, r5
+; CHECK-THUMB-NEXT:  .LBB11_4:
+; CHECK-THUMB-NEXT:    ldr r5, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT:    ldr r2, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT:    blt .LBB11_6
+; CHECK-THUMB-NEXT:  @ %bb.5:
+; CHECK-THUMB-NEXT:    mov r2, r1
+; CHECK-THUMB-NEXT:  .LBB11_6:
+; CHECK-THUMB-NEXT:    blt .LBB11_8
+; CHECK-THUMB-NEXT:  @ %bb.7:
+; CHECK-THUMB-NEXT:    mov r5, r0
+; CHECK-THUMB-NEXT:  .LBB11_8:
+; CHECK-THUMB-NEXT:    movs r3, #0
+; CHECK-THUMB-NEXT:    rsbs r0, r5, #0
+; CHECK-THUMB-NEXT:    mov r1, r3
+; CHECK-THUMB-NEXT:    sbcs r1, r2
+; CHECK-THUMB-NEXT:    mov r2, r3
+; CHECK-THUMB-NEXT:    sbcs r2, r4
+; CHECK-THUMB-NEXT:    ldr r4, [sp, #24] @ 4-byte Reload
+; CHECK-THUMB-NEXT:    sbcs r3, r4
+; CHECK-THUMB-NEXT:    add sp, #28
+; CHECK-THUMB-NEXT:    pop {r4, r5, r6, r7, pc}
+  %aext = sext i128 %a to i256
+  %bext = sext i128 %b to i256
+  %sub = sub i256 %aext, %bext
+  %abs = call i256 @llvm.abs.i256(i256 %sub, i1 false)
+  %nabs = sub i256 0, %abs
+  %trunc = trunc i256 %nabs to i128
+  ret i128 %trunc
+}
+
+define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_ext_i128_undef:
+; CHECK-ARM:       @ %bb.0:
+; CHECK-ARM-NEXT:    .save {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT:    push {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT:    ldr r9, [sp, #32]
+; CHECK-ARM-NEXT:    ldr r8, [sp, #36]
+; CHECK-ARM-NEXT:    subs r6, r0, r9
+; CHECK-ARM-NEXT:    ldr lr, [sp, #40]
+; CHECK-ARM-NEXT:    sbcs r7, r1, r8
+; CHECK-ARM-NEXT:    ldr r12, [sp, #44]
+; CHECK-ARM-NEXT:    sbcs r4, r2, lr
+; CHECK-ARM-NEXT:    sbc r5, r3, r12
+; CHECK-ARM-NEXT:    subs r0, r9, r0
+; CHECK-ARM-NEXT:    sbcs r1, r8, r1
+; CHECK-ARM-NEXT:    sbcs r2, lr, r2
+; CHECK-ARM-NEXT:    sbcs r3, r12, r3
+; CHECK-ARM-NEXT:    ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/206291


More information about the llvm-commits mailing list