public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* MIPS: the method of getting GOT address for PIC code
@ 2023-08-25  7:16 YunQiang Su
  2024-01-15  6:04 ` YunQiang Su
  0 siblings, 1 reply; 2+ messages in thread
From: YunQiang Su @ 2023-08-25  7:16 UTC (permalink / raw)
  To: apinski--- via Gcc-patches

When working on LLVM, I found this problem
https://github.com/llvm/llvm-project/issues/64974.
Maybe it's time for us to reconsider the way of getting GOT address
for PIC code.

1.Background[1]:
All of the accessing of global variables and normal function calls
needs help from GOT.
So normally, the first 3 instructions of a function are to compute the
address of GOT.
Normally like:
        lui     $gp,%hi(_gp_disp)
        addiu   $gp,$gp,%lo(_gp_disp)
        addu    $gp,$gp,$t9
These 3 instructions load the value of _gp_disp, which is a link-time
constant value,
and add them with $t9, which normally contains the address of the
current function.

So, why $t9? The reason is that the pre-R6 MIPS lacks instructions to
get the PC value.
Thus, the ABI defines that, the caller should call functions with
jr/jarl $t9. So the callee
can get the address of itself by $t9.

2. What's my proposal?
2.1 For MIPSr6, its has instructions to get the current PC value, so
we can use them,
which can gain performance improvement.

2.2 For pre-R6, in fact, it can get the value of PC with NAL
instruction [2], while the performance will be some worse. For the
worst case, the decreasing of performance will be 20%-40%
My plan for pre-R6, is to add a non-default option to use NAL to get
the address of GOT.
Some software, like Linux kernel (for Kalsr support) will need it.

Any suggestions?

[1] https://refspecs.linuxfoundation.org/elf/mipsabi.pdf
[2] https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00087-2B-MIPS64BIS-AFP-6.06.pdf
Page 404


-- 
YunQiang Su

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: MIPS: the method of getting GOT address for PIC code
  2023-08-25  7:16 MIPS: the method of getting GOT address for PIC code YunQiang Su
@ 2024-01-15  6:04 ` YunQiang Su
  0 siblings, 0 replies; 2+ messages in thread
From: YunQiang Su @ 2024-01-15  6:04 UTC (permalink / raw)
  To: apinski--- via Gcc-patches

[-- Attachment #1: Type: text/plain, Size: 438 bytes --]

YunQiang Su <wzssyqa@gmail.com> 于2023年8月25日周五 15:16写道:
>
> When working on LLVM, I found this problem
> https://github.com/llvm/llvm-project/issues/64974.
> Maybe it's time for us to reconsider the way of getting GOT address
> for PIC code.
>

I have my draft patch pushed to GitHub:
    https://github.com/wzssyqa/gcc/tree/pcrel
And the patch is also attached.

Any comment is welcome.

-- 
YunQiang Su

[-- Attachment #2: 0001-MIPS-PCREL-support.patch --]
[-- Type: application/octet-stream, Size: 16678 bytes --]

From 0c2e26830edbcc60fff67e8c6d889755e39276f9 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq@gcc.gnu.org>
Date: Thu, 11 Jan 2024 18:09:20 +0800
Subject: [PATCH] MIPS: PCREL support

1. Use auipc to get GOT instead of t9.
2. Use auipc to access non-preemptible variables/functions.
3. Add an option -mforce-pcrel: use BAL on r2.
4. -mno-shared for executable or kernel.

TODO:
1. Use ALUIPC/NO_GOT_BASE_REGISTER for R6.
   Need R_MIPS_GOTPC_HI/LO support in binutils.
   Use GOT_BASE_REGISTER, as it will caculate once only for
       a single function; caculate GOT is expensive on R2.
2. 4+(a+4) instead of a+8.
---
 gcc/config/mips/mips.cc  | 148 +++++++++++++++++++++++++++++++++++++--
 gcc/config/mips/mips.h   |  17 ++++-
 gcc/config/mips/mips.md  |  49 ++++++++++++-
 gcc/config/mips/mips.opt |   4 ++
 gcc/rtl.h                |   1 +
 gcc/rtlanal.cc           |  20 ++++--
 6 files changed, 225 insertions(+), 14 deletions(-)

diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 30e99811ff6..c31acc9f58a 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -2217,7 +2217,18 @@ mips_classify_symbol (const_rtx x, enum mips_symbol_context context)
 	 access will work for any kind of symbol.  However, there seems
 	 little point in doing things differently.  */
       if (mips_global_symbol_p (x))
-	return SYMBOL_GOT_DISP;
+	{
+	  if (TARGET_PCREL_PIC
+	      && SYMBOL_REF_LOCAL_P (x) && !SYMBOL_REF_EXTERNAL_P (x))
+	    return SYMBOL_PC_RELATIVE;
+	  else
+	    return SYMBOL_GOT_DISP;
+	}
+
+      if (TARGET_PCREL_PIC && strcmp (XSTR (x, 0), "_gp_disp") == 0)
+	{
+	  return ABI_HAS_64BIT_SYMBOLS ? SYMBOL_64_LOW : SYMBOL_ABSOLUTE;
+	}
 
       return SYMBOL_GOT_PAGE_OFST;
     }
@@ -5243,6 +5254,7 @@ mips_output_move (rtx dest, rtx src)
   bool dbl_p = (GET_MODE_SIZE (mode) == 8);
   bool msa_p = MSA_SUPPORTED_MODE_P (mode);
   enum mips_symbol_type symbol_type;
+  rtx src0;
 
   if (mips_split_move_p (dest, src, SPLIT_IF_NECESSARY))
     return "#";
@@ -5385,7 +5397,43 @@ mips_output_move (rtx dest, rtx src)
 	}
 
       if (src_code == HIGH)
