public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-4851] LoongArch: Use explicit relocs for addresses only used for one load or store with -mexplicit-relocs=
@ 2023-10-23  7:31 Xi Ruoyao
  0 siblings, 0 replies; only message in thread
From: Xi Ruoyao @ 2023-10-23  7:31 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:83e24e8c1e5eb3366e35d5b8494a4cd9a2395b59

commit r14-4851-g83e24e8c1e5eb3366e35d5b8494a4cd9a2395b59
Author: Xi Ruoyao <xry111@xry111.site>
Date:   Sun Oct 1 11:14:29 2023 +0800

    LoongArch: Use explicit relocs for addresses only used for one load or store with -mexplicit-relocs=auto and -mcmodel={normal,medium}
    
    In these cases, if we use explicit relocs, we end up with 2
    instructions:
    
        pcalau12i    t0, %pc_hi20(x)
        ld.d         t0, t0, %pc_lo12(x)
    
    If we use la.local pseudo-op, in the best scenario (x is in +/- 2MiB
    range) we still have 2 instructions:
    
        pcaddi       t0, %pcrel_20(x)
        ld.d         t0, t0, 0
    
    If x is out of the range we'll have 3 instructions.  So for these cases
    just emit machine instructions with explicit relocs.
    
    gcc/ChangeLog:
    
            * config/loongarch/predicates.md (symbolic_pcrel_operand): New
            predicate.
            * config/loongarch/loongarch.md (define_peephole2): Optimize
            la.local + ld/st to pcalau12i + ld/st if the address is only used
            once if -mexplicit-relocs=auto and -mcmodel=normal or medium.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/loongarch/explicit-relocs-auto-single-load-store.c:
            New test.
            * gcc.target/loongarch/explicit-relocs-auto-single-load-store-no-anchor.c:
            New test.

Diff:
---
 gcc/config/loongarch/loongarch.md                  | 122 +++++++++++++++++++++
 gcc/config/loongarch/predicates.md                 |   7 ++
 ...licit-relocs-auto-single-load-store-no-anchor.c |   6 +
 .../explicit-relocs-auto-single-load-store.c       |  14 +++
 4 files changed, 149 insertions(+)

diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index 695c8eb9a6f2..134734721711 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -65,6 +65,7 @@
 
   UNSPEC_LOAD_FROM_GOT
   UNSPEC_PCALAU12I
+  UNSPEC_PCALAU12I_GR
   UNSPEC_ORI_L_LO12
   UNSPEC_LUI_L_HI20
   UNSPEC_LUI_H_LO20
@@ -2297,6 +2298,16 @@
   "pcalau12i\t%0,%%pc_hi20(%1)"
   [(set_attr "type" "move")])
 
