[llvm] [ARM] Take advantage of built-in mod of shift amount in variable-shift rotations and shifts (PR #157208)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 5 17:57:37 PDT 2025
https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/157208
>From 420dab42506650d5ba8ca714606ba858476b2211 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Fri, 5 Sep 2025 12:03:17 -0400
Subject: [PATCH 1/2] Pre-commit test (NFC)
---
llvm/test/CodeGen/ARM/shift-mod.ll | 1068 ++++++++++++++++++++++++++++
1 file changed, 1068 insertions(+)
create mode 100644 llvm/test/CodeGen/ARM/shift-mod.ll
diff --git a/llvm/test/CodeGen/ARM/shift-mod.ll b/llvm/test/CodeGen/ARM/shift-mod.ll
new file mode 100644
index 0000000000000..3ba591e11acd1
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/shift-mod.ll
@@ -0,0 +1,1068 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=armv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-ARM
+; RUN: llc -mtriple=armv7eb-linux-gnueabihf %s -o - | FileCheck %s --check-prefixes=CHECK-BE
+; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-THUMB
+; RUN: llc -mtriple=thumbv7m %s -o - | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-THUMB
+; RUN: llc -mtriple=thumbv7m -mattr=+strict-align %s -o - | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-ALIGN
+; RUN: llc -mtriple=thumbv6m %s -o - | FileCheck %s --check-prefix=CHECK-V6M
+
+; -----------------------------------------------------------------
+; LSL (shl) group
+; -----------------------------------------------------------------
+
+; (amount = amt + 32) => should remove the ADD and emit LSL directly.
+define i32 @lsl_add_mod(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: lsl_add_mod:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: add r1, r1, #32
+; CHECK-NEXT: lsl r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: lsl_add_mod:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: add r1, r1, #32
+; CHECK-ARM-NEXT: lsl r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: lsl_add_mod:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: add r1, r1, #32
+; CHECK-BE-NEXT: lsl r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: lsl_add_mod:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: adds r1, #32
+; CHECK-THUMB-NEXT: lsls r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: lsl_add_mod:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: adds r1, #32
+; CHECK-ALIGN-NEXT: lsls r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: lsl_add_mod:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: adds r1, #32
+; CHECK-V6M-NEXT: lsls r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = add i32 %amt, 32
+ %r = shl i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = 32 - amt) => should become RSB/NEG then used by LSL.
+define i32 @lsl_sub_rsb(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: lsl_sub_rsb:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: rsb r1, r1, #32
+; CHECK-NEXT: lsl r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: lsl_sub_rsb:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: lsl r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: lsl_sub_rsb:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: lsl r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: lsl_sub_rsb:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: lsls r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: lsl_sub_rsb:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: lsls r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: lsl_sub_rsb:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #32
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: lsls r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 32, %amt
+ %r = shl i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = 31 - amt) => should become MVN(amt) then used by LSL.
+define i32 @lsl_sub_mvn(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: lsl_sub_mvn:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: rsb r1, r1, #31
+; CHECK-NEXT: lsl r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: lsl_sub_mvn:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: lsl r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: lsl_sub_mvn:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: lsl r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: lsl_sub_mvn:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: lsls r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: lsl_sub_mvn:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: lsls r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: lsl_sub_mvn:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: lsls r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 31, %amt
+ %r = shl i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = amt & 31) => AND is redundant; should be removed and emit LSL only.
+define i32 @lsl_and_mask(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: lsl_and_mask:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: and r1, r1, #31
+; CHECK-NEXT: lsl r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: lsl_and_mask:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: and r1, r1, #31
+; CHECK-ARM-NEXT: lsl r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: lsl_and_mask:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: and r1, r1, #31
+; CHECK-BE-NEXT: lsl r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: lsl_and_mask:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: and r1, r1, #31
+; CHECK-THUMB-NEXT: lsls r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: lsl_and_mask:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: and r1, r1, #31
+; CHECK-ALIGN-NEXT: lsls r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: lsl_and_mask:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: ands r2, r1
+; CHECK-V6M-NEXT: lsls r0, r2
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = and i32 %amt, 31
+ %r = shl i32 %val, %sa
+ ret i32 %r
+}
+
+; -----------------------------------------------------------------
+; LSR (logical right) group
+; -----------------------------------------------------------------
+
+; (amount = amt + 32) => should remove the ADD and emit LSR directly.
+define i32 @lsr_add_mod(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: lsr_add_mod:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: add r1, r1, #32
+; CHECK-NEXT: lsr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: lsr_add_mod:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: add r1, r1, #32
+; CHECK-ARM-NEXT: lsr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: lsr_add_mod:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: add r1, r1, #32
+; CHECK-BE-NEXT: lsr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: lsr_add_mod:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: adds r1, #32
+; CHECK-THUMB-NEXT: lsrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: lsr_add_mod:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: adds r1, #32
+; CHECK-ALIGN-NEXT: lsrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: lsr_add_mod:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: adds r1, #32
+; CHECK-V6M-NEXT: lsrs r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = add i32 %amt, 32
+ %r = lshr i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = 32 - amt) => should become RSB/NEG then used by LSR (and in some targets may be lowered to ROR form).
+define i32 @lsr_sub_rsb(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: lsr_sub_rsb:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: rsb r1, r1, #32
+; CHECK-NEXT: lsr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: lsr_sub_rsb:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: lsr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: lsr_sub_rsb:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: lsr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: lsr_sub_rsb:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: lsrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: lsr_sub_rsb:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: lsrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: lsr_sub_rsb:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #32
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: lsrs r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 32, %amt
+ %r = lshr i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = 31 - amt) => should become MVN(amt) then used by LSR.
+define i32 @lsr_sub_mvn(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: lsr_sub_mvn:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: rsb r1, r1, #31
+; CHECK-NEXT: lsr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: lsr_sub_mvn:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: lsr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: lsr_sub_mvn:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: lsr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: lsr_sub_mvn:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: lsrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: lsr_sub_mvn:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: lsrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: lsr_sub_mvn:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: lsrs r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 31, %amt
+ %r = lshr i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = amt & 31) => AND is redundant; should be removed and emit LSR only.
+define i32 @lsr_and_mask(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: lsr_and_mask:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: and r1, r1, #31
+; CHECK-NEXT: lsr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: lsr_and_mask:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: and r1, r1, #31
+; CHECK-ARM-NEXT: lsr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: lsr_and_mask:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: and r1, r1, #31
+; CHECK-BE-NEXT: lsr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: lsr_and_mask:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: and r1, r1, #31
+; CHECK-THUMB-NEXT: lsrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: lsr_and_mask:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: and r1, r1, #31
+; CHECK-ALIGN-NEXT: lsrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: lsr_and_mask:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: ands r2, r1
+; CHECK-V6M-NEXT: lsrs r0, r2
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = and i32 %amt, 31
+ %r = lshr i32 %val, %sa
+ ret i32 %r
+}
+
+; -----------------------------------------------------------------
+; ASR (arithmetic right) group
+; -----------------------------------------------------------------
+
+; (amount = amt + 32) => should remove the ADD and emit ASR directly.
+; CHECK-LABEL: asr_add_mod:
+; CHECK-NOT: add
+; CHECK: asr
+; THUMB-LABEL: asr_add_mod:
+; THUMB-NOT: add
+; THUMB: asr
+define i32 @asr_add_mod(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: asr_add_mod:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: add r1, r1, #32
+; CHECK-NEXT: asr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: asr_add_mod:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: add r1, r1, #32
+; CHECK-ARM-NEXT: asr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: asr_add_mod:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: add r1, r1, #32
+; CHECK-BE-NEXT: asr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: asr_add_mod:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: adds r1, #32
+; CHECK-THUMB-NEXT: asrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: asr_add_mod:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: adds r1, #32
+; CHECK-ALIGN-NEXT: asrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: asr_add_mod:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: adds r1, #32
+; CHECK-V6M-NEXT: asrs r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = add i32 %amt, 32
+ %r = ashr i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = 32 - amt) => should become RSB/NEG then used by ASR.
+; CHECK-LABEL: asr_sub_rsb:
+; CHECK: rsb
+; CHECK: asr
+; THUMB-LABEL: asr_sub_rsb:
+; THUMB: rsb
+; THUMB: asr
+define i32 @asr_sub_rsb(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: asr_sub_rsb:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: rsb r1, r1, #32
+; CHECK-NEXT: asr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: asr_sub_rsb:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: asr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: asr_sub_rsb:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: asr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: asr_sub_rsb:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: asrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: asr_sub_rsb:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: asrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: asr_sub_rsb:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #32
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: asrs r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 32, %amt
+ %r = ashr i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = 31 - amt) => should become MVN(amt) then used by ASR.
+; CHECK-LABEL: asr_sub_mvn:
+; CHECK: mvn
+; CHECK: asr
+; THUMB-LABEL: asr_sub_mvn:
+; THUMB: mvn
+; THUMB: asr
+define i32 @asr_sub_mvn(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: asr_sub_mvn:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: rsb r1, r1, #31
+; CHECK-NEXT: asr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: asr_sub_mvn:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: asr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: asr_sub_mvn:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: asr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: asr_sub_mvn:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: asrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: asr_sub_mvn:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: asrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: asr_sub_mvn:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: asrs r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 31, %amt
+ %r = ashr i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = amt & 31) => AND is redundant; should be removed and emit ASR only.
+; CHECK-LABEL: asr_and_mask:
+; CHECK-NOT: and
+; CHECK: asr
+; THUMB-LABEL: asr_and_mask:
+; THUMB-NOT: and
+; THUMB: asr
+define i32 @asr_and_mask(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: asr_and_mask:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: and r1, r1, #31
+; CHECK-NEXT: asr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: asr_and_mask:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: and r1, r1, #31
+; CHECK-ARM-NEXT: asr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: asr_and_mask:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: and r1, r1, #31
+; CHECK-BE-NEXT: asr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: asr_and_mask:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: and r1, r1, #31
+; CHECK-THUMB-NEXT: asrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: asr_and_mask:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: and r1, r1, #31
+; CHECK-ALIGN-NEXT: asrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: asr_and_mask:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: ands r2, r1
+; CHECK-V6M-NEXT: asrs r0, r2
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = and i32 %amt, 31
+ %r = ashr i32 %val, %sa
+ ret i32 %r
+}
+
+; (amount = amt + 32) => remove ADD and emit ROR/LSR as appropriate (we check for absence of ADD and presence of LSR/ROR)
+define i32 @ror_add_mod(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: ror_add_mod:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: add r1, r1, #32
+; CHECK-NEXT: lsr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: ror_add_mod:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: add r1, r1, #32
+; CHECK-ARM-NEXT: lsr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: ror_add_mod:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: add r1, r1, #32
+; CHECK-BE-NEXT: lsr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: ror_add_mod:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: adds r1, #32
+; CHECK-THUMB-NEXT: lsrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: ror_add_mod:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: adds r1, #32
+; CHECK-ALIGN-NEXT: lsrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: ror_add_mod:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: adds r1, #32
+; CHECK-V6M-NEXT: lsrs r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = add i32 %amt, 32
+ %r = lshr i32 %val, %sa
+ ret i32 %r
+}
+
+define i32 @ror_sub_rsb(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: ror_sub_rsb:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: rsb r1, r1, #32
+; CHECK-NEXT: lsr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: ror_sub_rsb:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: lsr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: ror_sub_rsb:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: lsr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: ror_sub_rsb:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: lsrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: ror_sub_rsb:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: lsrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: ror_sub_rsb:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #32
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: lsrs r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 32, %amt
+ %r = lshr i32 %val, %sa
+ ret i32 %r
+}
+
+define i32 @ror_sub_mvn(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: ror_sub_mvn:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: rsb r1, r1, #31
+; CHECK-NEXT: lsr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: ror_sub_mvn:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: lsr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: ror_sub_mvn:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: lsr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: ror_sub_mvn:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: lsrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: ror_sub_mvn:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: lsrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: ror_sub_mvn:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: lsrs r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 31, %amt
+ %r = lshr i32 %val, %sa
+ ret i32 %r
+}
+
+define i32 @ror_and_mask(i32 %val, i32 %amt) #0 {
+; CHECK-LABEL: ror_and_mask:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: and r1, r1, #31
+; CHECK-NEXT: lsr r0, r0, r1
+; CHECK-NEXT: bx lr
+;
+; CHECK-ARM-LABEL: ror_and_mask:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: and r1, r1, #31
+; CHECK-ARM-NEXT: lsr r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: ror_and_mask:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: and r1, r1, #31
+; CHECK-BE-NEXT: lsr r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: ror_and_mask:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: and r1, r1, #31
+; CHECK-THUMB-NEXT: lsrs r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: ror_and_mask:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: and r1, r1, #31
+; CHECK-ALIGN-NEXT: lsrs r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: ror_and_mask:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: ands r2, r1
+; CHECK-V6M-NEXT: lsrs r0, r2
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = and i32 %amt, 31
+ %r = lshr i32 %val, %sa
+ ret i32 %r
+}
+
+
+declare i32 @llvm.fshl.i32(i32, i32, i32)
+declare i32 @llvm.fshr.i32(i32, i32, i32)
+
+; -----------------------
+; fshl (funnel-shift left) group
+; fshl(x,x, s) == rotate-left(x, s)
+; -----------------------
+
+; amt + 32 -> REMOVE ADD (mod 32), expect rotate lowering (ror/lsl/lsr depending on selector)
+define i32 @fshl_add_mod(i32 %x, i32 %amt) #0 {
+; CHECK-ARM-LABEL: fshl_add_mod:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: mvn r2, #31
+; CHECK-ARM-NEXT: sub r1, r2, r1
+; CHECK-ARM-NEXT: ror r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: fshl_add_mod:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: mvn r2, #31
+; CHECK-BE-NEXT: sub r1, r2, r1
+; CHECK-BE-NEXT: ror r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: fshl_add_mod:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: mvn r2, #31
+; CHECK-THUMB-NEXT: subs r1, r2, r1
+; CHECK-THUMB-NEXT: rors r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: fshl_add_mod:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: mvn r2, #31
+; CHECK-ALIGN-NEXT: subs r1, r2, r1
+; CHECK-ALIGN-NEXT: rors r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: fshl_add_mod:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: mvns r2, r2
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: rors r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = add i32 %amt, 32
+ %r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %sa)
+ ret i32 %r
+}
+
+; 32 - amt -> expect RSB/NEG materialization then rotate lowering
+; CHECK-LABEL: fshl_sub_rsb:
+; CHECK: rsb
+; CHECK: ror
+; THUMB-LABEL: fshl_sub_rsb:
+; THUMB: rsb
+; THUMB: ror
+define i32 @fshl_sub_rsb(i32 %x, i32 %amt) #0 {
+; CHECK-ARM-LABEL: fshl_sub_rsb:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: sub r1, r1, #32
+; CHECK-ARM-NEXT: ror r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: fshl_sub_rsb:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: sub r1, r1, #32
+; CHECK-BE-NEXT: ror r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: fshl_sub_rsb:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: subs r1, #32
+; CHECK-THUMB-NEXT: rors r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: fshl_sub_rsb:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: subs r1, #32
+; CHECK-ALIGN-NEXT: rors r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: fshl_sub_rsb:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: subs r1, #32
+; CHECK-V6M-NEXT: rors r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 32, %amt
+ %r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %sa)
+ ret i32 %r
+}
+
+; 31 - amt -> expect MVN(amt) (i.e. NOT) then rotate lowering (selector may use NOT+rotate form)
+; CHECK-LABEL: fshl_sub_mvn:
+; CHECK: mvn
+; CHECK: ror
+; THUMB-LABEL: fshl_sub_mvn:
+; THUMB: mvn
+; THUMB: ror
+define i32 @fshl_sub_mvn(i32 %x, i32 %amt) #0 {
+; CHECK-ARM-LABEL: fshl_sub_mvn:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: sub r1, r1, #31
+; CHECK-ARM-NEXT: ror r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: fshl_sub_mvn:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: sub r1, r1, #31
+; CHECK-BE-NEXT: ror r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: fshl_sub_mvn:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: subs r1, #31
+; CHECK-THUMB-NEXT: rors r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: fshl_sub_mvn:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: subs r1, #31
+; CHECK-ALIGN-NEXT: rors r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: fshl_sub_mvn:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: subs r1, #31
+; CHECK-V6M-NEXT: rors r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 31, %amt
+ %r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %sa)
+ ret i32 %r
+}
+
+; amt & 31 -> AND redundant (hardware masks low 5 bits) -> expect rotate lowering with no AND
+define i32 @fshl_and_mask(i32 %x, i32 %amt) #0 {
+; CHECK-ARM-LABEL: fshl_and_mask:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #0
+; CHECK-ARM-NEXT: ror r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: fshl_and_mask:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #0
+; CHECK-BE-NEXT: ror r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: fshl_and_mask:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsbs r1, r1, #0
+; CHECK-THUMB-NEXT: rors r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: fshl_and_mask:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsbs r1, r1, #0
+; CHECK-ALIGN-NEXT: rors r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: fshl_and_mask:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: rsbs r1, r1, #0
+; CHECK-V6M-NEXT: rors r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = and i32 %amt, 31
+ %r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %sa)
+ ret i32 %r
+}
+
+; -----------------------
+; fshr (funnel-shift right) group
+; fshr(x,x, s) == rotate-right(x, s)
+; -----------------------
+
+; amt + 32 -> REMOVE ADD (mod 32) -> expect rotate lowering
+define i32 @fshr_add_mod(i32 %x, i32 %amt) #0 {
+; CHECK-ARM-LABEL: fshr_add_mod:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: add r1, r1, #32
+; CHECK-ARM-NEXT: ror r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: fshr_add_mod:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: add r1, r1, #32
+; CHECK-BE-NEXT: ror r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: fshr_add_mod:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: adds r1, #32
+; CHECK-THUMB-NEXT: rors r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: fshr_add_mod:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: adds r1, #32
+; CHECK-ALIGN-NEXT: rors r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: fshr_add_mod:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: adds r1, #32
+; CHECK-V6M-NEXT: rors r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = add i32 %amt, 32
+ %r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %sa)
+ ret i32 %r
+}
+
+; 32 - amt -> expect RSB then rotate lowering
+define i32 @fshr_sub_rsb(i32 %x, i32 %amt) #0 {
+; CHECK-ARM-LABEL: fshr_sub_rsb:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: ror r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: fshr_sub_rsb:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: ror r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: fshr_sub_rsb:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: rors r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: fshr_sub_rsb:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: rors r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: fshr_sub_rsb:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #32
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: rors r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 32, %amt
+ %r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %sa)
+ ret i32 %r
+}
+
+; 31 - amt -> expect MVN then rotate lowering
+define i32 @fshr_sub_mvn(i32 %x, i32 %amt) #0 {
+; CHECK-ARM-LABEL: fshr_sub_mvn:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: ror r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: fshr_sub_mvn:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: ror r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: fshr_sub_mvn:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: rors r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: fshr_sub_mvn:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: rors r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: fshr_sub_mvn:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: movs r2, #31
+; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: rors r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = sub i32 31, %amt
+ %r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %sa)
+ ret i32 %r
+}
+
+; amt & 31 -> AND redundant -> expect rotate lowering with no AND
+define i32 @fshr_and_mask(i32 %x, i32 %amt) #0 {
+; CHECK-ARM-LABEL: fshr_and_mask:
+; CHECK-ARM: @ %bb.0: @ %entry
+; CHECK-ARM-NEXT: ror r0, r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-BE-LABEL: fshr_and_mask:
+; CHECK-BE: @ %bb.0: @ %entry
+; CHECK-BE-NEXT: ror r0, r0, r1
+; CHECK-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: fshr_and_mask:
+; CHECK-THUMB: @ %bb.0: @ %entry
+; CHECK-THUMB-NEXT: rors r0, r1
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-ALIGN-LABEL: fshr_and_mask:
+; CHECK-ALIGN: @ %bb.0: @ %entry
+; CHECK-ALIGN-NEXT: rors r0, r1
+; CHECK-ALIGN-NEXT: bx lr
+;
+; CHECK-V6M-LABEL: fshr_and_mask:
+; CHECK-V6M: @ %bb.0: @ %entry
+; CHECK-V6M-NEXT: rors r0, r1
+; CHECK-V6M-NEXT: bx lr
+entry:
+ %sa = and i32 %amt, 31
+ %r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %sa)
+ ret i32 %r
+}
+
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK-COMMON: {{.*}}
>From ee37cdca903580b6ea6802aeedc9f01f94be87e3 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Fri, 5 Sep 2025 12:19:34 -0400
Subject: [PATCH 2/2] [ARM] Take advantage of built-in mod of shift amount in
variable-shift rotations
---
.../Target/AArch64/AArch64ISelDAGToDAG.cpp | 2 +-
llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp | 156 +++++++++++++++
llvm/test/CodeGen/ARM/funnel-shift-rot.ll | 20 +-
llvm/test/CodeGen/ARM/funnel-shift.ll | 120 ++++++-----
...st-and-by-const-from-lshr-in-eqcmp-zero.ll | 47 ++---
...ist-and-by-const-from-shl-in-eqcmp-zero.ll | 40 +---
llvm/test/CodeGen/ARM/rotate-add.ll | 3 +-
llvm/test/CodeGen/ARM/shift-i64.ll | 2 +-
llvm/test/CodeGen/ARM/shift-mod.ll | 188 ++++++------------
llvm/test/CodeGen/ARM/shifter_operand.ll | 2 -
llvm/test/CodeGen/Thumb2/shift_parts.ll | 59 +++---
llvm/test/CodeGen/Thumb2/thumb2-shifter.ll | 3 -
12 files changed, 336 insertions(+), 306 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 6fdc981fc21a5..28e84fe4ce88b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -527,7 +527,7 @@ char AArch64DAGToDAGISelLegacy::ID = 0;
INITIALIZE_PASS(AArch64DAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
/// isIntImmediate - This method tests to see if the node is a constant
-/// operand. If so Imm will receive the 32-bit value.
+/// operand. If so Imm will receive the 64-bit value.
static bool isIntImmediate(const SDNode *N, uint64_t &Imm) {
if (const ConstantSDNode *C = dyn_cast<const ConstantSDNode>(N)) {
Imm = C->getZExtValue();
diff --git a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 9ad46df159c20..4427a6fed52a7 100644
--- a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -306,6 +306,8 @@ class ARMDAGToDAGISel : public SelectionDAGISel {
bool tryInsertVectorElt(SDNode *N);
+ bool tryShiftAmountMod(SDNode *N);
+
// Select special operations if node forms integer ABS pattern
bool tryABSOp(SDNode *N);
@@ -3158,6 +3160,152 @@ bool ARMDAGToDAGISel::tryInsertVectorElt(SDNode *N) {
return false;
}
+/// tryShiftAmountMod - Take advantage of built-in mod of shift amount in
+/// variable shift/rotate instructions.
+bool ARMDAGToDAGISel::tryShiftAmountMod(SDNode *N) {
+ EVT VT = N->getValueType(0);
+
+ if (VT != MVT::i32)
+ return false;
+
+ unsigned Opc;
+ switch (N->getOpcode()) {
+ case ISD::ROTR:
+ Opc = Subtarget->isThumb()
+ ? (Subtarget->hasThumb2() ? ARM::t2RORrr : ARM::tROR)
+ : ARM::MOVsr;
+ break;
+ case ISD::SHL:
+ Opc = Subtarget->isThumb()
+ ? (Subtarget->hasThumb2() ? ARM::t2LSLrr : ARM::tLSLrr)
+ : ARM::MOVsr;
+ break;
+ case ISD::SRL:
+ Opc = Subtarget->isThumb()
+ ? (Subtarget->hasThumb2() ? ARM::t2LSRrr : ARM::tLSRrr)
+ : ARM::MOVsr;
+ break;
+ case ISD::SRA:
+ Opc = Subtarget->isThumb()
+ ? (Subtarget->hasThumb2() ? ARM::t2ASRrr : ARM::tASRrr)
+ : ARM::MOVsr;
+ break;
+ default:
+ return false;
+ }
+
+ SDValue ShiftAmt = N->getOperand(1);
+ SDLoc DL(N);
+ SDValue NewShiftAmt;
+
+ if (ShiftAmt->getOpcode() == ISD::ADD || ShiftAmt->getOpcode() == ISD::SUB) {
+ SDValue Add0 = ShiftAmt->getOperand(0);
+ SDValue Add1 = ShiftAmt->getOperand(1);
+ unsigned Add0Imm;
+ unsigned Add1Imm;
+
+ if (isInt32Immediate(Add1, Add1Imm) && ((Add1Imm & 31) == 0)) {
+ NewShiftAmt = Add0;
+ } else if (ShiftAmt->getOpcode() == ISD::SUB &&
+ isInt32Immediate(Add0, Add0Imm) && Add0Imm != 0 &&
+ ((Add0Imm & 31) == 0)) {
+
+ unsigned NegOpc =
+ Subtarget->isThumb()
+ ? (Subtarget->hasThumb2() ? ARM::t2RSBri : ARM::tRSB)
+ : ARM::RSBri;
+
+ SDValue ZeroImm = CurDAG->getTargetConstant(0, DL, MVT::i32);
+
+ if (Subtarget->isThumb2()) {
+ SDValue Ops[] = {Add1, ZeroImm, getAL(CurDAG, DL),
+ CurDAG->getRegister(0, MVT::i32),
+ CurDAG->getRegister(0, MVT::i32)};
+ MachineSDNode *Neg = CurDAG->getMachineNode(NegOpc, DL, MVT::i32, Ops);
+ NewShiftAmt = SDValue(Neg, 0);
+ } else if (Subtarget->isThumb1Only()) {
+ SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Add1,
+ getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32)};
+ MachineSDNode *Neg = CurDAG->getMachineNode(NegOpc, DL, MVT::i32, Ops);
+ NewShiftAmt = SDValue(Neg, 0);
+ } else {
+ SDValue Ops[] = {Add1, ZeroImm, getAL(CurDAG, DL),
+ CurDAG->getRegister(0, MVT::i32),
+ CurDAG->getRegister(0, MVT::i32)};
+ MachineSDNode *Neg = CurDAG->getMachineNode(NegOpc, DL, MVT::i32, Ops);
+ NewShiftAmt = SDValue(Neg, 0);
+ }
+ } else if (ShiftAmt->getOpcode() == ISD::SUB &&
+ isInt32Immediate(Add0, Add0Imm) && ((Add0Imm & 31) == 31)) {
+ unsigned NotOpc = Subtarget->isThumb()
+ ? (Subtarget->isThumb2() ? ARM::t2MVNr : ARM::tMVN)
+ : ARM::MVNr;
+
+ if (Subtarget->isThumb2()) {
+ SDValue Ops[] = {Add1, getAL(CurDAG, DL),
+ CurDAG->getRegister(0, MVT::i32),
+ CurDAG->getRegister(0, MVT::i32)};
+ MachineSDNode *Not = CurDAG->getMachineNode(NotOpc, DL, MVT::i32, Ops);
+ NewShiftAmt = SDValue(Not, 0);
+ } else if (Subtarget->isThumb1Only()) {
+ SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Add1,
+ getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32)};
+ MachineSDNode *Not = CurDAG->getMachineNode(NotOpc, DL, MVT::i32, Ops);
+ NewShiftAmt = SDValue(Not, 0);
+ } else {
+ SDValue Ops[] = {Add1, getAL(CurDAG, DL),
+ CurDAG->getRegister(0, MVT::i32),
+ CurDAG->getRegister(0, MVT::i32)};
+ MachineSDNode *Not = CurDAG->getMachineNode(NotOpc, DL, MVT::i32, Ops);
+ NewShiftAmt = SDValue(Not, 0);
+ }
+ } else {
+ return false;
+ }
+ } else {
+ // Check if shift amount is masked with AND covering low 5 bits
+ unsigned MaskImm;
+ if (!isOpcWithIntImmediate(ShiftAmt.getNode(), ISD::AND, MaskImm))
+ return false;
+
+ if ((unsigned)llvm::countr_one(MaskImm) < 5)
+ return false;
+
+ NewShiftAmt = ShiftAmt->getOperand(0);
+ }
+
+ if (Subtarget->isThumb()) {
+ if (Subtarget->isThumb1Only()) {
+ SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
+ N->getOperand(0), NewShiftAmt, getAL(CurDAG, DL),
+ CurDAG->getRegister(0, MVT::i32)};
+ CurDAG->SelectNodeTo(N, Opc, VT, Ops);
+ } else {
+ SDValue Ops[] = {N->getOperand(0), NewShiftAmt, getAL(CurDAG, DL),
+ CurDAG->getRegister(0, MVT::i32),
+ CurDAG->getRegister(0, MVT::i32)};
+ CurDAG->SelectNodeTo(N, Opc, VT, Ops);
+ }
+ } else {
+ ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N->getOpcode());
+ if (ShOpcVal == ARM_AM::no_shift)
+ return false;
+
+ SDValue BaseReg = N->getOperand(0);
+ SDValue ShReg = NewShiftAmt;
+ SDValue OpcEnc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, 0),
+ DL, MVT::i32);
+ SDValue Ops[] = {BaseReg,
+ ShReg,
+ OpcEnc,
+ getAL(CurDAG, DL),
+ CurDAG->getRegister(0, MVT::i32),
+ CurDAG->getRegister(0, MVT::i32)};
+ CurDAG->SelectNodeTo(N, Opc, VT, Ops);
+ }
+ return true;
+}
+
bool ARMDAGToDAGISel::transformFixedFloatingPointConversion(SDNode *N,
SDNode *FMul,
bool IsUnsigned,
@@ -3770,11 +3918,19 @@ void ARMDAGToDAGISel::Select(SDNode *N) {
case ISD::SRL:
if (tryV6T2BitfieldExtractOp(N, false))
return;
+ if (tryShiftAmountMod(N))
+ return;
break;
case ISD::SIGN_EXTEND_INREG:
case ISD::SRA:
if (tryV6T2BitfieldExtractOp(N, true))
return;
+ [[fallthrough]];
+ case ISD::ROTR:
+ case ISD::SHL:
+ if (tryShiftAmountMod(N))
+ return;
+ break;
break;
case ISD::FP_TO_UINT:
case ISD::FP_TO_SINT:
diff --git a/llvm/test/CodeGen/ARM/funnel-shift-rot.ll b/llvm/test/CodeGen/ARM/funnel-shift-rot.ll
index a1b6847d623d0..dd5c5ee4f26c2 100644
--- a/llvm/test/CodeGen/ARM/funnel-shift-rot.ll
+++ b/llvm/test/CodeGen/ARM/funnel-shift-rot.ll
@@ -73,17 +73,16 @@ define i64 @rotl_i64(i64 %x, i64 %z) {
; CHECK-NEXT: push {r4, lr}
; CHECK-NEXT: tst r2, #32
; CHECK-NEXT: mov r3, r0
-; CHECK-NEXT: and r12, r2, #31
; CHECK-NEXT: movne r3, r1
; CHECK-NEXT: movne r1, r0
-; CHECK-NEXT: mov r4, #31
-; CHECK-NEXT: bic r2, r4, r2
-; CHECK-NEXT: lsl lr, r3, r12
-; CHECK-NEXT: lsr r0, r1, #1
-; CHECK-NEXT: lsl r1, r1, r12
-; CHECK-NEXT: lsr r3, r3, #1
-; CHECK-NEXT: orr r0, lr, r0, lsr r2
-; CHECK-NEXT: orr r1, r1, r3, lsr r2
+; CHECK-NEXT: mov r0, #31
+; CHECK-NEXT: bic r4, r0, r2
+; CHECK-NEXT: lsr lr, r1, #1
+; CHECK-NEXT: lsl r12, r3, r2
+; CHECK-NEXT: lsl r1, r1, r2
+; CHECK-NEXT: lsr r2, r3, #1
+; CHECK-NEXT: orr r0, r12, lr, lsr r4
+; CHECK-NEXT: orr r1, r1, r2, lsr r4
; CHECK-NEXT: pop {r4, pc}
%f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %z)
ret i64 %f
@@ -210,9 +209,8 @@ define i64 @rotr_i64(i64 %x, i64 %z) {
; CHECK-NEXT: mov r3, r1
; CHECK-NEXT: moveq r3, r0
; CHECK-NEXT: moveq r0, r1
-; CHECK-NEXT: mov r1, #31
+; CHECK-NEXT: mvn r1, r2
; CHECK-NEXT: lsl r12, r0, #1
-; CHECK-NEXT: bic r1, r1, r2
; CHECK-NEXT: and r2, r2, #31
; CHECK-NEXT: lsl r12, r12, r1
; CHECK-NEXT: orr r12, r12, r3, lsr r2
diff --git a/llvm/test/CodeGen/ARM/funnel-shift.ll b/llvm/test/CodeGen/ARM/funnel-shift.ll
index 191155ae30f3e..f48bf9ef8ef82 100644
--- a/llvm/test/CodeGen/ARM/funnel-shift.ll
+++ b/llvm/test/CodeGen/ARM/funnel-shift.ll
@@ -32,10 +32,9 @@ define i32 @fshl_i32(i32 %x, i32 %y, i32 %z) {
; CHECK-LABEL: fshl_i32:
; CHECK: @ %bb.0:
; CHECK-NEXT: mov r3, #31
-; CHECK-NEXT: lsr r1, r1, #1
-; CHECK-NEXT: bic r3, r3, r2
-; CHECK-NEXT: and r2, r2, #31
; CHECK-NEXT: lsl r0, r0, r2
+; CHECK-NEXT: bic r3, r3, r2
+; CHECK-NEXT: lsr r1, r1, #1
; CHECK-NEXT: orr r0, r0, r1, lsr r3
; CHECK-NEXT: bx lr
%f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %z)
@@ -47,9 +46,9 @@ declare i37 @llvm.fshl.i37(i37, i37, i37)
define i37 @fshl_i37(i37 %x, i37 %y, i37 %z) {
; SCALAR-LABEL: fshl_i37:
; SCALAR: @ %bb.0:
-; SCALAR-NEXT: .save {r4, r5, r6, r7, r8, lr}
-; SCALAR-NEXT: push {r4, r5, r6, r7, r8, lr}
-; SCALAR-NEXT: mov r8, r0
+; SCALAR-NEXT: .save {r4, r5, r6, r7, r11, lr}
+; SCALAR-NEXT: push {r4, r5, r6, r7, r11, lr}
+; SCALAR-NEXT: mov r7, r0
; SCALAR-NEXT: ldr r0, [sp, #28]
; SCALAR-NEXT: mov r4, r1
; SCALAR-NEXT: mov r5, r3
@@ -60,30 +59,29 @@ define i37 @fshl_i37(i37 %x, i37 %y, i37 %z) {
; SCALAR-NEXT: mov r3, #0
; SCALAR-NEXT: bl __aeabi_uldivmod
; SCALAR-NEXT: lsl r0, r5, #27
-; SCALAR-NEXT: tst r2, #32
+; SCALAR-NEXT: mov r5, #31
; SCALAR-NEXT: orr r0, r0, r6, lsr #5
-; SCALAR-NEXT: mov r1, r8
-; SCALAR-NEXT: and r3, r2, #31
-; SCALAR-NEXT: mov r7, #31
+; SCALAR-NEXT: tst r2, #32
+; SCALAR-NEXT: mov r1, r7
+; SCALAR-NEXT: bic r5, r5, r2
; SCALAR-NEXT: movne r1, r0
; SCALAR-NEXT: lslne r0, r6, #27
-; SCALAR-NEXT: bic r2, r7, r2
-; SCALAR-NEXT: lsl r5, r1, r3
+; SCALAR-NEXT: lsl r3, r1, r2
; SCALAR-NEXT: lsr r0, r0, #1
-; SCALAR-NEXT: movne r4, r8
+; SCALAR-NEXT: movne r4, r7
; SCALAR-NEXT: lsr r1, r1, #1
-; SCALAR-NEXT: lsl r3, r4, r3
-; SCALAR-NEXT: orr r0, r5, r0, lsr r2
-; SCALAR-NEXT: orr r1, r3, r1, lsr r2
-; SCALAR-NEXT: pop {r4, r5, r6, r7, r8, pc}
+; SCALAR-NEXT: lsl r2, r4, r2
+; SCALAR-NEXT: orr r0, r3, r0, lsr r5
+; SCALAR-NEXT: orr r1, r2, r1, lsr r5
+; SCALAR-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; NEON-LABEL: fshl_i37:
; NEON: @ %bb.0:
-; NEON-NEXT: .save {r4, r5, r6, r7, r8, lr}
-; NEON-NEXT: push {r4, r5, r6, r7, r8, lr}
+; NEON-NEXT: .save {r4, r5, r6, r7, r11, lr}
+; NEON-NEXT: push {r4, r5, r6, r7, r11, lr}
; NEON-NEXT: mov r4, r1
; NEON-NEXT: ldr r1, [sp, #28]
-; NEON-NEXT: mov r8, r0
+; NEON-NEXT: mov r7, r0
; NEON-NEXT: ldr r0, [sp, #24]
; NEON-NEXT: and r1, r1, #31
; NEON-NEXT: mov r5, r3
@@ -92,22 +90,21 @@ define i37 @fshl_i37(i37 %x, i37 %y, i37 %z) {
; NEON-NEXT: mov r3, #0
; NEON-NEXT: bl __aeabi_uldivmod
; NEON-NEXT: lsl r0, r5, #27
-; NEON-NEXT: tst r2, #32
+; NEON-NEXT: mov r5, #31
; NEON-NEXT: orr r0, r0, r6, lsr #5
-; NEON-NEXT: mov r1, r8
-; NEON-NEXT: and r3, r2, #31
-; NEON-NEXT: mov r7, #31
+; NEON-NEXT: tst r2, #32
+; NEON-NEXT: mov r1, r7
+; NEON-NEXT: bic r5, r5, r2
; NEON-NEXT: movne r1, r0
; NEON-NEXT: lslne r0, r6, #27
-; NEON-NEXT: bic r2, r7, r2
-; NEON-NEXT: lsl r5, r1, r3
+; NEON-NEXT: lsl r3, r1, r2
; NEON-NEXT: lsr r0, r0, #1
-; NEON-NEXT: movne r4, r8
+; NEON-NEXT: movne r4, r7
; NEON-NEXT: lsr r1, r1, #1
-; NEON-NEXT: lsl r3, r4, r3
-; NEON-NEXT: orr r0, r5, r0, lsr r2
-; NEON-NEXT: orr r1, r3, r1, lsr r2
-; NEON-NEXT: pop {r4, r5, r6, r7, r8, pc}
+; NEON-NEXT: lsl r2, r4, r2
+; NEON-NEXT: orr r0, r3, r0, lsr r5
+; NEON-NEXT: orr r1, r2, r1, lsr r5
+; NEON-NEXT: pop {r4, r5, r6, r7, r11, pc}
%f = call i37 @llvm.fshl.i37(i37 %x, i37 %y, i37 %z)
ret i37 %f
}
@@ -219,9 +216,8 @@ define i16 @fshr_i16(i16 %x, i16 %y, i16 %z) {
define i32 @fshr_i32(i32 %x, i32 %y, i32 %z) {
; CHECK-LABEL: fshr_i32:
; CHECK: @ %bb.0:
-; CHECK-NEXT: mov r3, #31
+; CHECK-NEXT: mvn r3, r2
; CHECK-NEXT: lsl r0, r0, #1
-; CHECK-NEXT: bic r3, r3, r2
; CHECK-NEXT: and r2, r2, #31
; CHECK-NEXT: lsl r0, r0, r3
; CHECK-NEXT: orr r0, r0, r1, lsr r2
@@ -237,33 +233,32 @@ define i37 @fshr_i37(i37 %x, i37 %y, i37 %z) {
; SCALAR: @ %bb.0:
; SCALAR-NEXT: .save {r4, r5, r6, r7, r11, lr}
; SCALAR-NEXT: push {r4, r5, r6, r7, r11, lr}
-; SCALAR-NEXT: mov r5, r0
+; SCALAR-NEXT: mov r7, r0
; SCALAR-NEXT: ldr r0, [sp, #28]
; SCALAR-NEXT: mov r4, r1
-; SCALAR-NEXT: mov r6, r3
+; SCALAR-NEXT: mov r5, r3
; SCALAR-NEXT: and r1, r0, #31
; SCALAR-NEXT: ldr r0, [sp, #24]
-; SCALAR-NEXT: mov r7, r2
+; SCALAR-NEXT: mov r6, r2
; SCALAR-NEXT: mov r2, #37
; SCALAR-NEXT: mov r3, #0
; SCALAR-NEXT: bl __aeabi_uldivmod
; SCALAR-NEXT: add r0, r2, #27
-; SCALAR-NEXT: lsl r2, r6, #27
-; SCALAR-NEXT: orr r2, r2, r7, lsr #5
-; SCALAR-NEXT: mov r1, #31
+; SCALAR-NEXT: lsl r2, r5, #27
+; SCALAR-NEXT: orr r2, r2, r6, lsr #5
; SCALAR-NEXT: tst r0, #32
-; SCALAR-NEXT: mov r3, r5
+; SCALAR-NEXT: mov r3, r7
+; SCALAR-NEXT: mvn r1, r0
; SCALAR-NEXT: moveq r3, r2
-; SCALAR-NEXT: lsleq r2, r7, #27
-; SCALAR-NEXT: bic r1, r1, r0
-; SCALAR-NEXT: and r7, r0, #31
-; SCALAR-NEXT: lsl r6, r3, #1
-; SCALAR-NEXT: moveq r4, r5
-; SCALAR-NEXT: lsl r6, r6, r1
-; SCALAR-NEXT: orr r0, r6, r2, lsr r7
+; SCALAR-NEXT: lsleq r2, r6, #27
+; SCALAR-NEXT: and r6, r0, #31
+; SCALAR-NEXT: lsl r5, r3, #1
+; SCALAR-NEXT: moveq r4, r7
+; SCALAR-NEXT: lsl r5, r5, r1
+; SCALAR-NEXT: orr r0, r5, r2, lsr r6
; SCALAR-NEXT: lsl r2, r4, #1
; SCALAR-NEXT: lsl r1, r2, r1
-; SCALAR-NEXT: orr r1, r1, r3, lsr r7
+; SCALAR-NEXT: orr r1, r1, r3, lsr r6
; SCALAR-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; NEON-LABEL: fshr_i37:
@@ -272,31 +267,30 @@ define i37 @fshr_i37(i37 %x, i37 %y, i37 %z) {
; NEON-NEXT: push {r4, r5, r6, r7, r11, lr}
; NEON-NEXT: mov r4, r1
; NEON-NEXT: ldr r1, [sp, #28]
-; NEON-NEXT: mov r5, r0
+; NEON-NEXT: mov r7, r0
; NEON-NEXT: ldr r0, [sp, #24]
; NEON-NEXT: and r1, r1, #31
-; NEON-NEXT: mov r6, r3
-; NEON-NEXT: mov r7, r2
+; NEON-NEXT: mov r5, r3
+; NEON-NEXT: mov r6, r2
; NEON-NEXT: mov r2, #37
; NEON-NEXT: mov r3, #0
; NEON-NEXT: bl __aeabi_uldivmod
; NEON-NEXT: add r0, r2, #27
-; NEON-NEXT: lsl r2, r6, #27
-; NEON-NEXT: orr r2, r2, r7, lsr #5
-; NEON-NEXT: mov r1, #31
+; NEON-NEXT: lsl r2, r5, #27
+; NEON-NEXT: orr r2, r2, r6, lsr #5
; NEON-NEXT: tst r0, #32
-; NEON-NEXT: mov r3, r5
+; NEON-NEXT: mov r3, r7
+; NEON-NEXT: mvn r1, r0
; NEON-NEXT: moveq r3, r2
-; NEON-NEXT: lsleq r2, r7, #27
-; NEON-NEXT: bic r1, r1, r0
-; NEON-NEXT: and r7, r0, #31
-; NEON-NEXT: lsl r6, r3, #1
-; NEON-NEXT: moveq r4, r5
-; NEON-NEXT: lsl r6, r6, r1
-; NEON-NEXT: orr r0, r6, r2, lsr r7
+; NEON-NEXT: lsleq r2, r6, #27
+; NEON-NEXT: and r6, r0, #31
+; NEON-NEXT: lsl r5, r3, #1
+; NEON-NEXT: moveq r4, r7
+; NEON-NEXT: lsl r5, r5, r1
+; NEON-NEXT: orr r0, r5, r2, lsr r6
; NEON-NEXT: lsl r2, r4, #1
; NEON-NEXT: lsl r1, r2, r1
-; NEON-NEXT: orr r1, r1, r3, lsr r7
+; NEON-NEXT: orr r1, r1, r3, lsr r6
; NEON-NEXT: pop {r4, r5, r6, r7, r11, pc}
%f = call i37 @llvm.fshr.i37(i37 %x, i37 %y, i37 %z)
ret i37 %f
diff --git a/llvm/test/CodeGen/ARM/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll b/llvm/test/CodeGen/ARM/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
index 7cc623fb0a616..5b732ef928455 100644
--- a/llvm/test/CodeGen/ARM/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
+++ b/llvm/test/CodeGen/ARM/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
@@ -20,7 +20,6 @@
define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
; ARM-LABEL: scalar_i8_signbit_eq:
; ARM: @ %bb.0:
-; ARM-NEXT: uxtb r1, r1
; ARM-NEXT: lsl r0, r0, r1
; ARM-NEXT: mov r1, #1
; ARM-NEXT: uxtb r0, r0
@@ -29,7 +28,6 @@ define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: scalar_i8_signbit_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: lsls r0, r1
; THUMB6-NEXT: movs r1, #128
; THUMB6-NEXT: ands r0, r1
@@ -39,7 +37,6 @@ define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
;
; THUMB78-LABEL: scalar_i8_signbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
; THUMB78-NEXT: lsls r0, r1
; THUMB78-NEXT: movs r1, #1
; THUMB78-NEXT: uxtb r0, r0
@@ -61,7 +58,6 @@ define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: scalar_i8_lowestbit_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: lsls r0, r1
; THUMB6-NEXT: movs r1, #1
; THUMB6-NEXT: ands r0, r1
@@ -71,7 +67,6 @@ define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
;
; THUMB78-LABEL: scalar_i8_lowestbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
; THUMB78-NEXT: lsls r0, r1
; THUMB78-NEXT: movs r1, #1
; THUMB78-NEXT: bic.w r0, r1, r0
@@ -94,7 +89,6 @@ define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: scalar_i8_bitsinmiddle_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: lsls r0, r1
; THUMB6-NEXT: movs r1, #24
; THUMB6-NEXT: ands r0, r1
@@ -104,7 +98,6 @@ define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
;
; THUMB78-LABEL: scalar_i8_bitsinmiddle_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
; THUMB78-NEXT: lsls r0, r1
; THUMB78-NEXT: and r0, r0, #24
; THUMB78-NEXT: clz r0, r0
@@ -121,7 +114,6 @@ define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
; ARM-LABEL: scalar_i16_signbit_eq:
; ARM: @ %bb.0:
-; ARM-NEXT: uxth r1, r1
; ARM-NEXT: lsl r0, r0, r1
; ARM-NEXT: mov r1, #1
; ARM-NEXT: uxth r0, r0
@@ -130,7 +122,6 @@ define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
;
; THUMB6-LABEL: scalar_i16_signbit_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxth r1, r1
; THUMB6-NEXT: lsls r0, r1
; THUMB6-NEXT: movs r1, #1
; THUMB6-NEXT: lsls r1, r1, #15
@@ -141,7 +132,6 @@ define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
;
; THUMB78-LABEL: scalar_i16_signbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxth r1, r1
; THUMB78-NEXT: lsls r0, r1
; THUMB78-NEXT: movs r1, #1
; THUMB78-NEXT: uxth r0, r0
@@ -163,7 +153,6 @@ define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
;
; THUMB6-LABEL: scalar_i16_lowestbit_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxth r1, r1
; THUMB6-NEXT: lsls r0, r1
; THUMB6-NEXT: movs r1, #1
; THUMB6-NEXT: ands r0, r1
@@ -173,7 +162,6 @@ define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
;
; THUMB78-LABEL: scalar_i16_lowestbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxth r1, r1
; THUMB78-NEXT: lsls r0, r1
; THUMB78-NEXT: movs r1, #1
; THUMB78-NEXT: bic.w r0, r1, r0
@@ -196,7 +184,6 @@ define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
;
; THUMB6-LABEL: scalar_i16_bitsinmiddle_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxth r1, r1
; THUMB6-NEXT: lsls r0, r1
; THUMB6-NEXT: movs r1, #255
; THUMB6-NEXT: lsls r1, r1, #4
@@ -207,7 +194,6 @@ define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
;
; THUMB78-LABEL: scalar_i16_bitsinmiddle_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxth r1, r1
; THUMB78-NEXT: lsls r0, r1
; THUMB78-NEXT: and r0, r0, #4080
; THUMB78-NEXT: clz r0, r0
@@ -330,7 +316,7 @@ define i1 @scalar_i32_bitsinmiddle_eq(i32 %x, i32 %y) nounwind {
define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
; ARM-LABEL: scalar_i64_signbit_eq:
; ARM: @ %bb.0:
-; ARM-NEXT: rsb r3, r2, #32
+; ARM-NEXT: rsb r3, r2, #0
; ARM-NEXT: lsr r3, r0, r3
; ARM-NEXT: orr r1, r3, r1, lsl r2
; ARM-NEXT: subs r2, r2, #32
@@ -352,11 +338,11 @@ define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
;
; THUMB78-LABEL: scalar_i64_signbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: rsb.w r3, r2, #32
+; THUMB78-NEXT: rsbs r3, r2, #0
; THUMB78-NEXT: lsls r1, r2
-; THUMB78-NEXT: subs r2, #32
; THUMB78-NEXT: lsr.w r3, r0, r3
-; THUMB78-NEXT: orr.w r1, r1, r3
+; THUMB78-NEXT: orrs r1, r3
+; THUMB78-NEXT: subs.w r3, r2, #32
; THUMB78-NEXT: it pl
; THUMB78-NEXT: lslpl.w r1, r0, r2
; THUMB78-NEXT: mvns r0, r1
@@ -415,7 +401,7 @@ define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) nounwind {
define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
; ARM6-LABEL: scalar_i64_bitsinmiddle_eq:
; ARM6: @ %bb.0:
-; ARM6-NEXT: rsb r3, r2, #32
+; ARM6-NEXT: rsb r3, r2, #0
; ARM6-NEXT: lsr r3, r0, r3
; ARM6-NEXT: orr r1, r3, r1, lsl r2
; ARM6-NEXT: subs r3, r2, #32
@@ -429,7 +415,7 @@ define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
;
; ARM78-LABEL: scalar_i64_bitsinmiddle_eq:
; ARM78: @ %bb.0:
-; ARM78-NEXT: rsb r3, r2, #32
+; ARM78-NEXT: rsb r3, r2, #0
; ARM78-NEXT: lsr r3, r0, r3
; ARM78-NEXT: orr r1, r3, r1, lsl r2
; ARM78-NEXT: subs r3, r2, #32
@@ -459,17 +445,16 @@ define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
;
; THUMB78-LABEL: scalar_i64_bitsinmiddle_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: rsb.w r3, r2, #32
+; THUMB78-NEXT: rsbs r3, r2, #0
; THUMB78-NEXT: lsls r1, r2
; THUMB78-NEXT: lsr.w r3, r0, r3
-; THUMB78-NEXT: orrs r1, r3
-; THUMB78-NEXT: subs.w r3, r2, #32
-; THUMB78-NEXT: it pl
-; THUMB78-NEXT: lslpl.w r1, r0, r3
-; THUMB78-NEXT: lsl.w r0, r0, r2
-; THUMB78-NEXT: it pl
+; THUMB78-NEXT: lsls r0, r2
+; THUMB78-NEXT: subs r2, #32
+; THUMB78-NEXT: mov r2, r0
+; THUMB78-NEXT: ite mi
+; THUMB78-NEXT: orrmi.w r2, r3, r1
; THUMB78-NEXT: movpl r0, #0
-; THUMB78-NEXT: pkhbt r0, r1, r0
+; THUMB78-NEXT: pkhbt r0, r2, r0
; THUMB78-NEXT: clz r0, r0
; THUMB78-NEXT: lsrs r0, r0, #5
; THUMB78-NEXT: bx lr
@@ -864,7 +849,6 @@ define <4 x i1> @vec_4xi32_nonsplat_undef2_eq(<4 x i32> %x, <4 x i32> %y) nounwi
define i1 @scalar_i8_signbit_ne(i8 %x, i8 %y) nounwind {
; ARM-LABEL: scalar_i8_signbit_ne:
; ARM: @ %bb.0:
-; ARM-NEXT: uxtb r1, r1
; ARM-NEXT: lsl r0, r0, r1
; ARM-NEXT: uxtb r0, r0
; ARM-NEXT: lsr r0, r0, #7
@@ -872,7 +856,6 @@ define i1 @scalar_i8_signbit_ne(i8 %x, i8 %y) nounwind {
;
; THUMB-LABEL: scalar_i8_signbit_ne:
; THUMB: @ %bb.0:
-; THUMB-NEXT: uxtb r1, r1
; THUMB-NEXT: lsls r0, r1
; THUMB-NEXT: uxtb r0, r0
; THUMB-NEXT: lsrs r0, r0, #7
@@ -986,7 +969,6 @@ define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: negative_scalar_i8_bitsinmiddle_slt:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: movs r2, #24
; THUMB6-NEXT: lsrs r2, r1
; THUMB6-NEXT: ands r2, r0
@@ -1000,7 +982,6 @@ define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
;
; THUMB78-LABEL: negative_scalar_i8_bitsinmiddle_slt:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
; THUMB78-NEXT: movs r2, #24
; THUMB78-NEXT: lsr.w r1, r2, r1
; THUMB78-NEXT: ands r0, r1
@@ -1027,7 +1008,6 @@ define i1 @scalar_i8_signbit_eq_with_nonzero(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: scalar_i8_signbit_eq_with_nonzero:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: movs r2, #128
; THUMB6-NEXT: lsrs r2, r1
; THUMB6-NEXT: ands r2, r0
@@ -1038,7 +1018,6 @@ define i1 @scalar_i8_signbit_eq_with_nonzero(i8 %x, i8 %y) nounwind {
;
; THUMB78-LABEL: scalar_i8_signbit_eq_with_nonzero:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
; THUMB78-NEXT: movs r2, #128
; THUMB78-NEXT: lsr.w r1, r2, r1
; THUMB78-NEXT: ands r0, r1
diff --git a/llvm/test/CodeGen/ARM/hoist-and-by-const-from-shl-in-eqcmp-zero.ll b/llvm/test/CodeGen/ARM/hoist-and-by-const-from-shl-in-eqcmp-zero.ll
index a8421ae9a6a89..fb07d205c8e23 100644
--- a/llvm/test/CodeGen/ARM/hoist-and-by-const-from-shl-in-eqcmp-zero.ll
+++ b/llvm/test/CodeGen/ARM/hoist-and-by-const-from-shl-in-eqcmp-zero.ll
@@ -20,7 +20,6 @@
define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
; ARM-LABEL: scalar_i8_signbit_eq:
; ARM: @ %bb.0:
-; ARM-NEXT: uxtb r1, r1
; ARM-NEXT: uxtb r0, r0
; ARM-NEXT: lsr r0, r0, r1
; ARM-NEXT: mov r1, #1
@@ -29,7 +28,6 @@ define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: scalar_i8_signbit_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: uxtb r0, r0
; THUMB6-NEXT: lsrs r0, r1
; THUMB6-NEXT: movs r1, #128
@@ -40,7 +38,6 @@ define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
;
; THUMB78-LABEL: scalar_i8_signbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
; THUMB78-NEXT: uxtb r0, r0
; THUMB78-NEXT: lsrs r0, r1
; THUMB78-NEXT: movs r1, #1
@@ -63,7 +60,6 @@ define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: scalar_i8_lowestbit_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: uxtb r0, r0
; THUMB6-NEXT: lsrs r0, r1
; THUMB6-NEXT: movs r1, #1
@@ -74,7 +70,6 @@ define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
;
; THUMB78-LABEL: scalar_i8_lowestbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
; THUMB78-NEXT: uxtb r0, r0
; THUMB78-NEXT: lsrs r0, r1
; THUMB78-NEXT: movs r1, #1
@@ -99,7 +94,6 @@ define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: scalar_i8_bitsinmiddle_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: uxtb r0, r0
; THUMB6-NEXT: lsrs r0, r1
; THUMB6-NEXT: movs r1, #24
@@ -110,7 +104,6 @@ define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
;
; THUMB78-LABEL: scalar_i8_bitsinmiddle_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
; THUMB78-NEXT: uxtb r0, r0
; THUMB78-NEXT: lsrs r0, r1
; THUMB78-NEXT: and r0, r0, #24
@@ -128,7 +121,6 @@ define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
; ARM-LABEL: scalar_i16_signbit_eq:
; ARM: @ %bb.0:
-; ARM-NEXT: uxth r1, r1
; ARM-NEXT: uxth r0, r0
; ARM-NEXT: lsr r0, r0, r1
; ARM-NEXT: mov r1, #1
@@ -137,7 +129,6 @@ define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
;
; THUMB6-LABEL: scalar_i16_signbit_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxth r1, r1
; THUMB6-NEXT: uxth r0, r0
; THUMB6-NEXT: lsrs r0, r1
; THUMB6-NEXT: movs r1, #1
@@ -149,7 +140,6 @@ define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
;
; THUMB78-LABEL: scalar_i16_signbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxth r1, r1
; THUMB78-NEXT: uxth r0, r0
; THUMB78-NEXT: lsrs r0, r1
; THUMB78-NEXT: movs r1, #1
@@ -172,7 +162,6 @@ define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
;
; THUMB6-LABEL: scalar_i16_lowestbit_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxth r1, r1
; THUMB6-NEXT: uxth r0, r0
; THUMB6-NEXT: lsrs r0, r1
; THUMB6-NEXT: movs r1, #1
@@ -183,7 +172,6 @@ define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
;
; THUMB78-LABEL: scalar_i16_lowestbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxth r1, r1
; THUMB78-NEXT: uxth r0, r0
; THUMB78-NEXT: lsrs r0, r1
; THUMB78-NEXT: movs r1, #1
@@ -208,7 +196,6 @@ define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
;
; THUMB6-LABEL: scalar_i16_bitsinmiddle_eq:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxth r1, r1
; THUMB6-NEXT: uxth r0, r0
; THUMB6-NEXT: lsrs r0, r1
; THUMB6-NEXT: movs r1, #255
@@ -220,7 +207,6 @@ define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
;
; THUMB78-LABEL: scalar_i16_bitsinmiddle_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxth r1, r1
; THUMB78-NEXT: uxth r0, r0
; THUMB78-NEXT: lsrs r0, r1
; THUMB78-NEXT: and r0, r0, #4080
@@ -410,11 +396,11 @@ define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) nounwind {
;
; THUMB78-LABEL: scalar_i64_lowestbit_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: rsb.w r3, r2, #32
+; THUMB78-NEXT: rsbs r3, r2, #0
; THUMB78-NEXT: lsrs r0, r2
-; THUMB78-NEXT: subs r2, #32
; THUMB78-NEXT: lsl.w r3, r1, r3
-; THUMB78-NEXT: orr.w r0, r0, r3
+; THUMB78-NEXT: orrs r0, r3
+; THUMB78-NEXT: subs.w r3, r2, #32
; THUMB78-NEXT: it pl
; THUMB78-NEXT: lsrpl.w r0, r1, r2
; THUMB78-NEXT: movs r1, #1
@@ -473,17 +459,16 @@ define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
;
; THUMB78-LABEL: scalar_i64_bitsinmiddle_eq:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: rsb.w r3, r2, #32
+; THUMB78-NEXT: rsbs r3, r2, #0
; THUMB78-NEXT: lsrs r0, r2
; THUMB78-NEXT: lsl.w r3, r1, r3
-; THUMB78-NEXT: orrs r0, r3
-; THUMB78-NEXT: subs.w r3, r2, #32
-; THUMB78-NEXT: it pl
-; THUMB78-NEXT: lsrpl.w r0, r1, r3
-; THUMB78-NEXT: lsr.w r1, r1, r2
-; THUMB78-NEXT: it pl
+; THUMB78-NEXT: lsrs r1, r2
+; THUMB78-NEXT: subs r2, #32
+; THUMB78-NEXT: mov r2, r1
+; THUMB78-NEXT: ite mi
+; THUMB78-NEXT: orrmi.w r2, r0, r3
; THUMB78-NEXT: movpl r1, #0
-; THUMB78-NEXT: pkhbt r0, r1, r0
+; THUMB78-NEXT: pkhbt r0, r1, r2
; THUMB78-NEXT: clz r0, r0
; THUMB78-NEXT: lsrs r0, r0, #5
; THUMB78-NEXT: bx lr
@@ -876,7 +861,6 @@ define <4 x i1> @vec_4xi32_nonsplat_undef2_eq(<4 x i32> %x, <4 x i32> %y) nounwi
define i1 @scalar_i8_signbit_ne(i8 %x, i8 %y) nounwind {
; ARM-LABEL: scalar_i8_signbit_ne:
; ARM: @ %bb.0:
-; ARM-NEXT: uxtb r1, r1
; ARM-NEXT: uxtb r0, r0
; ARM-NEXT: lsr r0, r0, r1
; ARM-NEXT: lsr r0, r0, #7
@@ -884,7 +868,6 @@ define i1 @scalar_i8_signbit_ne(i8 %x, i8 %y) nounwind {
;
; THUMB-LABEL: scalar_i8_signbit_ne:
; THUMB: @ %bb.0:
-; THUMB-NEXT: uxtb r1, r1
; THUMB-NEXT: uxtb r0, r0
; THUMB-NEXT: lsrs r0, r1
; THUMB-NEXT: lsrs r0, r0, #7
@@ -1029,7 +1012,6 @@ define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: negative_scalar_i8_bitsinmiddle_slt:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: movs r2, #24
; THUMB6-NEXT: lsls r2, r1
; THUMB6-NEXT: ands r2, r0
@@ -1045,7 +1027,6 @@ define i1 @negative_scalar_i8_bitsinmiddle_slt(i8 %x, i8 %y) nounwind {
;
; THUMB78-LABEL: negative_scalar_i8_bitsinmiddle_slt:
; THUMB78: @ %bb.0:
-; THUMB78-NEXT: uxtb r1, r1
; THUMB78-NEXT: movs r2, #24
; THUMB78-NEXT: lsl.w r1, r2, r1
; THUMB78-NEXT: ands r0, r1
@@ -1069,7 +1050,6 @@ define i1 @scalar_i8_signbit_eq_with_nonzero(i8 %x, i8 %y) nounwind {
;
; THUMB6-LABEL: scalar_i8_signbit_eq_with_nonzero:
; THUMB6: @ %bb.0:
-; THUMB6-NEXT: uxtb r1, r1
; THUMB6-NEXT: movs r2, #127
; THUMB6-NEXT: mvns r2, r2
; THUMB6-NEXT: lsls r2, r1
diff --git a/llvm/test/CodeGen/ARM/rotate-add.ll b/llvm/test/CodeGen/ARM/rotate-add.ll
index fd3055e5e2725..62d6089178db2 100644
--- a/llvm/test/CodeGen/ARM/rotate-add.ll
+++ b/llvm/test/CodeGen/ARM/rotate-add.ll
@@ -29,7 +29,7 @@ define i32 @test_simple_rotr(i32 %x) {
define i32 @test_rotl_var(i32 %x, i32 %y) {
; CHECK-LABEL: test_rotl_var:
; CHECK: @ %bb.0:
-; CHECK-NEXT: rsb r1, r1, #32
+; CHECK-NEXT: rsb r1, r1, #0
; CHECK-NEXT: ror r0, r0, r1
; CHECK-NEXT: bx lr
%shl = shl i32 %x, %y
@@ -55,7 +55,6 @@ define i32 @test_invalid_rotl_var_and(i32 %x, i32 %y) {
; CHECK-LABEL: test_invalid_rotl_var_and:
; CHECK: @ %bb.0:
; CHECK-NEXT: rsb r2, r1, #0
-; CHECK-NEXT: and r2, r2, #31
; CHECK-NEXT: lsr r2, r0, r2
; CHECK-NEXT: add r0, r2, r0, lsl r1
; CHECK-NEXT: bx lr
diff --git a/llvm/test/CodeGen/ARM/shift-i64.ll b/llvm/test/CodeGen/ARM/shift-i64.ll
index c326ac1529b2f..1c297731baf67 100644
--- a/llvm/test/CodeGen/ARM/shift-i64.ll
+++ b/llvm/test/CodeGen/ARM/shift-i64.ll
@@ -5,7 +5,7 @@
define i64 @test_shl(i64 %val, i64 %amt) {
; CHECK-LABEL: test_shl:
; CHECK: @ %bb.0:
-; CHECK-NEXT: rsb r3, r2, #32
+; CHECK-NEXT: rsb r3, r2, #0
; CHECK-NEXT: lsr r3, r0, r3
; CHECK-NEXT: orr r1, r3, r1, lsl r2
; CHECK-NEXT: subs r3, r2, #32
diff --git a/llvm/test/CodeGen/ARM/shift-mod.ll b/llvm/test/CodeGen/ARM/shift-mod.ll
index 3ba591e11acd1..931a8d766ab4f 100644
--- a/llvm/test/CodeGen/ARM/shift-mod.ll
+++ b/llvm/test/CodeGen/ARM/shift-mod.ll
@@ -20,31 +20,26 @@ define i32 @lsl_add_mod(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: lsl_add_mod:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: add r1, r1, #32
; CHECK-ARM-NEXT: lsl r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: lsl_add_mod:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: add r1, r1, #32
; CHECK-BE-NEXT: lsl r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: lsl_add_mod:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: adds r1, #32
; CHECK-THUMB-NEXT: lsls r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: lsl_add_mod:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: adds r1, #32
; CHECK-ALIGN-NEXT: lsls r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: lsl_add_mod:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: adds r1, #32
; CHECK-V6M-NEXT: lsls r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -63,32 +58,31 @@ define i32 @lsl_sub_rsb(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: lsl_sub_rsb:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: rsb r1, r1, #0
; CHECK-ARM-NEXT: lsl r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: lsl_sub_rsb:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: rsb r1, r1, #0
; CHECK-BE-NEXT: lsl r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: lsl_sub_rsb:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: rsbs r1, r1, #0
; CHECK-THUMB-NEXT: lsls r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: lsl_sub_rsb:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: rsbs r1, r1, #0
; CHECK-ALIGN-NEXT: lsls r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: lsl_sub_rsb:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #32
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: rsbs r1, r1, #0
; CHECK-V6M-NEXT: lsls r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -107,32 +101,31 @@ define i32 @lsl_sub_mvn(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: lsl_sub_mvn:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: mvn r1, r1
; CHECK-ARM-NEXT: lsl r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: lsl_sub_mvn:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: mvn r1, r1
; CHECK-BE-NEXT: lsl r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: lsl_sub_mvn:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: mvns r1, r1
; CHECK-THUMB-NEXT: lsls r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: lsl_sub_mvn:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: mvns r1, r1
; CHECK-ALIGN-NEXT: lsls r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: lsl_sub_mvn:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: mvns r1, r1
; CHECK-V6M-NEXT: lsls r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -151,33 +144,27 @@ define i32 @lsl_and_mask(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: lsl_and_mask:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: and r1, r1, #31
; CHECK-ARM-NEXT: lsl r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: lsl_and_mask:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: and r1, r1, #31
; CHECK-BE-NEXT: lsl r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: lsl_and_mask:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: and r1, r1, #31
; CHECK-THUMB-NEXT: lsls r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: lsl_and_mask:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: and r1, r1, #31
; CHECK-ALIGN-NEXT: lsls r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: lsl_and_mask:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: ands r2, r1
-; CHECK-V6M-NEXT: lsls r0, r2
+; CHECK-V6M-NEXT: lsls r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = and i32 %amt, 31
@@ -199,31 +186,26 @@ define i32 @lsr_add_mod(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: lsr_add_mod:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: add r1, r1, #32
; CHECK-ARM-NEXT: lsr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: lsr_add_mod:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: add r1, r1, #32
; CHECK-BE-NEXT: lsr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: lsr_add_mod:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: adds r1, #32
; CHECK-THUMB-NEXT: lsrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: lsr_add_mod:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: adds r1, #32
; CHECK-ALIGN-NEXT: lsrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: lsr_add_mod:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: adds r1, #32
; CHECK-V6M-NEXT: lsrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -242,32 +224,31 @@ define i32 @lsr_sub_rsb(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: lsr_sub_rsb:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: rsb r1, r1, #0
; CHECK-ARM-NEXT: lsr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: lsr_sub_rsb:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: rsb r1, r1, #0
; CHECK-BE-NEXT: lsr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: lsr_sub_rsb:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: rsbs r1, r1, #0
; CHECK-THUMB-NEXT: lsrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: lsr_sub_rsb:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: rsbs r1, r1, #0
; CHECK-ALIGN-NEXT: lsrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: lsr_sub_rsb:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #32
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: rsbs r1, r1, #0
; CHECK-V6M-NEXT: lsrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -286,32 +267,31 @@ define i32 @lsr_sub_mvn(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: lsr_sub_mvn:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: mvn r1, r1
; CHECK-ARM-NEXT: lsr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: lsr_sub_mvn:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: mvn r1, r1
; CHECK-BE-NEXT: lsr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: lsr_sub_mvn:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: mvns r1, r1
; CHECK-THUMB-NEXT: lsrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: lsr_sub_mvn:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: mvns r1, r1
; CHECK-ALIGN-NEXT: lsrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: lsr_sub_mvn:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: mvns r1, r1
; CHECK-V6M-NEXT: lsrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -330,33 +310,27 @@ define i32 @lsr_and_mask(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: lsr_and_mask:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: and r1, r1, #31
; CHECK-ARM-NEXT: lsr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: lsr_and_mask:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: and r1, r1, #31
; CHECK-BE-NEXT: lsr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: lsr_and_mask:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: and r1, r1, #31
; CHECK-THUMB-NEXT: lsrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: lsr_and_mask:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: and r1, r1, #31
; CHECK-ALIGN-NEXT: lsrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: lsr_and_mask:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: ands r2, r1
-; CHECK-V6M-NEXT: lsrs r0, r2
+; CHECK-V6M-NEXT: lsrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = and i32 %amt, 31
@@ -384,31 +358,26 @@ define i32 @asr_add_mod(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: asr_add_mod:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: add r1, r1, #32
; CHECK-ARM-NEXT: asr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: asr_add_mod:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: add r1, r1, #32
; CHECK-BE-NEXT: asr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: asr_add_mod:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: adds r1, #32
; CHECK-THUMB-NEXT: asrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: asr_add_mod:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: adds r1, #32
; CHECK-ALIGN-NEXT: asrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: asr_add_mod:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: adds r1, #32
; CHECK-V6M-NEXT: asrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -433,32 +402,31 @@ define i32 @asr_sub_rsb(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: asr_sub_rsb:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: rsb r1, r1, #0
; CHECK-ARM-NEXT: asr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: asr_sub_rsb:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: rsb r1, r1, #0
; CHECK-BE-NEXT: asr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: asr_sub_rsb:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: rsbs r1, r1, #0
; CHECK-THUMB-NEXT: asrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: asr_sub_rsb:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: rsbs r1, r1, #0
; CHECK-ALIGN-NEXT: asrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: asr_sub_rsb:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #32
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: rsbs r1, r1, #0
; CHECK-V6M-NEXT: asrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -483,32 +451,31 @@ define i32 @asr_sub_mvn(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: asr_sub_mvn:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: mvn r1, r1
; CHECK-ARM-NEXT: asr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: asr_sub_mvn:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: mvn r1, r1
; CHECK-BE-NEXT: asr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: asr_sub_mvn:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: mvns r1, r1
; CHECK-THUMB-NEXT: asrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: asr_sub_mvn:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: mvns r1, r1
; CHECK-ALIGN-NEXT: asrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: asr_sub_mvn:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: mvns r1, r1
; CHECK-V6M-NEXT: asrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -533,33 +500,27 @@ define i32 @asr_and_mask(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: asr_and_mask:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: and r1, r1, #31
; CHECK-ARM-NEXT: asr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: asr_and_mask:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: and r1, r1, #31
; CHECK-BE-NEXT: asr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: asr_and_mask:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: and r1, r1, #31
; CHECK-THUMB-NEXT: asrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: asr_and_mask:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: and r1, r1, #31
; CHECK-ALIGN-NEXT: asrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: asr_and_mask:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: ands r2, r1
-; CHECK-V6M-NEXT: asrs r0, r2
+; CHECK-V6M-NEXT: asrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = and i32 %amt, 31
@@ -577,31 +538,26 @@ define i32 @ror_add_mod(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: ror_add_mod:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: add r1, r1, #32
; CHECK-ARM-NEXT: lsr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: ror_add_mod:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: add r1, r1, #32
; CHECK-BE-NEXT: lsr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: ror_add_mod:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: adds r1, #32
; CHECK-THUMB-NEXT: lsrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: ror_add_mod:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: adds r1, #32
; CHECK-ALIGN-NEXT: lsrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: ror_add_mod:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: adds r1, #32
; CHECK-V6M-NEXT: lsrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -619,32 +575,31 @@ define i32 @ror_sub_rsb(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: ror_sub_rsb:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: rsb r1, r1, #0
; CHECK-ARM-NEXT: lsr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: ror_sub_rsb:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: rsb r1, r1, #0
; CHECK-BE-NEXT: lsr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: ror_sub_rsb:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: rsbs r1, r1, #0
; CHECK-THUMB-NEXT: lsrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: ror_sub_rsb:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: rsbs r1, r1, #0
; CHECK-ALIGN-NEXT: lsrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: ror_sub_rsb:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #32
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: rsbs r1, r1, #0
; CHECK-V6M-NEXT: lsrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -662,32 +617,31 @@ define i32 @ror_sub_mvn(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: ror_sub_mvn:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: mvn r1, r1
; CHECK-ARM-NEXT: lsr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: ror_sub_mvn:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: mvn r1, r1
; CHECK-BE-NEXT: lsr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: ror_sub_mvn:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: mvns r1, r1
; CHECK-THUMB-NEXT: lsrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: ror_sub_mvn:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: mvns r1, r1
; CHECK-ALIGN-NEXT: lsrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: ror_sub_mvn:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: mvns r1, r1
; CHECK-V6M-NEXT: lsrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -705,33 +659,27 @@ define i32 @ror_and_mask(i32 %val, i32 %amt) #0 {
;
; CHECK-ARM-LABEL: ror_and_mask:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: and r1, r1, #31
; CHECK-ARM-NEXT: lsr r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: ror_and_mask:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: and r1, r1, #31
; CHECK-BE-NEXT: lsr r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: ror_and_mask:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: and r1, r1, #31
; CHECK-THUMB-NEXT: lsrs r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: ror_and_mask:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: and r1, r1, #31
; CHECK-ALIGN-NEXT: lsrs r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: ror_and_mask:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: ands r2, r1
-; CHECK-V6M-NEXT: lsrs r0, r2
+; CHECK-V6M-NEXT: lsrs r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = and i32 %amt, 31
@@ -752,37 +700,31 @@ declare i32 @llvm.fshr.i32(i32, i32, i32)
define i32 @fshl_add_mod(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshl_add_mod:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: mvn r2, #31
-; CHECK-ARM-NEXT: sub r1, r2, r1
+; CHECK-ARM-NEXT: rsb r1, r1, #0
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshl_add_mod:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: mvn r2, #31
-; CHECK-BE-NEXT: sub r1, r2, r1
+; CHECK-BE-NEXT: rsb r1, r1, #0
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshl_add_mod:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: mvn r2, #31
-; CHECK-THUMB-NEXT: subs r1, r2, r1
+; CHECK-THUMB-NEXT: rsbs r1, r1, #0
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: fshl_add_mod:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: mvn r2, #31
-; CHECK-ALIGN-NEXT: subs r1, r2, r1
+; CHECK-ALIGN-NEXT: rsbs r1, r1, #0
; CHECK-ALIGN-NEXT: rors r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshl_add_mod:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: mvns r2, r2
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: rsbs r1, r1, #0
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -801,31 +743,26 @@ entry:
define i32 @fshl_sub_rsb(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshl_sub_rsb:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: sub r1, r1, #32
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshl_sub_rsb:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: sub r1, r1, #32
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshl_sub_rsb:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: subs r1, #32
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: fshl_sub_rsb:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: subs r1, #32
; CHECK-ALIGN-NEXT: rors r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshl_sub_rsb:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: subs r1, #32
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -923,31 +860,26 @@ entry:
define i32 @fshr_add_mod(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshr_add_mod:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: add r1, r1, #32
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshr_add_mod:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: add r1, r1, #32
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshr_add_mod:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: adds r1, #32
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: fshr_add_mod:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: adds r1, #32
; CHECK-ALIGN-NEXT: rors r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshr_add_mod:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: adds r1, #32
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -960,32 +892,31 @@ entry:
define i32 @fshr_sub_rsb(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshr_sub_rsb:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #32
+; CHECK-ARM-NEXT: rsb r1, r1, #0
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshr_sub_rsb:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #32
+; CHECK-BE-NEXT: rsb r1, r1, #0
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshr_sub_rsb:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #32
+; CHECK-THUMB-NEXT: rsbs r1, r1, #0
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: fshr_sub_rsb:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #32
+; CHECK-ALIGN-NEXT: rsbs r1, r1, #0
; CHECK-ALIGN-NEXT: rors r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshr_sub_rsb:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #32
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: rsbs r1, r1, #0
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
@@ -998,32 +929,31 @@ entry:
define i32 @fshr_sub_mvn(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshr_sub_mvn:
; CHECK-ARM: @ %bb.0: @ %entry
-; CHECK-ARM-NEXT: rsb r1, r1, #31
+; CHECK-ARM-NEXT: mvn r1, r1
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshr_sub_mvn:
; CHECK-BE: @ %bb.0: @ %entry
-; CHECK-BE-NEXT: rsb r1, r1, #31
+; CHECK-BE-NEXT: mvn r1, r1
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshr_sub_mvn:
; CHECK-THUMB: @ %bb.0: @ %entry
-; CHECK-THUMB-NEXT: rsb.w r1, r1, #31
+; CHECK-THUMB-NEXT: mvns r1, r1
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: fshr_sub_mvn:
; CHECK-ALIGN: @ %bb.0: @ %entry
-; CHECK-ALIGN-NEXT: rsb.w r1, r1, #31
+; CHECK-ALIGN-NEXT: mvns r1, r1
; CHECK-ALIGN-NEXT: rors r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshr_sub_mvn:
; CHECK-V6M: @ %bb.0: @ %entry
-; CHECK-V6M-NEXT: movs r2, #31
-; CHECK-V6M-NEXT: subs r1, r2, r1
+; CHECK-V6M-NEXT: mvns r1, r1
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
diff --git a/llvm/test/CodeGen/ARM/shifter_operand.ll b/llvm/test/CodeGen/ARM/shifter_operand.ll
index 00922b1bf2492..b9e2a3aa30e4d 100644
--- a/llvm/test/CodeGen/ARM/shifter_operand.ll
+++ b/llvm/test/CodeGen/ARM/shifter_operand.ll
@@ -14,7 +14,6 @@ define i32 @test1(i32 %X, i32 %Y, i8 %sh) {
;
; CHECK-THUMB-LABEL: test1:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: uxtb r2, r2
; CHECK-THUMB-NEXT: lsls r1, r2
; CHECK-THUMB-NEXT: add r0, r1
; CHECK-THUMB-NEXT: bx lr
@@ -33,7 +32,6 @@ define i32 @test2(i32 %X, i32 %Y, i8 %sh) {
;
; CHECK-THUMB-LABEL: test2:
; CHECK-THUMB: @ %bb.0:
-; CHECK-THUMB-NEXT: uxtb r2, r2
; CHECK-THUMB-NEXT: asrs r1, r2
; CHECK-THUMB-NEXT: bics r0, r1
; CHECK-THUMB-NEXT: bx lr
diff --git a/llvm/test/CodeGen/Thumb2/shift_parts.ll b/llvm/test/CodeGen/Thumb2/shift_parts.ll
index b4ac405d82ed5..6e2103b140b25 100644
--- a/llvm/test/CodeGen/Thumb2/shift_parts.ll
+++ b/llvm/test/CodeGen/Thumb2/shift_parts.ll
@@ -10,15 +10,14 @@ define i64 @shift_left_reg(i64 %x, i64 %y) {
;
; CHECK-NON-MVE-LABEL: shift_left_reg:
; CHECK-NON-MVE: @ %bb.0: @ %entry
-; CHECK-NON-MVE-NEXT: rsb.w r3, r2, #32
-; CHECK-NON-MVE-NEXT: lsls r1, r2
-; CHECK-NON-MVE-NEXT: lsr.w r3, r0, r3
-; CHECK-NON-MVE-NEXT: orrs r1, r3
-; CHECK-NON-MVE-NEXT: subs.w r3, r2, #32
-; CHECK-NON-MVE-NEXT: it pl
-; CHECK-NON-MVE-NEXT: lslpl.w r1, r0, r3
-; CHECK-NON-MVE-NEXT: lsl.w r0, r0, r2
-; CHECK-NON-MVE-NEXT: it pl
+; CHECK-NON-MVE-NEXT: lsl.w r12, r1, r2
+; CHECK-NON-MVE-NEXT: rsbs r1, r2, #0
+; CHECK-NON-MVE-NEXT: lsr.w r3, r0, r1
+; CHECK-NON-MVE-NEXT: lsls r0, r2
+; CHECK-NON-MVE-NEXT: subs.w r1, r2, #32
+; CHECK-NON-MVE-NEXT: mov r1, r0
+; CHECK-NON-MVE-NEXT: ite mi
+; CHECK-NON-MVE-NEXT: orrmi.w r1, r3, r12
; CHECK-NON-MVE-NEXT: movpl r0, #0
; CHECK-NON-MVE-NEXT: bx lr
entry:
@@ -85,15 +84,14 @@ define i64 @shift_right_reg(i64 %x, i64 %y) {
;
; CHECK-NON-MVE-LABEL: shift_right_reg:
; CHECK-NON-MVE: @ %bb.0: @ %entry
-; CHECK-NON-MVE-NEXT: rsb.w r3, r2, #32
-; CHECK-NON-MVE-NEXT: lsrs r0, r2
-; CHECK-NON-MVE-NEXT: lsl.w r3, r1, r3
-; CHECK-NON-MVE-NEXT: orrs r0, r3
-; CHECK-NON-MVE-NEXT: subs.w r3, r2, #32
-; CHECK-NON-MVE-NEXT: it pl
-; CHECK-NON-MVE-NEXT: lsrpl.w r0, r1, r3
-; CHECK-NON-MVE-NEXT: lsr.w r1, r1, r2
-; CHECK-NON-MVE-NEXT: it pl
+; CHECK-NON-MVE-NEXT: lsr.w r12, r0, r2
+; CHECK-NON-MVE-NEXT: rsbs r0, r2, #0
+; CHECK-NON-MVE-NEXT: lsl.w r3, r1, r0
+; CHECK-NON-MVE-NEXT: lsrs r1, r2
+; CHECK-NON-MVE-NEXT: subs.w r0, r2, #32
+; CHECK-NON-MVE-NEXT: mov r0, r1
+; CHECK-NON-MVE-NEXT: ite mi
+; CHECK-NON-MVE-NEXT: orrmi.w r0, r12, r3
; CHECK-NON-MVE-NEXT: movpl r1, #0
; CHECK-NON-MVE-NEXT: bx lr
entry:
@@ -159,18 +157,19 @@ define i64 @shift_arithmetic_right_reg(i64 %x, i64 %y) {
;
; CHECK-NON-MVE-LABEL: shift_arithmetic_right_reg:
; CHECK-NON-MVE: @ %bb.0: @ %entry
-; CHECK-NON-MVE-NEXT: rsb.w r3, r2, #32
-; CHECK-NON-MVE-NEXT: lsrs r0, r2
-; CHECK-NON-MVE-NEXT: lsl.w r3, r1, r3
-; CHECK-NON-MVE-NEXT: orrs r0, r3
-; CHECK-NON-MVE-NEXT: subs.w r3, r2, #32
-; CHECK-NON-MVE-NEXT: asr.w r2, r1, r2
-; CHECK-NON-MVE-NEXT: it pl
-; CHECK-NON-MVE-NEXT: asrpl.w r0, r1, r3
-; CHECK-NON-MVE-NEXT: it pl
-; CHECK-NON-MVE-NEXT: asrpl r2, r1, #31
-; CHECK-NON-MVE-NEXT: mov r1, r2
-; CHECK-NON-MVE-NEXT: bx lr
+; CHECK-NON-MVE-NEXT: .save {r7, lr}
+; CHECK-NON-MVE-NEXT: push {r7, lr}
+; CHECK-NON-MVE-NEXT: lsr.w r12, r0, r2
+; CHECK-NON-MVE-NEXT: rsbs r0, r2, #0
+; CHECK-NON-MVE-NEXT: asr.w r3, r1, r2
+; CHECK-NON-MVE-NEXT: lsl.w lr, r1, r0
+; CHECK-NON-MVE-NEXT: subs.w r0, r2, #32
+; CHECK-NON-MVE-NEXT: mov r0, r3
+; CHECK-NON-MVE-NEXT: ite mi
+; CHECK-NON-MVE-NEXT: orrmi.w r0, r12, lr
+; CHECK-NON-MVE-NEXT: asrpl r3, r1, #31
+; CHECK-NON-MVE-NEXT: mov r1, r3
+; CHECK-NON-MVE-NEXT: pop {r7, pc}
entry:
%shr = ashr i64 %x, %y
ret i64 %shr
diff --git a/llvm/test/CodeGen/Thumb2/thumb2-shifter.ll b/llvm/test/CodeGen/Thumb2/thumb2-shifter.ll
index 538fc2214d2c8..effa595ba073e 100644
--- a/llvm/test/CodeGen/Thumb2/thumb2-shifter.ll
+++ b/llvm/test/CodeGen/Thumb2/thumb2-shifter.ll
@@ -40,7 +40,6 @@ define i32 @t2ADDrs_ror(i32 %X, i32 %Y) {
define i32 @t2ADDrs_noRegShift(i32 %X, i32 %Y, i8 %sh) {
; A8: t2ADDrs_noRegShift
-; A8: uxtb r2, r2
; A8: lsls r1, r2
; A8: add r0, r1
@@ -55,7 +54,6 @@ define i32 @t2ADDrs_noRegShift(i32 %X, i32 %Y, i8 %sh) {
define i32 @t2ADDrs_noRegShift2(i32 %X, i32 %Y, i8 %sh) {
; A8: t2ADDrs_noRegShift2
-; A8: uxtb r2, r2
; A8: lsrs r1, r2
; A8: add r0, r1
@@ -70,7 +68,6 @@ define i32 @t2ADDrs_noRegShift2(i32 %X, i32 %Y, i8 %sh) {
define i32 @t2ADDrs_noRegShift3(i32 %X, i32 %Y, i8 %sh) {
; A8: t2ADDrs_noRegShift3
-; A8: uxtb r2, r2
; A8: asrs r1, r2
; A8: add r0, r1
More information about the llvm-commits
mailing list