-	return (TARGET_MIPS16 && !ISA_HAS_MIPS16E2) ? "#" : "lui\t%0,%h1";
+	{
+	  src0 = XEXP (src, 0);
+	  enum mips_loadgp_style loadgp_style = mips_current_loadgp_style ();
+	  const_rtx symbol_ref;
+	  const char *label;
+	  if (TARGET_PCREL_PIC
+	      && (symbol_ref = get_first_code_subrtx (src0, SYMBOL_REF))
+	      && mips_symbolic_constant_p (src0, SYMBOL_CONTEXT_LEA, &symbol_type)
+	      && (symbol_type == SYMBOL_PC_RELATIVE
+		  || (symbol_type == SYMBOL_ABSOLUTE
+		      && loadgp_style == LOADGP_OLDABI
+		      && strcmp (XSTR (src0, 0), "_gp_disp") == 0)
+		  || (symbol_type == SYMBOL_GOTOFF_LOADGP
+		      && loadgp_style == LOADGP_NEWABI)))
+	    {
+	      if (symbol_type == SYMBOL_GOTOFF_LOADGP)
+		{
+		  label = XSTR (symbol_ref, 0);
+		  if (TARGET_PCREL_INSN)
+		    /* FIXME: Use ALUIPC when binutils is ready.  */
+		    return concat ("\n", label, ":\n\tauipc\t%0,%h1", NULL);
+		  else if (TARGET_64BIT)
+		    return concat ("bal\t. + 8\n\tlui\t%0,%h1\n", label, ":\n\tdaddu\t%0,%0,$ra", NULL);
+		  else
+		    return concat ("bal\t. + 8\n\tlui\t%0,%h1\n", label, ":\n\taddu\t%0,%0,$ra", NULL);
+		}
+	      if (!TARGET_PCREL_INSN)
+		return TARGET_64BIT ? "bal\t. + 8\n\tlui\t%0,%h1\n\tdaddu\t%0,%0,$ra"
+				    : "bal\t. + 8\n\tlui\t%0,%h1\n\taddu\t%0,%0,$ra";
+	      else if (TARGET_PCREL_INSN)
+		/* FIXME: Use ALUIPC when binutils is ready.  */
+		return "auipc\t%0,%h1";
+	      else
+		gcc_unreachable ();
+	    }
+	  return (TARGET_MIPS16 && !ISA_HAS_MIPS16E2) ? "#" : "lui\t%0,%h1";
+	}
 
       if (CONST_GP_P (src))
 	return "move\t%0,%1";
@@ -8908,6 +8956,10 @@ mips_init_relocs (void)
 
 	      mips_split_p[SYMBOL_ABSOLUTE] = true;
 	      mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo(";
+
+	      mips_split_p[SYMBOL_PC_RELATIVE] = true;
+	      mips_hi_relocs[SYMBOL_PC_RELATIVE] = "%pcrel_hi(";
+	      mips_lo_relocs[SYMBOL_PC_RELATIVE] = "(%pcrel_lo(";
 	    }
 	}
       else