+;; @pcalau12i may be used for sibcall so it has a strict constraint.  This
+;; allows any general register as the operand.
+(define_insn "@pcalau12i_gr<mode>"
+  [(set (match_operand:P 0 "register_operand" "=r")
+       (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
+       UNSPEC_PCALAU12I_GR))]
+  ""
+  "pcalau12i\t%0,%%pc_hi20(%1)"
+  [(set_attr "type" "move")])
+
 (define_insn "@ori_l_lo12<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
 	(unspec:P [(match_operand:P 1 "register_operand" "r")
@@ -3748,6 +3759,117 @@
   [(set_attr "type" "unknown")
    (set_attr "mode" "<MODE>")])
 
+;; With normal or medium code models, if the only use of a pc-relative
+;; address is for loading or storing a value, then relying on linker
+;; relaxation is not better than emitting the machine instruction directly.
+;; Even if the la.local pseudo op can be relaxed, we get:
+;;
+;;     pcaddi     $t0, %pcrel_20(x)
+;;     ld.d       $t0, $t0, 0
+;;
+;; There are still two instructions, same as using the machine instructions
+;; and explicit relocs:
+;;
+;;     pcalau12i  $t0, %pc_hi20(x)
+;;     ld.d       $t0, $t0, %pc_lo12(x)
+;;
+;; And if the pseudo op cannot be relaxed, we'll get a worse result (with
+;; 3 instructions).
+(define_peephole2
+  [(set (match_operand:P 0 "register_operand")
+	(match_operand:P 1 "symbolic_pcrel_operand"))
+   (set (match_operand:GPR 2 "register_operand")
+	(mem:GPR (match_dup 0)))]
+  "la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO \
+   && (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM) \
+   && (peep2_reg_dead_p (2, operands[0]) \
+       || REGNO (operands[0]) == REGNO (operands[2]))"
+  [(set (match_dup 2) (mem:GPR (lo_sum:P (match_dup 0) (match_dup 1))))]
+  {
+    emit_insn (gen_pcalau12i_gr<P:mode> (operands[0], operands[1]));
+  })
+
+(define_peephole2
+  [(set (match_operand:P 0 "register_operand")
+	(match_operand:P 1 "symbolic_pcrel_operand"))
+   (set (match_operand:GPR 2 "register_operand")
+	(mem:GPR (plus (match_dup 0)
+		       (match_operand 3 "const_int_operand"))))]
+  "la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO \
+   && (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM) \
+   && (peep2_reg_dead_p (2, operands[0]) \
+       || REGNO (operands[0]) == REGNO (operands[2]))"
+  [(set (match_dup 2) (mem:GPR (lo_sum:P (match_dup 0) (match_dup 1))))]
+  {
+    operands[1] = plus_constant (Pmode, operands[1], INTVAL (operands[3]));
+    emit_insn (gen_pcalau12i_gr<P:mode> (operands[0], operands[1]));
+  })
+
+(define_peephole2
+  [(set (match_operand:P 0 "register_operand")
+	(match_operand:P 1 "symbolic_pcrel_operand"))
+   (set (match_operand:GPR 2 "register_operand")
+	(any_extend:GPR (mem:SUBDI (match_dup 0))))]
+  "la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO \
+   && (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM) \
+   && (peep2_reg_dead_p (2, operands[0]) \
+       || REGNO (operands[0]) == REGNO (operands[2]))"
+  [(set (match_dup 2)
+	(any_extend:GPR (mem:SUBDI (lo_sum:P (match_dup 0)
+					     (match_dup 1)))))]
+  {
+    emit_insn (gen_pcalau12i_gr<P:mode> (operands[0], operands[1]));
+  })
+
+(define_peephole2
+  [(set (match_operand:P 0 "register_operand")
+	(match_operand:P 1 "symbolic_pcrel_operand"))
+   (set (match_operand:GPR 2 "register_operand")
+	(any_extend:GPR
+	  (mem:SUBDI (plus (match_dup 0)
+			   (match_operand 3 "const_int_operand")))))]
+  "la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO \
+   && (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM) \
+   && (peep2_reg_dead_p (2, operands[0]) \
+       || REGNO (operands[0]) == REGNO (operands[2]))"
+  [(set (match_dup 2)
+	(any_extend:GPR (mem:SUBDI (lo_sum:P (match_dup 0)
+					     (match_dup 1)))))]
+  {
+    operands[1] = plus_constant (Pmode, operands[1], INTVAL (operands[3]));
+    emit_insn (gen_pcalau12i_gr<P:mode> (operands[0], operands[1]));
+  })
+
+(define_peephole2
+  [(set (match_operand:P 0 "register_operand")
+	(match_operand:P 1 "symbolic_pcrel_operand"))
+   (set (mem:QHWD (match_dup 0))
+	(match_operand:QHWD 2 "register_operand"))]
+  "la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO \
+   && (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM) \
+   && (peep2_reg_dead_p (2, operands[0])) \
+   && REGNO (operands[0]) != REGNO (operands[2])"
+  [(set (mem:QHWD (lo_sum:P (match_dup 0) (match_dup 1))) (match_dup 2))]
+  {
+    emit_insn (gen_pcalau12i_gr<P:mode> (operands[0], operands[1]));
+  })
+
+(define_peephole2
+  [(set (match_operand:P 0 "register_operand")
+	(match_operand:P 1 "symbolic_pcrel_operand"))
+   (set (mem:QHWD (plus (match_dup 0)
+			(match_operand 3 "const_int_operand")))
+	(match_operand:QHWD 2 "register_operand"))]
+  "la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO \
+   && (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM) \
+   && (peep2_reg_dead_p (2, operands[0])) \
+   && REGNO (operands[0]) != REGNO (operands[2])"
+  [(set (mem:QHWD (lo_sum:P (match_dup 0) (match_dup 1))) (match_dup 2))]
+  {
+    operands[1] = plus_constant (Pmode, operands[1], INTVAL (operands[3]));
+    emit_insn (gen_pcalau12i_gr<P:mode> (operands[0], operands[1]));
+  })
+
 ;; Synchronization instructions.
 
 (include "sync.md")
diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md
index 359878f5bcf2..946ed0d8212d 100644
--- a/gcc/config/loongarch/predicates.md
+++ b/gcc/config/loongarch/predicates.md
@@ -563,6 +563,13 @@
   return loongarch_symbolic_constant_p (op, &type);
 })
 
+(define_predicate "symbolic_pcrel_operand"
+  (match_code "const,symbol_ref,label_ref")
+{
+  enum loongarch_symbol_type type;
+  return loongarch_symbolic_constant_p (op, &type) && type == SYMBOL_PCREL;
+})
+
 (define_predicate "equality_operator"
   (match_code "eq,ne"))
 
diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-single-load-store-no-anchor.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-single-load-store-no-anchor.c
new file mode 100644
index 000000000000..fb03403d756e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-single-load-store-no-anchor.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d -mexplicit-relocs=auto -fno-section-anchors" } */
+
+#include "explicit-relocs-auto-single-load-store.c"
+
+/* { dg-final { scan-assembler-not "la.local" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-single-load-store.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-single-load-store.c
new file mode 100644
index 000000000000..0d53644cda70
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-single-load-store.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d -mexplicit-relocs=auto" } */
+
+long a;
+int b;
+unsigned int c;
+
+long load_a() { return a; }
+long load_b() { return b; }
+long load_c() { return c; }
+void store_a(long x) { a = x; }
+void store_b(int x) { b = x; }
+
+/* { dg-final { scan-assembler-not "la.local" } } */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-10-23  7:31 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-23  7:31 [gcc r14-4851] LoongArch: Use explicit relocs for addresses only used for one load or store with -mexplicit-relocs= Xi Ruoyao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).