Hi,

This patch supercedes and extends 
https://gcc.gnu.org/ml/gcc-patches/2018-01/msg01479.html,
adding the remaining big-endian support for -mno-speculate-indirect-jumps.
This includes 32-bit support for indirect calls and sibling calls, and 
64-bit support for indirect calls.  The endian-neutral switch handling has
already been committed.

Using -m32 -O2 on safe-indirect-jumps-1.c results in a test for a sibling 
call, so this has been added as safe-indirect-jumps-8.c.  Also, 
safe-indirect-jumps-7.c adds a variant that will not generate a sibling 
call for -m32, so we still get indirect call coverage.

Bootstrapped and tested on powerpc64-linux-gnu and powerpc64le-linux-gnu 
with no regressions.  Is this okay for trunk?

Thanks,
Bill


[gcc]

2018-01-16  Bill Schmidt  <wschm...@linux.vnet.ibm.com>

        * config/rs6000/rs6000.md (*call_indirect_nonlocal_sysv<mode>):
        Generate different code for -mno-speculate-indirect-jumps.
        (*call_value_indirect_nonlocal_sysv<mode>): Likewise.
        (*call_indirect_aix<mode>): Disable for
        -mno-speculate-indirect-jumps.
        (*call_indirect_aix<mode>_nospec): New define_insn.
        (*call_value_indirect_aix<mode>): Disable for
        -mno-speculate-indirect-jumps.
        (*call_value_indirect_aix<mode>_nospec): New define_insn.
        (*sibcall_nonlocal_sysv<mode>): Generate different code for
        -mno-speculate-indirect-jumps.
        (*sibcall_value_nonlocal_sysv<mode>): Likewise.

[gcc/testsuite]

2018-01-16  Bill Schmidt  <wschm...@linux.vnet.ibm.com>

        * gcc.target/powerpc/safe-indirect-jump-1.c: Remove endian
        restriction, but still restrict to 64-bit.
        * gcc.target/powerpc/safe-indirect-jump-7.c: New file.
        * gcc.target/powerpc/safe-indirect-jump-8.c: New file.


Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 256753)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -10453,10 +10453,35 @@
   else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn ("creqv 6,6,6", operands);
 