@@ -8919,6 +8971,10 @@ mips_init_relocs (void)
 	      mips_split_p[SYMBOL_ABSOLUTE] = true;
 	      mips_hi_relocs[SYMBOL_ABSOLUTE] = "%hi(";
 	      mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo(";
+
+	      mips_split_p[SYMBOL_PC_RELATIVE] = true;
+	      mips_hi_relocs[SYMBOL_PC_RELATIVE] = "%pcrel_hi(";
+	      mips_lo_relocs[SYMBOL_PC_RELATIVE] = "(%pcrel_lo(";
 	    }
 	}
     }
@@ -9016,12 +9072,22 @@ mips_print_operand_reloc (FILE *file, rtx op, enum mips_symbol_context context,
 {
   enum mips_symbol_type symbol_type;
   const char *p;
+  static int count_pcrel_lo;
 
   symbol_type = mips_classify_symbolic_expression (op, context);
   gcc_assert (relocs[symbol_type]);
 
   fputs (relocs[symbol_type], file);
   output_addr_const (file, mips_strip_unspec_address (op));
+  if (strcmp (relocs[symbol_type], "%pcrel_hi(") == 0)
+    count_pcrel_lo = 0;
+  if (strcmp (relocs[symbol_type], "(%pcrel_lo(") == 0)
+    {
+      count_pcrel_lo ++;
+      fprintf (file, ")+%d)", 4 * count_pcrel_lo);
+      return;
+    }
+
   for (p = relocs[symbol_type]; *p != 0; p++)
     if (*p == '(')
       fputc (')', file);
@@ -11198,6 +11264,10 @@ mips_save_reg_p (unsigned int regno)
   if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return)
     return true;
 
+  /* We need to use NAL to get PC.  NAL will clobber $ra.  */
+  if (TARGET_PCREL_PIC && !TARGET_PCREL_INSN && regno == RETURN_ADDR_REGNUM)
+    return true;
+
   return false;
 }
 
@@ -12140,7 +12210,8 @@ mips_output_function_prologue (FILE *file)
      Also emit the ".set noreorder; .set nomacro" sequence for functions
      that need it.  */
   if (mips_must_initialize_gp_p ()
-      && mips_current_loadgp_style () == LOADGP_OLDABI)
+      && mips_current_loadgp_style () == LOADGP_OLDABI
+      && !TARGET_PCREL_PIC)
     {
       if (TARGET_MIPS16)
 	{
@@ -12225,6 +12296,10 @@ mips_frame_barrier (void)
 
 static GTY(()) rtx mips_gnu_local_gp;
 
+/* The _gp_disp symbol.  */
+
+static GTY(()) rtx mips_gp_disp;
+
 /* If we're generating n32 or n64 abicalls, emit instructions
    to set up the global pointer.  */
 
@@ -12248,14 +12323,37 @@ mips_emit_loadgp (void)
 
     case LOADGP_OLDABI:
       /* Added by mips_output_function_prologue.  */
+      if (!TARGET_PCREL_PIC)
+	break;
+      if (mips_gp_disp == NULL)
+	{
+	  mips_gp_disp = gen_rtx_SYMBOL_REF (Pmode, "_gp_disp");
+	  SYMBOL_REF_FLAGS (mips_gp_disp) |= SYMBOL_FLAG_LOCAL;
+	}
+      emit_insn (gen_rtx_SET (pic_reg, gen_rtx_HIGH (Pmode, mips_gp_disp)));
+      emit_insn (gen_rtx_SET (pic_reg, gen_rtx_LO_SUM (Pmode, pic_reg, mips_gp_disp)));
+      SCHED_GROUP_P (get_last_insn ()) = 1;
       break;
 
     case LOADGP_NEWABI:
+      if (TARGET_PCREL_PIC)
+	{
+	  char *label_name = concat (".L_",
+				     IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
+				     "_gotcalc", NULL);
+	  addr = gen_rtx_SYMBOL_REF (Pmode, label_name);
+	  SYMBOL_REF_FLAGS (addr) |= SYMBOL_FLAG_LOCAL;
+	  offset = mips_unspec_address (addr, SYMBOL_GOTOFF_LOADGP);
+	  incoming_address = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
+	  emit_insn (PMODE_INSN (gen_loadgp_newabi_pcrel,
+				(pic_reg, offset, incoming_address)));
+	  break;
+	}
       addr = XEXP (DECL_RTL (current_function_decl), 0);
       offset = mips_unspec_address (addr, SYMBOL_GOTOFF_LOADGP);
       incoming_address = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
       emit_insn (PMODE_INSN (gen_loadgp_newabi,
-			     (pic_reg, offset, incoming_address)));
+			    (pic_reg, offset, incoming_address)));
       break;
 
     case LOADGP_RTP:
