[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