diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -1693,8 +1693,14 @@ multiclass unpred_store { - def : Pat<(Store (Ty ZPR:$val), (am_sve_fi GPR64sp:$base, simm4s1:$offset)), - (RegImmInst ZPR:$val, (PTrue 31), GPR64sp:$base, simm4s1:$offset)>; + let AddedComplexity = 1 in { + def _imm : Pat<(Store (Ty ZPR:$val), (am_sve_indexed_s4 GPR64sp:$base, simm4s1:$offset)), + (RegImmInst ZPR:$val, (PTrue 31), GPR64sp:$base, simm4s1:$offset)>; + } + let AddedComplexity = 2 in { + def _fi : Pat<(Store (Ty ZPR:$val), (am_sve_fi GPR64sp:$base, simm4s1:$offset)), + (RegImmInst ZPR:$val, (PTrue 31), GPR64sp:$base, simm4s1:$offset)>; + } def : Pat<(Store (Ty ZPR:$val), GPR64:$base), (RegImmInst ZPR:$val, (PTrue 31), GPR64:$base, (i64 0))>; diff --git a/llvm/test/CodeGen/AArch64/sve-st1-addressing-mode-reg-imm.ll b/llvm/test/CodeGen/AArch64/sve-st1-addressing-mode-reg-imm.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve-st1-addressing-mode-reg-imm.ll @@ -0,0 +1,102 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve < %s | FileCheck %s + +; ST1B + +define void @st1b_lower_bound( %data, * %a) { +; CHECK-LABEL: st1b_lower_bound: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p0.b +; CHECK-NEXT: st1b { z0.b }, p0, [x0, #-8, mul vl] +; CHECK-NEXT: ret + %base = getelementptr , * %a, i64 -8 + store %data, * %base + ret void +} + +define void @st1b_inbound( %data, * %a) { +; CHECK-LABEL: st1b_inbound: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p0.b +; CHECK-NEXT: st1b { z0.b }, p0, [x0, #1, mul vl] +; CHECK-NEXT: ret + %base = getelementptr , * %a, i64 1 + store %data, * %base + ret void +} + +define void @st1b_upper_bound( %data, * %a) { +; CHECK-LABEL: st1b_upper_bound: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p0.b +; CHECK-NEXT: st1b { z0.b }, p0, [x0, #7, mul vl] +; CHECK-NEXT: ret + %base = getelementptr , * %a, i64 7 + store %data, * %base + ret void +} + +define void @st1b_out_of_upper_bound( %data, * %a) { +; CHECK-LABEL: st1b_out_of_upper_bound: +; CHECK: // %bb.0: +; CHECK-NEXT: rdvl x8, #8 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ptrue p0.b +; CHECK-NEXT: st1b { z0.b }, p0, [x8] +; CHECK-NEXT: ret + %base = getelementptr , * %a, i64 8 + store %data, * %base + ret void +} + +define void @st1b_out_of_lower_bound( %data, * %a) { +; CHECK-LABEL: st1b_out_of_lower_bound: +; CHECK: // %bb.0: +; CHECK-NEXT: rdvl x8, #-9 +; CHECK-NEXT: add x8, x0, x8 +; CHECK-NEXT: ptrue p0.b +; CHECK-NEXT: st1b { z0.b }, p0, [x8] +; CHECK-NEXT: ret + %base = getelementptr , * %a, i64 -9 + store %data, * %base + ret void +} + +; ST1H + +define void @st1h_inbound( %data, * %a) { +; CHECK-LABEL: st1h_inbound: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p0.h +; CHECK-NEXT: st1h { z0.h }, p0, [x0, #-6, mul vl] +; CHECK-NEXT: ret + %base = getelementptr , * %a, i64 -6 + store %data, * %base + ret void +} + +; ST1W + +define void @st1w_inbound( %data, * %a) { +; CHECK-LABEL: st1w_inbound: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p0.s +; CHECK-NEXT: st1w { z0.s }, p0, [x0, #2, mul vl] +; CHECK-NEXT: ret + %base = getelementptr , * %a, i64 2 + store %data, * %base + ret void +} + +; ST1D + +define void @st1d_inbound( %data, * %a) { +; CHECK-LABEL: st1d_inbound: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p0.d +; CHECK-NEXT: st1d { z0.d }, p0, [x0, #5, mul vl] +; CHECK-NEXT: ret + %base = getelementptr , * %a, i64 5 + store %data, * %base + ret void +}