In some cases, the pre pass will separate the shift and add of
shift+add+ld/st ins into different blocks, resulting in combine ldx/stx
instead of alsl, but for consecutive reg+reg memory access instructions,
this may cause read port conflicts and reduce efficiency.
Try to directly generate alsl, processing the following RTL into alsl:
(plus:DI (mult:DI (reg/v:DI 81 [ index ])
(const_int 4 [0x4]))
(reg/f:DI 84))
todo:
(plus:DI (ashift:DI (reg/v:DI 81 [ index ])
(const_int 2 [0x4]))
(reg/f:DI 84))
ADD_OPTIONS: -mcombine-addr-alsl
gcc/ChangeLog:
* config/loongarch/genopts/loongarch.opt.in: Add new option.
* config/loongarch/loongarch.cc: Add specific case function.
* config/loongarch/loongarch.opt: Add new option.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/alsl_addr.c: New test.
---
gcc/config/loongarch/genopts/loongarch.opt.in | 4 ++
gcc/config/loongarch/loongarch.cc | 37 +++++++++++++++++++
gcc/config/loongarch/loongarch.opt | 4 ++
.../gcc.target/loongarch/alsl_addr.c | 34 +++++++++++++++++
4 files changed, 79 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/loongarch/alsl_addr.c
diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in
b/gcc/config/loongarch/genopts/loongarch.opt.in
index f0c089a928e..b8e4ed6cebe 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -313,3 +313,7 @@ HOST_WIDE_INT la_isa_evolution = 0
mannotate-tablejump
Target Mask(ANNOTATE_TABLEJUMP) Save
Annotate table jump instruction (jr {reg}) to correlate it with the jump table.
+
+mcombine-addr-alsl
+Target Var(flag_la_combine_addr_alsl) Optimization Init(0)
+Enable to simplify instructions of base address and index to alsl.
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index fcca0ec8252..c10f0df9472 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -3419,6 +3419,22 @@ mem_shadd_or_shadd_rtx_p (rtx x)
&& IN_RANGE (exact_log2 (INTVAL (XEXP (x, 1))), 1, 3))));
}
+/* Helper loongarch_legitimize_address. Given X, return true if it
+ is a left shift by 1, 2, 3 or 4 positions or a multiply by 2, 4, 8 or 16.
+
+ This respectively represent canonical shift-add rtxs or scaled
+ memory addresses. */
+static bool
+mem_shadd_or_shadd_rtx_p_1 (rtx x)
+{
+ return ((GET_CODE (x) == ASHIFT
+ || GET_CODE (x) == MULT)
+ && CONST_INT_P (XEXP (x, 1))
+ && ((GET_CODE (x) == ASHIFT && IN_RANGE (INTVAL (XEXP (x, 1)), 1, 4))
+ || (GET_CODE (x) == MULT
+ && IN_RANGE (exact_log2 (INTVAL (XEXP (x, 1))), 1, 4))));
+}
+
/* This function is used to implement LEGITIMIZE_ADDRESS. If X can
be legitimized in a way that the generic machinery might not expect,
return a new address, otherwise return NULL. MODE is the mode of
@@ -3475,6 +3491,27 @@ loongarch_legitimize_address (rtx x, rtx oldx
ATTRIBUTE_UNUSED,
return loongarch_force_address (addr, mode);
}
+ if (flag_la_combine_addr_alsl
+ && oldx == x
+ && GET_CODE (x) == PLUS && mem_shadd_or_shadd_rtx_p_1 (XEXP (x, 0))
+ && REG_P (XEXP (x, 1)))
+ {
+ rtx index = XEXP (x, 0);
+ rtx org_base = XEXP (x, 1);
+
+ int shift_val = INTVAL (XEXP (index, 1));
+ if (GET_CODE (index) == MULT)
+ shift_val = exact_log2 (shift_val);
+
+ rtx reg1 = gen_reg_rtx (Pmode);
+ loongarch_emit_binary (PLUS, reg1,
+ gen_rtx_ASHIFT (Pmode, XEXP (index, 0),
+ GEN_INT (shift_val)),
+ org_base);
+
+ return reg1;
+ }
+
return x;
}
diff --git a/gcc/config/loongarch/loongarch.opt
b/gcc/config/loongarch/loongarch.opt
index 628eabe8d59..1bcfa7f3fd1 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -345,3 +345,7 @@ Support sc.q instruction.
mld-seq-sa
Target Mask(ISA_LD_SEQ_SA) Var(la_isa_evolution)
Do not need load-load barriers (dbar 0x700).
+
+mcombine-addr-alsl
+Target Var(flag_la_combine_addr_alsl) Optimization Init(0)
+Enable to simplify instructions of base address and index to alsl.
diff --git a/gcc/testsuite/gcc.target/loongarch/alsl_addr.c
b/gcc/testsuite/gcc.target/loongarch/alsl_addr.c
new file mode 100644
index 00000000000..9eca0c48964
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/alsl_addr.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcombine-addr-alsl" } */
+
+extern int arr_i[];
+extern float arr_f[];
+
+void
+foo_i (int index, int ra, int rb)
+{
+ int org = arr_i[index];
+ arr_i[index] = ra;
+
+ if (ra > rb)
+ arr_i[ra] = org;
+ else
+ arr_i[rb] = org;
+}
+
+void
+foo_f (int index, int ra, int rb, float rc)
+{
+ float org = arr_f[index];
+ arr_f[index] = rc;
+
+ if (ra > rb)
+ arr_f[ra] = org;
+ else
+ arr_f[rb] = org;
+}
+
+/* { dg-final { scan-assembler-not "ldx\.\[dw\]" } } */
+/* { dg-final { scan-assembler-not "fldx\.\[sw\]" } } */
+/* { dg-final { scan-assembler-not "stx\.\[dw\]" } } */
+/* { dg-final { scan-assembler-not "fstx\.\[sw\]" } } */
--
2.20.1