@@ -15451,6 +15549,43 @@ mips_sched_reorder2 (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
   return cached_can_issue_more;
 }
 
+/* Implement TARGET_SCHED_MACRO_FUSION_PAIR_P.  Return true if PREV and CURR
+   should be kept together during scheduling.
+   TARGET_SCHED_MACRO_FUSION_P is set to always true.  */
+
+static bool
+mips_macro_fusion_pair_p (rtx_insn *prev ATTRIBUTE_UNUSED, rtx_insn *curr)
+{
+  rtx curr_set = single_set (curr);
+  rtx csrc = SET_SRC (curr_set);
+
+  /* If TARGET_PCREL_PIC,
+     (set (reg/i:SI 2 $2)
+	  (mem/c:SI (lo_sum:SI (reg/f:SI 2 $2 [196])
+			(symbol_ref:SI ("g") [flags 0x2])) [1 g+0 S4 A32]))
+     (set (reg/f:SI 201)
+	  (lo_sum:SI (reg/f:SI 202)
+		     (symbol_ref:SI ("f") [flags 0x3])))
+     (set (reg:SI 3 $3 [ g+4 ])
+	  (mem/c:SI (lo_sum:SI (reg/f:SI 2 $2 [196])
+			       (const:SI (plus:SI (symbol_ref:SI ("g") [flags 0x2])
+						  (const_int 4 [0x4])))) [1 g+4 S4 A32]))
+     will be convert to %pcrel_lo.  */
+  if (TARGET_PCREL_PIC)
+    {
+      const_rtx symbol_ref = NULL_RTX;
+      const_rtx lo_sum = get_first_code_subrtx (csrc, LO_SUM);
+      if (lo_sum)
+	symbol_ref = get_first_code_subrtx (lo_sum, SYMBOL_REF);
+
+      if (symbol_ref && SYMBOL_REF_P (symbol_ref)
+	  && SYMBOL_REF_LOCAL_P (symbol_ref) && !SYMBOL_REF_EXTERNAL_P (symbol_ref))
+	return true;
+    }
+
+  return false;
+}
+
 /* Update round-robin counters for ALU1/2 and FALU1/2.  */
 
 static void
@@ -23076,6 +23211,11 @@ mips_bit_clear_p (enum machine_mode mode, unsigned HOST_WIDE_INT m)
 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
   mips_multipass_dfa_lookahead
+#undef TARGET_SCHED_MACRO_FUSION_P
+#define TARGET_SCHED_MACRO_FUSION_P hook_bool_void_true
+#undef TARGET_SCHED_MACRO_FUSION_PAIR_P
+#define TARGET_SCHED_MACRO_FUSION_PAIR_P mips_macro_fusion_pair_p
+
 #undef TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P
 #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P \
   mips_small_register_classes_for_mode_p
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 8768933ba37..ac283669a25 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -154,6 +154,16 @@ struct mips_cpu_info {
 #define TARGET_ABICALLS_PIC2 \
   (TARGET_ABICALLS && !TARGET_ABICALLS_PIC0)
 
+/* True if there are instructions that can get value of PC without side effects.
+   Otherwise, we will need to use NAL, which clobbers $31.  */
+#define TARGET_PCREL_INSN (mips_isa_rev >= 6)
+
+/* True if the output file is shared but not abicall, aka pcrel.
+   FIXME: enable it for MIPS16 and microMIPS?  */
+#define TARGET_PCREL_PIC (flag_pic && TARGET_EXPLICIT_RELOCS		\
+			  && !TARGET_MIPS16 && !TARGET_MICROMIPS	\
+			  && (TARGET_PCREL_INSN || TARGET_FORCE_PCREL))
+
 /* True if the call patterns should be split into a jalr followed by
    an instruction to restore $gp.  It is only safe to split the load
    from the call when every use of $gp is explicit.
@@ -175,7 +185,8 @@ struct mips_cpu_info {
   (TARGET_ABICALLS			\
    && !TARGET_SHARED			\
    && TARGET_EXPLICIT_RELOCS		\
-   && !ABI_HAS_64BIT_SYMBOLS)
+   && !ABI_HAS_64BIT_SYMBOLS		\
+   && !TARGET_PCREL_PIC)
 
 /* True if we can optimize sibling calls.  For simplicity, we only
    handle cases in which call_insn_operand will reject invalid
@@ -192,7 +203,9 @@ struct mips_cpu_info {
   (!TARGET_MIPS16 && (!TARGET_USE_GOT || TARGET_EXPLICIT_RELOCS))
 
 /* True if we need to use a global offset table to access some symbols.  */
