diff mbox series

[2/6,RS6000] rs6000_indirect_call_template

Message ID 20181113124903.GR29784@bubble.grove.modra.org
State New
Headers show
Series [1/6,RS6000] rs6000_call_template for external call insn assembly output | expand

Commit Message

Alan Modra Nov. 13, 2018, 12:49 p.m. UTC
Version 2.

Like the last patch for external calls, now handle most assembly code
for indirect calls in one place.  The patch also merges some insns,
correcting some !rs6000_speculate_indirect_jumps cases branching to
LR, which don't require a speculation barrier.

	* config/rs6000/rs6000-protos.h (rs6000_indirect_call_template),
	(rs6000_indirect_sibcall_template): Declare.
	* config/rs6000/rs6000.c (rs6000_indirect_call_template_1),
	(rs6000_indirect_call_template, rs6000_indirect_sibcall_template):
	New functions.
	* config/rs6000/rs6000.md (call_indirect_nonlocal_sysv),
	(call_value_indirect_nonlocal_sysv, sibcall_nonlocal_sysv),
	(call_indirect_aix, call_value_indirect_aix): Use
	rs6000_indirect_call_template and rs6000_indirect_sibcall_template.
	call_indirect_elfv2, call_value_indirect_elfv2): Likewise, and
	handle both speculation and non-speculation cases.
	(call_indirect_aix_nospec, call_value_indirect_aix_nospec): Delete.
	(call_indirect_elfv2_nospec, call_value_indirect_elfv2_nospec): Delete.

Comments

Segher Boessenkool Nov. 20, 2018, 4:23 p.m. UTC | #1
Hi Alan,

On Tue, Nov 13, 2018 at 11:19:03PM +1030, Alan Modra wrote:
> Like the last patch for external calls, now handle most assembly code
> for indirect calls in one place.  The patch also merges some insns,
> correcting some !rs6000_speculate_indirect_jumps cases branching to
> LR, which don't require a speculation barrier.

Okay for trunk.  Thanks!


Segher


> 	* config/rs6000/rs6000-protos.h (rs6000_indirect_call_template),
> 	(rs6000_indirect_sibcall_template): Declare.
> 	* config/rs6000/rs6000.c (rs6000_indirect_call_template_1),
> 	(rs6000_indirect_call_template, rs6000_indirect_sibcall_template):
> 	New functions.
> 	* config/rs6000/rs6000.md (call_indirect_nonlocal_sysv),
> 	(call_value_indirect_nonlocal_sysv, sibcall_nonlocal_sysv),
> 	(call_indirect_aix, call_value_indirect_aix): Use
> 	rs6000_indirect_call_template and rs6000_indirect_sibcall_template.
> 	call_indirect_elfv2, call_value_indirect_elfv2): Likewise, and
> 	handle both speculation and non-speculation cases.
> 	(call_indirect_aix_nospec, call_value_indirect_aix_nospec): Delete.
> 	(call_indirect_elfv2_nospec, call_value_indirect_elfv2_nospec): Delete.
diff mbox series

Patch

diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 303ba7b91c3..967f65e2d94 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -113,6 +113,8 @@  extern void print_operand (FILE *, rtx, int);
 extern void print_operand_address (FILE *, rtx);
 extern const char *rs6000_call_template (rtx *, unsigned int, const char *);
 extern const char *rs6000_sibcall_template (rtx *, unsigned int, const char *);
+extern const char *rs6000_indirect_call_template (rtx *, unsigned int);
+extern const char *rs6000_indirect_sibcall_template (rtx *, unsigned int);
 extern enum rtx_code rs6000_reverse_condition (machine_mode,
 					       enum rtx_code);
 extern rtx rs6000_emit_eqne (machine_mode, rtx, rtx, rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 6e84f5053c2..cd1ab95166e 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -21416,6 +21416,83 @@  rs6000_sibcall_template (rtx *operands, unsigned int funop, const char *arg)
   return rs6000_call_template_1 (operands, funop, true, arg);
 }
 
