[v2,rs6000] Implement 32- and 64-bit BE handling for -mno-speculate-indirect-jumps

Message ID 3e150d8a-f6be-4334-b4ed-63155bfc4119@linux.vnet.ibm.com
State New
Headers show
Series
  • [v2,rs6000] Implement 32- and 64-bit BE handling for -mno-speculate-indirect-jumps
Related show

Commit Message

Bill Schmidt Jan. 17, 2018, 2:08 a.m.
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  <wschmidt@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  <wschmidt@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.

Comments

Segher Boessenkool Jan. 17, 2018, 8:38 p.m. | #1
On Tue, Jan 16, 2018 at 08:08:57PM -0600, Bill Schmidt wrote:
> 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?


Okay for trunk and backports.  A few possible cleanups (okay with or
without, you need to get this in soon):

> -   (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")


You could leave out the "4" cases, it's the default.  Might be easier
to read.

I'd use "ne 0" instead of "eq 1", but this will work I guess.

> @@ -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\";


You can write the block as a block ({}) instead of as a string ("*{}")
so you don't need all the backslashes.

Thanks for all the work!


Segher
David Edelsohn Jan. 19, 2018, 6:32 p.m. | #2
This patch is incorrect for AIX.  Which also means that the backport
to GCC 7 branch is incorrect for AIX and must be corrected before the
release.

AIX assembler does not accept "." (period) as the current address.

"b ." is incorrect.  And testing for "b ." is incorrect.  I am going
to try testing with "$" in trunk.

GCC 7.3 must be re-spun.

Thanks, David

On Tue, Jan 16, 2018 at 9:08 PM, Bill Schmidt
<wschmidt@linux.vnet.ibm.com> wrote:
> 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  <wschmidt@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  <wschmidt@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 ." } } */

>
Bill Schmidt Jan. 19, 2018, 8:44 p.m. | #3
On Jan 19, 2018, at 12:32 PM, David Edelsohn <dje.gcc@gmail.com> wrote:
> 

> This patch is incorrect for AIX.  Which also means that the backport

> to GCC 7 branch is incorrect for AIX and must be corrected before the

> release.

> 

> AIX assembler does not accept "." (period) as the current address.

> 

> "b ." is incorrect.  And testing for "b ." is incorrect.  I am going

> to try testing with "$" in trunk.

> 

> GCC 7.3 must be re-spun.


Thanks, David, patch in progress.

FYI, I missed the 7.3 RC deadline, so this will only get picked up on a respin
anyway.  So I should have the fix in place before that happens.

Bill
> 

> Thanks, David

> 

> On Tue, Jan 16, 2018 at 9:08 PM, Bill Schmidt

> <wschmidt@linux.vnet.ibm.com> wrote:

>> 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  <wschmidt@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  <wschmidt@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 ." } } */

>> 

>

Patch

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 ." } } */