[llvm] 2b91b5b - [AArch64][SVE] Use ADD/ADR instead of MUL/MLA for x*N (#198566)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 24 03:43:34 PDT 2026
Author: Tomas Matheson
Date: 2026-06-24T11:43:29+01:00
New Revision: 2b91b5b61a218c102e75806f5d1381a9861977d1
URL: https://github.com/llvm/llvm-project/commit/2b91b5b61a218c102e75806f5d1381a9861977d1
DIFF: https://github.com/llvm/llvm-project/commit/2b91b5b61a218c102e75806f5d1381a9861977d1.diff
LOG: [AArch64][SVE] Use ADD/ADR instead of MUL/MLA for x*N (#198566)
Avoid `MUL`/`MLA` for all-active multiplies by small constants when
cheaper `ADD`/`ADR` sequences are available.
Vector multiplication (int32_t/uint32_t base types) by 2, 3, 5, 9 can be
done with ADD (for 2) ADR (for 3,5,9).
Similarly, operations of the form a + x * {1,2,4,8} can use ADR.
Added:
llvm/test/CodeGen/AArch64/sve-mul-imm-add-adr.ll
Modified:
llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
llvm/test/CodeGen/AArch64/sve-intrinsics-int-arith-undef.ll
llvm/test/CodeGen/AArch64/sve2-histcnt.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 4712406e37e6b..64dab3296dddd 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -1948,6 +1948,57 @@ let Predicates = [HasSVE] in {
defm : adrShiftPat<nxv4i32, nxv4i1, i32, ADR_LSL_ZZZ_S_2, 2>;
defm : adrShiftPat<nxv4i32, nxv4i1, i32, ADR_LSL_ZZZ_S_3, 3>;
+ // Avoid MUL/MLA for small constants where ADD/ADR forms are available.
+ multiclass sveMulMlaImmAddAdrPat<ValueType Ty, ValueType PredTy,
+ ValueType ScalarTy,
+ Instruction Add, Instruction Adr1,
+ Instruction Adr2, Instruction Adr3> {
+ // MUL
+ def : Pat<(Ty (AArch64mul_p (PredTy (SVEAnyPredicate)), Ty:$Op,
+ (Ty (splat_vector (ScalarTy 2))))),
+ (Add $Op, $Op)>;
+ def : Pat<(Ty (AArch64mul_p (PredTy (SVEAnyPredicate)), Ty:$Op,
+ (Ty (splat_vector (ScalarTy 3))))),
+ (Adr1 $Op, $Op)>;
+ def : Pat<(Ty (AArch64mul_p (PredTy (SVEAnyPredicate)), Ty:$Op,
+ (Ty (splat_vector (ScalarTy 5))))),
+ (Adr2 $Op, $Op)>;
+ def : Pat<(Ty (AArch64mul_p (PredTy (SVEAnyPredicate)), Ty:$Op,
+ (Ty (splat_vector (ScalarTy 9))))),
+ (Adr3 $Op, $Op)>;
+
+ // MLA
+ def : Pat<(Ty (AArch64mla_p (PredTy (SVEAnyPredicate)), Ty:$Acc, Ty:$Op,
+ (Ty (splat_vector (ScalarTy 2))))),
+ (Adr1 $Acc, $Op)>;
+ def : Pat<(Ty (AArch64mla_p (PredTy (SVEAnyPredicate)), Ty:$Acc, Ty:$Op,
+ (Ty (splat_vector (ScalarTy 4))))),
+ (Adr2 $Acc, $Op)>;
+ def : Pat<(Ty (AArch64mla_p (PredTy (SVEAnyPredicate)), Ty:$Acc, Ty:$Op,
+ (Ty (splat_vector (ScalarTy 8))))),
+ (Adr3 $Acc, $Op)>;
+
+ // MLA commuted. These can be removed if the commuted forms are canonicalized.
+ def : Pat<(Ty (AArch64mla_p (PredTy (SVEAnyPredicate)), Ty:$Acc,
+ (Ty (splat_vector (ScalarTy 2))), Ty:$Op)),
+ (Adr1 $Acc, $Op)>;
+ def : Pat<(Ty (AArch64mla_p (PredTy (SVEAnyPredicate)), Ty:$Acc,
+ (Ty (splat_vector (ScalarTy 4))), Ty:$Op)),
+ (Adr2 $Acc, $Op)>;
+ def : Pat<(Ty (AArch64mla_p (PredTy (SVEAnyPredicate)), Ty:$Acc,
+ (Ty (splat_vector (ScalarTy 8))), Ty:$Op)),
+ (Adr3 $Acc, $Op)>;
+ }
+
+ let AddedComplexity = 10 in {
+ defm : sveMulMlaImmAddAdrPat<nxv2i64, nxv2i1, i64,
+ ADD_ZZZ_D, ADR_LSL_ZZZ_D_1,
+ ADR_LSL_ZZZ_D_2, ADR_LSL_ZZZ_D_3>;
+ defm : sveMulMlaImmAddAdrPat<nxv4i32, nxv4i1, i32,
+ ADD_ZZZ_S, ADR_LSL_ZZZ_S_1,
+ ADR_LSL_ZZZ_S_2, ADR_LSL_ZZZ_S_3>;
+ }
+
// adr z0.d, [z0.d, z0.d, uxtw #<shift>]
// adr z0.d, [z0.d, z0.d, sxtw #<shift>]
multiclass adrXtwShiftPat<ValueType Ty, ValueType PredTy, int ShiftAmt> {
diff --git a/llvm/test/CodeGen/AArch64/sve-intrinsics-int-arith-undef.ll b/llvm/test/CodeGen/AArch64/sve-intrinsics-int-arith-undef.ll
index 82b39785a07b5..1446f6956cf04 100644
--- a/llvm/test/CodeGen/AArch64/sve-intrinsics-int-arith-undef.ll
+++ b/llvm/test/CodeGen/AArch64/sve-intrinsics-int-arith-undef.ll
@@ -301,7 +301,7 @@ define <vscale x 8 x i16> @mul_imm_i16(<vscale x 8 x i1> %pg, <vscale x 8 x i16>
define <vscale x 4 x i32> @mul_imm_i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a) {
; CHECK-LABEL: mul_imm_i32:
; CHECK: // %bb.0:
-; CHECK-NEXT: mul z0.s, z0.s, #5
+; CHECK-NEXT: adr z0.s, [z0.s, z0.s, lsl #2]
; CHECK-NEXT: ret
%out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.u.nxv4i32(<vscale x 4 x i1> %pg,
<vscale x 4 x i32> %a,
diff --git a/llvm/test/CodeGen/AArch64/sve-mul-imm-add-adr.ll b/llvm/test/CodeGen/AArch64/sve-mul-imm-add-adr.ll
new file mode 100644
index 0000000000000..91423fc1d068d
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve-mul-imm-add-adr.ll
@@ -0,0 +1,372 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve < %s | FileCheck %s
+
+
+define <vscale x 4 x i32> @mul_i32_by_2(<vscale x 4 x i32> %x) {
+; CHECK-LABEL: mul_i32_by_2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: lsl z0.s, z0.s, #1
+; CHECK-NEXT: ret
+ %out = mul <vscale x 4 x i32> %x, splat(i32 2)
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @mul_i32_by_3(<vscale x 4 x i32> %x) {
+; CHECK-LABEL: mul_i32_by_3:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z0.s, lsl #1]
+; CHECK-NEXT: ret
+ %out = mul <vscale x 4 x i32> %x, splat(i32 3)
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @mul_i32_by_5(<vscale x 4 x i32> %x) {
+; CHECK-LABEL: mul_i32_by_5:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z0.s, lsl #2]
+; CHECK-NEXT: ret
+ %out = mul <vscale x 4 x i32> %x, splat(i32 5)
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @mul_i32_by_9(<vscale x 4 x i32> %x) {
+; CHECK-LABEL: mul_i32_by_9:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z0.s, lsl #3]
+; CHECK-NEXT: ret
+ %out = mul <vscale x 4 x i32> %x, splat(i32 9)
+ ret <vscale x 4 x i32> %out
+}
+
+
+define <vscale x 2 x i64> @mul_i64_by_2_commuted(<vscale x 2 x i64> %x) {
+; CHECK-LABEL: mul_i64_by_2_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: lsl z0.d, z0.d, #1
+; CHECK-NEXT: ret
+ %out = mul <vscale x 2 x i64> splat(i64 2), %x
+ ret <vscale x 2 x i64> %out
+}
+
+define <vscale x 2 x i64> @mul_i64_by_3_commuted(<vscale x 2 x i64> %x) {
+; CHECK-LABEL: mul_i64_by_3_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.d, [z0.d, z0.d, lsl #1]
+; CHECK-NEXT: ret
+ %out = mul <vscale x 2 x i64> splat(i64 3), %x
+ ret <vscale x 2 x i64> %out
+}
+
+define <vscale x 2 x i64> @mul_i64_by_5_commuted(<vscale x 2 x i64> %x) {
+; CHECK-LABEL: mul_i64_by_5_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.d, [z0.d, z0.d, lsl #2]
+; CHECK-NEXT: ret
+ %out = mul <vscale x 2 x i64> splat(i64 5), %x
+ ret <vscale x 2 x i64> %out
+}
+
+define <vscale x 2 x i64> @mul_i64_by_9_commuted(<vscale x 2 x i64> %x) {
+; CHECK-LABEL: mul_i64_by_9_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.d, [z0.d, z0.d, lsl #3]
+; CHECK-NEXT: ret
+ %out = mul <vscale x 2 x i64> splat(i64 9), %x
+ ret <vscale x 2 x i64> %out
+}
+
+
+define <vscale x 4 x i32> @mla_i32_by_2(<vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: mla_i32_by_2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z1.s, lsl #1]
+; CHECK-NEXT: ret
+ %mul = mul <vscale x 4 x i32> %x, splat(i32 2)
+ %out = add <vscale x 4 x i32> %a, %mul
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @mla_i32_by_4(<vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: mla_i32_by_4:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z1.s, lsl #2]
+; CHECK-NEXT: ret
+ %mul = mul <vscale x 4 x i32> %x, splat(i32 4)
+ %out = add <vscale x 4 x i32> %a, %mul
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @mla_i32_by_8(<vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: mla_i32_by_8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z1.s, lsl #3]
+; CHECK-NEXT: ret
+ %mul = mul <vscale x 4 x i32> %x, splat(i32 8)
+ %out = add <vscale x 4 x i32> %a, %mul
+ ret <vscale x 4 x i32> %out
+}
+
+
+define <vscale x 2 x i64> @mla_i64_by_2_commuted(<vscale x 2 x i64> %a, <vscale x 2 x i64> %x) {
+; CHECK-LABEL: mla_i64_by_2_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.d, [z0.d, z1.d, lsl #1]
+; CHECK-NEXT: ret
+ %mul = mul <vscale x 2 x i64> splat(i64 2), %x
+ %out = add <vscale x 2 x i64> %a, %mul
+ ret <vscale x 2 x i64> %out
+}
+
+define <vscale x 2 x i64> @mla_i64_by_4_commuted(<vscale x 2 x i64> %a, <vscale x 2 x i64> %x) {
+; CHECK-LABEL: mla_i64_by_4_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.d, [z0.d, z1.d, lsl #2]
+; CHECK-NEXT: ret
+ %mul = mul <vscale x 2 x i64> splat(i64 4), %x
+ %out = add <vscale x 2 x i64> %a, %mul
+ ret <vscale x 2 x i64> %out
+}
+
+define <vscale x 2 x i64> @mla_i64_by_8_commuted(<vscale x 2 x i64> %a, <vscale x 2 x i64> %x) {
+; CHECK-LABEL: mla_i64_by_8_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.d, [z0.d, z1.d, lsl #3]
+; CHECK-NEXT: ret
+ %mul = mul <vscale x 2 x i64> splat(i64 8), %x
+ %out = add <vscale x 2 x i64> %a, %mul
+ ret <vscale x 2 x i64> %out
+}
+
+
+define <vscale x 4 x i32> @svmul_u_i32_by_2(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_u_i32_by_2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: add z0.s, z0.s, z0.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 2))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmul_u_i32_by_3(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_u_i32_by_3:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z0.s, lsl #1]
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 3))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmul_u_i32_by_5(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_u_i32_by_5:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z0.s, lsl #2]
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 5))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmul_u_i32_by_9(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_u_i32_by_9:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z0.s, lsl #3]
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 9))
+ ret <vscale x 4 x i32> %out
+}
+
+
+define <vscale x 4 x i32> @svmul_m_partial_i32_by_2(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_m_partial_i32_by_2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z1.s, #2 // =0x2
+; CHECK-NEXT: mul z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 2))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmul_m_partial_i32_by_3(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_m_partial_i32_by_3:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z1.s, #3 // =0x3
+; CHECK-NEXT: mul z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 3))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmul_m_partial_i32_by_5(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_m_partial_i32_by_5:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z1.s, #5 // =0x5
+; CHECK-NEXT: mul z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 5))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmul_m_partial_i32_by_9(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_m_partial_i32_by_9:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z1.s, #9 // =0x9
+; CHECK-NEXT: mul z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 9))
+ ret <vscale x 4 x i32> %out
+}
+
+
+define <vscale x 4 x i32> @svmul_u_i32_by_2_commuted(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_u_i32_by_2_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z1.s, #2 // =0x2
+; CHECK-NEXT: mul z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> splat(i32 2), <vscale x 4 x i32> %x)
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmul_u_i32_by_3_commuted(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_u_i32_by_3_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z1.s, #3 // =0x3
+; CHECK-NEXT: mul z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> splat(i32 3), <vscale x 4 x i32> %x)
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmul_u_i32_by_5_commuted(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_u_i32_by_5_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z1.s, #5 // =0x5
+; CHECK-NEXT: mul z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> splat(i32 5), <vscale x 4 x i32> %x)
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmul_u_i32_by_9_commuted(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmul_u_i32_by_9_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z1.s, #9 // =0x9
+; CHECK-NEXT: mul z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mul.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> splat(i32 9), <vscale x 4 x i32> %x)
+ ret <vscale x 4 x i32> %out
+}
+
+
+define <vscale x 4 x i32> @svmla_u_i32_by_2(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmla_u_i32_by_2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z1.s, lsl #1]
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mla.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 2))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmla_u_i32_by_4(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmla_u_i32_by_4:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z1.s, lsl #2]
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mla.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 4))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmla_u_i32_by_8(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmla_u_i32_by_8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z1.s, lsl #3]
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mla.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 8))
+ ret <vscale x 4 x i32> %out
+}
+
+
+define <vscale x 4 x i32> @svmla_u_i32_by_2_commuted(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmla_u_i32_by_2_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z1.s, lsl #1]
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mla.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> splat(i32 2), <vscale x 4 x i32> %x)
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmla_u_i32_by_4_commuted(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmla_u_i32_by_4_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z1.s, lsl #2]
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mla.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> splat(i32 4), <vscale x 4 x i32> %x)
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmla_u_i32_by_8_commuted(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmla_u_i32_by_8_commuted:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.s, [z0.s, z1.s, lsl #3]
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mla.u.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> splat(i32 8), <vscale x 4 x i32> %x)
+ ret <vscale x 4 x i32> %out
+}
+
+
+define <vscale x 4 x i32> @svmla_m_partial_i32_by_2(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmla_m_partial_i32_by_2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z2.s, #2 // =0x2
+; CHECK-NEXT: mla z0.s, p0/m, z1.s, z2.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mla.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 2))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmla_m_partial_i32_by_4(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmla_m_partial_i32_by_4:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z2.s, #4 // =0x4
+; CHECK-NEXT: mla z0.s, p0/m, z1.s, z2.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mla.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 4))
+ ret <vscale x 4 x i32> %out
+}
+
+define <vscale x 4 x i32> @svmla_m_partial_i32_by_8(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x) {
+; CHECK-LABEL: svmla_m_partial_i32_by_8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov z2.s, #8 // =0x8
+; CHECK-NEXT: mla z0.s, p0/m, z1.s, z2.s
+; CHECK-NEXT: ret
+ %out = call <vscale x 4 x i32> @llvm.aarch64.sve.mla.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %x, <vscale x 4 x i32> splat(i32 8))
+ ret <vscale x 4 x i32> %out
+}
+
+
+define <vscale x 2 x i64> @svmla_u_i64_by_2(<vscale x 2 x i1> %pg, <vscale x 2 x i64> %a, <vscale x 2 x i64> %x) {
+; CHECK-LABEL: svmla_u_i64_by_2:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.d, [z0.d, z1.d, lsl #1]
+; CHECK-NEXT: ret
+ %out = call <vscale x 2 x i64> @llvm.aarch64.sve.mla.u.nxv2i64(<vscale x 2 x i1> %pg, <vscale x 2 x i64> %a, <vscale x 2 x i64> %x, <vscale x 2 x i64> splat(i64 2))
+ ret <vscale x 2 x i64> %out
+}
+
+define <vscale x 2 x i64> @svmla_u_i64_by_4(<vscale x 2 x i1> %pg, <vscale x 2 x i64> %a, <vscale x 2 x i64> %x) {
+; CHECK-LABEL: svmla_u_i64_by_4:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.d, [z0.d, z1.d, lsl #2]
+; CHECK-NEXT: ret
+ %out = call <vscale x 2 x i64> @llvm.aarch64.sve.mla.u.nxv2i64(<vscale x 2 x i1> %pg, <vscale x 2 x i64> %a, <vscale x 2 x i64> %x, <vscale x 2 x i64> splat(i64 4))
+ ret <vscale x 2 x i64> %out
+}
+
+define <vscale x 2 x i64> @svmla_u_i64_by_8(<vscale x 2 x i1> %pg, <vscale x 2 x i64> %a, <vscale x 2 x i64> %x) {
+; CHECK-LABEL: svmla_u_i64_by_8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adr z0.d, [z0.d, z1.d, lsl #3]
+; CHECK-NEXT: ret
+ %out = call <vscale x 2 x i64> @llvm.aarch64.sve.mla.u.nxv2i64(<vscale x 2 x i1> %pg, <vscale x 2 x i64> %a, <vscale x 2 x i64> %x, <vscale x 2 x i64> splat(i64 8))
+ ret <vscale x 2 x i64> %out
+}
diff --git a/llvm/test/CodeGen/AArch64/sve2-histcnt.ll b/llvm/test/CodeGen/AArch64/sve2-histcnt.ll
index 6596abe2f105a..a49bdafb8a46a 100644
--- a/llvm/test/CodeGen/AArch64/sve2-histcnt.ll
+++ b/llvm/test/CodeGen/AArch64/sve2-histcnt.ll
@@ -147,10 +147,8 @@ define void @histogram_i16_literal_2(ptr %base, <vscale x 4 x i32> %indices, <vs
; CHECK-LABEL: histogram_i16_literal_2:
; CHECK: // %bb.0:
; CHECK-NEXT: histcnt z1.s, p0/z, z0.s, z0.s
-; CHECK-NEXT: mov z3.s, #2 // =0x2
; CHECK-NEXT: ld1h { z2.s }, p0/z, [x0, z0.s, sxtw #1]
-; CHECK-NEXT: ptrue p1.s
-; CHECK-NEXT: mad z1.s, p1/m, z3.s, z2.s
+; CHECK-NEXT: adr z1.s, [z2.s, z1.s, lsl #1]
; CHECK-NEXT: st1h { z1.s }, p0, [x0, z0.s, sxtw #1]
; CHECK-NEXT: ret
%buckets = getelementptr i16, ptr %base, <vscale x 4 x i32> %indices
More information about the llvm-commits
mailing list