-#define TARGET_USE_GOT (TARGET_ABICALLS || TARGET_RTP_PIC)
+#define TARGET_USE_GOT ((TARGET_ABICALLS				\
+			 && !(TARGET_PCREL_PIC && !TARGET_SHARED))	\
+			|| TARGET_RTP_PIC)
 
 /* True if TARGET_USE_GOT and if $gp is a call-clobbered register.  */
 #define TARGET_CALL_CLOBBERED_GP (TARGET_ABICALLS && TARGET_OLDABI)
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 17dfcbd6722..51ab2eac676 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -4748,7 +4748,7 @@ (define_insn_and_split "*got_disp<mode>"
 	(match_operand:P 1 "got_disp_operand" ""))]
   "TARGET_EXPLICIT_RELOCS && !mips_split_p[SYMBOL_GOT_DISP]"
   "#"
-  "&& reload_completed"
+  "&& reload_completed && !(TARGET_PCREL_PIC && SYMBOL_REF_LOCAL_P (operands[1]) && !SYMBOL_REF_EXTERNAL_P (operands[1]))"
   [(set (match_dup 0) (match_dup 2))]
   { operands[2] = mips_got_load (NULL, operands[1], SYMBOL_GOTOFF_DISP); }
   [(set_attr "got" "load")
@@ -4978,6 +4978,34 @@ (define_expand "mov<mode>"
     DONE;
 })
 
+;; PCREL uses NAL to get PC on pre-R6.  NAL will clobber $RA.
+(define_peephole2
+  [(set (match_operand:P 0 "register_operand")
+	(high:P (match_operand:P 1 "symbol_ref_operand")))]
+  "TARGET_PCREL_PIC && !TARGET_PCREL_INSN
+   && GET_CODE (operands[1]) == SYMBOL_REF
+   && SYMBOL_REF_LOCAL_P (operands[1]) && !SYMBOL_REF_EXTERNAL_P (operands[1])"
+  [(parallel [(clobber (reg:P RETURN_ADDR_REGNUM))
+	      (set (match_dup 0)
+		   (high:P (match_dup 1)))])]
+  "")
+
+(define_insn "*mov<mode>_pcrel"
+  [(clobber (reg:P RETURN_ADDR_REGNUM))
+   (set (match_operand:P 0 "register_operand" "=d")
+	(match_operand:P 1 "move_operand" "Yd"))]
+  "TARGET_PCREL_PIC
+   && GET_CODE (operands[1]) == HIGH
+   && contains_symbol_ref_p (XEXP (operands[1], 0))
+   && SYMBOL_REF_LOCAL_P (get_first_code_subrtx (XEXP (operands[1], 0), SYMBOL_REF))
+   && !SYMBOL_REF_EXTERNAL_P (get_first_code_subrtx (XEXP (operands[1], 0), SYMBOL_REF))"
+  { return mips_output_move (operands[0], operands[1]); }
+  [(set_attr "move_type" "move")
+   (set (attr "insn_count")
+	(if_then_else (match_test "TARGET_PCREL_INSN")
+		      (const_int 1)
+		      (const_int 3)))])
+
 ;; The difference between these two is whether or not ints are allowed
 ;; in FP registers (off by default, use -mdebugh to enable).
 
