diff options
| author | Florian Hahn <florian.hahn@arm.com> | 2018-03-02 13:02:55 +0000 |
|---|---|---|
| committer | Florian Hahn <florian.hahn@arm.com> | 2018-03-02 13:02:55 +0000 |
| commit | 9deef20b6c4fa36d76cde43700301ca07cbdcc5c (patch) | |
| tree | 9618fa491c40d8628f7f9a645a1ef074b5ff5fcc /llvm/test | |
| parent | ddf6a333064bc81bfbeff901546b2aabf1ab3823 (diff) | |
| download | bcm5719-llvm-9deef20b6c4fa36d76cde43700301ca07cbdcc5c.tar.gz bcm5719-llvm-9deef20b6c4fa36d76cde43700301ca07cbdcc5c.zip | |
[ARM] Fix codegen for VLD3/VLD4/VST3/VST4 with WB
Code generation of VLD3, VLD4, VST3 and VST4 with register writeback is
broken due to 2 separate bugs:
1) VLD1d64TPseudoWB_register and VLD1d64QPseudoWB_register are missing
rules to expand them to non pseudo MIR. These are selected for
ARMISD::VLD3_UPD/VLD4_UPD with v1i64 vectors in SelectVLD.
2) Selection of the right VLD/VST instruction is broken for load and
store of 3 and 4 v1i64 vectors. SelectVLD and SelectVST are called
with MIR opcode for fixed writeback (ie increment is access size)
and call getVLDSTRegisterUpdateOpcode() to select an opcode with
register writeback if base register update is of a different size.
Since getVLDSTRegisterUpdateOpcode() only knows about
VLD1/VLD2/VST1/VST2 the call is currently conditional on the number
of element in the vector.
However, VLD1/VST1 is selected by SelectVLD/SelectVST's caller for
load and stores of 3 or 4 v1i64 vectors. Therefore the opcode is not
updated which later lead to a fixed writeback instruction being
constructed with an extra operand for the register writeback.
This patch addresses the two issues as follows:
- it adds the necessary mapping from VLD1d64TPseudoWB_register and
VLD1d64QPseudoWB_register to VLD1d64Twb_register and
VLD1d64Qwb_register respectively. Like for the existing _fixed
variants, the cost of these is bumped for unaligned access.
- it changes the logic in SelectVLD and SelectVSD to call isVLDfixed
and isVSTfixed respectively to decide whether the opcode should be
updated. It also reworks the logic and comments for pushing the
writeback offset operand and r0 operand to clarify the logic:
writeback offset needs to be pushed if it's a register writeback,
r0 needs to be pushed if not and the instruction is a
VLD1/VLD2/VST1/VST2.
Reviewers: rengolin, t.p.northover, samparker
Reviewed By: samparker
Patch by Thomas Preud'homme <thomas.preudhomme@arm.com>
Differential Revision: https://reviews.llvm.org/D42970
llvm-svn: 326570
Diffstat (limited to 'llvm/test')
| -rw-r--r-- | llvm/test/CodeGen/ARM/vld3.ll | 13 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/vld4.ll | 13 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/vst3.ll | 12 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/vst4.ll | 12 |
4 files changed, 50 insertions, 0 deletions
diff --git a/llvm/test/CodeGen/ARM/vld3.ll b/llvm/test/CodeGen/ARM/vld3.ll index 0eaad0f9003..46e17c97e6e 100644 --- a/llvm/test/CodeGen/ARM/vld3.ll +++ b/llvm/test/CodeGen/ARM/vld3.ll @@ -96,6 +96,19 @@ define <1 x i64> @vld3i64_update(i64** %ptr, i64* %A) nounwind { ret <1 x i64> %tmp4 } +define <1 x i64> @vld3i64_reg_update(i64** %ptr, i64* %A) nounwind { +;CHECK-LABEL: vld3i64_reg_update: +;CHECK: vld1.64 {d16, d17, d18}, [{{r[0-9]+|lr}}:64], {{r[0-9]+|lr}} + %tmp0 = bitcast i64* %A to i8* + %tmp1 = call %struct.__neon_int64x1x3_t @llvm.arm.neon.vld3.v1i64.p0i8(i8* %tmp0, i32 16) + %tmp5 = getelementptr i64, i64* %A, i32 1 + store i64* %tmp5, i64** %ptr + %tmp2 = extractvalue %struct.__neon_int64x1x3_t %tmp1, 0 + %tmp3 = extractvalue %struct.__neon_int64x1x3_t %tmp1, 2 + %tmp4 = add <1 x i64> %tmp2, %tmp3 + ret <1 x i64> %tmp4 +} + define <16 x i8> @vld3Qi8(i8* %A) nounwind { ;CHECK-LABEL: vld3Qi8: ;Check the alignment value. Max for this instruction is 64 bits: diff --git a/llvm/test/CodeGen/ARM/vld4.ll b/llvm/test/CodeGen/ARM/vld4.ll index 5663e6d41f0..679c9ae4450 100644 --- a/llvm/test/CodeGen/ARM/vld4.ll +++ b/llvm/test/CodeGen/ARM/vld4.ll @@ -96,6 +96,19 @@ define <1 x i64> @vld4i64_update(i64** %ptr, i64* %A) nounwind { ret <1 x i64> %tmp4 } +define <1 x i64> @vld4i64_reg_update(i64** %ptr, i64* %A) nounwind { +;CHECK-LABEL: vld4i64_reg_update: +;CHECK: vld1.64 {d16, d17, d18, d19}, [{{r[0-9]+|lr}}:256], {{r[0-9]+|lr}} + %tmp0 = bitcast i64* %A to i8* + %tmp1 = call %struct.__neon_int64x1x4_t @llvm.arm.neon.vld4.v1i64.p0i8(i8* %tmp0, i32 64) + %tmp5 = getelementptr i64, i64* %A, i32 1 + store i64* %tmp5, i64** %ptr + %tmp2 = extractvalue %struct.__neon_int64x1x4_t %tmp1, 0 + %tmp3 = extractvalue %struct.__neon_int64x1x4_t %tmp1, 2 + %tmp4 = add <1 x i64> %tmp2, %tmp3 + ret <1 x i64> %tmp4 +} + define <16 x i8> @vld4Qi8(i8* %A) nounwind { ;CHECK-LABEL: vld4Qi8: ;Check the alignment value. Max for this instruction is 256 bits: diff --git a/llvm/test/CodeGen/ARM/vst3.ll b/llvm/test/CodeGen/ARM/vst3.ll index d70d5957900..1723304e82b 100644 --- a/llvm/test/CodeGen/ARM/vst3.ll +++ b/llvm/test/CodeGen/ARM/vst3.ll @@ -73,6 +73,18 @@ define void @vst3i64_update(i64** %ptr, <1 x i64>* %B) nounwind { ret void } +define void @vst3i64_reg_update(i64** %ptr, <1 x i64>* %B) nounwind { +;CHECK-LABEL: vst3i64_reg_update +;CHECK: vst1.64 {d{{.*}}, d{{.*}}, d{{.*}}}, [r{{.*}}], r{{.*}} + %A = load i64*, i64** %ptr + %tmp0 = bitcast i64* %A to i8* + %tmp1 = load <1 x i64>, <1 x i64>* %B + call void @llvm.arm.neon.vst3.p0i8.v1i64(i8* %tmp0, <1 x i64> %tmp1, <1 x i64> %tmp1, <1 x i64> %tmp1, i32 1) + %tmp2 = getelementptr i64, i64* %A, i32 1 + store i64* %tmp2, i64** %ptr + ret void +} + define void @vst3Qi8(i8* %A, <16 x i8>* %B) nounwind { ;CHECK-LABEL: vst3Qi8: ;Check the alignment value. Max for this instruction is 64 bits: diff --git a/llvm/test/CodeGen/ARM/vst4.ll b/llvm/test/CodeGen/ARM/vst4.ll index afa4321c91a..ca9e5e7a59d 100644 --- a/llvm/test/CodeGen/ARM/vst4.ll +++ b/llvm/test/CodeGen/ARM/vst4.ll @@ -72,6 +72,18 @@ define void @vst4i64_update(i64** %ptr, <1 x i64>* %B) nounwind { ret void } +define void @vst4i64_reg_update(i64** %ptr, <1 x i64>* %B) nounwind { +;CHECK-LABEL: vst4i64_reg_update: +;CHECK: vst1.64 {d16, d17, d18, d19}, [r{{[0-9]+}}], r{{[0-9]+}} + %A = load i64*, i64** %ptr + %tmp0 = bitcast i64* %A to i8* + %tmp1 = load <1 x i64>, <1 x i64>* %B + call void @llvm.arm.neon.vst4.p0i8.v1i64(i8* %tmp0, <1 x i64> %tmp1, <1 x i64> %tmp1, <1 x i64> %tmp1, <1 x i64> %tmp1, i32 1) + %tmp2 = getelementptr i64, i64* %A, i32 1 + store i64* %tmp2, i64** %ptr + ret void +} + define void @vst4Qi8(i8* %A, <16 x i8>* %B) nounwind { ;CHECK-LABEL: vst4Qi8: ;Check the alignment value. Max for this instruction is 256 bits: |

