From: Matthew Fortune <[email protected]>
This option redirects the destination of a load to $0 if it is
volatile and the result is not used.
Mark R6 unaligned access.
gcc/ChangeLog:
* config/mips/loongson-mmi.md: Add the additional
argument.
* config/mips/mips-msa.md: Likewise.
* config/mips/mips-protos.h (mips_output_move): Add
the additional parameter.
* config/mips/mips.cc (mips_output_move): Perform
the redirection. Mark unaligned load and store with
a comment.
* config/mips/mips.md: Same as the other .md files.
* config/mips/mips.opt: Add the option -mdead-loads.
* doc/invoke.texi: Document the option -mdead-loads.
gcc/testsuite/ChangeLog:
* gcc.target/mips/dead-loads-1.c: New test.
* gcc.target/mips/dead-loads-2.c: New test.
* gcc.target/mips/mips.exp: Add dead-loads to the test options.
Cherry-picked a9a9df621143d9cac0e898f2a0bedd98b4db8ae4,
and 42be7aa50f3b04a88768e08c000cfe7923f22b0f
from https://github.com/MIPS/gcc
Signed-off-by: Matthew Fortune <[email protected]>
Signed-off-by: Faraz Shahbazker <[email protected]>
Signed-off-by: Aleksandar Rakic <[email protected]>
Signed-off-by: Eldar Osmanovic <[email protected]>
---
gcc/config/mips/loongson-mmi.md | 2 +-
gcc/config/mips/mips-msa.md | 2 +-
gcc/config/mips/mips-protos.h | 2 +-
gcc/config/mips/mips.cc | 57 +++++++++++++++-----
gcc/config/mips/mips.md | 54 +++++++++----------
gcc/config/mips/mips.opt | 4 ++
gcc/doc/invoke.texi | 13 +++++
gcc/testsuite/gcc.target/mips/dead-loads-1.c | 11 ++++
gcc/testsuite/gcc.target/mips/dead-loads-2.c | 12 +++++
gcc/testsuite/gcc.target/mips/mips.exp | 1 +
10 files changed, 116 insertions(+), 42 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/mips/dead-loads-1.c
create mode 100644 gcc/testsuite/gcc.target/mips/dead-loads-2.c
diff --git a/gcc/config/mips/loongson-mmi.md b/gcc/config/mips/loongson-mmi.md
index 33f4bfccc44..182fa163c1e 100644
--- a/gcc/config/mips/loongson-mmi.md
+++ b/gcc/config/mips/loongson-mmi.md
@@ -112,7 +112,7 @@
[(set (match_operand:VWHB 0 "nonimmediate_operand" "=m,f,d,f, d, m, d")
(match_operand:VWHB 1 "move_operand" "f,m,f,dYG,dYG,dYG,m"))]
"TARGET_HARD_FLOAT && TARGET_LOONGSON_MMI"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "fpstore,fpload,mfc,mtc,move,store,load")
(set_attr "mode" "DI")])
diff --git a/gcc/config/mips/mips-msa.md b/gcc/config/mips/mips-msa.md
index decf98d4688..284f3933fa1 100644
--- a/gcc/config/mips/mips-msa.md
+++ b/gcc/config/mips/mips-msa.md
@@ -680,7 +680,7 @@
[(set (match_operand:MSA 0 "nonimmediate_operand" "=f,f,R,*d,*f")
(match_operand:MSA 1 "move_operand" "fYGYI,R,f,*f,*d"))]
"ISA_HAS_MSA"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "type" "simd_move,simd_load,simd_store,simd_copy,simd_insert")
(set_attr "mode" "<MODE>")])
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 472baac8fde..73513b5d4f5 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -222,7 +222,7 @@ extern bool mips_split_128bit_move_p (rtx, rtx);
extern void mips_split_msa_copy_d (rtx, rtx, rtx, rtx (*)(rtx, rtx, rtx));
extern void mips_split_msa_insert_d (rtx, rtx, rtx, rtx);
extern void mips_split_msa_fill_d (rtx, rtx);
-extern const char *mips_output_move (rtx, rtx);
+extern const char *mips_output_move (rtx, rtx, rtx);
extern bool mips_cfun_has_cprestore_slot_p (void);
extern bool mips_cprestore_address_p (rtx, bool);
extern void mips_save_gp_to_cprestore_slot (rtx, rtx, rtx, rtx);
diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 6799057646c..d03145a16d8 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -5371,7 +5371,7 @@ mips_split_move_insn (rtx dest, rtx src, rtx insn)
that SRC is operand 1 and DEST is operand 0. */
const char *
-mips_output_move (rtx dest, rtx src)
+mips_output_move (rtx insn, rtx dest, rtx src)
{
enum rtx_code dest_code = GET_CODE (dest);
enum rtx_code src_code = GET_CODE (src);
@@ -5444,9 +5444,15 @@ mips_output_move (rtx dest, rtx src)
switch (GET_MODE_SIZE (mode))
{
case 1: return "sb\t%z1,%0";
- case 2: return "sh\t%z1,%0";
- case 4: return "sw\t%z1,%0";
- case 8: return "sd\t%z1,%0";
+ case 2: return ((MEM_ALIGN (dest) >= BITS_PER_UNIT * 2)
+ ? "sh\t%z1,%0"
+ : "sh\t%z1,%0 # unaligned");
+ case 4: return ((MEM_ALIGN (dest) >= BITS_PER_UNIT * 4)
+ ? "sw\t%z1,%0"
+ : "sw\t%z1,%0 # unaligned");
+ case 8: return ((MEM_ALIGN (dest) >= BITS_PER_UNIT * 8)
+ ? "sd\t%z1,%0"
+ : "sd\t%z1,%0 # unaligned");
default: gcc_unreachable ();
}
}
@@ -5491,14 +5497,41 @@ mips_output_move (rtx dest, rtx src)
}
if (src_code == MEM)
- switch (GET_MODE_SIZE (mode))
- {
- case 1: return "lbu\t%0,%1";
- case 2: return "lhu\t%0,%1";
- case 4: return "lw\t%0,%1";
- case 8: return "ld\t%0,%1";
- default: gcc_unreachable ();
- }
+ {
+ if (TARGET_DEAD_LOADS
+ && MEM_VOLATILE_P (src)
+ && find_regno_note (insn, REG_UNUSED, REGNO (dest))
+ && !TARGET_MIPS16)
+ switch (GET_MODE_SIZE (mode))
+ {
+ case 1: return "lbu\t$0,%1";
+ case 2: return ((MEM_ALIGN (src) >= BITS_PER_UNIT * 2)
+ ? "lhu\t$0,%1"
+ : "lhu\t$0,%1 # unaligned");
+ case 4: return ((MEM_ALIGN (src) >= BITS_PER_UNIT * 4)
+ ? "lw\t$0,%1"
+ : "lw\t$0,%1 # unaligned");
+ case 8: return ((MEM_ALIGN (src) >= BITS_PER_UNIT * 8)
+ ? "ld\t$0,%1"
+ : "ld\t$0,%1 # unaligned");
+ default: gcc_unreachable ();
+ }
+ else
+ switch (GET_MODE_SIZE (mode))
+ {
+ case 1: return "lbu\t%0,%1";
+ case 2: return ((MEM_ALIGN (src) >= BITS_PER_UNIT * 2)
+ ? "lhu\t%0,%1"
+ : "lhu\t%0,%1 # unaligned");
+ case 4: return ((MEM_ALIGN (src) >= BITS_PER_UNIT * 4)
+ ? "lw\t%0,%1"
+ : "lw\t%0,%1 # unaligned");
+ case 8: return ((MEM_ALIGN (src) >= BITS_PER_UNIT * 8)
+ ? "ld\t%0,%1"
+ : "ld\t%0,%1 # unaligned");
+ default: gcc_unreachable ();
+ }
+ }
if (src_code == CONST_INT)
{
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 18244e4abcc..868a21e8cba 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -4915,7 +4915,7 @@
"!TARGET_64BIT && !TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type"
"move,const,load,store,imul,mtlo,mflo,mtc,fpload,mfc,fpstore,mtc,fpload,mfc,fpstore")
(set (attr "mode")
(if_then_else (eq_attr "move_type" "imul")
@@ -4928,7 +4928,7 @@
"!TARGET_64BIT && TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,move,move,const,constN,load,store,mflo")
(set_attr "mode" "DI")])
@@ -4938,7 +4938,7 @@
"TARGET_64BIT && !TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type"
"move,const,const,load,store,mtc,fpload,mfc,fpstore,mtlo,mflo,mtc,fpload,mfc,fpstore")
(set_attr "mode" "DI")])
@@ -4948,7 +4948,7 @@
"TARGET_64BIT && TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type"
"move,move,move,const,constN,const,loadpool,load,store,mflo")
(set_attr "mode" "DI")])
@@ -5016,7 +5016,7 @@
"!TARGET_MIPS16
&& (register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type"
"move,move,const,const,const,load,load,load,store,store,store,mtc,fpload,mfc,fpstore,mfc,mtc,mtlo,mflo,mtc,fpload,mfc,fpstore")
(set_attr "compression"
"all,micromips,micromips,*,*,micromips,micromips,*,micromips,micromips,*,*,*,*,*,*,*,*,*,*,*,*,*")
(set_attr "mode" "SI")])
@@ -5027,7 +5027,7 @@
"TARGET_MIPS16
&& (register_operand (operands[0], <MODE>mode)
|| register_operand (operands[1], <MODE>mode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type"
"move,move,move,const,constN,const,loadpool,load,store,mflo")
(set_attr "mode" "SI")])
@@ -5157,7 +5157,7 @@
"!TARGET_MIPS16
&& (register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,const,const,load,load,store,store,mtlo,mflo")
(set_attr "compression" "all,micromips,*,micromips,*,micromips,*,*,*")
(set_attr "mode" "HI")])
@@ -5168,7 +5168,7 @@
"TARGET_MIPS16
&& (register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,move,move,const,constN,load,store,mflo")
(set_attr "mode" "HI")])
@@ -5233,7 +5233,7 @@
"!TARGET_MIPS16
&& (register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,const,const,load,load,store,store,mtlo,mflo")
(set_attr "compression" "all,micromips,*,micromips,*,micromips,*,*,*")
(set_attr "mode" "QI")])
@@ -5244,7 +5244,7 @@
"TARGET_MIPS16
&& (register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,move,move,const,constN,load,store,mflo")
(set_attr "mode" "QI")])
@@ -5290,7 +5290,7 @@
[(set (match_operand:CCF 0 "nonimmediate_operand" "=f,f,m")
(match_operand:CCF 1 "nonimmediate_operand" "f,m,f"))]
"ISA_HAS_CCF"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "fmove,fpload,fpstore")])
(define_insn "*movsf_hardfloat"
@@ -5299,7 +5299,7 @@
"TARGET_HARD_FLOAT
&& (register_operand (operands[0], SFmode)
|| reg_or_0_operand (operands[1], SFmode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type"
"fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
(set_attr "mode" "SF")])
@@ -5309,7 +5309,7 @@
"TARGET_SOFT_FLOAT && !TARGET_MIPS16
&& (register_operand (operands[0], SFmode)
|| reg_or_0_operand (operands[1], SFmode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,load,store")
(set_attr "mode" "SF")])
@@ -5319,7 +5319,7 @@
"TARGET_MIPS16
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,move,move,load,store")
(set_attr "mode" "SF")])
@@ -5340,7 +5340,7 @@
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
&& (register_operand (operands[0], DFmode)
|| reg_or_0_operand (operands[1], DFmode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type"
"fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
(set_attr "mode" "DF")])
@@ -5350,7 +5350,7 @@
"(TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT) && !TARGET_MIPS16
&& (register_operand (operands[0], DFmode)
|| reg_or_0_operand (operands[1], DFmode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,load,store")
(set_attr "mode" "DF")])
@@ -5360,7 +5360,7 @@
"TARGET_MIPS16
&& (register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,move,move,load,store")
(set_attr "mode" "DF")])
@@ -5382,7 +5382,7 @@
&& !TARGET_MIPS16
&& (register_operand (operands[0], TImode)
|| reg_or_0_operand (operands[1], TImode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type" "move,const,load,store,imul,mtlo,mflo")
(set (attr "mode")
(if_then_else (eq_attr "move_type" "imul")
@@ -5487,7 +5487,7 @@
&& TARGET_PAIRED_SINGLE_FLOAT
&& (register_operand (operands[0], V2SFmode)
|| reg_or_0_operand (operands[1], V2SFmode))"
- { return mips_output_move (operands[0], operands[1]); }
+ { return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "move_type"
"fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
(set_attr "mode" "DF")])
@@ -5562,7 +5562,7 @@
"TARGET_HARD_FLOAT"
{
operands[0] = mips_subword (operands[0], 0);
- return mips_output_move (operands[0], operands[1]);
+ return mips_output_move (insn, operands[0], operands[1]);
}
[(set_attr "move_type" "mtc,fpload")
(set_attr "mode" "<HALFMODE>")])
@@ -5577,7 +5577,7 @@
"TARGET_HARD_FLOAT"
{
operands[0] = mips_subword (operands[0], 1);
- return mips_output_move (operands[0], operands[1]);
+ return mips_output_move (insn, operands[0], operands[1]);
}
[(set_attr "move_type" "mtc,fpload")
(set_attr "mode" "<HALFMODE>")])
@@ -5592,7 +5592,7 @@
"TARGET_HARD_FLOAT"
{
operands[1] = mips_subword (operands[1], INTVAL (operands[2]));
- return mips_output_move (operands[0], operands[1]);
+ return mips_output_move (insn, operands[0], operands[1]);
}
[(set_attr "move_type" "mfc,fpstore")
(set_attr "mode" "<HALFMODE>")])
@@ -6934,7 +6934,7 @@
(unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d,B")]
UNSPEC_COP0))]
""
-{ return mips_output_move (operands[0], operands[1]); }
+{ return mips_output_move (insn, operands[0], operands[1]); }
[(set_attr "type" "mtc,mfc")
(set_attr "mode" "SI")])
@@ -7964,16 +7964,16 @@
However, order of the loads need to be checked for correctness. */
if (!load_p || !reg_overlap_mentioned_p (operands[0], operands[1]))
{
- output_asm_insn (mips_output_move (operands[0], operands[1]),
+ output_asm_insn (mips_output_move (insn, operands[0], operands[1]),
operands);
- output_asm_insn (mips_output_move (operands[2], operands[3]),
+ output_asm_insn (mips_output_move (insn, operands[2], operands[3]),
&operands[2]);
}
else
{
- output_asm_insn (mips_output_move (operands[2], operands[3]),
+ output_asm_insn (mips_output_move (insn, operands[2], operands[3]),
&operands[2]);
- output_asm_insn (mips_output_move (operands[0], operands[1]),
+ output_asm_insn (mips_output_move (insn, operands[0], operands[1]),
operands);
}
return "";
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index 9f6849d1b5e..11b252a6530 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -529,3 +529,7 @@ Enum(mips_lib_setting) String(small) Value(MIPS_LIB_SMALL)
EnumValue
Enum(mips_lib_setting) String(tiny) Value(MIPS_LIB_TINY)
+
+mdead-loads
+Target Var(TARGET_DEAD_LOADS) Init(0)
+Redirect dead loads to $0 to avoid spurious output dependencies.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 78052b229a5..ae01f8f2456 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1237,6 +1237,7 @@ Objective-C and Objective-C++ Dialects}.
-G@var{num} -mno-local-sdata -mno-extern-sdata -mno-gopt
-membedded-data -muninit-const-in-rodata
-mcode-readable=@var{setting} -mno-data-in-code -mcode-xonly
+-mdead-loads -mno-dead-loads
-msplit-addresses -mexplicit-relocs -mexplicit-relocs=@var{release}
-mno-check-zero-division -mdivide-traps -mdivide-breaks
-mno-load-store-pairs
@@ -29618,6 +29619,18 @@ SRAM interface but that (unlike the M4K) do not
automatically redirect
PC-relative loads to the instruction RAM.
@end table
+@opindex mdead-loads
+@opindex mno-dead-loads
+@item -mdead-loads
+@itemx -mno-dead-loads
+Apply (do not apply) special handling to avoid output dependency stalls
+for volatile loads where the result is unused. Volatile loads tend
+to be high latency as they represent access to special data or hardware.
+When the result of such a load is unused then there may be an output
+dependency stall if the result register is reused soon after the load.
+For MIPS32 a dead load will be redirected to @code{$0} to avoid the output
+dependency.
+
On SDE targets, @option{-mcode-data-in-code} is available as a
traditional alias for @option{-mcode-readable=no}, and @option{-mcode-xonly}
for @option{-mcode-readable=pcrel}.
diff --git a/gcc/testsuite/gcc.target/mips/dead-loads-1.c
b/gcc/testsuite/gcc.target/mips/dead-loads-1.c
new file mode 100644
index 00000000000..39e2df4b8e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/dead-loads-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-mdead-loads -mno-mips16 -mno-micromips" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+void
+foo (volatile unsigned int *p)
+{
+ *p;
+}
+
+/* { dg-final { scan-assembler "\tlw\t\\\$0," } } */
diff --git a/gcc/testsuite/gcc.target/mips/dead-loads-2.c
b/gcc/testsuite/gcc.target/mips/dead-loads-2.c
new file mode 100644
index 00000000000..0822fc11ef1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/dead-loads-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-dead-loads -mno-mips16 -mno-micromips" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+void
+foo (volatile unsigned int *p)
+{
+ *p;
+}
+
+/* { dg-final { scan-assembler-not "\tlw\t\\\$0," } } */
+/* { dg-final { scan-assembler "\tlw\t\\\$\[1-9\]\[0-9\]*," } } */
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp
b/gcc/testsuite/gcc.target/mips/mips.exp
index 9492b1dcaf8..a57e030798a 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -277,6 +277,7 @@ for { set option 0 } { $option < 32 } { incr option } {
foreach option {
abicalls
branch-likely
+ dead-loads
dsp
dspr2
explicit-relocs
--
2.43.0