+/* As above, for indirect calls.  */
+
+static const char *
+rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop,
+				 bool sibcall)
+{
+  /* -Wformat-overflow workaround, without which gcc thinks that %u
+      might produce 10 digits.  */
+  gcc_assert (funop <= MAX_RECOG_OPERANDS);
+
+  static char str[144];
+  const char *ptrload = TARGET_64BIT ? "d" : "wz";
+
+  /* We don't need the extra code to stop indirect call speculation if
+     calling via LR.  */
+  bool speculate = (TARGET_MACHO
+		    || rs6000_speculate_indirect_jumps
+		    || (REG_P (operands[funop])
+			&& REGNO (operands[funop]) == LR_REGNO));
+
+  if (DEFAULT_ABI == ABI_AIX)
+    {
+      if (speculate)
+	sprintf (str,
+		 "l%s 2,%%%u\n\t"
+		 "b%%T%ul\n\t"
+		 "l%s 2,%%%u(1)",
+		 ptrload, funop + 2, funop, ptrload, funop + 3);
+      else
+	sprintf (str,
+		 "crset 2\n\t"
+		 "l%s 2,%%%u\n\t"
+		 "beq%%T%ul-\n\t"
+		 "l%s 2,%%%u(1)",
+		 ptrload, funop + 2, funop, ptrload, funop + 3);
+    }
+  else if (DEFAULT_ABI == ABI_ELFv2)
+    {
+      if (speculate)
+	sprintf (str,
+		 "b%%T%ul\n\t"
+		 "l%s 2,%%%u(1)",
+		 funop, ptrload, funop + 2);
+      else
+	sprintf (str,
+		 "crset 2\n\t"
+		 "beq%%T%ul-\n\t"
+		 "l%s 2,%%%u(1)",
+		 funop, ptrload, funop + 2);
+    }
+  else
+    {
+      if (speculate)
+	sprintf (str,
+		 "b%%T%u%s",
+		 funop, sibcall ? "" : "l");
+      else
+	sprintf (str,
+		 "crset 2\n\t"
+		 "beq%%T%u%s-%s",
+		 funop, sibcall ? "" : "l", sibcall ? "\n\tb $" : "");
+    }
+  return str;
+}
+
+const char *
+rs6000_indirect_call_template (rtx *operands, unsigned int funop)
+{
+  return rs6000_indirect_call_template_1 (operands, funop, false);
+}
+
+const char *
+rs6000_indirect_sibcall_template (rtx *operands, unsigned int funop)
+{
+  return rs6000_indirect_call_template_1 (operands, funop, true);
+}
+
 #if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO
 /* Emit an assembler directive to set symbol visibility for DECL to
    VISIBILITY_TYPE.  */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index db9cfe92c72..fe904b1966b 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10539,11 +10539,7 @@  (define_insn "*call_indirect_nonlocal_sysv<mode>"
   else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn ("creqv 6,6,6", operands);
 
-  if (rs6000_speculate_indirect_jumps
-      || which_alternative == 1 || which_alternative == 3)
-    return "b%T0l";
-  else
-    return "crset 2\;beq%T0l-";
+  return rs6000_indirect_call_template (operands, 0);
 }
   [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
    (set_attr_alternative "length"
@@ -10629,11 +10625,7 @@  (define_insn "*call_value_indirect_nonlocal_sysv<mode>"
   else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn ("creqv 6,6,6", operands);
 
-  if (rs6000_speculate_indirect_jumps
-      || which_alternative == 1 || which_alternative == 3)
-    return "b%T1l";
-  else
-    return "crset 2\;beq%T1l-";
+  return rs6000_indirect_call_template (operands, 1);
 }
   [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
    (set_attr_alternative "length"
@@ -10764,21 +10756,16 @@  (define_insn "*call_indirect_aix<mode>"
    (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
    (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX && rs6000_speculate_indirect_jumps"
-  "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3(1)"
-  [(set_attr "type" "jmpreg")
-   (set_attr "length" "12")])
-
-(define_insn "*call_indirect_aix<mode>_nospec"
-  [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
-	 (match_operand 1 "" "g,g"))
-   (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
-   (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
-   (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX && !rs6000_speculate_indirect_jumps"
-  "crset 2\;<ptrload> 2,%2\;beq%T0l-\;<ptrload> 2,%3(1)"
+  "DEFAULT_ABI == ABI_AIX"
+{
+  return rs6000_indirect_call_template (operands, 0);
+}
   [(set_attr "type" "jmpreg")
-   (set_attr "length" "16")])
+   (set (attr "length")
+	(if_then_else (and (match_test "!rs6000_speculate_indirect_jumps")
+			   (match_test "which_alternative != 1"))
+		      (const_string "16")
+		      (const_string "12")))])
 
 (define_insn "*call_value_indirect_aix<mode>"
   [(set (match_operand 0 "" "")
@@ -10787,22 +10774,16 @@  (define_insn "*call_value_indirect_aix<mode>"
    (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
    (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 4 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX && rs6000_speculate_indirect_jumps"
-  "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4(1)"
-  [(set_attr "type" "jmpreg")
-   (set_attr "length" "12")])
-
-(define_insn "*call_value_indirect_aix<mode>_nospec"
-  [(set (match_operand 0 "" "")
-	(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
-	      (match_operand 2 "" "g,g")))
-   (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
-   (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 4 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
-   (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX && !rs6000_speculate_indirect_jumps"
-  "crset 2\;<ptrload> 2,%3\;beq%T1l-\;<ptrload> 2,%4(1)"
+  "DEFAULT_ABI == ABI_AIX"
+{
+  return rs6000_indirect_call_template (operands, 1);
+}
   [(set_attr "type" "jmpreg")
-   (set_attr "length" "16")])
+   (set (attr "length")
+	(if_then_else (and (match_test "!rs6000_speculate_indirect_jumps")
+			   (match_test "which_alternative != 1"))
+		      (const_string "16")
+		      (const_string "12")))])
 
 ;; Call to indirect functions with the ELFv2 ABI.
 ;; Operand0 is the addresss of the function to call
@@ -10813,21 +10794,16 @@  (define_insn "*call_indirect_elfv2<mode>"
 	 (match_operand 1 "" "g,g"))
    (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps"
-  "b%T0l\;<ptrload> 2,%2(1)"
-  [(set_attr "type" "jmpreg")
-   (set_attr "length" "8")])
-
-;; Variant with deliberate misprediction.
-(define_insn "*call_indirect_elfv2<mode>_nospec"
-  [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
-	 (match_operand 1 "" "g,g"))
-   (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
-   (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps"
-  "crset 2\;beq%T0l-\;<ptrload> 2,%2(1)"
+  "DEFAULT_ABI == ABI_ELFv2"
+{
+  return rs6000_indirect_call_template (operands, 0);
+}
   [(set_attr "type" "jmpreg")
-   (set_attr "length" "12")])
+   (set (attr "length")
+	(if_then_else (and (match_test "!rs6000_speculate_indirect_jumps")
+			   (match_test "which_alternative != 1"))
+		      (const_string "12")
+		      (const_string "8")))])
 
 (define_insn "*call_value_indirect_elfv2<mode>"
   [(set (match_operand 0 "" "")
@@ -10835,22 +10811,16 @@  (define_insn "*call_value_indirect_elfv2<mode>"
 	      (match_operand 2 "" "g,g")))
    (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps"
-  "b%T1l\;<ptrload> 2,%3(1)"
-  [(set_attr "type" "jmpreg")
-   (set_attr "length" "8")])
-
-; Variant with deliberate misprediction.
-(define_insn "*call_value_indirect_elfv2<mode>_nospec"
-  [(set (match_operand 0 "" "")
-	(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
-	      (match_operand 2 "" "g,g")))
-   (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
-   (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps"
-  "crset 2\;beq%T1l-\;<ptrload> 2,%3(1)"
+  "DEFAULT_ABI == ABI_ELFv2"
+{
+  return rs6000_indirect_call_template (operands, 1);
+}
   [(set_attr "type" "jmpreg")
-   (set_attr "length" "12")])
+   (set (attr "length")
+	(if_then_else (and (match_test "!rs6000_speculate_indirect_jumps")
+			   (match_test "which_alternative != 1"))
+		      (const_string "12")
+		      (const_string "8")))])
 
 ;; Call subroutine returning any type.
 (define_expand "untyped_call"
@@ -11019,13 +10989,7 @@  (define_insn "*sibcall_nonlocal_sysv<mode>"
     output_asm_insn ("creqv 6,6,6", operands);
 
   if (which_alternative >= 2)
-    {
-      if (rs6000_speculate_indirect_jumps)
-	return "b%T0";
-      else
-	/* Can use CR0 since it is volatile across sibcalls.  */
-	return "crset 2\;beq%T0-\;b $";
-    }
+    return rs6000_indirect_sibcall_template (operands, 0);
   else
     return rs6000_sibcall_template (operands, 0, "");
 }