@@ -5603,7 +5631,7 @@ (define_insn_and_split "loadgp_newabi_<mode>"
 	(unspec:P [(match_operand:P 1)
 		   (match_operand:P 2 "register_operand" "d")]
 		  UNSPEC_LOADGP))]
-  "mips_current_loadgp_style () == LOADGP_NEWABI"
+  "mips_current_loadgp_style () == LOADGP_NEWABI && !TARGET_PCREL_PIC"
   { return mips_must_initialize_gp_p () ? "#" : ""; }
   "&& mips_must_initialize_gp_p ()"
   [(set (match_dup 0) (match_dup 3))
@@ -5616,6 +5644,23 @@ (define_insn_and_split "loadgp_newabi_<mode>"
 }
   [(set_attr "type" "ghost")])
 
+(define_insn_and_split "loadgp_newabi_pcrel_<mode>"
+  [(set (match_operand:P 0 "register_operand" "=&d")
+	(unspec:P [(match_operand:P 1)
+		   (match_operand:P 2 "register_operand" "d")]
+		  UNSPEC_LOADGP))]
+  "mips_current_loadgp_style () == LOADGP_NEWABI && TARGET_PCREL_PIC"
+  { return mips_must_initialize_gp_p () ? "#" : ""; }
+  "&& mips_must_initialize_gp_p ()"
+  [(parallel [(clobber (reg:P RETURN_ADDR_REGNUM))
+	      (set (match_dup 0) (match_dup 3))])
+    (set (match_dup 0) (match_dup 4))]
+{
+  operands[3] = gen_rtx_HIGH (Pmode, operands[1]);
+  operands[4] = gen_rtx_LO_SUM (Pmode, operands[0], operands[1]);
+}
+  [(set_attr "type" "ghost")])
+
 ;; Likewise, for -mno-shared code.  Operand 0 is the __gnu_local_gp symbol.
 (define_insn_and_split "loadgp_absolute_<mode>"
   [(set (match_operand:P 0 "register_operand" "=d")
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index e8b411a8ffe..e5c62fcf8c7 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -54,6 +54,10 @@ mabicalls
 Target Mask(ABICALLS)
 Generate code that can be used in SVR4-style dynamic objects.
 
+mforce-pcrel
+Target Mask(FORCE_PCREL)
+Use PC-relative operations even with significant performance degrading.
+
 mmad
 Target Var(TARGET_MAD)
 Use PMC-style 'mad' instructions.
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 2370d608161..55945131040 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3600,6 +3600,7 @@ extern void set_insn_deleted (rtx_insn *);
 
 extern rtx single_set_2 (const rtx_insn *, const_rtx);
 extern rtx simple_regno_set (rtx, unsigned int);
+extern const_rtx get_first_code_subrtx (const_rtx, enum rtx_code);
 extern bool contains_symbol_ref_p (const_rtx);
 extern bool contains_symbolic_reference_p (const_rtx);
 extern bool contains_constant_pool_address_p (const_rtx);
diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc
index ec65cf173b4..3e5fa65bb53 100644
--- a/gcc/rtlanal.cc
+++ b/gcc/rtlanal.cc
@@ -6840,17 +6840,25 @@ get_index_code (const struct address_info *info)
   return SCRATCH;
 }
 
-/* Return true if RTL X contains a SYMBOL_REF.  */
+/* Return first subrtx with CODE of RTL X.  */
 
-bool
-contains_symbol_ref_p (const_rtx x)
+const_rtx
+get_first_code_subrtx (const_rtx x, enum rtx_code code)
 {
   subrtx_iterator::array_type array;
   FOR_EACH_SUBRTX (iter, array, x, ALL)
-    if (SYMBOL_REF_P (*iter))
-      return true;
+    if (GET_CODE (*iter) == code)
+      return *iter;
 
-  return false;
+  return NULL_RTX;
+}
+
+/* Return true if RTL X contains a SYMBOL_REF.  */
+
+bool
+contains_symbol_ref_p (const_rtx x)
+{
+  return !! get_first_code_subrtx (x, SYMBOL_REF);
 }
 
 /* Return true if RTL X contains a SYMBOL_REF or LABEL_REF.  */
-- 
2.39.2


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-01-15  6:04 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-25  7:16 MIPS: the method of getting GOT address for PIC code YunQiang Su
2024-01-15  6:04 ` YunQiang Su

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).