-  return "b%T0l";
+  if (rs6000_speculate_indirect_jumps
+      || which_alternative == 1 || which_alternative == 3)
+    return "b%T0l";
+  else
+    return "crset eq\;beq%T0l-";
 }
   [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
-   (set_attr "length" "4,4,8,8")])
+   (set (attr "length")
+       (cond [(and (eq (symbol_ref "which_alternative") (const_int 0))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 1)))
+                 (const_string "4")
+              (and (eq (symbol_ref "which_alternative") (const_int 0))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 0)))
+                 (const_string "8")
+              (eq (symbol_ref "which_alternative") (const_int 1))
+                 (const_string "4")
+              (and (eq (symbol_ref "which_alternative") (const_int 2))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 1)))
+                 (const_string "8")
+              (and (eq (symbol_ref "which_alternative") (const_int 2))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 0)))
+                 (const_string "12")
+              (eq (symbol_ref "which_alternative") (const_int 3))
+                 (const_string "8")]
+             (const_string "4")))])
 
 (define_insn_and_split "*call_nonlocal_sysv<mode>"
   [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s"))
@@ -10541,10 +10566,35 @@
   else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn ("creqv 6,6,6", operands);
 
-  return "b%T1l";
+  if (rs6000_speculate_indirect_jumps
+      || which_alternative == 1 || which_alternative == 3)
+    return "b%T1l";
+  else
+    return "crset eq\;beq%T1l-";
 }
   [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
-   (set_attr "length" "4,4,8,8")])
+   (set (attr "length")
+       (cond [(and (eq (symbol_ref "which_alternative") (const_int 0))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 1)))
+                 (const_string "4")
+              (and (eq (symbol_ref "which_alternative") (const_int 0))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 0)))
+                 (const_string "8")
+              (eq (symbol_ref "which_alternative") (const_int 1))
+                 (const_string "4")
+              (and (eq (symbol_ref "which_alternative") (const_int 2))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 1)))
+                 (const_string "8")
+              (and (eq (symbol_ref "which_alternative") (const_int 2))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 0)))
+                 (const_string "12")
+              (eq (symbol_ref "which_alternative") (const_int 3))
+                 (const_string "8")]
+             (const_string "4")))])
 
 (define_insn_and_split "*call_value_nonlocal_sysv<mode>"
   [(set (match_operand 0 "" "")
@@ -10669,11 +10719,22 @@
    (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"
+  "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 eq\;<ptrload> 2,%2\;beq%T0l-\;<ptrload> 2,%3(1)"
+  [(set_attr "type" "jmpreg")
+   (set_attr "length" "16")])
+
 (define_insn "*call_value_indirect_aix<mode>"
   [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
@@ -10681,11 +10742,23 @@
    (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"
+  "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 eq\;<ptrload> 2,%3\;beq%T1l-\;<ptrload> 2,%4(1)"
+  [(set_attr "type" "jmpreg")
+   (set_attr "length" "16")])
+
 ;; Call to indirect functions with the ELFv2 ABI.
 ;; Operand0 is the addresss of the function to call
 ;; Operand2 is the offset of the stack location holding the current TOC pointer
@@ -10909,7 +10982,13 @@
     output_asm_insn (\"creqv 6,6,6\", operands);
 
   if (which_alternative >= 2)
-    return \"b%T0\";
+    {
+      if (rs6000_speculate_indirect_jumps)
+       return \"b%T0\";
+      else
+       /* Can use CR0 since it is volatile across sibcalls.  */
+       return \"crset eq\;beq%T0-\;b .\";
+    }
   else if (DEFAULT_ABI == ABI_V4 && flag_pic)
     {
       gcc_assert (!TARGET_SECURE_PLT);
@@ -10919,7 +10998,28 @@
     return \"b %z0\";
 }"
   [(set_attr "type" "branch")
-   (set_attr "length" "4,8,4,8")])
+   (set (attr "length")
+       (cond [(eq (symbol_ref "which_alternative") (const_int 0))
+                 (const_string "4")
+              (eq (symbol_ref "which_alternative") (const_int 1))
+                 (const_string "8")
+              (and (eq (symbol_ref "which_alternative") (const_int 2))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 1)))
+                 (const_string "4")
+              (and (eq (symbol_ref "which_alternative") (const_int 2))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 0)))
+                 (const_string "12")
+              (and (eq (symbol_ref "which_alternative") (const_int 3))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 1)))
+                 (const_string "8")
+              (and (eq (symbol_ref "which_alternative") (const_int 3))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 0)))
+                 (const_string "16")]
+             (const_string "4")))])
 
 (define_insn "*sibcall_value_nonlocal_sysv<mode>"
   [(set (match_operand 0 "" "")
@@ -10939,7 +11039,13 @@
     output_asm_insn (\"creqv 6,6,6\", operands);
 
   if (which_alternative >= 2)
-    return \"b%T1\";
+    {
+      if (rs6000_speculate_indirect_jumps)
+       return \"b%T1\";
+      else
+       /* Can use CR0 since it is volatile across sibcalls.  */
+       return \"crset eq\;beq%T1-\;b .\";
+    }
   else if (DEFAULT_ABI == ABI_V4 && flag_pic)
     {
       gcc_assert (!TARGET_SECURE_PLT);
@@ -10949,7 +11055,28 @@
     return \"b %z1\";
 }"
   [(set_attr "type" "branch")
-   (set_attr "length" "4,8,4,8")])
+   (set (attr "length")
+       (cond [(eq (symbol_ref "which_alternative") (const_int 0))
+                 (const_string "4")
+              (eq (symbol_ref "which_alternative") (const_int 1))
+                 (const_string "8")
+              (and (eq (symbol_ref "which_alternative") (const_int 2))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 1)))
+                 (const_string "4")
+              (and (eq (symbol_ref "which_alternative") (const_int 2))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 0)))
+                 (const_string "12")
+              (and (eq (symbol_ref "which_alternative") (const_int 3))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 1)))
+                 (const_string "8")
+              (and (eq (symbol_ref "which_alternative") (const_int 3))
+                   (eq (symbol_ref "rs6000_speculate_indirect_jumps")
+                       (const_int 0)))
+                 (const_string "16")]
+             (const_string "4")))])
 
 ;; AIX ABI sibling call patterns.
 
Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c     (revision 
256753)
+++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c     (working copy)
@@ -1,7 +1,7 @@
-/* { dg-do compile { target { powerpc64le-*-* } } } */
+/* { dg-do compile { target { lp64 } } } */
 /* { dg-additional-options "-mno-speculate-indirect-jumps" } */
 
-/* Test for deliberate misprediction of indirect calls for ELFv2.  */
+/* Test for deliberate misprediction of indirect calls.  */
 
 extern int (*f)();
 
Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c     (nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c     (working copy)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
+
+/* Test for deliberate misprediction of indirect calls.  */
+
+extern int (*f)();
+
+int bar ()
+{
+  return (*f) () * 53;
+}
+
+/* { dg-final { scan-assembler "crset eq" } } */
+/* { dg-final { scan-assembler "beqctrl-" } } */
Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-8.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-8.c     (nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-8.c     (working copy)
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { ilp32 } } } */
+/* { dg-additional-options "-O2 -mno-speculate-indirect-jumps" } */
+
+/* Test for deliberate misprediction of -m32 sibcalls.  */
+
+extern int (*f)();
+
+int bar ()
+{
+  return (*f) ();
+}
+
+/* { dg-final { scan-assembler "crset eq" } } */
+/* { dg-final { scan-assembler "beqctr-" } } */
+/* { dg-final { scan-assembler "b ." } } */

Reply via email to