[14/61] MIPS: Add support for -mdead-loads

Message ID 20250131171232.1018281-16-aleksandar.rakic@htecgroup.com
State New
Headers
Series Improve Mips target |

Commit Message

Aleksandar Rakic Jan. 31, 2025, 5:13 p.m. UTC
  From: Matthew Fortune <matthew.fortune@imgtec.com>

This option redirects the destination of a load to $0 if it is
volatile and the result is not used.

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.c (mips_output_move): Perform
	  the redirection.
        * 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.

Cherry-picked a9a9df621143d9cac0e898f2a0bedd98b4db8ae4
from https://github.com/MIPS/gcc

Signed-off-by: Matthew Fortune <matthew.fortune@imgtec.com>
Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
Signed-off-by: Aleksandar Rakic <aleksandar.rakic@htecgroup.com>
---
 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         | 33 ++++++++++++++------
 gcc/config/mips/mips.md         | 54 ++++++++++++++++-----------------
 gcc/config/mips/mips.opt        |  4 +++
 gcc/doc/invoke.texi             | 13 ++++++++
 7 files changed, 71 insertions(+), 39 deletions(-)
  

Patch

diff --git a/gcc/config/mips/loongson-mmi.md b/gcc/config/mips/loongson-mmi.md
index 4d958730139..39682eeaeb6 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 976f296402e..f6edd5897a4 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 96e084e6e64..c514c0711de 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 069c7ef6a42..4c719fbaed5 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -5374,7 +5374,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);
@@ -5502,14 +5502,29 @@  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 "lhu\t$0,%1";
+	      case 4: return "lw\t$0,%1";
+	      case 8: return "ld\t$0,%1";
+	      default: gcc_unreachable ();
+	      }
+	  else
+	    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 (src_code == CONST_INT)
 	{
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index bf8a1217ee9..b1e55428682 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -4882,7 +4882,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")
@@ -4895,7 +4895,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")])
 
@@ -4905,7 +4905,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")])
 
@@ -4915,7 +4915,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")])
 
@@ -4983,7 +4983,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")])
@@ -4994,7 +4994,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")])
 
@@ -5124,7 +5124,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")])
@@ -5135,7 +5135,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")])
 
@@ -5200,7 +5200,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")])
@@ -5211,7 +5211,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")])
 
@@ -5257,7 +5257,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"
@@ -5266,7 +5266,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")])
 
@@ -5276,7 +5276,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")])
 
@@ -5286,7 +5286,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")])
 
@@ -5307,7 +5307,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")])
 
@@ -5317,7 +5317,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")])
 
@@ -5327,7 +5327,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")])
 
@@ -5349,7 +5349,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")
@@ -5454,7 +5454,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")])
 
@@ -5535,7 +5535,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>")])
@@ -5550,7 +5550,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>")])
@@ -5565,7 +5565,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>")])
@@ -6947,7 +6947,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")])
 
@@ -7954,16 +7954,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 64c3dca4cc2..28b8de216fe 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -536,3 +536,7 @@  Enum(mips_lib_setting) String(tiny) Value(MIPS_LIB_TINY)
 
 mforbidden-slots
 Target Undocumented Var(TARGET_FORBIDDEN_SLOTS) Init(1)
+
+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 aac7a0b75cd..636aea39e53 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1153,6 +1153,7 @@  Objective-C and Objective-C++ Dialects}.
 -membedded-data  -mno-embedded-data
 -muninit-const-in-rodata  -mno-uninit-const-in-rodata
 -mcode-readable=@var{setting}
+-mdead-loads -mno-dead-loads
 -msplit-addresses  -mno-split-addresses
 -mexplicit-relocs  -mno-explicit-relocs
 -mexplicit-relocs=@var{release}
@@ -28837,6 +28838,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.
+
 @opindex msplit-addresses
 @opindex mno-split-addresses
 @item -msplit-addresses