Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ARM] Add support for the MVE long shift instructions
MVE adds the lsll, lsrl and asrl instructions, which perform a shift on a 64 bit value separated into two 32 bit registers. The Expand64BitShift function is modified to accept ISD::SHL, ISD::SRL and ISD::SRA and convert it into the appropriate opcode in ARMISD. An SHL is converted into an lsll, an SRL is converted into an lsrl for the immediate form and a negation and lsll for the register form, and SRA is converted into an asrl. test/CodeGen/ARM/shift_parts.ll is added to test the logic of emitting these instructions. Differential Revision: https://reviews.llvm.org/D63430 llvm-svn: 364654
- Loading branch information
Sam Tebbs
committed
Jun 28, 2019
1 parent
176b9f6
commit e39e958
Showing
5 changed files
with
306 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
; RUN: llc --verify-machineinstrs -mtriple=thumbv8.1-m.main-none-eabi -mattr=+mve %s -o - | FileCheck %s -check-prefix=CHECK --check-prefix=CHECK-MVE | ||
; RUN: llc --verify-machineinstrs -mtriple=thumbv8.1-m.main-none-eabi %s -o - | FileCheck %s -check-prefix=CHECK --check-prefix=CHECK-NON-MVE | ||
|
||
define i64 @shift_left_reg(i64 %x, i64 %y) { | ||
; CHECK-MVE-LABEL: shift_left_reg: | ||
; CHECK-MVE: @ %bb.0: @ %entry | ||
; CHECK-MVE-NEXT: lsll r0, r1, r2 | ||
; CHECK-MVE-NEXT: bx lr | ||
; | ||
; CHECK-NON-MVE-LABEL: shift_left_reg: | ||
; CHECK-NON-MVE: @ %bb.0: @ %entry | ||
; CHECK-NON-MVE-NEXT: .save {r7, lr} | ||
; CHECK-NON-MVE-NEXT: push {r7, lr} | ||
; CHECK-NON-MVE-NEXT: bl __aeabi_llsl | ||
; CHECK-NON-MVE-NEXT: pop {r7} | ||
; CHECK-NON-MVE-NEXT: pop {r2} | ||
; CHECK-NON-MVE-NEXT: bx r2 | ||
entry: | ||
%shl = shl i64 %x, %y | ||
ret i64 %shl | ||
} | ||
|
||
define i64 @shift_left_imm(i64 %x) { | ||
; CHECK-MVE-LABEL: shift_left_imm: | ||
; CHECK-MVE: @ %bb.0: @ %entry | ||
; CHECK-MVE-NEXT: lsll r0, r1, #3 | ||
; CHECK-MVE-NEXT: bx lr | ||
; | ||
; CHECK-NON-MVE-LABEL: shift_left_imm: | ||
; CHECK-NON-MVE: @ %bb.0: @ %entry | ||
; CHECK-NON-MVE-NEXT: lsrs r2, r0, #29 | ||
; CHECK-NON-MVE-NEXT: lsls r1, r1, #3 | ||
; CHECK-NON-MVE-NEXT: adds r1, r1, r2 | ||
; CHECK-NON-MVE-NEXT: lsls r0, r0, #3 | ||
; CHECK-NON-MVE-NEXT: bx lr | ||
entry: | ||
%shl = shl i64 %x, 3 | ||
ret i64 %shl | ||
} | ||
|
||
define i64 @shift_left_imm_big(i64 %x) { | ||
; CHECK-LABEL: shift_left_imm_big: | ||
; CHECK: @ %bb.0: @ %entry | ||
; CHECK-NEXT: lsls r1, r0, #16 | ||
; CHECK-NEXT: movs r0, #0 | ||
; CHECK-NEXT: bx lr | ||
entry: | ||
%shl = shl i64 %x, 48 | ||
ret i64 %shl | ||
} | ||
|
||
define i64 @shift_left_imm_big2(i64 %x) { | ||
; CHECK-MVE-LABEL: shift_left_imm_big2: | ||
; CHECK-MVE: @ %bb.0: @ %entry | ||
; CHECK-MVE-NEXT: lsll r0, r1, #32 | ||
; CHECK-MVE-NEXT: bx lr | ||
; | ||
; CHECK-NON-MVE-LABEL: shift_left_imm_big2: | ||
; CHECK-NON-MVE: @ %bb.0: @ %entry | ||
; CHECK-NON-MVE-NEXT: movs r1, r0 | ||
; CHECK-NON-MVE-NEXT: movs r0, #0 | ||
; CHECK-NON-MVE-NEXT: bx lr | ||
entry: | ||
%shl = shl i64 %x, 32 | ||
ret i64 %shl | ||
} | ||
|
||
define i64 @shift_left_imm_big3(i64 %x) { | ||
; CHECK-LABEL: shift_left_imm_big3: | ||
; CHECK: @ %bb.0: @ %entry | ||
; CHECK-NEXT: lsls r1, r0, #1 | ||
; CHECK-NEXT: movs r0, #0 | ||
; CHECK-NEXT: bx lr | ||
entry: | ||
%shl = shl i64 %x, 33 | ||
ret i64 %shl | ||
} | ||
|
||
define i64 @shift_right_reg(i64 %x, i64 %y) { | ||
; CHECK-MVE-LABEL: shift_right_reg: | ||
; CHECK-MVE: @ %bb.0: @ %entry | ||
; CHECK-MVE-NEXT: rsbs r2, r2, #0 | ||
; CHECK-MVE-NEXT: lsll r0, r1, r2 | ||
; CHECK-MVE-NEXT: bx lr | ||
; | ||
; CHECK-NON-MVE-LABEL: shift_right_reg: | ||
; CHECK-NON-MVE: @ %bb.0: @ %entry | ||
; CHECK-NON-MVE-NEXT: .save {r7, lr} | ||
; CHECK-NON-MVE-NEXT: push {r7, lr} | ||
; CHECK-NON-MVE-NEXT: bl __aeabi_llsr | ||
; CHECK-NON-MVE-NEXT: pop {r7} | ||
; CHECK-NON-MVE-NEXT: pop {r2} | ||
; CHECK-NON-MVE-NEXT: bx r2 | ||
entry: | ||
%shr = lshr i64 %x, %y | ||
ret i64 %shr | ||
} | ||
|
||
define i64 @shift_right_imm(i64 %x) { | ||
; CHECK-MVE-LABEL: shift_right_imm: | ||
; CHECK-MVE: @ %bb.0: @ %entry | ||
; CHECK-MVE-NEXT: lsrl r0, r1, #3 | ||
; CHECK-MVE-NEXT: bx lr | ||
; | ||
; CHECK-NON-MVE-LABEL: shift_right_imm: | ||
; CHECK-NON-MVE: @ %bb.0: @ %entry | ||
; CHECK-NON-MVE-NEXT: lsls r2, r1, #29 | ||
; CHECK-NON-MVE-NEXT: lsrs r0, r0, #3 | ||
; CHECK-NON-MVE-NEXT: adds r0, r0, r2 | ||
; CHECK-NON-MVE-NEXT: lsrs r1, r1, #3 | ||
; CHECK-NON-MVE-NEXT: bx lr | ||
entry: | ||
%shr = lshr i64 %x, 3 | ||
ret i64 %shr | ||
} | ||
|
||
define i64 @shift_right_imm_big(i64 %x) { | ||
; CHECK-LABEL: shift_right_imm_big: | ||
; CHECK: @ %bb.0: @ %entry | ||
; CHECK-NEXT: lsrs r0, r1, #16 | ||
; CHECK-NEXT: movs r1, #0 | ||
; CHECK-NEXT: bx lr | ||
entry: | ||
%shr = lshr i64 %x, 48 | ||
ret i64 %shr | ||
} | ||
|
||
define i64 @shift_right_imm_big2(i64 %x) { | ||
; CHECK-MVE-LABEL: shift_right_imm_big2: | ||
; CHECK-MVE: @ %bb.0: @ %entry | ||
; CHECK-MVE-NEXT: lsrl r0, r1, #32 | ||
; CHECK-MVE-NEXT: bx lr | ||
; | ||
; CHECK-NON-MVE-LABEL: shift_right_imm_big2: | ||
; CHECK-NON-MVE: @ %bb.0: @ %entry | ||
; CHECK-NON-MVE-NEXT: movs r0, r1 | ||
; CHECK-NON-MVE-NEXT: movs r1, #0 | ||
; CHECK-NON-MVE-NEXT: bx lr | ||
entry: | ||
%shr = lshr i64 %x, 32 | ||
ret i64 %shr | ||
} | ||
|
||
define i64 @shift_right_imm_big3(i64 %x) { | ||
; CHECK-LABEL: shift_right_imm_big3: | ||
; CHECK: @ %bb.0: @ %entry | ||
; CHECK-NEXT: lsrs r0, r1, #1 | ||
; CHECK-NEXT: movs r1, #0 | ||
; CHECK-NEXT: bx lr | ||
entry: | ||
%shr = lshr i64 %x, 33 | ||
ret i64 %shr | ||
} | ||
|
||
define i64 @shift_arithmetic_right_reg(i64 %x, i64 %y) { | ||
; CHECK-MVE-LABEL: shift_arithmetic_right_reg: | ||
; CHECK-MVE: @ %bb.0: @ %entry | ||
; CHECK-MVE-NEXT: asrl r0, r1, r2 | ||
; CHECK-MVE-NEXT: bx lr | ||
; | ||
; CHECK-NON-MVE-LABEL: shift_arithmetic_right_reg: | ||
; CHECK-NON-MVE: @ %bb.0: @ %entry | ||
; CHECK-NON-MVE-NEXT: .save {r7, lr} | ||
; CHECK-NON-MVE-NEXT: push {r7, lr} | ||
; CHECK-NON-MVE-NEXT: bl __aeabi_lasr | ||
; CHECK-NON-MVE-NEXT: pop {r7} | ||
; CHECK-NON-MVE-NEXT: pop {r2} | ||
; CHECK-NON-MVE-NEXT: bx r2 | ||
entry: | ||
%shr = ashr i64 %x, %y | ||
ret i64 %shr | ||
} | ||
|
||
define i64 @shift_arithmetic_right_imm(i64 %x) { | ||
; CHECK-MVE-LABEL: shift_arithmetic_right_imm: | ||
; CHECK-MVE: @ %bb.0: @ %entry | ||
; CHECK-MVE-NEXT: asrl r0, r1, #3 | ||
; CHECK-MVE-NEXT: bx lr | ||
; | ||
; CHECK-NON-MVE-LABEL: shift_arithmetic_right_imm: | ||
; CHECK-NON-MVE: @ %bb.0: @ %entry | ||
; CHECK-NON-MVE-NEXT: lsls r2, r1, #29 | ||
; CHECK-NON-MVE-NEXT: lsrs r0, r0, #3 | ||
; CHECK-NON-MVE-NEXT: adds r0, r0, r2 | ||
; CHECK-NON-MVE-NEXT: asrs r1, r1, #3 | ||
; CHECK-NON-MVE-NEXT: bx lr | ||
entry: | ||
%shr = ashr i64 %x, 3 | ||
ret i64 %shr | ||
} | ||
|
||
%struct.bar = type { i16, i8, [5 x i8] } | ||
|
||
define arm_aapcs_vfpcc void @fn1(%struct.bar* nocapture %a) { | ||
; CHECK-MVE-LABEL: fn1: | ||
; CHECK-MVE: @ %bb.0: @ %entry | ||
; CHECK-MVE-NEXT: ldr r2, [r0, #4] | ||
; CHECK-MVE-NEXT: movs r1, #0 | ||
; CHECK-MVE-NEXT: lsll r2, r1, #8 | ||
; CHECK-MVE-NEXT: strb r1, [r0, #7] | ||
; CHECK-MVE-NEXT: str.w r2, [r0, #3] | ||
; CHECK-MVE-NEXT: bx lr | ||
; | ||
; CHECK-NON-MVE-LABEL: fn1: | ||
; CHECK-NON-MVE: @ %bb.0: @ %entry | ||
; CHECK-NON-MVE-NEXT: ldr r1, [r0, #4] | ||
; CHECK-NON-MVE-NEXT: lsls r2, r1, #8 | ||
; CHECK-NON-MVE-NEXT: movs r3, #3 | ||
; CHECK-NON-MVE-NEXT: str r2, [r0, r3] | ||
; CHECK-NON-MVE-NEXT: adds r0, r0, #3 | ||
; CHECK-NON-MVE-NEXT: lsrs r1, r1, #24 | ||
; CHECK-NON-MVE-NEXT: strb r1, [r0, #4] | ||
; CHECK-NON-MVE-NEXT: bx lr | ||
entry: | ||
%carey = getelementptr inbounds %struct.bar, %struct.bar* %a, i32 0, i32 2 | ||
%0 = bitcast [5 x i8]* %carey to i40* | ||
%bf.load = load i40, i40* %0, align 1 | ||
%bf.clear = and i40 %bf.load, -256 | ||
store i40 %bf.clear, i40* %0, align 1 | ||
ret void | ||
} |