[llvm] [ARM] Custom lower abdu and abds (PR #182696)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 22 14:14:33 PST 2026
https://github.com/SiliconA-Z updated https://github.com/llvm/llvm-project/pull/182696
>From a39233766f0ec01c90298521ea3a8ecb12f37c21 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sun, 22 Feb 2026 15:02:47 -0500
Subject: [PATCH 1/3] Pre-commit tests (NFC)
---
llvm/test/CodeGen/ARM/abds-neg.ll | 1391 ++++++++++++++++++++++++++
llvm/test/CodeGen/ARM/abds.ll | 1524 +++++++++++++++++++++++++++++
llvm/test/CodeGen/ARM/abdu-neg.ll | 1055 ++++++++++++++++++++
llvm/test/CodeGen/ARM/abdu.ll | 1067 ++++++++++++++++++++
llvm/test/CodeGen/ARM/iabs.ll | 112 ++-
5 files changed, 5115 insertions(+), 34 deletions(-)
create mode 100644 llvm/test/CodeGen/ARM/abds-neg.ll
create mode 100644 llvm/test/CodeGen/ARM/abds.ll
create mode 100644 llvm/test/CodeGen/ARM/abdu-neg.ll
create mode 100644 llvm/test/CodeGen/ARM/abdu.ll
diff --git a/llvm/test/CodeGen/ARM/abds-neg.ll b/llvm/test/CodeGen/ARM/abds-neg.ll
new file mode 100644
index 0000000000000..99caa1260afe3
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/abds-neg.ll
@@ -0,0 +1,1391 @@
+; 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: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; 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: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; 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: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; 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: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; 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: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; 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: 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_undef:
+; 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 .LBB12_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: str r4, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: .LBB12_2:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB12_4
+; CHECK-THUMB-NEXT: @ %bb.3:
+; CHECK-THUMB-NEXT: mov r4, r5
+; CHECK-THUMB-NEXT: .LBB12_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 .LBB12_6
+; CHECK-THUMB-NEXT: @ %bb.5:
+; CHECK-THUMB-NEXT: mov r2, r1
+; CHECK-THUMB-NEXT: .LBB12_6:
+; CHECK-THUMB-NEXT: blt .LBB12_8
+; CHECK-THUMB-NEXT: @ %bb.7:
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: .LBB12_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 true)
+ %nabs = sub i256 0, %abs
+ %trunc = trunc i256 %nabs to i128
+ ret i128 %trunc
+}
+
+;
+; sub(smin(a,b),smax(a,b)) -> nabds(a,b)
+;
+
+define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: lsl r1, r1, #24
+; CHECK-ARM-NEXT: lsl r0, r0, #24
+; CHECK-ARM-NEXT: asr r2, r1, #24
+; CHECK-ARM-NEXT: asr r3, r0, #24
+; CHECK-ARM-NEXT: cmp r3, r1, asr #24
+; CHECK-ARM-NEXT: mov r1, r2
+; CHECK-ARM-NEXT: asrgt r1, r0, #24
+; CHECK-ARM-NEXT: asrlt r2, r0, #24
+; CHECK-ARM-NEXT: sub r0, r2, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: sxtb r1, r1
+; CHECK-THUMB-NEXT: sxtb r0, r0
+; CHECK-THUMB-NEXT: cmp r0, r1
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: ble .LBB13_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB13_4
+; CHECK-THUMB-NEXT: .LBB13_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB13_3:
+; CHECK-THUMB-NEXT: mov r2, r1
+; CHECK-THUMB-NEXT: blt .LBB13_2
+; CHECK-THUMB-NEXT: .LBB13_4:
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)
+ %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)
+ %sub = sub i8 %min, %max
+ ret i8 %sub
+}
+
+define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: lsl r1, r1, #16
+; CHECK-ARM-NEXT: lsl r0, r0, #16
+; CHECK-ARM-NEXT: asr r2, r1, #16
+; CHECK-ARM-NEXT: asr r3, r0, #16
+; CHECK-ARM-NEXT: cmp r3, r1, asr #16
+; CHECK-ARM-NEXT: mov r1, r2
+; CHECK-ARM-NEXT: asrgt r1, r0, #16
+; CHECK-ARM-NEXT: asrlt r2, r0, #16
+; CHECK-ARM-NEXT: sub r0, r2, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: sxth r1, r1
+; CHECK-THUMB-NEXT: sxth r0, r0
+; CHECK-THUMB-NEXT: cmp r0, r1
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: ble .LBB14_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB14_4
+; CHECK-THUMB-NEXT: .LBB14_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB14_3:
+; CHECK-THUMB-NEXT: mov r2, r1
+; CHECK-THUMB-NEXT: blt .LBB14_2
+; CHECK-THUMB-NEXT: .LBB14_4:
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i16 @llvm.smin.i16(i16 %a, i16 %b)
+ %max = call i16 @llvm.smax.i16(i16 %a, i16 %b)
+ %sub = sub i16 %min, %max
+ ret i16 %sub
+}
+
+define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: cmp r0, r1
+; CHECK-ARM-NEXT: mov r2, r1
+; CHECK-ARM-NEXT: movgt r2, r0
+; CHECK-ARM-NEXT: movlt r1, r0
+; CHECK-ARM-NEXT: sub r0, r1, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: cmp r0, r1
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: ble .LBB15_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB15_4
+; CHECK-THUMB-NEXT: .LBB15_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB15_3:
+; CHECK-THUMB-NEXT: mov r2, r1
+; CHECK-THUMB-NEXT: blt .LBB15_2
+; CHECK-THUMB-NEXT: .LBB15_4:
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i32 @llvm.smin.i32(i32 %a, i32 %b)
+ %max = call i32 @llvm.smax.i32(i32 %a, i32 %b)
+ %sub = sub i32 %min, %max
+ ret i32 %sub
+}
+
+define i64 @abd_minmax_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, lr}
+; CHECK-ARM-NEXT: push {r4, lr}
+; CHECK-ARM-NEXT: subs r12, r2, r0
+; CHECK-ARM-NEXT: mov lr, r2
+; CHECK-ARM-NEXT: sbcs r12, r3, r1
+; CHECK-ARM-NEXT: mov r12, r3
+; CHECK-ARM-NEXT: movlt lr, r0
+; CHECK-ARM-NEXT: movlt r12, r1
+; CHECK-ARM-NEXT: subs r4, r0, r2
+; CHECK-ARM-NEXT: sbcs r4, r1, r3
+; CHECK-ARM-NEXT: movlt r3, r1
+; CHECK-ARM-NEXT: movlt r2, r0
+; CHECK-ARM-NEXT: subs r0, r2, lr
+; CHECK-ARM-NEXT: sbc r1, r3, r12
+; CHECK-ARM-NEXT: pop {r4, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, r5, r6, lr}
+; CHECK-THUMB-NEXT: push {r4, r5, r6, lr}
+; CHECK-THUMB-NEXT: subs r4, r2, r0
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: sbcs r4, r1
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: blt .LBB16_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: .LBB16_2:
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: blt .LBB16_4
+; CHECK-THUMB-NEXT: @ %bb.3:
+; CHECK-THUMB-NEXT: mov r5, r2
+; CHECK-THUMB-NEXT: .LBB16_4:
+; CHECK-THUMB-NEXT: subs r6, r0, r2
+; CHECK-THUMB-NEXT: mov r6, r1
+; CHECK-THUMB-NEXT: sbcs r6, r3
+; CHECK-THUMB-NEXT: blt .LBB16_6
+; CHECK-THUMB-NEXT: @ %bb.5:
+; CHECK-THUMB-NEXT: mov r1, r3
+; CHECK-THUMB-NEXT: .LBB16_6:
+; CHECK-THUMB-NEXT: blt .LBB16_8
+; CHECK-THUMB-NEXT: @ %bb.7:
+; CHECK-THUMB-NEXT: mov r0, r2
+; CHECK-THUMB-NEXT: .LBB16_8:
+; CHECK-THUMB-NEXT: subs r0, r0, r5
+; CHECK-THUMB-NEXT: sbcs r1, r4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, pc}
+ %min = call i64 @llvm.smin.i64(i64 %a, i64 %b)
+ %max = call i64 @llvm.smax.i64(i64 %a, i64 %b)
+ %sub = sub i64 %min, %max
+ ret i64 %sub
+}
+
+define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i128:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r6, r7, r8, r9, r10, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #32]
+; CHECK-ARM-NEXT: ldr r4, [sp, #36]
+; CHECK-ARM-NEXT: subs r6, r5, r0
+; CHECK-ARM-NEXT: ldr r12, [sp, #44]
+; CHECK-ARM-NEXT: ldr lr, [sp, #40]
+; CHECK-ARM-NEXT: sbcs r6, r4, r1
+; CHECK-ARM-NEXT: mov r10, r4
+; CHECK-ARM-NEXT: mov r7, r5
+; CHECK-ARM-NEXT: sbcs r6, lr, r2
+; CHECK-ARM-NEXT: mov r8, r12
+; CHECK-ARM-NEXT: sbcs r6, r12, r3
+; CHECK-ARM-NEXT: mov r9, lr
+; CHECK-ARM-NEXT: movlt r8, r3
+; CHECK-ARM-NEXT: movlt r9, r2
+; CHECK-ARM-NEXT: movlt r10, r1
+; CHECK-ARM-NEXT: movlt r7, r0
+; CHECK-ARM-NEXT: subs r6, r0, r5
+; CHECK-ARM-NEXT: sbcs r6, r1, r4
+; CHECK-ARM-NEXT: sbcs r6, r2, lr
+; CHECK-ARM-NEXT: sbcs r6, r3, r12
+; CHECK-ARM-NEXT: movlt r12, r3
+; CHECK-ARM-NEXT: movlt lr, r2
+; CHECK-ARM-NEXT: movlt r4, r1
+; CHECK-ARM-NEXT: movlt r5, r0
+; CHECK-ARM-NEXT: subs r0, r5, r7
+; CHECK-ARM-NEXT: sbcs r1, r4, r10
+; CHECK-ARM-NEXT: sbcs r2, lr, r9
+; CHECK-ARM-NEXT: sbc r3, r12, r8
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_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 #20
+; CHECK-THUMB-NEXT: sub sp, #20
+; CHECK-THUMB-NEXT: ldr r5, [sp, #52]
+; CHECK-THUMB-NEXT: add r7, sp, #40
+; CHECK-THUMB-NEXT: ldm r7, {r4, r6, r7}
+; CHECK-THUMB-NEXT: str r4, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT: subs r4, r4, r0
+; CHECK-THUMB-NEXT: mov r4, r6
+; CHECK-THUMB-NEXT: sbcs r4, r1
+; CHECK-THUMB-NEXT: mov r4, r7
+; CHECK-THUMB-NEXT: sbcs r4, r2
+; CHECK-THUMB-NEXT: mov r4, r5
+; CHECK-THUMB-NEXT: sbcs r4, r3
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: bge .LBB17_12
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: str r2, [sp, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: bge .LBB17_13
+; CHECK-THUMB-NEXT: .LBB17_2:
+; CHECK-THUMB-NEXT: str r1, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: blt .LBB17_4
+; CHECK-THUMB-NEXT: .LBB17_3:
+; CHECK-THUMB-NEXT: str r6, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: .LBB17_4:
+; CHECK-THUMB-NEXT: str r4, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r4, r0
+; CHECK-THUMB-NEXT: blt .LBB17_6
+; CHECK-THUMB-NEXT: @ %bb.5:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: .LBB17_6:
+; CHECK-THUMB-NEXT: str r4, [sp] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r4, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: subs r4, r0, r4
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: sbcs r4, r6
+; CHECK-THUMB-NEXT: mov r4, r2
+; CHECK-THUMB-NEXT: sbcs r4, r7
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: sbcs r4, r5
+; CHECK-THUMB-NEXT: bge .LBB17_14
+; CHECK-THUMB-NEXT: @ %bb.7:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB17_15
+; CHECK-THUMB-NEXT: .LBB17_8:
+; CHECK-THUMB-NEXT: bge .LBB17_16
+; CHECK-THUMB-NEXT: .LBB17_9:
+; CHECK-THUMB-NEXT: blt .LBB17_11
+; CHECK-THUMB-NEXT: .LBB17_10:
+; CHECK-THUMB-NEXT: ldr r0, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: .LBB17_11:
+; CHECK-THUMB-NEXT: ldr r5, [sp] @ 4-byte Reload
+; CHECK-THUMB-NEXT: subs r0, r0, r5
+; CHECK-THUMB-NEXT: ldr r5, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r1, r5
+; CHECK-THUMB-NEXT: ldr r5, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: add sp, #20
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-THUMB-NEXT: .LBB17_12:
+; CHECK-THUMB-NEXT: mov r4, r5
+; CHECK-THUMB-NEXT: str r2, [sp, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: blt .LBB17_2
+; CHECK-THUMB-NEXT: .LBB17_13:
+; CHECK-THUMB-NEXT: str r7, [sp, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: str r1, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: bge .LBB17_3
+; CHECK-THUMB-NEXT: b .LBB17_4
+; CHECK-THUMB-NEXT: .LBB17_14:
+; CHECK-THUMB-NEXT: mov r3, r5
+; CHECK-THUMB-NEXT: ldr r4, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB17_8
+; CHECK-THUMB-NEXT: .LBB17_15:
+; CHECK-THUMB-NEXT: mov r2, r7
+; CHECK-THUMB-NEXT: blt .LBB17_9
+; CHECK-THUMB-NEXT: .LBB17_16:
+; CHECK-THUMB-NEXT: mov r1, r6
+; CHECK-THUMB-NEXT: bge .LBB17_10
+; CHECK-THUMB-NEXT: b .LBB17_11
+ %min = call i128 @llvm.smin.i128(i128 %a, i128 %b)
+ %max = call i128 @llvm.smax.i128(i128 %a, i128 %b)
+ %sub = sub i128 %min, %max
+ ret i128 %sub
+}
+
+;
+; select(icmp(a,b),sub(a,b),sub(b,a)) -> nabds(a,b)
+;
+
+define i8 @abd_cmp_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: lsl r3, r0, #24
+; CHECK-ARM-NEXT: lsl r12, r1, #24
+; CHECK-ARM-NEXT: asr r3, r3, #24
+; CHECK-ARM-NEXT: sub r2, r1, r0
+; CHECK-ARM-NEXT: cmp r3, r12, asr #24
+; CHECK-ARM-NEXT: suble r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: sxtb r2, r1
+; CHECK-THUMB-NEXT: sxtb r3, r0
+; CHECK-THUMB-NEXT: cmp r3, r2
+; CHECK-THUMB-NEXT: ble .LBB18_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB18_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp sle i8 %a, %b
+ %ab = sub i8 %a, %b
+ %ba = sub i8 %b, %a
+ %sel = select i1 %cmp, i8 %ab, i8 %ba
+ ret i8 %sel
+}
+
+define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: lsl r3, r0, #16
+; CHECK-ARM-NEXT: lsl r12, r1, #16
+; CHECK-ARM-NEXT: asr r3, r3, #16
+; CHECK-ARM-NEXT: sub r2, r1, r0
+; CHECK-ARM-NEXT: cmp r3, r12, asr #16
+; CHECK-ARM-NEXT: sublt r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: sxth r2, r1
+; CHECK-THUMB-NEXT: sxth r3, r0
+; CHECK-THUMB-NEXT: cmp r3, r2
+; CHECK-THUMB-NEXT: blt .LBB19_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB19_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp slt i16 %a, %b
+ %ab = sub i16 %a, %b
+ %ba = sub i16 %b, %a
+ %sel = select i1 %cmp, i16 %ab, i16 %ba
+ ret i16 %sel
+}
+
+define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r2, r0, r1
+; CHECK-ARM-NEXT: subge r2, r1, r0
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: blt .LBB20_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r1, r2
+; CHECK-THUMB-NEXT: .LBB20_2:
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp sge i32 %a, %b
+ %ab = sub i32 %a, %b
+ %ba = sub i32 %b, %a
+ %sel = select i1 %cmp, i32 %ba, i32 %ab
+ ret i32 %sel
+}
+
+define i64 @abd_cmp_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r11, lr}
+; CHECK-ARM-NEXT: push {r11, lr}
+; CHECK-ARM-NEXT: subs r12, r2, r0
+; CHECK-ARM-NEXT: sbc lr, r3, r1
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbcs r1, r1, r3
+; CHECK-ARM-NEXT: movge r0, r12
+; CHECK-ARM-NEXT: movge r1, lr
+; CHECK-ARM-NEXT: pop {r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_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, r2, r0
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: sbcs r4, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: bge .LBB21_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB21_4
+; CHECK-THUMB-NEXT: .LBB21_2:
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+; CHECK-THUMB-NEXT: .LBB21_3:
+; CHECK-THUMB-NEXT: mov r0, r5
+; CHECK-THUMB-NEXT: blt .LBB21_2
+; CHECK-THUMB-NEXT: .LBB21_4:
+; CHECK-THUMB-NEXT: mov r1, r4
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+ %cmp = icmp slt i64 %a, %b
+ %ab = sub i64 %a, %b
+ %ba = sub i64 %b, %a
+ %sel = select i1 %cmp, i64 %ab, i64 %ba
+ ret i64 %sel
+}
+
+define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_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, r9, r0
+; CHECK-ARM-NEXT: ldr lr, [sp, #40]
+; CHECK-ARM-NEXT: sbcs r7, r8, r1
+; CHECK-ARM-NEXT: ldr r12, [sp, #44]
+; CHECK-ARM-NEXT: sbcs r4, lr, r2
+; CHECK-ARM-NEXT: sbc r5, r12, r3
+; CHECK-ARM-NEXT: subs r0, r0, r9
+; CHECK-ARM-NEXT: sbcs r1, r1, r8
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbcs r3, r3, r12
+; CHECK-ARM-NEXT: movge r0, r6
+; CHECK-ARM-NEXT: movge r1, r7
+; CHECK-ARM-NEXT: movge r2, r4
+; CHECK-ARM-NEXT: movge r3, r5
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_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 r2, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: str r1, [sp, #20] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r1, r0
+; CHECK-THUMB-NEXT: add r6, sp, #52
+; CHECK-THUMB-NEXT: ldm r6, {r0, r5, r6}
+; CHECK-THUMB-NEXT: ldr r2, [sp, #48]
+; CHECK-THUMB-NEXT: subs r7, r2, r1
+; CHECK-THUMB-NEXT: str r7, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r7, r0
+; CHECK-THUMB-NEXT: sbcs r7, r4
+; CHECK-THUMB-NEXT: str r7, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r7, r5
+; CHECK-THUMB-NEXT: ldr r4, [sp, #24] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r7, r4
+; CHECK-THUMB-NEXT: str r7, [sp, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r7, r6
+; CHECK-THUMB-NEXT: sbcs r7, r3
+; CHECK-THUMB-NEXT: str r7, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT: subs r2, r1, r2
+; CHECK-THUMB-NEXT: ldr r1, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r1, r0
+; CHECK-THUMB-NEXT: sbcs r4, r5
+; CHECK-THUMB-NEXT: sbcs r3, r6
+; CHECK-THUMB-NEXT: bge .LBB22_6
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB22_7
+; CHECK-THUMB-NEXT: .LBB22_2:
+; CHECK-THUMB-NEXT: bge .LBB22_8
+; CHECK-THUMB-NEXT: .LBB22_3:
+; CHECK-THUMB-NEXT: blt .LBB22_5
+; CHECK-THUMB-NEXT: .LBB22_4:
+; CHECK-THUMB-NEXT: ldr r3, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: .LBB22_5:
+; CHECK-THUMB-NEXT: mov r0, r2
+; CHECK-THUMB-NEXT: mov r2, r4
+; CHECK-THUMB-NEXT: add sp, #28
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-THUMB-NEXT: .LBB22_6:
+; CHECK-THUMB-NEXT: ldr r2, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB22_2
+; CHECK-THUMB-NEXT: .LBB22_7:
+; CHECK-THUMB-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB22_3
+; CHECK-THUMB-NEXT: .LBB22_8:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB22_4
+; CHECK-THUMB-NEXT: b .LBB22_5
+ %cmp = icmp slt i128 %a, %b
+ %ab = sub i128 %a, %b
+ %ba = sub i128 %b, %a
+ %sel = select i1 %cmp, i128 %ab, i128 %ba
+ ret i128 %sel
+}
+
+;
+; nabs(sub_nsw(x, y)) -> nabds(a,b)
+;
+
+define i8 @abd_subnsw_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: lsl r1, r0, #24
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: rsb r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sxtb r1, r0
+; CHECK-THUMB-NEXT: asrs r1, r1, #7
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i8 %a, %b
+ %abs = call i8 @llvm.abs.i8(i8 %sub, i1 false)
+ %nabs = sub i8 0, %abs
+ ret i8 %nabs
+}
+
+define i8 @abd_subnsw_i8_undef(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i8_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: lsl r1, r0, #24
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: rsb r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i8_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sxtb r1, r0
+; CHECK-THUMB-NEXT: asrs r1, r1, #7
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i8 %a, %b
+ %abs = call i8 @llvm.abs.i8(i8 %sub, i1 true)
+ %nabs = sub i8 0, %abs
+ ret i8 %nabs
+}
+
+define i16 @abd_subnsw_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: lsl r1, r0, #16
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: rsb r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sxth r1, r0
+; CHECK-THUMB-NEXT: asrs r1, r1, #15
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i16 %a, %b
+ %abs = call i16 @llvm.abs.i16(i16 %sub, i1 false)
+ %nabs = sub i16 0, %abs
+ ret i16 %nabs
+}
+
+define i16 @abd_subnsw_i16_undef(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i16_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: lsl r1, r0, #16
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: rsb r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i16_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sxth r1, r0
+; CHECK-THUMB-NEXT: asrs r1, r1, #15
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i16 %a, %b
+ %abs = call i16 @llvm.abs.i16(i16 %sub, i1 true)
+ %nabs = sub i16 0, %abs
+ ret i16 %nabs
+}
+
+define i32 @abd_subnsw_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i32:
+; CHECK-THUMB: @ %bb.0:
+; 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
+ %sub = sub nsw i32 %a, %b
+ %abs = call i32 @llvm.abs.i32(i32 %sub, i1 false)
+ %nabs = sub i32 0, %abs
+ ret i32 %nabs
+}
+
+define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i32_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i32_undef:
+; CHECK-THUMB: @ %bb.0:
+; 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
+ %sub = sub nsw i32 %a, %b
+ %abs = call i32 @llvm.abs.i32(i32 %sub, i1 true)
+ %nabs = sub i32 0, %abs
+ ret i32 %nabs
+}
+
+define i64 @abd_subnsw_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r3
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: eor r2, r1, r1, asr #31
+; CHECK-ARM-NEXT: rsbs r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: rsc r1, r2, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: asrs r2, r1, #31
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r2, r0
+; CHECK-THUMB-NEXT: sbcs r2, r1
+; CHECK-THUMB-NEXT: mov r1, r2
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i64 %a, %b
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+ %nabs = sub i64 0, %abs
+ ret i64 %nabs
+}
+
+define i64 @abd_subnsw_i64_undef(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i64_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r3
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: eor r2, r1, r1, asr #31
+; CHECK-ARM-NEXT: rsbs r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: rsc r1, r2, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i64_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: asrs r2, r1, #31
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r2, r0
+; CHECK-THUMB-NEXT: sbcs r2, r1
+; CHECK-THUMB-NEXT: mov r1, r2
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i64 %a, %b
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
+ %nabs = sub i64 0, %abs
+ ret i64 %nabs
+}
+
+define i128 @abd_subnsw_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i128:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbc r3, r3, r12
+; CHECK-ARM-NEXT: eor r0, r0, r3, asr #31
+; CHECK-ARM-NEXT: eor r1, r1, r3, asr #31
+; CHECK-ARM-NEXT: rsbs r0, r0, r3, asr #31
+; CHECK-ARM-NEXT: eor r2, r2, r3, asr #31
+; CHECK-ARM-NEXT: rscs r1, r1, r3, asr #31
+; CHECK-ARM-NEXT: eor r5, r3, r3, asr #31
+; CHECK-ARM-NEXT: rscs r2, r2, r3, asr #31
+; CHECK-ARM-NEXT: rsc r3, r5, r3, asr #31
+; CHECK-ARM-NEXT: pop {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: ldr r4, [sp, #36]
+; CHECK-THUMB-NEXT: ldr r5, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r6, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #24]
+; CHECK-THUMB-NEXT: subs r0, r0, r7
+; CHECK-THUMB-NEXT: sbcs r1, r6
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: asrs r4, r3, #31
+; CHECK-THUMB-NEXT: eors r3, r4
+; CHECK-THUMB-NEXT: eors r2, r4
+; CHECK-THUMB-NEXT: eors r1, r4
+; CHECK-THUMB-NEXT: eors r0, r4
+; CHECK-THUMB-NEXT: subs r0, r4, r0
+; CHECK-THUMB-NEXT: mov r5, r4
+; CHECK-THUMB-NEXT: sbcs r5, r1
+; CHECK-THUMB-NEXT: mov r6, r4
+; CHECK-THUMB-NEXT: sbcs r6, r2
+; CHECK-THUMB-NEXT: sbcs r4, r3
+; CHECK-THUMB-NEXT: mov r1, r5
+; CHECK-THUMB-NEXT: mov r2, r6
+; CHECK-THUMB-NEXT: mov r3, r4
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %sub = sub nsw i128 %a, %b
+ %abs = call i128 @llvm.abs.i128(i128 %sub, i1 false)
+ %nabs = sub i128 0, %abs
+ ret i128 %nabs
+}
+
+define i128 @abd_subnsw_i128_undef(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i128_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbc r3, r3, r12
+; CHECK-ARM-NEXT: eor r0, r0, r3, asr #31
+; CHECK-ARM-NEXT: eor r1, r1, r3, asr #31
+; CHECK-ARM-NEXT: rsbs r0, r0, r3, asr #31
+; CHECK-ARM-NEXT: eor r2, r2, r3, asr #31
+; CHECK-ARM-NEXT: rscs r1, r1, r3, asr #31
+; CHECK-ARM-NEXT: eor r5, r3, r3, asr #31
+; CHECK-ARM-NEXT: rscs r2, r2, r3, asr #31
+; CHECK-ARM-NEXT: rsc r3, r5, r3, asr #31
+; CHECK-ARM-NEXT: pop {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i128_undef:
+; 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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: ldr r4, [sp, #36]
+; CHECK-THUMB-NEXT: ldr r5, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r6, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #24]
+; CHECK-THUMB-NEXT: subs r0, r0, r7
+; CHECK-THUMB-NEXT: sbcs r1, r6
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: asrs r4, r3, #31
+; CHECK-THUMB-NEXT: eors r3, r4
+; CHECK-THUMB-NEXT: eors r2, r4
+; CHECK-THUMB-NEXT: eors r1, r4
+; CHECK-THUMB-NEXT: eors r0, r4
+; CHECK-THUMB-NEXT: subs r0, r4, r0
+; CHECK-THUMB-NEXT: mov r5, r4
+; CHECK-THUMB-NEXT: sbcs r5, r1
+; CHECK-THUMB-NEXT: mov r6, r4
+; CHECK-THUMB-NEXT: sbcs r6, r2
+; CHECK-THUMB-NEXT: sbcs r4, r3
+; CHECK-THUMB-NEXT: mov r1, r5
+; CHECK-THUMB-NEXT: mov r2, r6
+; CHECK-THUMB-NEXT: mov r3, r4
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %sub = sub nsw i128 %a, %b
+ %abs = call i128 @llvm.abs.i128(i128 %sub, i1 true)
+ %nabs = sub i128 0, %abs
+ ret i128 %nabs
+}
+
+declare i8 @llvm.abs.i8(i8, i1)
+declare i16 @llvm.abs.i16(i16, i1)
+declare i32 @llvm.abs.i32(i32, i1)
+declare i64 @llvm.abs.i64(i64, i1)
+declare i128 @llvm.abs.i128(i128, i1)
+
+declare i8 @llvm.smax.i8(i8, i8)
+declare i16 @llvm.smax.i16(i16, i16)
+declare i32 @llvm.smax.i32(i32, i32)
+declare i64 @llvm.smax.i64(i64, i64)
+
+declare i8 @llvm.smin.i8(i8, i8)
+declare i16 @llvm.smin.i16(i16, i16)
+declare i32 @llvm.smin.i32(i32, i32)
+declare i64 @llvm.smin.i64(i64, i64)
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/ARM/abds.ll b/llvm/test/CodeGen/ARM/abds.ll
new file mode 100644
index 0000000000000..9ebd60ed05f03
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/abds.ll
@@ -0,0 +1,1524 @@
+; 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(abs(sub(sext(a),sext(b)))) -> abds(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: rsbmi 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, r0, r1
+; 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)
+ %trunc = trunc i64 %abs 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: rsbmi 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, r0, r1
+; 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)
+ %trunc = trunc i64 %abs 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: rsbmi 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, r0, r1
+; 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)
+ %trunc = trunc i64 %abs 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: rsbmi 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, r0, r1
+; 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)
+ %trunc = trunc i64 %abs 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 r2, r0, #16
+; CHECK-ARM-NEXT: sub r0, r1, r2, asr #16
+; CHECK-ARM-NEXT: cmp r1, r2, asr #16
+; CHECK-ARM-NEXT: rsblt r0, r1, r2, asr #16
+; 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: 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)
+ %trunc = trunc i64 %abs 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: rsbmi 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, r0, r1
+; 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)
+ %trunc = trunc i64 %abs 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: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bge .LBB6_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB6_2:
+; 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)
+ %trunc = trunc i64 %abs 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 r2, r1, #16
+; CHECK-ARM-NEXT: rsb r1, r0, r2, asr #16
+; CHECK-ARM-NEXT: cmp r0, r2, asr #16
+; CHECK-ARM-NEXT: subgt r1, r0, r2, asr #16
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i32_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: sxth r1, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bge .LBB7_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB7_2:
+; 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)
+ %trunc = trunc i64 %abs 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: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i32_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bge .LBB8_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB8_2:
+; 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)
+ %trunc = trunc i64 %abs 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: 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: mov r4, r1
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: subs r2, r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: bge .LBB9_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB9_4
+; CHECK-THUMB-NEXT: .LBB9_2:
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+; CHECK-THUMB-NEXT: .LBB9_3:
+; CHECK-THUMB-NEXT: mov r0, r2
+; CHECK-THUMB-NEXT: blt .LBB9_2
+; CHECK-THUMB-NEXT: .LBB9_4:
+; CHECK-THUMB-NEXT: mov r1, r3
+; 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)
+ %trunc = trunc i128 %abs 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: 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: mov r4, r1
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: subs r2, r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: bge .LBB10_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB10_4
+; CHECK-THUMB-NEXT: .LBB10_2:
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+; CHECK-THUMB-NEXT: .LBB10_3:
+; CHECK-THUMB-NEXT: mov r0, r2
+; CHECK-THUMB-NEXT: blt .LBB10_2
+; CHECK-THUMB-NEXT: .LBB10_4:
+; CHECK-THUMB-NEXT: mov r1, r3
+; 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)
+ %trunc = trunc i128 %abs 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 r1, r7
+; CHECK-ARM-NEXT: movlt r2, r4
+; CHECK-ARM-NEXT: movlt r3, r5
+; 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, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r6, r2
+; CHECK-THUMB-NEXT: str r2, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: mov r1, r0
+; CHECK-THUMB-NEXT: str r0, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r0, [sp, #60]
+; CHECK-THUMB-NEXT: ldr r2, [sp, #56]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #52]
+; CHECK-THUMB-NEXT: ldr r5, [sp, #48]
+; CHECK-THUMB-NEXT: subs r3, r1, r5
+; CHECK-THUMB-NEXT: str r3, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r1, r4
+; CHECK-THUMB-NEXT: sbcs r1, r7
+; CHECK-THUMB-NEXT: str r1, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT: sbcs r6, r2
+; CHECK-THUMB-NEXT: str r6, [sp, #20] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r6, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r3, r6
+; CHECK-THUMB-NEXT: sbcs r3, r0
+; CHECK-THUMB-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT: subs r5, r5, r1
+; CHECK-THUMB-NEXT: sbcs r7, r4
+; CHECK-THUMB-NEXT: ldr r1, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r2, r1
+; CHECK-THUMB-NEXT: sbcs r0, r6
+; CHECK-THUMB-NEXT: bge .LBB11_6
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB11_7
+; CHECK-THUMB-NEXT: .LBB11_2:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB11_8
+; CHECK-THUMB-NEXT: .LBB11_3:
+; CHECK-THUMB-NEXT: blt .LBB11_5
+; CHECK-THUMB-NEXT: .LBB11_4:
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: .LBB11_5:
+; CHECK-THUMB-NEXT: ldr r0, [sp, #24] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r2, r4
+; CHECK-THUMB-NEXT: add sp, #28
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-THUMB-NEXT: .LBB11_6:
+; CHECK-THUMB-NEXT: str r5, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB11_2
+; CHECK-THUMB-NEXT: .LBB11_7:
+; CHECK-THUMB-NEXT: mov r1, r7
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB11_3
+; CHECK-THUMB-NEXT: .LBB11_8:
+; CHECK-THUMB-NEXT: mov r4, r2
+; CHECK-THUMB-NEXT: bge .LBB11_4
+; CHECK-THUMB-NEXT: b .LBB11_5
+ %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)
+ %trunc = trunc i256 %abs 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: movlt r0, r6
+; CHECK-ARM-NEXT: movlt r1, r7
+; CHECK-ARM-NEXT: movlt r2, r4
+; CHECK-ARM-NEXT: movlt r3, r5
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i128_undef:
+; 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, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r6, r2
+; CHECK-THUMB-NEXT: str r2, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: mov r1, r0
+; CHECK-THUMB-NEXT: str r0, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r0, [sp, #60]
+; CHECK-THUMB-NEXT: ldr r2, [sp, #56]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #52]
+; CHECK-THUMB-NEXT: ldr r5, [sp, #48]
+; CHECK-THUMB-NEXT: subs r3, r1, r5
+; CHECK-THUMB-NEXT: str r3, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r1, r4
+; CHECK-THUMB-NEXT: sbcs r1, r7
+; CHECK-THUMB-NEXT: str r1, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT: sbcs r6, r2
+; CHECK-THUMB-NEXT: str r6, [sp, #20] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r6, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r3, r6
+; CHECK-THUMB-NEXT: sbcs r3, r0
+; CHECK-THUMB-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT: subs r5, r5, r1
+; CHECK-THUMB-NEXT: sbcs r7, r4
+; CHECK-THUMB-NEXT: ldr r1, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r2, r1
+; CHECK-THUMB-NEXT: sbcs r0, r6
+; CHECK-THUMB-NEXT: bge .LBB12_6
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB12_7
+; CHECK-THUMB-NEXT: .LBB12_2:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB12_8
+; CHECK-THUMB-NEXT: .LBB12_3:
+; CHECK-THUMB-NEXT: blt .LBB12_5
+; CHECK-THUMB-NEXT: .LBB12_4:
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: .LBB12_5:
+; CHECK-THUMB-NEXT: ldr r0, [sp, #24] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r2, r4
+; CHECK-THUMB-NEXT: add sp, #28
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-THUMB-NEXT: .LBB12_6:
+; CHECK-THUMB-NEXT: str r5, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB12_2
+; CHECK-THUMB-NEXT: .LBB12_7:
+; CHECK-THUMB-NEXT: mov r1, r7
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB12_3
+; CHECK-THUMB-NEXT: .LBB12_8:
+; CHECK-THUMB-NEXT: mov r4, r2
+; CHECK-THUMB-NEXT: bge .LBB12_4
+; CHECK-THUMB-NEXT: b .LBB12_5
+ %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 true)
+ %trunc = trunc i256 %abs to i128
+ ret i128 %trunc
+}
+
+;
+; sub(smax(a,b),smin(a,b)) -> abds(a,b)
+;
+
+define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_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: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)
+ %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)
+ %sub = sub i8 %max, %min
+ ret i8 %sub
+}
+
+define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_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: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i16 @llvm.smin.i16(i16 %a, i16 %b)
+ %max = call i16 @llvm.smax.i16(i16 %a, i16 %b)
+ %sub = sub i16 %max, %min
+ ret i16 %sub
+}
+
+define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r2, r1, r0
+; CHECK-ARM-NEXT: sublt r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bge .LBB15_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB15_2:
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i32 @llvm.smin.i32(i32 %a, i32 %b)
+ %max = call i32 @llvm.smax.i32(i32 %a, i32 %b)
+ %sub = sub i32 %max, %min
+ ret i32 %sub
+}
+
+define i64 @abd_minmax_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_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: pop {r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: subs r2, r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: bge .LBB16_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB16_4
+; CHECK-THUMB-NEXT: .LBB16_2:
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+; CHECK-THUMB-NEXT: .LBB16_3:
+; CHECK-THUMB-NEXT: mov r0, r2
+; CHECK-THUMB-NEXT: blt .LBB16_2
+; CHECK-THUMB-NEXT: .LBB16_4:
+; CHECK-THUMB-NEXT: mov r1, r3
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+ %min = call i64 @llvm.smin.i64(i64 %a, i64 %b)
+ %max = call i64 @llvm.smax.i64(i64 %a, i64 %b)
+ %sub = sub i64 %max, %min
+ ret i64 %sub
+}
+
+define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_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 r1, r7
+; CHECK-ARM-NEXT: movlt r2, r4
+; CHECK-ARM-NEXT: movlt r3, r5
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_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, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r6, r2
+; CHECK-THUMB-NEXT: str r2, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: mov r1, r0
+; CHECK-THUMB-NEXT: str r0, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r0, [sp, #60]
+; CHECK-THUMB-NEXT: ldr r2, [sp, #56]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #52]
+; CHECK-THUMB-NEXT: ldr r5, [sp, #48]
+; CHECK-THUMB-NEXT: subs r3, r1, r5
+; CHECK-THUMB-NEXT: str r3, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r1, r4
+; CHECK-THUMB-NEXT: sbcs r1, r7
+; CHECK-THUMB-NEXT: str r1, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT: sbcs r6, r2
+; CHECK-THUMB-NEXT: str r6, [sp, #20] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r6, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r3, r6
+; CHECK-THUMB-NEXT: sbcs r3, r0
+; CHECK-THUMB-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT: subs r5, r5, r1
+; CHECK-THUMB-NEXT: sbcs r7, r4
+; CHECK-THUMB-NEXT: ldr r1, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r2, r1
+; CHECK-THUMB-NEXT: sbcs r0, r6
+; CHECK-THUMB-NEXT: bge .LBB17_6
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB17_7
+; CHECK-THUMB-NEXT: .LBB17_2:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB17_8
+; CHECK-THUMB-NEXT: .LBB17_3:
+; CHECK-THUMB-NEXT: blt .LBB17_5
+; CHECK-THUMB-NEXT: .LBB17_4:
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: .LBB17_5:
+; CHECK-THUMB-NEXT: ldr r0, [sp, #24] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r2, r4
+; CHECK-THUMB-NEXT: add sp, #28
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-THUMB-NEXT: .LBB17_6:
+; CHECK-THUMB-NEXT: str r5, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB17_2
+; CHECK-THUMB-NEXT: .LBB17_7:
+; CHECK-THUMB-NEXT: mov r1, r7
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB17_3
+; CHECK-THUMB-NEXT: .LBB17_8:
+; CHECK-THUMB-NEXT: mov r4, r2
+; CHECK-THUMB-NEXT: bge .LBB17_4
+; CHECK-THUMB-NEXT: b .LBB17_5
+ %min = call i128 @llvm.smin.i128(i128 %a, i128 %b)
+ %max = call i128 @llvm.smax.i128(i128 %a, i128 %b)
+ %sub = sub i128 %max, %min
+ ret i128 %sub
+}
+
+;
+; select(icmp(a,b),sub(a,b),sub(b,a)) -> abds(a,b)
+;
+
+define i8 @abd_cmp_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_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: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp sgt i8 %a, %b
+ %ab = sub i8 %a, %b
+ %ba = sub i8 %b, %a
+ %sel = select i1 %cmp, i8 %ab, i8 %ba
+ ret i8 %sel
+}
+
+define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_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: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp sge i16 %a, %b
+ %ab = sub i16 %a, %b
+ %ba = sub i16 %b, %a
+ %sel = select i1 %cmp, i16 %ab, i16 %ba
+ ret i16 %sel
+}
+
+define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r2, r1, r0
+; CHECK-ARM-NEXT: sublt r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bge .LBB20_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB20_2:
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp slt i32 %a, %b
+ %ab = sub i32 %a, %b
+ %ba = sub i32 %b, %a
+ %sel = select i1 %cmp, i32 %ba, i32 %ab
+ ret i32 %sel
+}
+
+define i64 @abd_cmp_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_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: pop {r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: subs r2, r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: bge .LBB21_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB21_4
+; CHECK-THUMB-NEXT: .LBB21_2:
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+; CHECK-THUMB-NEXT: .LBB21_3:
+; CHECK-THUMB-NEXT: mov r0, r2
+; CHECK-THUMB-NEXT: blt .LBB21_2
+; CHECK-THUMB-NEXT: .LBB21_4:
+; CHECK-THUMB-NEXT: mov r1, r3
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+ %cmp = icmp sge i64 %a, %b
+ %ab = sub i64 %a, %b
+ %ba = sub i64 %b, %a
+ %sel = select i1 %cmp, i64 %ab, i64 %ba
+ ret i64 %sel
+}
+
+define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_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 r1, r7
+; CHECK-ARM-NEXT: movlt r2, r4
+; CHECK-ARM-NEXT: movlt r3, r5
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_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, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r6, r2
+; CHECK-THUMB-NEXT: str r2, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: mov r1, r0
+; CHECK-THUMB-NEXT: str r0, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r0, [sp, #60]
+; CHECK-THUMB-NEXT: ldr r2, [sp, #56]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #52]
+; CHECK-THUMB-NEXT: ldr r5, [sp, #48]
+; CHECK-THUMB-NEXT: subs r3, r1, r5
+; CHECK-THUMB-NEXT: str r3, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r1, r4
+; CHECK-THUMB-NEXT: sbcs r1, r7
+; CHECK-THUMB-NEXT: str r1, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT: sbcs r6, r2
+; CHECK-THUMB-NEXT: str r6, [sp, #20] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r6, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r3, r6
+; CHECK-THUMB-NEXT: sbcs r3, r0
+; CHECK-THUMB-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT: subs r5, r5, r1
+; CHECK-THUMB-NEXT: sbcs r7, r4
+; CHECK-THUMB-NEXT: ldr r1, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r2, r1
+; CHECK-THUMB-NEXT: sbcs r0, r6
+; CHECK-THUMB-NEXT: bge .LBB22_6
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB22_7
+; CHECK-THUMB-NEXT: .LBB22_2:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB22_8
+; CHECK-THUMB-NEXT: .LBB22_3:
+; CHECK-THUMB-NEXT: blt .LBB22_5
+; CHECK-THUMB-NEXT: .LBB22_4:
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: .LBB22_5:
+; CHECK-THUMB-NEXT: ldr r0, [sp, #24] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r2, r4
+; CHECK-THUMB-NEXT: add sp, #28
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-THUMB-NEXT: .LBB22_6:
+; CHECK-THUMB-NEXT: str r5, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB22_2
+; CHECK-THUMB-NEXT: .LBB22_7:
+; CHECK-THUMB-NEXT: mov r1, r7
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB22_3
+; CHECK-THUMB-NEXT: .LBB22_8:
+; CHECK-THUMB-NEXT: mov r4, r2
+; CHECK-THUMB-NEXT: bge .LBB22_4
+; CHECK-THUMB-NEXT: b .LBB22_5
+ %cmp = icmp sge i128 %a, %b
+ %ab = sub i128 %a, %b
+ %ba = sub i128 %b, %a
+ %sel = select i1 %cmp, i128 %ab, i128 %ba
+ ret i128 %sel
+}
+
+;
+; abs(sub_nsw(x, y)) -> abds(a,b)
+;
+
+define i8 @abd_subnsw_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: lsl r1, r0, #24
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: sub r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sxtb r1, r0
+; CHECK-THUMB-NEXT: asrs r1, r1, #7
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i8 %a, %b
+ %abs = call i8 @llvm.abs.i8(i8 %sub, i1 false)
+ ret i8 %abs
+}
+
+define i8 @abd_subnsw_i8_undef(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i8_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: lsl r1, r0, #24
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: sub r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i8_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sxtb r1, r0
+; CHECK-THUMB-NEXT: asrs r1, r1, #7
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i8 %a, %b
+ %abs = call i8 @llvm.abs.i8(i8 %sub, i1 true)
+ ret i8 %abs
+}
+
+define i16 @abd_subnsw_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: lsl r1, r0, #16
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: sub r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sxth r1, r0
+; CHECK-THUMB-NEXT: asrs r1, r1, #15
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i16 %a, %b
+ %abs = call i16 @llvm.abs.i16(i16 %sub, i1 false)
+ ret i16 %abs
+}
+
+define i16 @abd_subnsw_i16_undef(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i16_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: lsl r1, r0, #16
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: sub r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i16_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sxth r1, r0
+; CHECK-THUMB-NEXT: asrs r1, r1, #15
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i16 %a, %b
+ %abs = call i16 @llvm.abs.i16(i16 %sub, i1 true)
+ ret i16 %abs
+}
+
+define i32 @abd_subnsw_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i32:
+; CHECK-THUMB: @ %bb.0:
+; 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i32 %a, %b
+ %abs = call i32 @llvm.abs.i32(i32 %sub, i1 false)
+ ret i32 %abs
+}
+
+define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i32_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i32_undef:
+; CHECK-THUMB: @ %bb.0:
+; 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i32 %a, %b
+ %abs = call i32 @llvm.abs.i32(i32 %sub, i1 true)
+ ret i32 %abs
+}
+
+define i64 @abd_subnsw_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r3
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: eor r2, r1, r1, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: sbc r1, r2, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: asrs r2, r1, #31
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i64 %a, %b
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+ ret i64 %abs
+}
+
+define i64 @abd_subnsw_i64_undef(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i64_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r3
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: eor r2, r1, r1, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: sbc r1, r2, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i64_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: asrs r2, r1, #31
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub nsw i64 %a, %b
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
+ ret i64 %abs
+}
+
+define i128 @abd_subnsw_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i128:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbc r3, r3, r12
+; CHECK-ARM-NEXT: eor r0, r0, r3, asr #31
+; CHECK-ARM-NEXT: eor r1, r1, r3, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r3, asr #31
+; CHECK-ARM-NEXT: eor r2, r2, r3, asr #31
+; CHECK-ARM-NEXT: sbcs r1, r1, r3, asr #31
+; CHECK-ARM-NEXT: eor r5, r3, r3, asr #31
+; CHECK-ARM-NEXT: sbcs r2, r2, r3, asr #31
+; CHECK-ARM-NEXT: sbc r3, r5, r3, asr #31
+; CHECK-ARM-NEXT: pop {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: ldr r4, [sp, #36]
+; CHECK-THUMB-NEXT: ldr r5, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r6, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #24]
+; CHECK-THUMB-NEXT: subs r0, r0, r7
+; CHECK-THUMB-NEXT: sbcs r1, r6
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: asrs r4, r3, #31
+; CHECK-THUMB-NEXT: eors r3, r4
+; CHECK-THUMB-NEXT: eors r2, r4
+; CHECK-THUMB-NEXT: eors r1, r4
+; CHECK-THUMB-NEXT: eors r0, r4
+; CHECK-THUMB-NEXT: subs r0, r0, r4
+; CHECK-THUMB-NEXT: sbcs r1, r4
+; CHECK-THUMB-NEXT: sbcs r2, r4
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %sub = sub nsw i128 %a, %b
+ %abs = call i128 @llvm.abs.i128(i128 %sub, i1 false)
+ ret i128 %abs
+}
+
+define i128 @abd_subnsw_i128_undef(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_subnsw_i128_undef:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbc r3, r3, r12
+; CHECK-ARM-NEXT: eor r0, r0, r3, asr #31
+; CHECK-ARM-NEXT: eor r1, r1, r3, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r3, asr #31
+; CHECK-ARM-NEXT: eor r2, r2, r3, asr #31
+; CHECK-ARM-NEXT: sbcs r1, r1, r3, asr #31
+; CHECK-ARM-NEXT: eor r5, r3, r3, asr #31
+; CHECK-ARM-NEXT: sbcs r2, r2, r3, asr #31
+; CHECK-ARM-NEXT: sbc r3, r5, r3, asr #31
+; CHECK-ARM-NEXT: pop {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_subnsw_i128_undef:
+; 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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: ldr r4, [sp, #36]
+; CHECK-THUMB-NEXT: ldr r5, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r6, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #24]
+; CHECK-THUMB-NEXT: subs r0, r0, r7
+; CHECK-THUMB-NEXT: sbcs r1, r6
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: asrs r4, r3, #31
+; CHECK-THUMB-NEXT: eors r3, r4
+; CHECK-THUMB-NEXT: eors r2, r4
+; CHECK-THUMB-NEXT: eors r1, r4
+; CHECK-THUMB-NEXT: eors r0, r4
+; CHECK-THUMB-NEXT: subs r0, r0, r4
+; CHECK-THUMB-NEXT: sbcs r1, r4
+; CHECK-THUMB-NEXT: sbcs r2, r4
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %sub = sub nsw i128 %a, %b
+ %abs = call i128 @llvm.abs.i128(i128 %sub, i1 true)
+ ret i128 %abs
+}
+
+;
+; negative tests
+;
+
+define i32 @abd_sub_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_sub_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_sub_i32:
+; CHECK-THUMB: @ %bb.0:
+; 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %sub = sub i32 %a, %b
+ %abs = call i32 @llvm.abs.i32(i32 %sub, i1 false)
+ ret i32 %abs
+}
+
+define i64 @vector_legalized(i16 %a, i16 %b) {
+; CHECK-ARM-LABEL: vector_legalized:
+; 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: mov r1, #0
+; CHECK-ARM-NEXT: cmp r0, #0
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: vector_legalized:
+; 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, r0, r1
+; CHECK-THUMB-NEXT: movs r1, #0
+; CHECK-THUMB-NEXT: bx lr
+ %ea = sext i16 %a to i32
+ %eb = sext i16 %b to i32
+ %s = sub i32 %ea, %eb
+ %ab = call i32 @llvm.abs.i32(i32 %s, i1 false)
+ %e = zext i32 %ab to i64
+ %red = call i64 @llvm.vector.reduce.add.v32i64(<32 x i64> zeroinitializer)
+ %z = add i64 %red, %e
+ ret i64 %z
+}
+
+;
+; sub(select(icmp(a,b),a,b),select(icmp(a,b),b,a)) -> abds(a,b)
+;
+
+define i8 @abd_select_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_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: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp slt i8 %a, %b
+ %ab = select i1 %cmp, i8 %a, i8 %b
+ %ba = select i1 %cmp, i8 %b, i8 %a
+ %sub = sub i8 %ba, %ab
+ ret i8 %sub
+}
+
+define i16 @abd_select_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_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: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp sle i16 %a, %b
+ %ab = select i1 %cmp, i16 %a, i16 %b
+ %ba = select i1 %cmp, i16 %b, i16 %a
+ %sub = sub i16 %ba, %ab
+ ret i16 %sub
+}
+
+define i32 @abd_select_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r2, r1, r0
+; CHECK-ARM-NEXT: sublt r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bge .LBB37_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB37_2:
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp sgt i32 %a, %b
+ %ab = select i1 %cmp, i32 %a, i32 %b
+ %ba = select i1 %cmp, i32 %b, i32 %a
+ %sub = sub i32 %ab, %ba
+ ret i32 %sub
+}
+
+define i64 @abd_select_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_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: pop {r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: subs r2, r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: bge .LBB38_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bge .LBB38_4
+; CHECK-THUMB-NEXT: .LBB38_2:
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+; CHECK-THUMB-NEXT: .LBB38_3:
+; CHECK-THUMB-NEXT: mov r0, r2
+; CHECK-THUMB-NEXT: blt .LBB38_2
+; CHECK-THUMB-NEXT: .LBB38_4:
+; CHECK-THUMB-NEXT: mov r1, r3
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+ %cmp = icmp sge i64 %a, %b
+ %ab = select i1 %cmp, i64 %a, i64 %b
+ %ba = select i1 %cmp, i64 %b, i64 %a
+ %sub = sub i64 %ab, %ba
+ ret i64 %sub
+}
+
+define i128 @abd_select_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_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 r1, r7
+; CHECK-ARM-NEXT: movlt r2, r4
+; CHECK-ARM-NEXT: movlt r3, r5
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_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, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r6, r2
+; CHECK-THUMB-NEXT: str r2, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: mov r1, r0
+; CHECK-THUMB-NEXT: str r0, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r0, [sp, #60]
+; CHECK-THUMB-NEXT: ldr r2, [sp, #56]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #52]
+; CHECK-THUMB-NEXT: ldr r5, [sp, #48]
+; CHECK-THUMB-NEXT: subs r3, r1, r5
+; CHECK-THUMB-NEXT: str r3, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r1, r4
+; CHECK-THUMB-NEXT: sbcs r1, r7
+; CHECK-THUMB-NEXT: str r1, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT: sbcs r6, r2
+; CHECK-THUMB-NEXT: str r6, [sp, #20] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r6, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r3, r6
+; CHECK-THUMB-NEXT: sbcs r3, r0
+; CHECK-THUMB-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT: subs r5, r5, r1
+; CHECK-THUMB-NEXT: sbcs r7, r4
+; CHECK-THUMB-NEXT: ldr r1, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r2, r1
+; CHECK-THUMB-NEXT: sbcs r0, r6
+; CHECK-THUMB-NEXT: bge .LBB39_6
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB39_7
+; CHECK-THUMB-NEXT: .LBB39_2:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bge .LBB39_8
+; CHECK-THUMB-NEXT: .LBB39_3:
+; CHECK-THUMB-NEXT: blt .LBB39_5
+; CHECK-THUMB-NEXT: .LBB39_4:
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: .LBB39_5:
+; CHECK-THUMB-NEXT: ldr r0, [sp, #24] @ 4-byte Reload
+; CHECK-THUMB-NEXT: mov r2, r4
+; CHECK-THUMB-NEXT: add sp, #28
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-THUMB-NEXT: .LBB39_6:
+; CHECK-THUMB-NEXT: str r5, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB39_2
+; CHECK-THUMB-NEXT: .LBB39_7:
+; CHECK-THUMB-NEXT: mov r1, r7
+; CHECK-THUMB-NEXT: ldr r4, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blt .LBB39_3
+; CHECK-THUMB-NEXT: .LBB39_8:
+; CHECK-THUMB-NEXT: mov r4, r2
+; CHECK-THUMB-NEXT: bge .LBB39_4
+; CHECK-THUMB-NEXT: b .LBB39_5
+ %cmp = icmp slt i128 %a, %b
+ %ab = select i1 %cmp, i128 %a, i128 %b
+ %ba = select i1 %cmp, i128 %b, i128 %a
+ %sub = sub i128 %ba, %ab
+ ret i128 %sub
+}
+
+declare i8 @llvm.abs.i8(i8, i1)
+declare i16 @llvm.abs.i16(i16, i1)
+declare i32 @llvm.abs.i32(i32, i1)
+declare i64 @llvm.abs.i64(i64, i1)
+declare i128 @llvm.abs.i128(i128, i1)
+
+declare i8 @llvm.smax.i8(i8, i8)
+declare i16 @llvm.smax.i16(i16, i16)
+declare i32 @llvm.smax.i32(i32, i32)
+declare i64 @llvm.smax.i64(i64, i64)
+
+declare i8 @llvm.smin.i8(i8, i8)
+declare i16 @llvm.smin.i16(i16, i16)
+declare i32 @llvm.smin.i32(i32, i32)
+declare i64 @llvm.smin.i64(i64, i64)
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/ARM/abdu-neg.ll b/llvm/test/CodeGen/ARM/abdu-neg.ll
new file mode 100644
index 0000000000000..571cba39e7f76
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/abdu-neg.ll
@@ -0,0 +1,1055 @@
+; 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(zext(a),zext(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: and r1, r1, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxtb r1, r1
+; CHECK-THUMB-NEXT: uxtb 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 = zext i8 %a to i64
+ %bext = zext 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: mov r2, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i8_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxtb 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 = zext i8 %a to i64
+ %bext = zext 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: and r1, r1, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i8_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxtb r1, r1
+; CHECK-THUMB-NEXT: uxtb 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 = zext i8 %a to i64
+ %bext = zext 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: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxth 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 = zext i16 %a to i64
+ %bext = zext 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: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: subs r2, r1, r0
+; CHECK-ARM-NEXT: sublo r2, r0, r1
+; 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: uxth r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r2
+; CHECK-THUMB-NEXT: bhs .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 = zext i16 %a to i64
+ %bext = zext 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: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
+; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i16_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxth 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 = zext i16 %a to i64
+ %bext = zext 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: sublo 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: bhs .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 = zext i32 %a to i64
+ %bext = zext 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: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: subs r2, r1, r0
+; CHECK-ARM-NEXT: sublo r2, r0, r1
+; 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: uxth r2, r1
+; CHECK-THUMB-NEXT: subs r1, r2, r0
+; CHECK-THUMB-NEXT: bhs .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 = zext i32 %a to i64
+ %bext = zext 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: sublo 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: bhs .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 = zext i32 %a to i64
+ %bext = zext 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: subs r0, r0, r2
+; CHECK-ARM-NEXT: mov r12, #0
+; CHECK-ARM-NEXT: sbcs r1, r1, r3
+; CHECK-ARM-NEXT: adc r2, r12, #0
+; CHECK-ARM-NEXT: eor r2, r2, #1
+; CHECK-ARM-NEXT: rsb r2, r2, #0
+; CHECK-ARM-NEXT: eor r0, r0, r2
+; CHECK-ARM-NEXT: eor r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r2
+; CHECK-ARM-NEXT: rsbs r0, r0, #0
+; CHECK-ARM-NEXT: rsc r1, r1, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, lr}
+; CHECK-THUMB-NEXT: push {r4, lr}
+; CHECK-THUMB-NEXT: movs r4, #0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: mov r2, r4
+; CHECK-THUMB-NEXT: adcs r2, r4
+; CHECK-THUMB-NEXT: movs r3, #1
+; CHECK-THUMB-NEXT: eors r3, r2
+; CHECK-THUMB-NEXT: rsbs r2, r3, #0
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: rsbs r0, r0, #0
+; CHECK-THUMB-NEXT: sbcs r4, r1
+; CHECK-THUMB-NEXT: mov r1, r4
+; CHECK-THUMB-NEXT: pop {r4, pc}
+ %aext = zext i64 %a to i128
+ %bext = zext 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: subs r0, r0, r2
+; CHECK-ARM-NEXT: mov r12, #0
+; CHECK-ARM-NEXT: sbcs r1, r1, r3
+; CHECK-ARM-NEXT: adc r2, r12, #0
+; CHECK-ARM-NEXT: eor r2, r2, #1
+; CHECK-ARM-NEXT: rsb r2, r2, #0
+; CHECK-ARM-NEXT: eor r0, r0, r2
+; CHECK-ARM-NEXT: eor r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r2
+; CHECK-ARM-NEXT: rsbs r0, r0, #0
+; CHECK-ARM-NEXT: rsc r1, r1, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i64_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, lr}
+; CHECK-THUMB-NEXT: push {r4, lr}
+; CHECK-THUMB-NEXT: movs r4, #0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: mov r2, r4
+; CHECK-THUMB-NEXT: adcs r2, r4
+; CHECK-THUMB-NEXT: movs r3, #1
+; CHECK-THUMB-NEXT: eors r3, r2
+; CHECK-THUMB-NEXT: rsbs r2, r3, #0
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: rsbs r0, r0, #0
+; CHECK-THUMB-NEXT: sbcs r4, r1
+; CHECK-THUMB-NEXT: mov r1, r4
+; CHECK-THUMB-NEXT: pop {r4, pc}
+ %aext = zext i64 %a to i128
+ %bext = zext 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, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: mov r6, #0
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbcs r3, r3, r12
+; CHECK-ARM-NEXT: adc r6, r6, #0
+; CHECK-ARM-NEXT: eor r6, r6, #1
+; CHECK-ARM-NEXT: rsb r6, r6, #0
+; CHECK-ARM-NEXT: eor r0, r0, r6
+; CHECK-ARM-NEXT: eor r1, r1, r6
+; CHECK-ARM-NEXT: subs r0, r0, r6
+; CHECK-ARM-NEXT: eor r2, r2, r6
+; CHECK-ARM-NEXT: sbcs r1, r1, r6
+; CHECK-ARM-NEXT: eor r3, r3, r6
+; CHECK-ARM-NEXT: sbcs r2, r2, r6
+; CHECK-ARM-NEXT: sbc r3, r3, r6
+; 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, 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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: ldr r0, [sp, #36]
+; CHECK-THUMB-NEXT: str r0, [sp] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r6, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r0, [sp, #24]
+; CHECK-THUMB-NEXT: movs r4, #0
+; CHECK-THUMB-NEXT: subs r0, r5, r0
+; CHECK-THUMB-NEXT: sbcs r1, r7
+; CHECK-THUMB-NEXT: sbcs r2, r6
+; CHECK-THUMB-NEXT: ldr r5, [sp] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: mov r5, r4
+; CHECK-THUMB-NEXT: adcs r5, r4
+; CHECK-THUMB-NEXT: movs r6, #1
+; CHECK-THUMB-NEXT: eors r6, r5
+; CHECK-THUMB-NEXT: rsbs r5, r6, #0
+; CHECK-THUMB-NEXT: eors r3, r5
+; CHECK-THUMB-NEXT: eors r2, r5
+; CHECK-THUMB-NEXT: eors r1, r5
+; CHECK-THUMB-NEXT: eors r0, r5
+; CHECK-THUMB-NEXT: subs r0, r0, r5
+; CHECK-THUMB-NEXT: sbcs r1, r5
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: rsbs r0, r0, #0
+; CHECK-THUMB-NEXT: mov r5, r4
+; CHECK-THUMB-NEXT: sbcs r5, r1
+; CHECK-THUMB-NEXT: mov r6, r4
+; CHECK-THUMB-NEXT: sbcs r6, r2
+; CHECK-THUMB-NEXT: sbcs r4, r3
+; CHECK-THUMB-NEXT: mov r1, r5
+; CHECK-THUMB-NEXT: mov r2, r6
+; CHECK-THUMB-NEXT: mov r3, r4
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %aext = zext i128 %a to i256
+ %bext = zext 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, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: mov r6, #0
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbcs r3, r3, r12
+; CHECK-ARM-NEXT: adc r6, r6, #0
+; CHECK-ARM-NEXT: eor r6, r6, #1
+; CHECK-ARM-NEXT: rsb r6, r6, #0
+; CHECK-ARM-NEXT: eor r0, r0, r6
+; CHECK-ARM-NEXT: eor r1, r1, r6
+; CHECK-ARM-NEXT: subs r0, r0, r6
+; CHECK-ARM-NEXT: eor r2, r2, r6
+; CHECK-ARM-NEXT: sbcs r1, r1, r6
+; CHECK-ARM-NEXT: eor r3, r3, r6
+; CHECK-ARM-NEXT: sbcs r2, r2, r6
+; CHECK-ARM-NEXT: sbc r3, r3, r6
+; 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, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i128_undef:
+; 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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: ldr r0, [sp, #36]
+; CHECK-THUMB-NEXT: str r0, [sp] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r6, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r0, [sp, #24]
+; CHECK-THUMB-NEXT: movs r4, #0
+; CHECK-THUMB-NEXT: subs r0, r5, r0
+; CHECK-THUMB-NEXT: sbcs r1, r7
+; CHECK-THUMB-NEXT: sbcs r2, r6
+; CHECK-THUMB-NEXT: ldr r5, [sp] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: mov r5, r4
+; CHECK-THUMB-NEXT: adcs r5, r4
+; CHECK-THUMB-NEXT: movs r6, #1
+; CHECK-THUMB-NEXT: eors r6, r5
+; CHECK-THUMB-NEXT: rsbs r5, r6, #0
+; CHECK-THUMB-NEXT: eors r3, r5
+; CHECK-THUMB-NEXT: eors r2, r5
+; CHECK-THUMB-NEXT: eors r1, r5
+; CHECK-THUMB-NEXT: eors r0, r5
+; CHECK-THUMB-NEXT: subs r0, r0, r5
+; CHECK-THUMB-NEXT: sbcs r1, r5
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: rsbs r0, r0, #0
+; CHECK-THUMB-NEXT: mov r5, r4
+; CHECK-THUMB-NEXT: sbcs r5, r1
+; CHECK-THUMB-NEXT: mov r6, r4
+; CHECK-THUMB-NEXT: sbcs r6, r2
+; CHECK-THUMB-NEXT: sbcs r4, r3
+; CHECK-THUMB-NEXT: mov r1, r5
+; CHECK-THUMB-NEXT: mov r2, r6
+; CHECK-THUMB-NEXT: mov r3, r4
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %aext = zext i128 %a to i256
+ %bext = zext i128 %b to i256
+ %sub = sub i256 %aext, %bext
+ %abs = call i256 @llvm.abs.i256(i256 %sub, i1 true)
+ %nabs = sub i256 0, %abs
+ %trunc = trunc i256 %nabs to i128
+ ret i128 %trunc
+}
+
+;
+; sub(umin(a,b),umax(a,b)) -> nabds(a,b)
+;
+
+define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: and r1, r1, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: cmp r0, r1
+; CHECK-ARM-NEXT: mov r2, r1
+; CHECK-ARM-NEXT: movlo r1, r0
+; CHECK-ARM-NEXT: movhi r2, r0
+; CHECK-ARM-NEXT: sub r0, r1, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxtb r1, r1
+; CHECK-THUMB-NEXT: uxtb r0, r0
+; CHECK-THUMB-NEXT: cmp r0, r1
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: bls .LBB13_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bhs .LBB13_4
+; CHECK-THUMB-NEXT: .LBB13_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB13_3:
+; CHECK-THUMB-NEXT: mov r2, r1
+; CHECK-THUMB-NEXT: blo .LBB13_2
+; CHECK-THUMB-NEXT: .LBB13_4:
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i8 @llvm.umin.i8(i8 %a, i8 %b)
+ %max = call i8 @llvm.umax.i8(i8 %a, i8 %b)
+ %sub = sub i8 %min, %max
+ ret i8 %sub
+}
+
+define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: cmp r0, r1
+; CHECK-ARM-NEXT: mov r2, r1
+; CHECK-ARM-NEXT: movlo r1, r0
+; CHECK-ARM-NEXT: movhi r2, r0
+; CHECK-ARM-NEXT: sub r0, r1, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxth r0, r0
+; CHECK-THUMB-NEXT: cmp r0, r1
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: bls .LBB14_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bhs .LBB14_4
+; CHECK-THUMB-NEXT: .LBB14_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB14_3:
+; CHECK-THUMB-NEXT: mov r2, r1
+; CHECK-THUMB-NEXT: blo .LBB14_2
+; CHECK-THUMB-NEXT: .LBB14_4:
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i16 @llvm.umin.i16(i16 %a, i16 %b)
+ %max = call i16 @llvm.umax.i16(i16 %a, i16 %b)
+ %sub = sub i16 %min, %max
+ ret i16 %sub
+}
+
+define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: cmp r0, r1
+; CHECK-ARM-NEXT: mov r2, r1
+; CHECK-ARM-NEXT: movhi r2, r0
+; CHECK-ARM-NEXT: movlo r1, r0
+; CHECK-ARM-NEXT: sub r0, r1, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: cmp r0, r1
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: bls .LBB15_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bhs .LBB15_4
+; CHECK-THUMB-NEXT: .LBB15_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB15_3:
+; CHECK-THUMB-NEXT: mov r2, r1
+; CHECK-THUMB-NEXT: blo .LBB15_2
+; CHECK-THUMB-NEXT: .LBB15_4:
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i32 @llvm.umin.i32(i32 %a, i32 %b)
+ %max = call i32 @llvm.umax.i32(i32 %a, i32 %b)
+ %sub = sub i32 %min, %max
+ ret i32 %sub
+}
+
+define i64 @abd_minmax_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, lr}
+; CHECK-ARM-NEXT: push {r4, lr}
+; CHECK-ARM-NEXT: subs r12, r2, r0
+; CHECK-ARM-NEXT: mov lr, r2
+; CHECK-ARM-NEXT: sbcs r12, r3, r1
+; CHECK-ARM-NEXT: mov r12, r3
+; CHECK-ARM-NEXT: movlo lr, r0
+; CHECK-ARM-NEXT: movlo r12, r1
+; CHECK-ARM-NEXT: subs r4, r0, r2
+; CHECK-ARM-NEXT: sbcs r4, r1, r3
+; CHECK-ARM-NEXT: movlo r3, r1
+; CHECK-ARM-NEXT: movlo r2, r0
+; CHECK-ARM-NEXT: subs r0, r2, lr
+; CHECK-ARM-NEXT: sbc r1, r3, r12
+; CHECK-ARM-NEXT: pop {r4, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, r5, r6, lr}
+; CHECK-THUMB-NEXT: push {r4, r5, r6, lr}
+; CHECK-THUMB-NEXT: subs r4, r2, r0
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: sbcs r4, r1
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: blo .LBB16_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: .LBB16_2:
+; CHECK-THUMB-NEXT: mov r5, r0
+; CHECK-THUMB-NEXT: blo .LBB16_4
+; CHECK-THUMB-NEXT: @ %bb.3:
+; CHECK-THUMB-NEXT: mov r5, r2
+; CHECK-THUMB-NEXT: .LBB16_4:
+; CHECK-THUMB-NEXT: subs r6, r0, r2
+; CHECK-THUMB-NEXT: mov r6, r1
+; CHECK-THUMB-NEXT: sbcs r6, r3
+; CHECK-THUMB-NEXT: blo .LBB16_6
+; CHECK-THUMB-NEXT: @ %bb.5:
+; CHECK-THUMB-NEXT: mov r1, r3
+; CHECK-THUMB-NEXT: .LBB16_6:
+; CHECK-THUMB-NEXT: blo .LBB16_8
+; CHECK-THUMB-NEXT: @ %bb.7:
+; CHECK-THUMB-NEXT: mov r0, r2
+; CHECK-THUMB-NEXT: .LBB16_8:
+; CHECK-THUMB-NEXT: subs r0, r0, r5
+; CHECK-THUMB-NEXT: sbcs r1, r4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, pc}
+ %min = call i64 @llvm.umin.i64(i64 %a, i64 %b)
+ %max = call i64 @llvm.umax.i64(i64 %a, i64 %b)
+ %sub = sub i64 %min, %max
+ ret i64 %sub
+}
+
+define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i128:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r6, r7, r8, r9, r10, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #32]
+; CHECK-ARM-NEXT: ldr r4, [sp, #36]
+; CHECK-ARM-NEXT: subs r6, r5, r0
+; CHECK-ARM-NEXT: ldr r12, [sp, #44]
+; CHECK-ARM-NEXT: ldr lr, [sp, #40]
+; CHECK-ARM-NEXT: sbcs r6, r4, r1
+; CHECK-ARM-NEXT: mov r10, r4
+; CHECK-ARM-NEXT: mov r7, r5
+; CHECK-ARM-NEXT: sbcs r6, lr, r2
+; CHECK-ARM-NEXT: mov r8, r12
+; CHECK-ARM-NEXT: sbcs r6, r12, r3
+; CHECK-ARM-NEXT: mov r9, lr
+; CHECK-ARM-NEXT: movlo r8, r3
+; CHECK-ARM-NEXT: movlo r9, r2
+; CHECK-ARM-NEXT: movlo r10, r1
+; CHECK-ARM-NEXT: movlo r7, r0
+; CHECK-ARM-NEXT: subs r6, r0, r5
+; CHECK-ARM-NEXT: sbcs r6, r1, r4
+; CHECK-ARM-NEXT: sbcs r6, r2, lr
+; CHECK-ARM-NEXT: sbcs r6, r3, r12
+; CHECK-ARM-NEXT: movlo r12, r3
+; CHECK-ARM-NEXT: movlo lr, r2
+; CHECK-ARM-NEXT: movlo r4, r1
+; CHECK-ARM-NEXT: movlo r5, r0
+; CHECK-ARM-NEXT: subs r0, r5, r7
+; CHECK-ARM-NEXT: sbcs r1, r4, r10
+; CHECK-ARM-NEXT: sbcs r2, lr, r9
+; CHECK-ARM-NEXT: sbc r3, r12, r8
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_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 #20
+; CHECK-THUMB-NEXT: sub sp, #20
+; CHECK-THUMB-NEXT: ldr r5, [sp, #52]
+; CHECK-THUMB-NEXT: add r7, sp, #40
+; CHECK-THUMB-NEXT: ldm r7, {r4, r6, r7}
+; CHECK-THUMB-NEXT: str r4, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT: subs r4, r4, r0
+; CHECK-THUMB-NEXT: mov r4, r6
+; CHECK-THUMB-NEXT: sbcs r4, r1
+; CHECK-THUMB-NEXT: mov r4, r7
+; CHECK-THUMB-NEXT: sbcs r4, r2
+; CHECK-THUMB-NEXT: mov r4, r5
+; CHECK-THUMB-NEXT: sbcs r4, r3
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: bhs .LBB17_12
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: str r2, [sp, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: bhs .LBB17_13
+; CHECK-THUMB-NEXT: .LBB17_2:
+; CHECK-THUMB-NEXT: str r1, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: blo .LBB17_4
+; CHECK-THUMB-NEXT: .LBB17_3:
+; CHECK-THUMB-NEXT: str r6, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: .LBB17_4:
+; CHECK-THUMB-NEXT: str r4, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r4, r0
+; CHECK-THUMB-NEXT: blo .LBB17_6
+; CHECK-THUMB-NEXT: @ %bb.5:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: .LBB17_6:
+; CHECK-THUMB-NEXT: str r4, [sp] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r4, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: subs r4, r0, r4
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: sbcs r4, r6
+; CHECK-THUMB-NEXT: mov r4, r2
+; CHECK-THUMB-NEXT: sbcs r4, r7
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: sbcs r4, r5
+; CHECK-THUMB-NEXT: bhs .LBB17_14
+; CHECK-THUMB-NEXT: @ %bb.7:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bhs .LBB17_15
+; CHECK-THUMB-NEXT: .LBB17_8:
+; CHECK-THUMB-NEXT: bhs .LBB17_16
+; CHECK-THUMB-NEXT: .LBB17_9:
+; CHECK-THUMB-NEXT: blo .LBB17_11
+; CHECK-THUMB-NEXT: .LBB17_10:
+; CHECK-THUMB-NEXT: ldr r0, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: .LBB17_11:
+; CHECK-THUMB-NEXT: ldr r5, [sp] @ 4-byte Reload
+; CHECK-THUMB-NEXT: subs r0, r0, r5
+; CHECK-THUMB-NEXT: ldr r5, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r1, r5
+; CHECK-THUMB-NEXT: ldr r5, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r4
+; CHECK-THUMB-NEXT: add sp, #20
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-THUMB-NEXT: .LBB17_12:
+; CHECK-THUMB-NEXT: mov r4, r5
+; CHECK-THUMB-NEXT: str r2, [sp, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: blo .LBB17_2
+; CHECK-THUMB-NEXT: .LBB17_13:
+; CHECK-THUMB-NEXT: str r7, [sp, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: str r1, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: bhs .LBB17_3
+; CHECK-THUMB-NEXT: b .LBB17_4
+; CHECK-THUMB-NEXT: .LBB17_14:
+; CHECK-THUMB-NEXT: mov r3, r5
+; CHECK-THUMB-NEXT: ldr r4, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blo .LBB17_8
+; CHECK-THUMB-NEXT: .LBB17_15:
+; CHECK-THUMB-NEXT: mov r2, r7
+; CHECK-THUMB-NEXT: blo .LBB17_9
+; CHECK-THUMB-NEXT: .LBB17_16:
+; CHECK-THUMB-NEXT: mov r1, r6
+; CHECK-THUMB-NEXT: bhs .LBB17_10
+; CHECK-THUMB-NEXT: b .LBB17_11
+ %min = call i128 @llvm.umin.i128(i128 %a, i128 %b)
+ %max = call i128 @llvm.umax.i128(i128 %a, i128 %b)
+ %sub = sub i128 %min, %max
+ ret i128 %sub
+}
+
+;
+; select(icmp(a,b),sub(a,b),sub(b,a)) -> nabds(a,b)
+;
+
+define i8 @abd_cmp_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: and r12, r1, #255
+; CHECK-ARM-NEXT: and r3, r0, #255
+; CHECK-ARM-NEXT: sub r2, r1, r0
+; CHECK-ARM-NEXT: cmp r3, r12
+; CHECK-ARM-NEXT: subls r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxtb r2, r1
+; CHECK-THUMB-NEXT: uxtb r3, r0
+; CHECK-THUMB-NEXT: cmp r3, r2
+; CHECK-THUMB-NEXT: bls .LBB18_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB18_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp ule i8 %a, %b
+ %ab = sub i8 %a, %b
+ %ba = sub i8 %b, %a
+ %sel = select i1 %cmp, i8 %ab, i8 %ba
+ ret i8 %sel
+}
+
+define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r11, lr}
+; CHECK-ARM-NEXT: push {r11, lr}
+; CHECK-ARM-NEXT: mov r12, #255
+; CHECK-ARM-NEXT: sub r2, r1, r0
+; CHECK-ARM-NEXT: orr r12, r12, #65280
+; CHECK-ARM-NEXT: and lr, r1, r12
+; CHECK-ARM-NEXT: and r3, r0, r12
+; CHECK-ARM-NEXT: cmp r3, lr
+; CHECK-ARM-NEXT: sublo r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: pop {r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r2, r1
+; CHECK-THUMB-NEXT: uxth r3, r0
+; CHECK-THUMB-NEXT: cmp r3, r2
+; CHECK-THUMB-NEXT: blo .LBB19_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB19_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp ult i16 %a, %b
+ %ab = sub i16 %a, %b
+ %ba = sub i16 %b, %a
+ %sel = select i1 %cmp, i16 %ab, i16 %ba
+ ret i16 %sel
+}
+
+define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r2, r0, r1
+; CHECK-ARM-NEXT: subhs r2, r1, r0
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: blo .LBB20_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r1, r2
+; CHECK-THUMB-NEXT: .LBB20_2:
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp uge i32 %a, %b
+ %ab = sub i32 %a, %b
+ %ba = sub i32 %b, %a
+ %sel = select i1 %cmp, i32 %ba, i32 %ab
+ ret i32 %sel
+}
+
+define i64 @abd_cmp_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r11, lr}
+; CHECK-ARM-NEXT: push {r11, lr}
+; CHECK-ARM-NEXT: subs r12, r2, r0
+; CHECK-ARM-NEXT: sbc lr, r3, r1
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbcs r1, r1, r3
+; CHECK-ARM-NEXT: movhs r0, r12
+; CHECK-ARM-NEXT: movhs r1, lr
+; CHECK-ARM-NEXT: pop {r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_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, r2, r0
+; CHECK-THUMB-NEXT: mov r4, r3
+; CHECK-THUMB-NEXT: sbcs r4, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: bhs .LBB21_3
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bhs .LBB21_4
+; CHECK-THUMB-NEXT: .LBB21_2:
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+; CHECK-THUMB-NEXT: .LBB21_3:
+; CHECK-THUMB-NEXT: mov r0, r5
+; CHECK-THUMB-NEXT: blo .LBB21_2
+; CHECK-THUMB-NEXT: .LBB21_4:
+; CHECK-THUMB-NEXT: mov r1, r4
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+ %cmp = icmp ult i64 %a, %b
+ %ab = sub i64 %a, %b
+ %ba = sub i64 %b, %a
+ %sel = select i1 %cmp, i64 %ab, i64 %ba
+ ret i64 %sel
+}
+
+define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_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, r9, r0
+; CHECK-ARM-NEXT: ldr lr, [sp, #40]
+; CHECK-ARM-NEXT: sbcs r7, r8, r1
+; CHECK-ARM-NEXT: ldr r12, [sp, #44]
+; CHECK-ARM-NEXT: sbcs r4, lr, r2
+; CHECK-ARM-NEXT: sbc r5, r12, r3
+; CHECK-ARM-NEXT: subs r0, r0, r9
+; CHECK-ARM-NEXT: sbcs r1, r1, r8
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbcs r3, r3, r12
+; CHECK-ARM-NEXT: movhs r0, r6
+; CHECK-ARM-NEXT: movhs r1, r7
+; CHECK-ARM-NEXT: movhs r2, r4
+; CHECK-ARM-NEXT: movhs r3, r5
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r8, r9, r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_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 r2, [sp, #24] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r4, r1
+; CHECK-THUMB-NEXT: str r1, [sp, #20] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r1, r0
+; CHECK-THUMB-NEXT: add r6, sp, #52
+; CHECK-THUMB-NEXT: ldm r6, {r0, r5, r6}
+; CHECK-THUMB-NEXT: ldr r2, [sp, #48]
+; CHECK-THUMB-NEXT: subs r7, r2, r1
+; CHECK-THUMB-NEXT: str r7, [sp, #4] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r7, r0
+; CHECK-THUMB-NEXT: sbcs r7, r4
+; CHECK-THUMB-NEXT: str r7, [sp, #8] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r7, r5
+; CHECK-THUMB-NEXT: ldr r4, [sp, #24] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r7, r4
+; CHECK-THUMB-NEXT: str r7, [sp, #12] @ 4-byte Spill
+; CHECK-THUMB-NEXT: mov r7, r6
+; CHECK-THUMB-NEXT: sbcs r7, r3
+; CHECK-THUMB-NEXT: str r7, [sp, #16] @ 4-byte Spill
+; CHECK-THUMB-NEXT: subs r2, r1, r2
+; CHECK-THUMB-NEXT: ldr r1, [sp, #20] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r1, r0
+; CHECK-THUMB-NEXT: sbcs r4, r5
+; CHECK-THUMB-NEXT: sbcs r3, r6
+; CHECK-THUMB-NEXT: bhs .LBB22_6
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: bhs .LBB22_7
+; CHECK-THUMB-NEXT: .LBB22_2:
+; CHECK-THUMB-NEXT: bhs .LBB22_8
+; CHECK-THUMB-NEXT: .LBB22_3:
+; CHECK-THUMB-NEXT: blo .LBB22_5
+; CHECK-THUMB-NEXT: .LBB22_4:
+; CHECK-THUMB-NEXT: ldr r3, [sp, #16] @ 4-byte Reload
+; CHECK-THUMB-NEXT: .LBB22_5:
+; CHECK-THUMB-NEXT: mov r0, r2
+; CHECK-THUMB-NEXT: mov r2, r4
+; CHECK-THUMB-NEXT: add sp, #28
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-THUMB-NEXT: .LBB22_6:
+; CHECK-THUMB-NEXT: ldr r2, [sp, #4] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blo .LBB22_2
+; CHECK-THUMB-NEXT: .LBB22_7:
+; CHECK-THUMB-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
+; CHECK-THUMB-NEXT: blo .LBB22_3
+; CHECK-THUMB-NEXT: .LBB22_8:
+; CHECK-THUMB-NEXT: ldr r4, [sp, #12] @ 4-byte Reload
+; CHECK-THUMB-NEXT: bhs .LBB22_4
+; CHECK-THUMB-NEXT: b .LBB22_5
+ %cmp = icmp ult i128 %a, %b
+ %ab = sub i128 %a, %b
+ %ba = sub i128 %b, %a
+ %sel = select i1 %cmp, i128 %ab, i128 %ba
+ ret i128 %sel
+}
+
+declare i8 @llvm.abs.i8(i8, i1)
+declare i16 @llvm.abs.i16(i16, i1)
+declare i32 @llvm.abs.i32(i32, i1)
+declare i64 @llvm.abs.i64(i64, i1)
+declare i128 @llvm.abs.i128(i128, i1)
+
+declare i8 @llvm.umax.i8(i8, i8)
+declare i16 @llvm.umax.i16(i16, i16)
+declare i32 @llvm.umax.i32(i32, i32)
+declare i64 @llvm.umax.i64(i64, i64)
+
+declare i8 @llvm.umin.i8(i8, i8)
+declare i16 @llvm.umin.i16(i16, i16)
+declare i32 @llvm.umin.i32(i32, i32)
+declare i64 @llvm.umin.i64(i64, i64)
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/ARM/abdu.ll b/llvm/test/CodeGen/ARM/abdu.ll
new file mode 100644
index 0000000000000..e8fdbe7487fc7
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/abdu.ll
@@ -0,0 +1,1067 @@
+; 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(abs(sub(zext(a),zext(b)))) -> abdu(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: and r1, r1, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxtb r1, r1
+; CHECK-THUMB-NEXT: uxtb 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %aext = zext i8 %a to i64
+ %bext = zext i8 %b to i64
+ %sub = sub i64 %aext, %bext
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+ %trunc = trunc i64 %abs 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: mov r2, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i8_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxtb 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %aext = zext i8 %a to i64
+ %bext = zext i16 %b to i64
+ %sub = sub i64 %aext, %bext
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+ %trunc = trunc i64 %abs 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: and r1, r1, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i8_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxtb r1, r1
+; CHECK-THUMB-NEXT: uxtb 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %aext = zext i8 %a to i64
+ %bext = zext i8 %b to i64
+ %sub = sub i64 %aext, %bext
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
+ %trunc = trunc i64 %abs 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: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxth 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %aext = zext i16 %a to i64
+ %bext = zext i16 %b to i64
+ %sub = sub i64 %aext, %bext
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+ %trunc = trunc i64 %abs 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: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r2, r0, r2
+; CHECK-ARM-NEXT: subs r0, r1, r2
+; CHECK-ARM-NEXT: sublo r0, r2, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i16_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r2
+; CHECK-THUMB-NEXT: bhs .LBB4_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB4_2:
+; CHECK-THUMB-NEXT: bx lr
+ %aext = zext i16 %a to i64
+ %bext = zext i32 %b to i64
+ %sub = sub i64 %aext, %bext
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+ %trunc = trunc i64 %abs 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: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i16_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxth 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %aext = zext i16 %a to i64
+ %bext = zext i16 %b to i64
+ %sub = sub i64 %aext, %bext
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
+ %trunc = trunc i64 %abs 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: sublo r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bhs .LBB6_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB6_2:
+; CHECK-THUMB-NEXT: bx lr
+ %aext = zext i32 %a to i64
+ %bext = zext i32 %b to i64
+ %sub = sub i64 %aext, %bext
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+ %trunc = trunc i64 %abs 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: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r2, r1, r2
+; CHECK-ARM-NEXT: subs r1, r2, r0
+; CHECK-ARM-NEXT: sublo r1, r0, r2
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i32_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bhs .LBB7_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB7_2:
+; CHECK-THUMB-NEXT: bx lr
+ %aext = zext i32 %a to i64
+ %bext = zext i16 %b to i64
+ %sub = sub i64 %aext, %bext
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false)
+ %trunc = trunc i64 %abs 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: sublo r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i32_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bhs .LBB8_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB8_2:
+; CHECK-THUMB-NEXT: bx lr
+ %aext = zext i32 %a to i64
+ %bext = zext i32 %b to i64
+ %sub = sub i64 %aext, %bext
+ %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true)
+ %trunc = trunc i64 %abs 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: subs r0, r0, r2
+; CHECK-ARM-NEXT: mov r12, #0
+; CHECK-ARM-NEXT: sbcs r1, r1, r3
+; CHECK-ARM-NEXT: adc r2, r12, #0
+; CHECK-ARM-NEXT: eor r2, r2, #1
+; CHECK-ARM-NEXT: rsb r2, r2, #0
+; CHECK-ARM-NEXT: eor r0, r0, r2
+; CHECK-ARM-NEXT: eor r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, lr}
+; CHECK-THUMB-NEXT: push {r4, lr}
+; CHECK-THUMB-NEXT: movs r4, #0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: adcs r4, r4
+; CHECK-THUMB-NEXT: movs r2, #1
+; CHECK-THUMB-NEXT: eors r2, r4
+; CHECK-THUMB-NEXT: rsbs r2, r2, #0
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: pop {r4, pc}
+ %aext = zext i64 %a to i128
+ %bext = zext i64 %b to i128
+ %sub = sub i128 %aext, %bext
+ %abs = call i128 @llvm.abs.i128(i128 %sub, i1 false)
+ %trunc = trunc i128 %abs 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: subs r0, r0, r2
+; CHECK-ARM-NEXT: mov r12, #0
+; CHECK-ARM-NEXT: sbcs r1, r1, r3
+; CHECK-ARM-NEXT: adc r2, r12, #0
+; CHECK-ARM-NEXT: eor r2, r2, #1
+; CHECK-ARM-NEXT: rsb r2, r2, #0
+; CHECK-ARM-NEXT: eor r0, r0, r2
+; CHECK-ARM-NEXT: eor r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i64_undef:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, lr}
+; CHECK-THUMB-NEXT: push {r4, lr}
+; CHECK-THUMB-NEXT: movs r4, #0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: adcs r4, r4
+; CHECK-THUMB-NEXT: movs r2, #1
+; CHECK-THUMB-NEXT: eors r2, r4
+; CHECK-THUMB-NEXT: rsbs r2, r2, #0
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: pop {r4, pc}
+ %aext = zext i64 %a to i128
+ %bext = zext i64 %b to i128
+ %sub = sub i128 %aext, %bext
+ %abs = call i128 @llvm.abs.i128(i128 %sub, i1 true)
+ %trunc = trunc i128 %abs 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, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: mov r6, #0
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbcs r3, r3, r12
+; CHECK-ARM-NEXT: adc r6, r6, #0
+; CHECK-ARM-NEXT: eor r6, r6, #1
+; CHECK-ARM-NEXT: rsb r6, r6, #0
+; CHECK-ARM-NEXT: eor r0, r0, r6
+; CHECK-ARM-NEXT: eor r1, r1, r6
+; CHECK-ARM-NEXT: subs r0, r0, r6
+; CHECK-ARM-NEXT: eor r2, r2, r6
+; CHECK-ARM-NEXT: sbcs r1, r1, r6
+; CHECK-ARM-NEXT: eor r3, r3, r6
+; CHECK-ARM-NEXT: sbcs r2, r2, r6
+; CHECK-ARM-NEXT: sbc r3, r3, r6
+; CHECK-ARM-NEXT: pop {r4, r5, r6, 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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: mov r4, r0
+; CHECK-THUMB-NEXT: ldr r0, [sp, #36]
+; CHECK-THUMB-NEXT: str r0, [sp] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r5, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r6, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #24]
+; CHECK-THUMB-NEXT: movs r0, #0
+; CHECK-THUMB-NEXT: subs r4, r4, r7
+; CHECK-THUMB-NEXT: sbcs r1, r6
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: ldr r5, [sp] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: adcs r0, r0
+; CHECK-THUMB-NEXT: movs r5, #1
+; CHECK-THUMB-NEXT: eors r5, r0
+; CHECK-THUMB-NEXT: rsbs r5, r5, #0
+; CHECK-THUMB-NEXT: eors r3, r5
+; CHECK-THUMB-NEXT: eors r2, r5
+; CHECK-THUMB-NEXT: eors r1, r5
+; CHECK-THUMB-NEXT: eors r4, r5
+; CHECK-THUMB-NEXT: subs r0, r4, r5
+; CHECK-THUMB-NEXT: sbcs r1, r5
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %aext = zext i128 %a to i256
+ %bext = zext i128 %b to i256
+ %sub = sub i256 %aext, %bext
+ %abs = call i256 @llvm.abs.i256(i256 %sub, i1 false)
+ %trunc = trunc i256 %abs 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, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: mov r6, #0
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbcs r3, r3, r12
+; CHECK-ARM-NEXT: adc r6, r6, #0
+; CHECK-ARM-NEXT: eor r6, r6, #1
+; CHECK-ARM-NEXT: rsb r6, r6, #0
+; CHECK-ARM-NEXT: eor r0, r0, r6
+; CHECK-ARM-NEXT: eor r1, r1, r6
+; CHECK-ARM-NEXT: subs r0, r0, r6
+; CHECK-ARM-NEXT: eor r2, r2, r6
+; CHECK-ARM-NEXT: sbcs r1, r1, r6
+; CHECK-ARM-NEXT: eor r3, r3, r6
+; CHECK-ARM-NEXT: sbcs r2, r2, r6
+; CHECK-ARM-NEXT: sbc r3, r3, r6
+; CHECK-ARM-NEXT: pop {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_ext_i128_undef:
+; 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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: mov r4, r0
+; CHECK-THUMB-NEXT: ldr r0, [sp, #36]
+; CHECK-THUMB-NEXT: str r0, [sp] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r5, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r6, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #24]
+; CHECK-THUMB-NEXT: movs r0, #0
+; CHECK-THUMB-NEXT: subs r4, r4, r7
+; CHECK-THUMB-NEXT: sbcs r1, r6
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: ldr r5, [sp] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: adcs r0, r0
+; CHECK-THUMB-NEXT: movs r5, #1
+; CHECK-THUMB-NEXT: eors r5, r0
+; CHECK-THUMB-NEXT: rsbs r5, r5, #0
+; CHECK-THUMB-NEXT: eors r3, r5
+; CHECK-THUMB-NEXT: eors r2, r5
+; CHECK-THUMB-NEXT: eors r1, r5
+; CHECK-THUMB-NEXT: eors r4, r5
+; CHECK-THUMB-NEXT: subs r0, r4, r5
+; CHECK-THUMB-NEXT: sbcs r1, r5
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %aext = zext i128 %a to i256
+ %bext = zext i128 %b to i256
+ %sub = sub i256 %aext, %bext
+ %abs = call i256 @llvm.abs.i256(i256 %sub, i1 true)
+ %trunc = trunc i256 %abs to i128
+ ret i128 %trunc
+}
+
+;
+; sub(umax(a,b),umin(a,b)) -> abdu(a,b)
+;
+
+define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: and r1, r1, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxtb r1, r1
+; CHECK-THUMB-NEXT: uxtb 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i8 @llvm.umin.i8(i8 %a, i8 %b)
+ %max = call i8 @llvm.umax.i8(i8 %a, i8 %b)
+ %sub = sub i8 %max, %min
+ ret i8 %sub
+}
+
+define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxth 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i16 @llvm.umin.i16(i16 %a, i16 %b)
+ %max = call i16 @llvm.umax.i16(i16 %a, i16 %b)
+ %sub = sub i16 %max, %min
+ ret i16 %sub
+}
+
+define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r2, r1, r0
+; CHECK-ARM-NEXT: sublo r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bhs .LBB15_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB15_2:
+; CHECK-THUMB-NEXT: bx lr
+ %min = call i32 @llvm.umin.i32(i32 %a, i32 %b)
+ %max = call i32 @llvm.umax.i32(i32 %a, i32 %b)
+ %sub = sub i32 %max, %min
+ ret i32 %sub
+}
+
+define i64 @abd_minmax_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: mov r12, #0
+; CHECK-ARM-NEXT: sbcs r1, r1, r3
+; CHECK-ARM-NEXT: adc r2, r12, #0
+; CHECK-ARM-NEXT: eor r2, r2, #1
+; CHECK-ARM-NEXT: rsb r2, r2, #0
+; CHECK-ARM-NEXT: eor r0, r0, r2
+; CHECK-ARM-NEXT: eor r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, lr}
+; CHECK-THUMB-NEXT: push {r4, lr}
+; CHECK-THUMB-NEXT: movs r4, #0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: adcs r4, r4
+; CHECK-THUMB-NEXT: movs r2, #1
+; CHECK-THUMB-NEXT: eors r2, r4
+; CHECK-THUMB-NEXT: rsbs r2, r2, #0
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: pop {r4, pc}
+ %min = call i64 @llvm.umin.i64(i64 %a, i64 %b)
+ %max = call i64 @llvm.umax.i64(i64 %a, i64 %b)
+ %sub = sub i64 %max, %min
+ ret i64 %sub
+}
+
+define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_minmax_i128:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: mov r6, #0
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbcs r3, r3, r12
+; CHECK-ARM-NEXT: adc r6, r6, #0
+; CHECK-ARM-NEXT: eor r6, r6, #1
+; CHECK-ARM-NEXT: rsb r6, r6, #0
+; CHECK-ARM-NEXT: eor r0, r0, r6
+; CHECK-ARM-NEXT: eor r1, r1, r6
+; CHECK-ARM-NEXT: subs r0, r0, r6
+; CHECK-ARM-NEXT: eor r2, r2, r6
+; CHECK-ARM-NEXT: sbcs r1, r1, r6
+; CHECK-ARM-NEXT: eor r3, r3, r6
+; CHECK-ARM-NEXT: sbcs r2, r2, r6
+; CHECK-ARM-NEXT: sbc r3, r3, r6
+; CHECK-ARM-NEXT: pop {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_minmax_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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: mov r4, r0
+; CHECK-THUMB-NEXT: ldr r0, [sp, #36]
+; CHECK-THUMB-NEXT: str r0, [sp] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r5, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r6, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #24]
+; CHECK-THUMB-NEXT: movs r0, #0
+; CHECK-THUMB-NEXT: subs r4, r4, r7
+; CHECK-THUMB-NEXT: sbcs r1, r6
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: ldr r5, [sp] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: adcs r0, r0
+; CHECK-THUMB-NEXT: movs r5, #1
+; CHECK-THUMB-NEXT: eors r5, r0
+; CHECK-THUMB-NEXT: rsbs r5, r5, #0
+; CHECK-THUMB-NEXT: eors r3, r5
+; CHECK-THUMB-NEXT: eors r2, r5
+; CHECK-THUMB-NEXT: eors r1, r5
+; CHECK-THUMB-NEXT: eors r4, r5
+; CHECK-THUMB-NEXT: subs r0, r4, r5
+; CHECK-THUMB-NEXT: sbcs r1, r5
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %min = call i128 @llvm.umin.i128(i128 %a, i128 %b)
+ %max = call i128 @llvm.umax.i128(i128 %a, i128 %b)
+ %sub = sub i128 %max, %min
+ ret i128 %sub
+}
+
+;
+; select(icmp(a,b),sub(a,b),sub(b,a)) -> abdu(a,b)
+;
+
+define i8 @abd_cmp_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: and r1, r1, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxtb r1, r1
+; CHECK-THUMB-NEXT: uxtb 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp ugt i8 %a, %b
+ %ab = sub i8 %a, %b
+ %ba = sub i8 %b, %a
+ %sel = select i1 %cmp, i8 %ab, i8 %ba
+ ret i8 %sel
+}
+
+define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxth 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp uge i16 %a, %b
+ %ab = sub i16 %a, %b
+ %ba = sub i16 %b, %a
+ %sel = select i1 %cmp, i16 %ab, i16 %ba
+ ret i16 %sel
+}
+
+define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r2, r1, r0
+; CHECK-ARM-NEXT: sublo r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bhs .LBB20_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB20_2:
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp ult i32 %a, %b
+ %ab = sub i32 %a, %b
+ %ba = sub i32 %b, %a
+ %sel = select i1 %cmp, i32 %ba, i32 %ab
+ ret i32 %sel
+}
+
+define i64 @abd_cmp_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: mov r12, #0
+; CHECK-ARM-NEXT: sbcs r1, r1, r3
+; CHECK-ARM-NEXT: adc r2, r12, #0
+; CHECK-ARM-NEXT: eor r2, r2, #1
+; CHECK-ARM-NEXT: rsb r2, r2, #0
+; CHECK-ARM-NEXT: eor r0, r0, r2
+; CHECK-ARM-NEXT: eor r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, lr}
+; CHECK-THUMB-NEXT: push {r4, lr}
+; CHECK-THUMB-NEXT: movs r4, #0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: adcs r4, r4
+; CHECK-THUMB-NEXT: movs r2, #1
+; CHECK-THUMB-NEXT: eors r2, r4
+; CHECK-THUMB-NEXT: rsbs r2, r2, #0
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: pop {r4, pc}
+ %cmp = icmp uge i64 %a, %b
+ %ab = sub i64 %a, %b
+ %ba = sub i64 %b, %a
+ %sel = select i1 %cmp, i64 %ab, i64 %ba
+ ret i64 %sel
+}
+
+define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_cmp_i128:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: mov r6, #0
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbcs r3, r3, r12
+; CHECK-ARM-NEXT: adc r6, r6, #0
+; CHECK-ARM-NEXT: eor r6, r6, #1
+; CHECK-ARM-NEXT: rsb r6, r6, #0
+; CHECK-ARM-NEXT: eor r0, r0, r6
+; CHECK-ARM-NEXT: eor r1, r1, r6
+; CHECK-ARM-NEXT: subs r0, r0, r6
+; CHECK-ARM-NEXT: eor r2, r2, r6
+; CHECK-ARM-NEXT: sbcs r1, r1, r6
+; CHECK-ARM-NEXT: eor r3, r3, r6
+; CHECK-ARM-NEXT: sbcs r2, r2, r6
+; CHECK-ARM-NEXT: sbc r3, r3, r6
+; CHECK-ARM-NEXT: pop {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_cmp_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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: mov r4, r0
+; CHECK-THUMB-NEXT: ldr r0, [sp, #36]
+; CHECK-THUMB-NEXT: str r0, [sp] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r5, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r6, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #24]
+; CHECK-THUMB-NEXT: movs r0, #0
+; CHECK-THUMB-NEXT: subs r4, r4, r7
+; CHECK-THUMB-NEXT: sbcs r1, r6
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: ldr r5, [sp] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: adcs r0, r0
+; CHECK-THUMB-NEXT: movs r5, #1
+; CHECK-THUMB-NEXT: eors r5, r0
+; CHECK-THUMB-NEXT: rsbs r5, r5, #0
+; CHECK-THUMB-NEXT: eors r3, r5
+; CHECK-THUMB-NEXT: eors r2, r5
+; CHECK-THUMB-NEXT: eors r1, r5
+; CHECK-THUMB-NEXT: eors r4, r5
+; CHECK-THUMB-NEXT: subs r0, r4, r5
+; CHECK-THUMB-NEXT: sbcs r1, r5
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %cmp = icmp uge i128 %a, %b
+ %ab = sub i128 %a, %b
+ %ba = sub i128 %b, %a
+ %sel = select i1 %cmp, i128 %ab, i128 %ba
+ ret i128 %sel
+}
+
+;
+; negative tests
+;
+
+define i64 @vector_legalized(i16 %a, i16 %b) {
+; CHECK-ARM-LABEL: vector_legalized:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: mov r1, #0
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: vector_legalized:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxth 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, r0, r1
+; CHECK-THUMB-NEXT: movs r1, #0
+; CHECK-THUMB-NEXT: bx lr
+ %ea = zext i16 %a to i32
+ %eb = zext i16 %b to i32
+ %s = sub i32 %ea, %eb
+ %ab = call i32 @llvm.abs.i32(i32 %s, i1 false)
+ %e = zext i32 %ab to i64
+ %red = call i64 @llvm.vector.reduce.add.v32i64(<32 x i64> zeroinitializer)
+ %z = add i64 %red, %e
+ ret i64 %z
+}
+
+;
+; sub(select(icmp(a,b),a,b),select(icmp(a,b),b,a)) -> abdu(a,b)
+;
+
+define i8 @abd_select_i8(i8 %a, i8 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: and r1, r1, #255
+; CHECK-ARM-NEXT: and r0, r0, #255
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxtb r1, r1
+; CHECK-THUMB-NEXT: uxtb 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp ult i8 %a, %b
+ %ab = select i1 %cmp, i8 %a, i8 %b
+ %ba = select i1 %cmp, i8 %b, i8 %a
+ %sub = sub i8 %ba, %ab
+ ret i8 %sub
+}
+
+define i16 @abd_select_i16(i16 %a, i16 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: mov r2, #255
+; CHECK-ARM-NEXT: orr r2, r2, #65280
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: uxth r1, r1
+; CHECK-THUMB-NEXT: uxth 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp ule i16 %a, %b
+ %ab = select i1 %cmp, i16 %a, i16 %b
+ %ba = select i1 %cmp, i16 %b, i16 %a
+ %sub = sub i16 %ba, %ab
+ ret i16 %sub
+}
+
+define i32 @abd_select_i32(i32 %a, i32 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r2, r1, r0
+; CHECK-ARM-NEXT: sublo r2, r0, r1
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: subs r0, r1, r0
+; CHECK-THUMB-NEXT: bhs .LBB26_2
+; CHECK-THUMB-NEXT: @ %bb.1:
+; CHECK-THUMB-NEXT: subs r0, r2, r1
+; CHECK-THUMB-NEXT: .LBB26_2:
+; CHECK-THUMB-NEXT: bx lr
+ %cmp = icmp ugt i32 %a, %b
+ %ab = select i1 %cmp, i32 %a, i32 %b
+ %ba = select i1 %cmp, i32 %b, i32 %a
+ %sub = sub i32 %ab, %ba
+ ret i32 %sub
+}
+
+define i64 @abd_select_i64(i64 %a, i64 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: mov r12, #0
+; CHECK-ARM-NEXT: sbcs r1, r1, r3
+; CHECK-ARM-NEXT: adc r2, r12, #0
+; CHECK-ARM-NEXT: eor r2, r2, #1
+; CHECK-ARM-NEXT: rsb r2, r2, #0
+; CHECK-ARM-NEXT: eor r0, r0, r2
+; CHECK-ARM-NEXT: eor r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r2
+; CHECK-ARM-NEXT: sbc r1, r1, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, lr}
+; CHECK-THUMB-NEXT: push {r4, lr}
+; CHECK-THUMB-NEXT: movs r4, #0
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r3
+; CHECK-THUMB-NEXT: adcs r4, r4
+; CHECK-THUMB-NEXT: movs r2, #1
+; CHECK-THUMB-NEXT: eors r2, r4
+; CHECK-THUMB-NEXT: rsbs r2, r2, #0
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: pop {r4, pc}
+ %cmp = icmp uge i64 %a, %b
+ %ab = select i1 %cmp, i64 %a, i64 %b
+ %ba = select i1 %cmp, i64 %b, i64 %a
+ %sub = sub i64 %ab, %ba
+ ret i64 %sub
+}
+
+define i128 @abd_select_i128(i128 %a, i128 %b) nounwind {
+; CHECK-ARM-LABEL: abd_select_i128:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: .save {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: push {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: ldr r5, [sp, #16]
+; CHECK-ARM-NEXT: mov r6, #0
+; CHECK-ARM-NEXT: ldr r4, [sp, #20]
+; CHECK-ARM-NEXT: subs r0, r0, r5
+; CHECK-ARM-NEXT: ldr lr, [sp, #24]
+; CHECK-ARM-NEXT: sbcs r1, r1, r4
+; CHECK-ARM-NEXT: ldr r12, [sp, #28]
+; CHECK-ARM-NEXT: sbcs r2, r2, lr
+; CHECK-ARM-NEXT: sbcs r3, r3, r12
+; CHECK-ARM-NEXT: adc r6, r6, #0
+; CHECK-ARM-NEXT: eor r6, r6, #1
+; CHECK-ARM-NEXT: rsb r6, r6, #0
+; CHECK-ARM-NEXT: eor r0, r0, r6
+; CHECK-ARM-NEXT: eor r1, r1, r6
+; CHECK-ARM-NEXT: subs r0, r0, r6
+; CHECK-ARM-NEXT: eor r2, r2, r6
+; CHECK-ARM-NEXT: sbcs r1, r1, r6
+; CHECK-ARM-NEXT: eor r3, r3, r6
+; CHECK-ARM-NEXT: sbcs r2, r2, r6
+; CHECK-ARM-NEXT: sbc r3, r3, r6
+; CHECK-ARM-NEXT: pop {r4, r5, r6, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: abd_select_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 #4
+; CHECK-THUMB-NEXT: sub sp, #4
+; CHECK-THUMB-NEXT: mov r4, r0
+; CHECK-THUMB-NEXT: ldr r0, [sp, #36]
+; CHECK-THUMB-NEXT: str r0, [sp] @ 4-byte Spill
+; CHECK-THUMB-NEXT: ldr r5, [sp, #32]
+; CHECK-THUMB-NEXT: ldr r6, [sp, #28]
+; CHECK-THUMB-NEXT: ldr r7, [sp, #24]
+; CHECK-THUMB-NEXT: movs r0, #0
+; CHECK-THUMB-NEXT: subs r4, r4, r7
+; CHECK-THUMB-NEXT: sbcs r1, r6
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: ldr r5, [sp] @ 4-byte Reload
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: adcs r0, r0
+; CHECK-THUMB-NEXT: movs r5, #1
+; CHECK-THUMB-NEXT: eors r5, r0
+; CHECK-THUMB-NEXT: rsbs r5, r5, #0
+; CHECK-THUMB-NEXT: eors r3, r5
+; CHECK-THUMB-NEXT: eors r2, r5
+; CHECK-THUMB-NEXT: eors r1, r5
+; CHECK-THUMB-NEXT: eors r4, r5
+; CHECK-THUMB-NEXT: subs r0, r4, r5
+; CHECK-THUMB-NEXT: sbcs r1, r5
+; CHECK-THUMB-NEXT: sbcs r2, r5
+; CHECK-THUMB-NEXT: sbcs r3, r5
+; CHECK-THUMB-NEXT: add sp, #4
+; CHECK-THUMB-NEXT: pop {r4, r5, r6, r7, pc}
+ %cmp = icmp ult i128 %a, %b
+ %ab = select i1 %cmp, i128 %a, i128 %b
+ %ba = select i1 %cmp, i128 %b, i128 %a
+ %sub = sub i128 %ba, %ab
+ ret i128 %sub
+}
+
+declare i8 @llvm.abs.i8(i8, i1)
+declare i16 @llvm.abs.i16(i16, i1)
+declare i32 @llvm.abs.i32(i32, i1)
+declare i64 @llvm.abs.i64(i64, i1)
+declare i128 @llvm.abs.i128(i128, i1)
+
+declare i8 @llvm.umax.i8(i8, i8)
+declare i16 @llvm.umax.i16(i16, i16)
+declare i32 @llvm.umax.i32(i32, i32)
+declare i64 @llvm.umax.i64(i64, i64)
+
+declare i8 @llvm.umin.i8(i8, i8)
+declare i16 @llvm.umin.i16(i16, i16)
+declare i32 @llvm.umin.i32(i32, i32)
+declare i64 @llvm.umin.i64(i64, i64)
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/ARM/iabs.ll b/llvm/test/CodeGen/ARM/iabs.ll
index 758fe7507c0b2..eaa47d9274c3f 100644
--- a/llvm/test/CodeGen/ARM/iabs.ll
+++ b/llvm/test/CodeGen/ARM/iabs.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: llc -mtriple=arm-eabi -mattr=+v4t %s -o - | FileCheck %s
+; 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
;; Integer absolute value, should produce something as good as: ARM:
;; movs r0, r0
@@ -7,11 +8,18 @@
;; bx lr
define i32 @test(i32 %a) {
-; CHECK-LABEL: test:
-; CHECK: @ %bb.0:
-; CHECK-NEXT: cmp r0, #0
-; CHECK-NEXT: rsbmi r0, r0, #0
-; CHECK-NEXT: bx lr
+; CHECK-ARM-LABEL: test:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: cmp r0, #0
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: asrs r1, r0, #31
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: bx lr
%tmp1neg = sub i32 0, %a
%b = icmp sgt i32 %a, -1
%abs = select i1 %b, i32 %a, i32 %tmp1neg
@@ -24,11 +32,19 @@ define i32 @test(i32 %a) {
;; rsbmi
;; bx
define i32 @test2(i32 %a, i32 %b) nounwind readnone ssp {
-; CHECK-LABEL: test2:
-; CHECK: @ %bb.0: @ %entry
-; CHECK-NEXT: subs r0, r0, r1
-; CHECK-NEXT: rsbmi r0, r0, #0
-; CHECK-NEXT: bx lr
+; CHECK-ARM-LABEL: test2:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test2:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; 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, r0, r1
+; CHECK-THUMB-NEXT: bx lr
entry:
%sub = sub nsw i32 %a, %b
%cmp = icmp sgt i32 %sub, -1
@@ -38,13 +54,22 @@ entry:
}
define i64 @test3(i64 %a) {
-; CHECK-LABEL: test3:
-; CHECK: @ %bb.0:
-; CHECK-NEXT: eor r0, r0, r1, asr #31
-; CHECK-NEXT: eor r2, r1, r1, asr #31
-; CHECK-NEXT: subs r0, r0, r1, asr #31
-; CHECK-NEXT: sbc r1, r2, r1, asr #31
-; CHECK-NEXT: bx lr
+; CHECK-ARM-LABEL: test3:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: eor r2, r1, r1, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: sbc r1, r2, r1, asr #31
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test3:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: asrs r2, r1, #31
+; CHECK-THUMB-NEXT: eors r1, r2
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: sbcs r1, r2
+; CHECK-THUMB-NEXT: bx lr
%tmp1neg = sub i64 0, %a
%b = icmp sgt i64 %a, -1
%abs = select i1 %b, i64 %a, i64 %tmp1neg
@@ -54,24 +79,43 @@ define i64 @test3(i64 %a) {
declare void @callee(...)
define void @testcallframe(i32 %a) {
-; CHECK-LABEL: testcallframe:
-; CHECK: @ %bb.0: @ %bb
-; CHECK-NEXT: .save {r11, lr}
-; CHECK-NEXT: push {r11, lr}
-; CHECK-NEXT: .pad #8
-; CHECK-NEXT: sub sp, sp, #8
-; CHECK-NEXT: cmp r0, #0
-; CHECK-NEXT: mov r1, #0
-; CHECK-NEXT: rsbmi r0, r0, #0
-; CHECK-NEXT: mov r2, #0
-; CHECK-NEXT: mov r3, #0
-; CHECK-NEXT: str r1, [sp]
-; CHECK-NEXT: bl callee
-; CHECK-NEXT: add sp, sp, #8
-; CHECK-NEXT: pop {r11, lr}
-; CHECK-NEXT: bx lr
+; CHECK-ARM-LABEL: testcallframe:
+; CHECK-ARM: @ %bb.0: @ %bb
+; CHECK-ARM-NEXT: .save {r11, lr}
+; CHECK-ARM-NEXT: push {r11, lr}
+; CHECK-ARM-NEXT: .pad #8
+; CHECK-ARM-NEXT: sub sp, sp, #8
+; CHECK-ARM-NEXT: cmp r0, #0
+; CHECK-ARM-NEXT: mov r1, #0
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: mov r2, #0
+; CHECK-ARM-NEXT: mov r3, #0
+; CHECK-ARM-NEXT: str r1, [sp]
+; CHECK-ARM-NEXT: bl callee
+; CHECK-ARM-NEXT: add sp, sp, #8
+; CHECK-ARM-NEXT: pop {r11, lr}
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: testcallframe:
+; CHECK-THUMB: @ %bb.0: @ %bb
+; CHECK-THUMB-NEXT: .save {r7, lr}
+; CHECK-THUMB-NEXT: push {r7, lr}
+; CHECK-THUMB-NEXT: .pad #8
+; CHECK-THUMB-NEXT: sub sp, #8
+; CHECK-THUMB-NEXT: movs r1, #0
+; CHECK-THUMB-NEXT: str r1, [sp]
+; CHECK-THUMB-NEXT: asrs r2, r0, #31
+; CHECK-THUMB-NEXT: eors r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: mov r2, r1
+; CHECK-THUMB-NEXT: mov r3, r1
+; CHECK-THUMB-NEXT: bl callee
+; CHECK-THUMB-NEXT: add sp, #8
+; CHECK-THUMB-NEXT: pop {r7, pc}
bb:
%i = tail call i32 @llvm.abs.i32(i32 %a, i1 false)
tail call void @callee(i32 %i, i32 0, i32 0, i32 0, i32 0)
ret void
}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
>From 92b9ceab584bb0af689c61f3f11d3d40c69a41e5 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sun, 22 Feb 2026 15:02:57 -0500
Subject: [PATCH 2/3] [ARM] Custom lower abdu and abds
We can manually lower them to a cmov of the negation if the subs results in a carry or overflow, depending on if it is signed or unsigned. For Thumb, we can use the negate if carry idiom using sbc directly for abdu.
---
llvm/lib/Target/ARM/ARMISelLowering.cpp | 91 +++++++++++-
llvm/lib/Target/ARM/ARMISelLowering.h | 1 +
llvm/test/CodeGen/ARM/abds-neg.ll | 90 +++++-------
llvm/test/CodeGen/ARM/abds.ll | 64 ++++-----
llvm/test/CodeGen/ARM/abdu-neg.ll | 181 ++++++++----------------
llvm/test/CodeGen/ARM/abdu.ll | 109 ++++++--------
llvm/test/CodeGen/ARM/iabs.ll | 2 +-
7 files changed, 264 insertions(+), 274 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index a086589705bb5..e0887c210c7be 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -597,8 +597,12 @@ 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);
+ setOperationAction(ISD::ABDS, MVT::i32, Custom);
+ }
+
+ setOperationAction(ISD::ABDU, MVT::i32, Custom);
setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
@@ -5279,6 +5283,88 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
return Result;
}
+SDValue ARMTargetLowering::LowerABD(SDValue Op, SelectionDAG &DAG) const {
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ SDLoc DL(Op);
+ EVT VT = Op.getValueType();
+
+ bool IsSigned = Op.getOpcode() == ISD::ABDS;
+ bool IsNonNegative = DAG.SignBitIsZero(LHS) && DAG.SignBitIsZero(RHS);
+
+ // If the subtract doesn't overflow then just use abs(sub()).
+ if (DAG.willNotOverflowSub(IsSigned || IsNonNegative, LHS, RHS))
+ return DAG.getNode(ISD::ABS, DL, VT,
+ DAG.getNode(ISD::SUB, DL, VT, LHS, RHS));
+
+ if (DAG.willNotOverflowSub(IsSigned || 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)) {
+ bool CanUseAdd = false;
+ if (IsSigned) {
+ if (RHS->getFlags().hasNoSignedWrap() || !DAG.computeKnownBits(SubRHS)
+ .getSignedMinValue()
+ .isMinSignedValue())
+ CanUseAdd = true;
+ } else {
+ if (DAG.isKnownNeverZero(SubRHS))
+ CanUseAdd = true;
+ }
+
+ if (CanUseAdd) {
+ Opcode = ARMISD::ADDC;
+ RHS = SubRHS;
+ }
+ }
+ }
+
+ SDValue SubWithFlags =
+ DAG.getNode(Opcode, DL, DAG.getVTList(VT, FlagsVT), LHS, RHS);
+
+ if (Subtarget->isThumb1Only() && !IsSigned) {
+ // 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));
+ }
+
+ SDValue SubResult = SubWithFlags.getValue(0);
+ SDValue Flags = SubWithFlags.getValue(1);
+
+ SDValue Neg = DAG.getNegative(SubResult, DL, VT);
+
+ // getCMOV(FalseVal, TrueVal, CC, Flags) selects TrueVal when CC holds,
+ // FalseVal otherwise. We want a >= b -> SubResult (a-b), a < b -> Neg (b-a),
+ // so use LT/LO (a < b) with (SubResult, Neg): when LT/LO holds we get Neg,
+ // otherwise SubResult.
+ ARMCC::CondCodes CC = IsSigned ? ARMCC::LT : ARMCC::LO;
+ SDValue ARMcc = DAG.getConstant(CC, DL, MVT::i32);
+
+ return getCMOV(DL, VT, SubResult, Neg, ARMcc, Flags, DAG);
+}
+
/// 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,
@@ -10397,6 +10483,9 @@ 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::ABDS:
+ case ISD::ABDU:
+ return LowerABD(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 e58d872c548e4..4e04e809497a9 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -570,6 +570,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 LowerABD(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
index 99caa1260afe3..b213409fc372e 100644
--- a/llvm/test/CodeGen/ARM/abds-neg.ll
+++ b/llvm/test/CodeGen/ARM/abds-neg.ll
@@ -13,8 +13,8 @@ define i8 @abd_ext_i8(i8 %a, i8 %b) nounwind {
; 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: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: cmp r0, #0
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i8:
@@ -42,8 +42,8 @@ define i8 @abd_ext_i8_i16(i8 %a, i16 %b) nounwind {
; 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: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; 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:
@@ -71,8 +71,8 @@ define i8 @abd_ext_i8_undef(i8 %a, i8 %b) nounwind {
; 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: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; 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:
@@ -100,8 +100,8 @@ define i16 @abd_ext_i16(i16 %a, i16 %b) nounwind {
; 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: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: cmp r0, #0
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i16:
@@ -126,10 +126,8 @@ 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: rsbs r0, r1, r0, asr #16
+; CHECK-ARM-NEXT: rsbge r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i16_i32:
@@ -158,8 +156,8 @@ define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
; 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: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; 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:
@@ -183,9 +181,8 @@ define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
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: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbge r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32:
@@ -210,10 +207,8 @@ 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: subs r0, r0, r1, asr #16
+; CHECK-ARM-NEXT: rsbge r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32_i16:
@@ -238,9 +233,8 @@ define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
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: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbge r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32_undef:
@@ -552,15 +546,12 @@ define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind {
define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
; CHECK-ARM-LABEL: abd_minmax_i8:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: lsl r1, r1, #24
; CHECK-ARM-NEXT: lsl r0, r0, #24
-; CHECK-ARM-NEXT: asr r2, r1, #24
-; CHECK-ARM-NEXT: asr r3, r0, #24
-; CHECK-ARM-NEXT: cmp r3, r1, asr #24
-; CHECK-ARM-NEXT: mov r1, r2
-; CHECK-ARM-NEXT: asrgt r1, r0, #24
-; CHECK-ARM-NEXT: asrlt r2, r0, #24
-; CHECK-ARM-NEXT: sub r0, r2, r1
+; 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_minmax_i8:
@@ -591,15 +582,12 @@ define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
; CHECK-ARM-LABEL: abd_minmax_i16:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: lsl r1, r1, #16
; CHECK-ARM-NEXT: lsl r0, r0, #16
-; CHECK-ARM-NEXT: asr r2, r1, #16
-; CHECK-ARM-NEXT: asr r3, r0, #16
-; CHECK-ARM-NEXT: cmp r3, r1, asr #16
-; CHECK-ARM-NEXT: mov r1, r2
-; CHECK-ARM-NEXT: asrgt r1, r0, #16
-; CHECK-ARM-NEXT: asrlt r2, r0, #16
-; CHECK-ARM-NEXT: sub r0, r2, r1
+; 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_minmax_i16:
@@ -630,11 +618,8 @@ define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_minmax_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: cmp r0, r1
-; CHECK-ARM-NEXT: mov r2, r1
-; CHECK-ARM-NEXT: movgt r2, r0
-; CHECK-ARM-NEXT: movlt r1, r0
-; CHECK-ARM-NEXT: sub r0, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbge r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_minmax_i32:
@@ -911,9 +896,8 @@ define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_cmp_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: subs r2, r0, r1
-; CHECK-ARM-NEXT: subge r2, r1, r0
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbge r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_cmp_i32:
@@ -1157,9 +1141,8 @@ define i16 @abd_subnsw_i16_undef(i16 %a, i16 %b) nounwind {
define i32 @abd_subnsw_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: sub r0, r0, r1
-; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbge r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i32:
@@ -1178,9 +1161,8 @@ define i32 @abd_subnsw_i32(i32 %a, i32 %b) nounwind {
define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i32_undef:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: sub r0, r0, r1
-; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbge r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i32_undef:
diff --git a/llvm/test/CodeGen/ARM/abds.ll b/llvm/test/CodeGen/ARM/abds.ll
index 9ebd60ed05f03..9f225ff0fee35 100644
--- a/llvm/test/CodeGen/ARM/abds.ll
+++ b/llvm/test/CodeGen/ARM/abds.ll
@@ -121,10 +121,9 @@ define i16 @abd_ext_i16(i16 %a, i16 %b) nounwind {
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 r2, r0, #16
-; CHECK-ARM-NEXT: sub r0, r1, r2, asr #16
-; CHECK-ARM-NEXT: cmp r1, r2, asr #16
-; CHECK-ARM-NEXT: rsblt r0, r1, r2, asr #16
+; CHECK-ARM-NEXT: lsl r0, r0, #16
+; CHECK-ARM-NEXT: rsbs r0, r1, r0, asr #16
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i16_i32:
@@ -175,9 +174,8 @@ define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
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: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32:
@@ -200,11 +198,9 @@ define i32 @abd_ext_i32(i32 %a, i32 %b) nounwind {
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 r2, r1, #16
-; CHECK-ARM-NEXT: rsb r1, r0, r2, asr #16
-; CHECK-ARM-NEXT: cmp r0, r2, asr #16
-; CHECK-ARM-NEXT: subgt r1, r0, r2, asr #16
-; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: lsl r1, r1, #16
+; CHECK-ARM-NEXT: subs r0, r0, r1, asr #16
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32_i16:
@@ -228,9 +224,8 @@ define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
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: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32_undef:
@@ -579,9 +574,8 @@ define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_minmax_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: subs r2, r1, r0
-; CHECK-ARM-NEXT: sublt r2, r0, r1
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_minmax_i32:
@@ -791,9 +785,8 @@ define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_cmp_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: subs r2, r1, r0
-; CHECK-ARM-NEXT: sublt r2, r0, r1
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_cmp_i32:
@@ -953,9 +946,10 @@ define i8 @abd_subnsw_i8(i8 %a, i8 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i8:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: mov r2, #0
; CHECK-ARM-NEXT: lsl r1, r0, #24
-; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
-; CHECK-ARM-NEXT: sub r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: asrs r0, r1, #24
+; CHECK-ARM-NEXT: submi r0, r2, r1, asr #24
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i8:
@@ -975,9 +969,10 @@ define i8 @abd_subnsw_i8_undef(i8 %a, i8 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i8_undef:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: mov r2, #0
; CHECK-ARM-NEXT: lsl r1, r0, #24
-; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
-; CHECK-ARM-NEXT: sub r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: asrs r0, r1, #24
+; CHECK-ARM-NEXT: submi r0, r2, r1, asr #24
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i8_undef:
@@ -997,9 +992,10 @@ define i16 @abd_subnsw_i16(i16 %a, i16 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i16:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: mov r2, #0
; CHECK-ARM-NEXT: lsl r1, r0, #16
-; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
-; CHECK-ARM-NEXT: sub r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: asrs r0, r1, #16
+; CHECK-ARM-NEXT: submi r0, r2, r1, asr #16
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i16:
@@ -1019,9 +1015,10 @@ define i16 @abd_subnsw_i16_undef(i16 %a, i16 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i16_undef:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: sub r0, r0, r1
+; CHECK-ARM-NEXT: mov r2, #0
; CHECK-ARM-NEXT: lsl r1, r0, #16
-; CHECK-ARM-NEXT: eor r0, r0, r1, asr #31
-; CHECK-ARM-NEXT: sub r0, r0, r1, asr #31
+; CHECK-ARM-NEXT: asrs r0, r1, #16
+; CHECK-ARM-NEXT: submi r0, r2, r1, asr #16
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i16_undef:
@@ -1041,7 +1038,7 @@ define i32 @abd_subnsw_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: subs r0, r0, r1
-; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i32:
@@ -1060,7 +1057,7 @@ define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i32_undef:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: subs r0, r0, r1
-; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i32_undef:
@@ -1351,9 +1348,8 @@ define i16 @abd_select_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_select_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_select_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: subs r2, r1, r0
-; CHECK-ARM-NEXT: sublt r2, r0, r1
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_select_i32:
diff --git a/llvm/test/CodeGen/ARM/abdu-neg.ll b/llvm/test/CodeGen/ARM/abdu-neg.ll
index 571cba39e7f76..452193475bcc2 100644
--- a/llvm/test/CodeGen/ARM/abdu-neg.ll
+++ b/llvm/test/CodeGen/ARM/abdu-neg.ll
@@ -11,9 +11,8 @@ define i8 @abd_ext_i8(i8 %a, i8 %b) nounwind {
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: and r1, r1, #255
; CHECK-ARM-NEXT: and r0, r0, #255
-; CHECK-ARM-NEXT: sub r0, r0, r1
-; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i8:
@@ -41,9 +40,8 @@ define i8 @abd_ext_i8_i16(i8 %a, i16 %b) nounwind {
; CHECK-ARM-NEXT: and r0, r0, #255
; CHECK-ARM-NEXT: orr r2, r2, #65280
; CHECK-ARM-NEXT: and r1, r1, r2
-; CHECK-ARM-NEXT: sub r0, r0, r1
-; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i8_i16:
@@ -69,9 +67,8 @@ define i8 @abd_ext_i8_undef(i8 %a, i8 %b) nounwind {
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: and r1, r1, #255
; CHECK-ARM-NEXT: and r0, r0, #255
-; CHECK-ARM-NEXT: sub r0, r0, r1
-; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i8_undef:
@@ -99,9 +96,8 @@ define i16 @abd_ext_i16(i16 %a, i16 %b) nounwind {
; CHECK-ARM-NEXT: orr r2, r2, #65280
; CHECK-ARM-NEXT: and r1, r1, r2
; CHECK-ARM-NEXT: and r0, r0, r2
-; CHECK-ARM-NEXT: sub r0, r0, r1
-; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i16:
@@ -128,20 +124,17 @@ define i16 @abd_ext_i16_i32(i16 %a, i32 %b) nounwind {
; CHECK-ARM-NEXT: mov r2, #255
; CHECK-ARM-NEXT: orr r2, r2, #65280
; CHECK-ARM-NEXT: and r0, r0, r2
-; CHECK-ARM-NEXT: subs r2, r1, r0
-; CHECK-ARM-NEXT: sublo r2, r0, r1
-; CHECK-ARM-NEXT: rsb r0, r2, #0
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbhs r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i16_i32:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: uxth r2, r0
-; CHECK-THUMB-NEXT: subs r0, r1, r2
-; CHECK-THUMB-NEXT: bhs .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: uxth r0, r0
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
; CHECK-THUMB-NEXT: bx lr
%aext = zext i16 %a to i64
%bext = zext i32 %b to i64
@@ -159,9 +152,8 @@ define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
; CHECK-ARM-NEXT: orr r2, r2, #65280
; CHECK-ARM-NEXT: and r1, r1, r2
; CHECK-ARM-NEXT: and r0, r0, r2
-; CHECK-ARM-NEXT: sub r0, r0, r1
-; CHECK-ARM-NEXT: eor r1, r0, r0, asr #31
-; CHECK-ARM-NEXT: rsb r0, r1, r0, asr #31
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i16_undef:
@@ -185,19 +177,16 @@ define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
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: sublo r2, r0, r1
-; CHECK-ARM-NEXT: rsb r0, r2, #0
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbhs r0, r0, #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: bhs .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: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
; CHECK-THUMB-NEXT: bx lr
%aext = zext i32 %a to i64
%bext = zext i32 %b to i64
@@ -214,20 +203,17 @@ define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
; CHECK-ARM-NEXT: mov r2, #255
; CHECK-ARM-NEXT: orr r2, r2, #65280
; CHECK-ARM-NEXT: and r1, r1, r2
-; CHECK-ARM-NEXT: subs r2, r1, r0
-; CHECK-ARM-NEXT: sublo r2, r0, r1
-; CHECK-ARM-NEXT: rsb r0, r2, #0
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbhs r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32_i16:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: uxth r2, r1
-; CHECK-THUMB-NEXT: subs r1, r2, r0
-; CHECK-THUMB-NEXT: bhs .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: uxth r1, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
; CHECK-THUMB-NEXT: bx lr
%aext = zext i32 %a to i64
%bext = zext i16 %b to i64
@@ -241,19 +227,16 @@ define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
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: sublo r2, r0, r1
-; CHECK-ARM-NEXT: rsb r0, r2, #0
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbhs r0, r0, #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: bhs .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: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
; CHECK-THUMB-NEXT: bx lr
%aext = zext i32 %a to i64
%bext = zext i32 %b to i64
@@ -529,33 +512,20 @@ define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind {
define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind {
; CHECK-ARM-LABEL: abd_minmax_i8:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: and r1, r1, #255
; CHECK-ARM-NEXT: and r0, r0, #255
-; CHECK-ARM-NEXT: cmp r0, r1
-; CHECK-ARM-NEXT: mov r2, r1
-; CHECK-ARM-NEXT: movlo r1, r0
-; CHECK-ARM-NEXT: movhi r2, r0
-; CHECK-ARM-NEXT: sub r0, r1, r2
+; CHECK-ARM-NEXT: and r1, r1, #255
+; CHECK-ARM-NEXT: subs r0, r1, r0
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_minmax_i8:
; CHECK-THUMB: @ %bb.0:
; CHECK-THUMB-NEXT: uxtb r1, r1
; CHECK-THUMB-NEXT: uxtb r0, r0
-; CHECK-THUMB-NEXT: cmp r0, r1
-; CHECK-THUMB-NEXT: mov r2, r0
-; CHECK-THUMB-NEXT: bls .LBB13_3
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: bhs .LBB13_4
-; CHECK-THUMB-NEXT: .LBB13_2:
-; CHECK-THUMB-NEXT: subs r0, r0, r2
-; CHECK-THUMB-NEXT: bx lr
-; CHECK-THUMB-NEXT: .LBB13_3:
-; CHECK-THUMB-NEXT: mov r2, r1
-; CHECK-THUMB-NEXT: blo .LBB13_2
-; CHECK-THUMB-NEXT: .LBB13_4:
-; CHECK-THUMB-NEXT: mov r0, r1
-; CHECK-THUMB-NEXT: subs r0, r0, r2
+; 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
%min = call i8 @llvm.umin.i8(i8 %a, i8 %b)
%max = call i8 @llvm.umax.i8(i8 %a, i8 %b)
@@ -568,33 +538,20 @@ define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: mov r2, #255
; CHECK-ARM-NEXT: orr r2, r2, #65280
-; CHECK-ARM-NEXT: and r1, r1, r2
; CHECK-ARM-NEXT: and r0, r0, r2
-; CHECK-ARM-NEXT: cmp r0, r1
-; CHECK-ARM-NEXT: mov r2, r1
-; CHECK-ARM-NEXT: movlo r1, r0
-; CHECK-ARM-NEXT: movhi r2, r0
-; CHECK-ARM-NEXT: sub r0, r1, r2
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r1, r0
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_minmax_i16:
; CHECK-THUMB: @ %bb.0:
; CHECK-THUMB-NEXT: uxth r1, r1
; CHECK-THUMB-NEXT: uxth r0, r0
-; CHECK-THUMB-NEXT: cmp r0, r1
-; CHECK-THUMB-NEXT: mov r2, r0
-; CHECK-THUMB-NEXT: bls .LBB14_3
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: bhs .LBB14_4
-; CHECK-THUMB-NEXT: .LBB14_2:
-; CHECK-THUMB-NEXT: subs r0, r0, r2
-; CHECK-THUMB-NEXT: bx lr
-; CHECK-THUMB-NEXT: .LBB14_3:
-; CHECK-THUMB-NEXT: mov r2, r1
-; CHECK-THUMB-NEXT: blo .LBB14_2
-; CHECK-THUMB-NEXT: .LBB14_4:
-; CHECK-THUMB-NEXT: mov r0, r1
-; CHECK-THUMB-NEXT: subs r0, r0, r2
+; 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
%min = call i16 @llvm.umin.i16(i16 %a, i16 %b)
%max = call i16 @llvm.umax.i16(i16 %a, i16 %b)
@@ -605,29 +562,16 @@ define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_minmax_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: cmp r0, r1
-; CHECK-ARM-NEXT: mov r2, r1
-; CHECK-ARM-NEXT: movhi r2, r0
-; CHECK-ARM-NEXT: movlo r1, r0
-; CHECK-ARM-NEXT: sub r0, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbhs r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_minmax_i32:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: cmp r0, r1
-; CHECK-THUMB-NEXT: mov r2, r0
-; CHECK-THUMB-NEXT: bls .LBB15_3
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: bhs .LBB15_4
-; CHECK-THUMB-NEXT: .LBB15_2:
-; CHECK-THUMB-NEXT: subs r0, r0, r2
-; CHECK-THUMB-NEXT: bx lr
-; CHECK-THUMB-NEXT: .LBB15_3:
-; CHECK-THUMB-NEXT: mov r2, r1
-; CHECK-THUMB-NEXT: blo .LBB15_2
-; CHECK-THUMB-NEXT: .LBB15_4:
-; CHECK-THUMB-NEXT: mov r0, r1
-; CHECK-THUMB-NEXT: subs r0, r0, r2
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
; CHECK-THUMB-NEXT: bx lr
%min = call i32 @llvm.umin.i32(i32 %a, i32 %b)
%max = call i32 @llvm.umax.i32(i32 %a, i32 %b)
@@ -889,19 +833,16 @@ define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_cmp_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: subs r2, r0, r1
-; CHECK-ARM-NEXT: subhs r2, r1, r0
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsbhs r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_cmp_i32:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: mov r2, r0
; CHECK-THUMB-NEXT: subs r0, r0, r1
-; CHECK-THUMB-NEXT: blo .LBB20_2
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: subs r0, r1, r2
-; CHECK-THUMB-NEXT: .LBB20_2:
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r1, r0
; CHECK-THUMB-NEXT: bx lr
%cmp = icmp uge i32 %a, %b
%ab = sub i32 %a, %b
diff --git a/llvm/test/CodeGen/ARM/abdu.ll b/llvm/test/CodeGen/ARM/abdu.ll
index e8fdbe7487fc7..6b727ca5017f7 100644
--- a/llvm/test/CodeGen/ARM/abdu.ll
+++ b/llvm/test/CodeGen/ARM/abdu.ll
@@ -119,19 +119,18 @@ define i16 @abd_ext_i16_i32(i16 %a, i32 %b) nounwind {
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: mov r2, #255
; CHECK-ARM-NEXT: orr r2, r2, #65280
-; CHECK-ARM-NEXT: and r2, r0, r2
-; CHECK-ARM-NEXT: subs r0, r1, r2
-; CHECK-ARM-NEXT: sublo r0, r2, r1
+; CHECK-ARM-NEXT: and r0, r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblo r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i16_i32:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: uxth r2, r0
-; CHECK-THUMB-NEXT: subs r0, r1, r2
-; CHECK-THUMB-NEXT: bhs .LBB4_2
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: subs r0, r2, r1
-; CHECK-THUMB-NEXT: .LBB4_2:
+; CHECK-THUMB-NEXT: uxth r0, r0
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
; CHECK-THUMB-NEXT: bx lr
%aext = zext i16 %a to i64
%bext = zext i32 %b to i64
@@ -172,19 +171,16 @@ define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind {
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: sublo r2, r0, r1
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblo r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: mov r2, r0
-; CHECK-THUMB-NEXT: subs r0, r1, r0
-; CHECK-THUMB-NEXT: bhs .LBB6_2
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: subs r0, r2, r1
-; CHECK-THUMB-NEXT: .LBB6_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
; CHECK-THUMB-NEXT: bx lr
%aext = zext i32 %a to i64
%bext = zext i32 %b to i64
@@ -199,21 +195,18 @@ define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: mov r2, #255
; CHECK-ARM-NEXT: orr r2, r2, #65280
-; CHECK-ARM-NEXT: and r2, r1, r2
-; CHECK-ARM-NEXT: subs r1, r2, r0
-; CHECK-ARM-NEXT: sublo r1, r0, r2
-; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: and r1, r1, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblo r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32_i16:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: mov r2, r0
; CHECK-THUMB-NEXT: uxth r1, r1
-; CHECK-THUMB-NEXT: subs r0, r1, r0
-; CHECK-THUMB-NEXT: bhs .LBB7_2
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: subs r0, r2, r1
-; CHECK-THUMB-NEXT: .LBB7_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
; CHECK-THUMB-NEXT: bx lr
%aext = zext i32 %a to i64
%bext = zext i16 %b to i64
@@ -226,19 +219,16 @@ define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind {
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: sublo r2, r0, r1
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblo r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_ext_i32_undef:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: mov r2, r0
-; CHECK-THUMB-NEXT: subs r0, r1, r0
-; CHECK-THUMB-NEXT: bhs .LBB8_2
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: subs r0, r2, r1
-; CHECK-THUMB-NEXT: .LBB8_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
; CHECK-THUMB-NEXT: bx lr
%aext = zext i32 %a to i64
%bext = zext i32 %b to i64
@@ -519,19 +509,16 @@ define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_minmax_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: subs r2, r1, r0
-; CHECK-ARM-NEXT: sublo r2, r0, r1
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblo r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_minmax_i32:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: mov r2, r0
-; CHECK-THUMB-NEXT: subs r0, r1, r0
-; CHECK-THUMB-NEXT: bhs .LBB15_2
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: subs r0, r2, r1
-; CHECK-THUMB-NEXT: .LBB15_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
; CHECK-THUMB-NEXT: bx lr
%min = call i32 @llvm.umin.i32(i32 %a, i32 %b)
%max = call i32 @llvm.umax.i32(i32 %a, i32 %b)
@@ -701,19 +688,16 @@ define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_cmp_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: subs r2, r1, r0
-; CHECK-ARM-NEXT: sublo r2, r0, r1
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblo r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_cmp_i32:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: mov r2, r0
-; CHECK-THUMB-NEXT: subs r0, r1, r0
-; CHECK-THUMB-NEXT: bhs .LBB20_2
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: subs r0, r2, r1
-; CHECK-THUMB-NEXT: .LBB20_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
; CHECK-THUMB-NEXT: bx lr
%cmp = icmp ult i32 %a, %b
%ab = sub i32 %a, %b
@@ -922,19 +906,16 @@ define i16 @abd_select_i16(i16 %a, i16 %b) nounwind {
define i32 @abd_select_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_select_i32:
; CHECK-ARM: @ %bb.0:
-; CHECK-ARM-NEXT: subs r2, r1, r0
-; CHECK-ARM-NEXT: sublo r2, r0, r1
-; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: subs r0, r0, r1
+; CHECK-ARM-NEXT: rsblo r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_select_i32:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: mov r2, r0
-; CHECK-THUMB-NEXT: subs r0, r1, r0
-; CHECK-THUMB-NEXT: bhs .LBB26_2
-; CHECK-THUMB-NEXT: @ %bb.1:
-; CHECK-THUMB-NEXT: subs r0, r2, r1
-; CHECK-THUMB-NEXT: .LBB26_2:
+; CHECK-THUMB-NEXT: subs r0, r0, r1
+; CHECK-THUMB-NEXT: sbcs r1, r1
+; CHECK-THUMB-NEXT: eors r0, r1
+; CHECK-THUMB-NEXT: subs r0, r0, r1
; CHECK-THUMB-NEXT: bx lr
%cmp = icmp ugt i32 %a, %b
%ab = select i1 %cmp, i32 %a, i32 %b
diff --git a/llvm/test/CodeGen/ARM/iabs.ll b/llvm/test/CodeGen/ARM/iabs.ll
index eaa47d9274c3f..22a86a1563ee2 100644
--- a/llvm/test/CodeGen/ARM/iabs.ll
+++ b/llvm/test/CodeGen/ARM/iabs.ll
@@ -35,7 +35,7 @@ define i32 @test2(i32 %a, i32 %b) nounwind readnone ssp {
; CHECK-ARM-LABEL: test2:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: subs r0, r0, r1
-; CHECK-ARM-NEXT: rsbmi r0, r0, #0
+; CHECK-ARM-NEXT: rsblt r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test2:
>From a172a2984296343b85acac9bf2f2d26694acd187 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sun, 22 Feb 2026 15:03:05 -0500
Subject: [PATCH 3/3] Revert back to mi
Prefer abs with nsw over abds for scalars.
---
llvm/lib/Target/ARM/ARMISelLowering.h | 4 ++++
llvm/test/CodeGen/ARM/abds-neg.ll | 4 ++--
llvm/test/CodeGen/ARM/abds.ll | 4 ++--
llvm/test/CodeGen/ARM/iabs.ll | 2 +-
4 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index 4e04e809497a9..94f9675608110 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -300,6 +300,10 @@ class VectorType;
bool preferSelectsOverBooleanArithmetic(EVT VT) const override;
+ bool preferABDSToABSWithNSW(EVT VT) const override {
+ return isOperationLegal(ISD::ABDS, VT) && VT.isVector();
+ }
+
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override;
bool hasAndNotCompare(SDValue V) const override {
diff --git a/llvm/test/CodeGen/ARM/abds-neg.ll b/llvm/test/CodeGen/ARM/abds-neg.ll
index b213409fc372e..52f7a99f23269 100644
--- a/llvm/test/CodeGen/ARM/abds-neg.ll
+++ b/llvm/test/CodeGen/ARM/abds-neg.ll
@@ -1142,7 +1142,7 @@ define i32 @abd_subnsw_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: subs r0, r0, r1
-; CHECK-ARM-NEXT: rsbge r0, r0, #0
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i32:
@@ -1162,7 +1162,7 @@ define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i32_undef:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: subs r0, r0, r1
-; CHECK-ARM-NEXT: rsbge r0, r0, #0
+; CHECK-ARM-NEXT: rsbpl r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i32_undef:
diff --git a/llvm/test/CodeGen/ARM/abds.ll b/llvm/test/CodeGen/ARM/abds.ll
index 9f225ff0fee35..85a0d6bf5ce73 100644
--- a/llvm/test/CodeGen/ARM/abds.ll
+++ b/llvm/test/CodeGen/ARM/abds.ll
@@ -1038,7 +1038,7 @@ define i32 @abd_subnsw_i32(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: subs r0, r0, r1
-; CHECK-ARM-NEXT: rsblt r0, r0, #0
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i32:
@@ -1057,7 +1057,7 @@ define i32 @abd_subnsw_i32_undef(i32 %a, i32 %b) nounwind {
; CHECK-ARM-LABEL: abd_subnsw_i32_undef:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: subs r0, r0, r1
-; CHECK-ARM-NEXT: rsblt r0, r0, #0
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: abd_subnsw_i32_undef:
diff --git a/llvm/test/CodeGen/ARM/iabs.ll b/llvm/test/CodeGen/ARM/iabs.ll
index 22a86a1563ee2..eaa47d9274c3f 100644
--- a/llvm/test/CodeGen/ARM/iabs.ll
+++ b/llvm/test/CodeGen/ARM/iabs.ll
@@ -35,7 +35,7 @@ define i32 @test2(i32 %a, i32 %b) nounwind readnone ssp {
; CHECK-ARM-LABEL: test2:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: subs r0, r0, r1
-; CHECK-ARM-NEXT: rsblt r0, r0, #0
+; CHECK-ARM-NEXT: rsbmi r0, r0, #0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test2:
More information about the llvm-commits
mailing list