backport: rs6000.c (rs6000_opt_vars): Add entry for -mspeculate-indirect-jumps.
[gcc] 2018-01-17 Bill Schmidt <wschmidt@linux.vnet.ibm.com> Backport from mainline 2018-01-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com> * config/rs6000/rs6000.c (rs6000_opt_vars): Add entry for -mspeculate-indirect-jumps. * config/rs6000/rs6000.md (*call_indirect_elfv2<mode>): Disable for -mno-speculate-indirect-jumps. (*call_indirect_elfv2<mode>_nospec): New define_insn. (*call_value_indirect_elfv2<mode>): Disable for -mno-speculate-indirect-jumps. (*call_value_indirect_elfv2<mode>_nospec): New define_insn. (indirect_jump): Emit different RTL for -mno-speculate-indirect-jumps. (*indirect_jump<mode>): Disable for -mno-speculate-indirect-jumps. (*indirect_jump<mode>_nospec): New define_insn. (tablejump): Emit different RTL for -mno-speculate-indirect-jumps. (tablejumpsi): Disable for -mno-speculate-indirect-jumps. (tablejumpsi_nospec): New define_expand. (tablejumpdi): Disable for -mno-speculate-indirect-jumps. (tablejumpdi_nospec): New define_expand. (*tablejump<mode>_internal1): Disable for -mno-speculate-indirect-jumps. (*tablejump<mode>_internal1_nospec): New define_insn. * config/rs6000/rs6000.opt (mspeculate-indirect-jumps): New option. Backport from mainline 2018-01-17 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-17 Bill Schmidt <wschmidt@linux.vnet.ibm.com> Backport from mainline 2018-01-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com> * gcc.target/powerpc/safe-indirect-jump-1.c: New file. * gcc.target/powerpc/safe-indirect-jump-2.c: New file. * gcc.target/powerpc/safe-indirect-jump-3.c: New file. * gcc.target/powerpc/safe-indirect-jump-4.c: New file. * gcc.target/powerpc/safe-indirect-jump-5.c: New file. * gcc.target/powerpc/safe-indirect-jump-6.c: New file. Backport from mainline 2018-01-17 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. From-SVN: r256832
This commit is contained in:
parent
a38e64ad03
commit
4a560547e3
|
@ -1,3 +1,49 @@
|
||||||
|
2018-01-17 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
Backport from mainline
|
||||||
|
2018-01-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
* config/rs6000/rs6000.c (rs6000_opt_vars): Add entry for
|
||||||
|
-mspeculate-indirect-jumps.
|
||||||
|
* config/rs6000/rs6000.md (*call_indirect_elfv2<mode>): Disable
|
||||||
|
for -mno-speculate-indirect-jumps.
|
||||||
|
(*call_indirect_elfv2<mode>_nospec): New define_insn.
|
||||||
|
(*call_value_indirect_elfv2<mode>): Disable for
|
||||||
|
-mno-speculate-indirect-jumps.
|
||||||
|
(*call_value_indirect_elfv2<mode>_nospec): New define_insn.
|
||||||
|
(indirect_jump): Emit different RTL for
|
||||||
|
-mno-speculate-indirect-jumps.
|
||||||
|
(*indirect_jump<mode>): Disable for
|
||||||
|
-mno-speculate-indirect-jumps.
|
||||||
|
(*indirect_jump<mode>_nospec): New define_insn.
|
||||||
|
(tablejump): Emit different RTL for
|
||||||
|
-mno-speculate-indirect-jumps.
|
||||||
|
(tablejumpsi): Disable for -mno-speculate-indirect-jumps.
|
||||||
|
(tablejumpsi_nospec): New define_expand.
|
||||||
|
(tablejumpdi): Disable for -mno-speculate-indirect-jumps.
|
||||||
|
(tablejumpdi_nospec): New define_expand.
|
||||||
|
(*tablejump<mode>_internal1): Disable for
|
||||||
|
-mno-speculate-indirect-jumps.
|
||||||
|
(*tablejump<mode>_internal1_nospec): New define_insn.
|
||||||
|
* config/rs6000/rs6000.opt (mspeculate-indirect-jumps): New
|
||||||
|
option.
|
||||||
|
|
||||||
|
Backport from mainline
|
||||||
|
2018-01-17 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.
|
||||||
|
|
||||||
2018-01-17 Richard Biener <rguenther@suse.de>
|
2018-01-17 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
Backport from mainline
|
Backport from mainline
|
||||||
|
|
|
@ -39223,6 +39223,9 @@ static struct rs6000_opt_var const rs6000_opt_vars[] =
|
||||||
{ "sched-epilog",
|
{ "sched-epilog",
|
||||||
offsetof (struct gcc_options, x_TARGET_SCHED_PROLOG),
|
offsetof (struct gcc_options, x_TARGET_SCHED_PROLOG),
|
||||||
offsetof (struct cl_target_option, x_TARGET_SCHED_PROLOG), },
|
offsetof (struct cl_target_option, x_TARGET_SCHED_PROLOG), },
|
||||||
|
{ "speculate-indirect-jumps",
|
||||||
|
offsetof (struct gcc_options, x_rs6000_speculate_indirect_jumps),
|
||||||
|
offsetof (struct cl_target_option, x_rs6000_speculate_indirect_jumps), },
|
||||||
{ "gen-cell-microcode",
|
{ "gen-cell-microcode",
|
||||||
offsetof (struct gcc_options, x_rs6000_gen_cell_microcode),
|
offsetof (struct gcc_options, x_rs6000_gen_cell_microcode),
|
||||||
offsetof (struct cl_target_option, x_rs6000_gen_cell_microcode), },
|
offsetof (struct cl_target_option, x_rs6000_gen_cell_microcode), },
|
||||||
|
|
|
@ -11002,10 +11002,35 @@
|
||||||
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
|
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
|
||||||
output_asm_insn ("creqv 6,6,6", operands);
|
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 "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>"
|
(define_insn_and_split "*call_nonlocal_sysv<mode>"
|
||||||
[(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s"))
|
[(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s"))
|
||||||
|
@ -11090,10 +11115,35 @@
|
||||||
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
|
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
|
||||||
output_asm_insn ("creqv 6,6,6", operands);
|
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 "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>"
|
(define_insn_and_split "*call_value_nonlocal_sysv<mode>"
|
||||||
[(set (match_operand 0 "" "")
|
[(set (match_operand 0 "" "")
|
||||||
|
@ -11218,11 +11268,22 @@
|
||||||
(use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
|
(use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
|
||||||
(set (reg:P TOC_REGNUM) (unspec [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
|
(set (reg:P TOC_REGNUM) (unspec [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
|
||||||
(clobber (reg:P LR_REGNO))]
|
(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)"
|
"<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3(1)"
|
||||||
[(set_attr "type" "jmpreg")
|
[(set_attr "type" "jmpreg")
|
||||||
(set_attr "length" "12")])
|
(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>"
|
(define_insn "*call_value_indirect_aix<mode>"
|
||||||
[(set (match_operand 0 "" "")
|
[(set (match_operand 0 "" "")
|
||||||
(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
|
(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
|
||||||
|
@ -11230,11 +11291,23 @@
|
||||||
(use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
|
(use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
|
||||||
(set (reg:P TOC_REGNUM) (unspec [(match_operand:P 4 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
|
(set (reg:P TOC_REGNUM) (unspec [(match_operand:P 4 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
|
||||||
(clobber (reg:P LR_REGNO))]
|
(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)"
|
"<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4(1)"
|
||||||
[(set_attr "type" "jmpreg")
|
[(set_attr "type" "jmpreg")
|
||||||
(set_attr "length" "12")])
|
(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.
|
;; Call to indirect functions with the ELFv2 ABI.
|
||||||
;; Operand0 is the addresss of the function to call
|
;; Operand0 is the addresss of the function to call
|
||||||
;; Operand2 is the offset of the stack location holding the current TOC pointer
|
;; Operand2 is the offset of the stack location holding the current TOC pointer
|
||||||
|
@ -11244,22 +11317,44 @@
|
||||||
(match_operand 1 "" "g,g"))
|
(match_operand 1 "" "g,g"))
|
||||||
(set (reg:P TOC_REGNUM) (unspec [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
|
(set (reg:P TOC_REGNUM) (unspec [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
|
||||||
(clobber (reg:P LR_REGNO))]
|
(clobber (reg:P LR_REGNO))]
|
||||||
"DEFAULT_ABI == ABI_ELFv2"
|
"DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps"
|
||||||
"b%T0l\;<ptrload> 2,%2(1)"
|
"b%T0l\;<ptrload> 2,%2(1)"
|
||||||
[(set_attr "type" "jmpreg")
|
[(set_attr "type" "jmpreg")
|
||||||
(set_attr "length" "8")])
|
(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 eq\;beq%T0l-\;<ptrload> 2,%2(1)"
|
||||||
|
[(set_attr "type" "jmpreg")
|
||||||
|
(set_attr "length" "12")])
|
||||||
|
|
||||||
(define_insn "*call_value_indirect_elfv2<mode>"
|
(define_insn "*call_value_indirect_elfv2<mode>"
|
||||||
[(set (match_operand 0 "" "")
|
[(set (match_operand 0 "" "")
|
||||||
(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
|
(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
|
||||||
(match_operand 2 "" "g,g")))
|
(match_operand 2 "" "g,g")))
|
||||||
(set (reg:P TOC_REGNUM) (unspec [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
|
(set (reg:P TOC_REGNUM) (unspec [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
|
||||||
(clobber (reg:P LR_REGNO))]
|
(clobber (reg:P LR_REGNO))]
|
||||||
"DEFAULT_ABI == ABI_ELFv2"
|
"DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps"
|
||||||
"b%T1l\;<ptrload> 2,%3(1)"
|
"b%T1l\;<ptrload> 2,%3(1)"
|
||||||
[(set_attr "type" "jmpreg")
|
[(set_attr "type" "jmpreg")
|
||||||
(set_attr "length" "8")])
|
(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 eq\;beq%T1l-\;<ptrload> 2,%3(1)"
|
||||||
|
[(set_attr "type" "jmpreg")
|
||||||
|
(set_attr "length" "12")])
|
||||||
|
|
||||||
;; Call subroutine returning any type.
|
;; Call subroutine returning any type.
|
||||||
(define_expand "untyped_call"
|
(define_expand "untyped_call"
|
||||||
|
@ -11436,7 +11531,13 @@
|
||||||
output_asm_insn (\"creqv 6,6,6\", operands);
|
output_asm_insn (\"creqv 6,6,6\", operands);
|
||||||
|
|
||||||
if (which_alternative >= 2)
|
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)
|
else if (DEFAULT_ABI == ABI_V4 && flag_pic)
|
||||||
{
|
{
|
||||||
gcc_assert (!TARGET_SECURE_PLT);
|
gcc_assert (!TARGET_SECURE_PLT);
|
||||||
|
@ -11446,7 +11547,28 @@
|
||||||
return \"b %z0\";
|
return \"b %z0\";
|
||||||
}"
|
}"
|
||||||
[(set_attr "type" "branch")
|
[(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>"
|
(define_insn "*sibcall_value_nonlocal_sysv<mode>"
|
||||||
[(set (match_operand 0 "" "")
|
[(set (match_operand 0 "" "")
|
||||||
|
@ -11466,7 +11588,13 @@
|
||||||
output_asm_insn (\"creqv 6,6,6\", operands);
|
output_asm_insn (\"creqv 6,6,6\", operands);
|
||||||
|
|
||||||
if (which_alternative >= 2)
|
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)
|
else if (DEFAULT_ABI == ABI_V4 && flag_pic)
|
||||||
{
|
{
|
||||||
gcc_assert (!TARGET_SECURE_PLT);
|
gcc_assert (!TARGET_SECURE_PLT);
|
||||||
|
@ -11476,7 +11604,28 @@
|
||||||
return \"b %z1\";
|
return \"b %z1\";
|
||||||
}"
|
}"
|
||||||
[(set_attr "type" "branch")
|
[(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.
|
;; AIX ABI sibling call patterns.
|
||||||
|
|
||||||
|
@ -12852,16 +13001,35 @@
|
||||||
[(set_attr "type" "jmpreg")])
|
[(set_attr "type" "jmpreg")])
|
||||||
|
|
||||||
(define_expand "indirect_jump"
|
(define_expand "indirect_jump"
|
||||||
[(set (pc) (match_operand 0 "register_operand" ""))])
|
[(set (pc) (match_operand 0 "register_operand"))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
if (!rs6000_speculate_indirect_jumps) {
|
||||||
|
rtx ccreg = gen_reg_rtx (CCmode);
|
||||||
|
if (Pmode == DImode)
|
||||||
|
emit_jump_insn (gen_indirect_jumpdi_nospec (operands[0], ccreg));
|
||||||
|
else
|
||||||
|
emit_jump_insn (gen_indirect_jumpsi_nospec (operands[0], ccreg));
|
||||||
|
DONE;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
(define_insn "*indirect_jump<mode>"
|
(define_insn "*indirect_jump<mode>"
|
||||||
[(set (pc) (match_operand:P 0 "register_operand" "c,*l"))]
|
[(set (pc) (match_operand:P 0 "register_operand" "c,*l"))]
|
||||||
""
|
"rs6000_speculate_indirect_jumps"
|
||||||
"@
|
"@
|
||||||
bctr
|
bctr
|
||||||
blr"
|
blr"
|
||||||
[(set_attr "type" "jmpreg")])
|
[(set_attr "type" "jmpreg")])
|
||||||
|
|
||||||
|
(define_insn "indirect_jump<mode>_nospec"
|
||||||
|
[(set (pc) (match_operand:P 0 "register_operand" "c,*l"))
|
||||||
|
(clobber (match_operand:CC 1 "cc_reg_operand" "=y,y"))]
|
||||||
|
"!rs6000_speculate_indirect_jumps"
|
||||||
|
"crset %E1\;beq%T0- %1\;b ."
|
||||||
|
[(set_attr "type" "jmpreg")
|
||||||
|
(set_attr "length" "12")])
|
||||||
|
|
||||||
;; Table jump for switch statements:
|
;; Table jump for switch statements:
|
||||||
(define_expand "tablejump"
|
(define_expand "tablejump"
|
||||||
[(use (match_operand 0 "" ""))
|
[(use (match_operand 0 "" ""))
|
||||||
|
@ -12869,10 +13037,23 @@
|
||||||
""
|
""
|
||||||
"
|
"
|
||||||
{
|
{
|
||||||
if (TARGET_32BIT)
|
if (rs6000_speculate_indirect_jumps)
|
||||||
emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
|
{
|
||||||
|
if (TARGET_32BIT)
|
||||||
|
emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
|
||||||
|
else
|
||||||
|
emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
|
{
|
||||||
|
rtx ccreg = gen_reg_rtx (CCmode);
|
||||||
|
rtx jump;
|
||||||
|
if (TARGET_32BIT)
|
||||||
|
jump = gen_tablejumpsi_nospec (operands[0], operands[1], ccreg);
|
||||||
|
else
|
||||||
|
jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg);
|
||||||
|
emit_jump_insn (jump);
|
||||||
|
}
|
||||||
DONE;
|
DONE;
|
||||||
}")
|
}")
|
||||||
|
|
||||||
|
@ -12882,13 +13063,28 @@
|
||||||
(match_dup 2)))
|
(match_dup 2)))
|
||||||
(parallel [(set (pc) (match_dup 3))
|
(parallel [(set (pc) (match_dup 3))
|
||||||
(use (label_ref (match_operand 1 "" "")))])]
|
(use (label_ref (match_operand 1 "" "")))])]
|
||||||
"TARGET_32BIT"
|
"TARGET_32BIT && rs6000_speculate_indirect_jumps"
|
||||||
"
|
"
|
||||||
{ operands[0] = force_reg (SImode, operands[0]);
|
{ operands[0] = force_reg (SImode, operands[0]);
|
||||||
operands[2] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1]));
|
operands[2] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1]));
|
||||||
operands[3] = gen_reg_rtx (SImode);
|
operands[3] = gen_reg_rtx (SImode);
|
||||||
}")
|
}")
|
||||||
|
|
||||||
|
(define_expand "tablejumpsi_nospec"
|
||||||
|
[(set (match_dup 4)
|
||||||
|
(plus:SI (match_operand:SI 0)
|
||||||
|
(match_dup 3)))
|
||||||
|
(parallel [(set (pc)
|
||||||
|
(match_dup 4))
|
||||||
|
(use (label_ref (match_operand 1)))
|
||||||
|
(clobber (match_operand 2))])]
|
||||||
|
"TARGET_32BIT && !rs6000_speculate_indirect_jumps"
|
||||||
|
{
|
||||||
|
operands[0] = force_reg (SImode, operands[0]);
|
||||||
|
operands[3] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1]));
|
||||||
|
operands[4] = gen_reg_rtx (SImode);
|
||||||
|
})
|
||||||
|
|
||||||
(define_expand "tablejumpdi"
|
(define_expand "tablejumpdi"
|
||||||
[(set (match_dup 4)
|
[(set (match_dup 4)
|
||||||
(sign_extend:DI (match_operand:SI 0 "lwa_operand" "")))
|
(sign_extend:DI (match_operand:SI 0 "lwa_operand" "")))
|
||||||
|
@ -12897,23 +13093,50 @@
|
||||||
(match_dup 2)))
|
(match_dup 2)))
|
||||||
(parallel [(set (pc) (match_dup 3))
|
(parallel [(set (pc) (match_dup 3))
|
||||||
(use (label_ref (match_operand 1 "" "")))])]
|
(use (label_ref (match_operand 1 "" "")))])]
|
||||||
"TARGET_64BIT"
|
"TARGET_64BIT && rs6000_speculate_indirect_jumps"
|
||||||
"
|
"
|
||||||
{ operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
|
{ operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
|
||||||
operands[3] = gen_reg_rtx (DImode);
|
operands[3] = gen_reg_rtx (DImode);
|
||||||
operands[4] = gen_reg_rtx (DImode);
|
operands[4] = gen_reg_rtx (DImode);
|
||||||
}")
|
}")
|
||||||
|
|
||||||
|
(define_expand "tablejumpdi_nospec"
|
||||||
|
[(set (match_dup 5)
|
||||||
|
(sign_extend:DI (match_operand:SI 0 "lwa_operand")))
|
||||||
|
(set (match_dup 4)
|
||||||
|
(plus:DI (match_dup 5)
|
||||||
|
(match_dup 3)))
|
||||||
|
(parallel [(set (pc)
|
||||||
|
(match_dup 4))
|
||||||
|
(use (label_ref (match_operand 1)))
|
||||||
|
(clobber (match_operand 2))])]
|
||||||
|
"TARGET_64BIT && !rs6000_speculate_indirect_jumps"
|
||||||
|
{
|
||||||
|
operands[3] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
|
||||||
|
operands[4] = gen_reg_rtx (DImode);
|
||||||
|
operands[5] = gen_reg_rtx (DImode);
|
||||||
|
})
|
||||||
|
|
||||||
(define_insn "*tablejump<mode>_internal1"
|
(define_insn "*tablejump<mode>_internal1"
|
||||||
[(set (pc)
|
[(set (pc)
|
||||||
(match_operand:P 0 "register_operand" "c,*l"))
|
(match_operand:P 0 "register_operand" "c,*l"))
|
||||||
(use (label_ref (match_operand 1 "" "")))]
|
(use (label_ref (match_operand 1 "" "")))]
|
||||||
""
|
"rs6000_speculate_indirect_jumps"
|
||||||
"@
|
"@
|
||||||
bctr
|
bctr
|
||||||
blr"
|
blr"
|
||||||
[(set_attr "type" "jmpreg")])
|
[(set_attr "type" "jmpreg")])
|
||||||
|
|
||||||
|
(define_insn "*tablejump<mode>_internal1_nospec"
|
||||||
|
[(set (pc)
|
||||||
|
(match_operand:P 0 "register_operand" "c,*l"))
|
||||||
|
(use (label_ref (match_operand 1)))
|
||||||
|
(clobber (match_operand:CC 2 "cc_reg_operand" "=y,y"))]
|
||||||
|
"!rs6000_speculate_indirect_jumps"
|
||||||
|
"crset %E2\;beq%T0- %2\;b ."
|
||||||
|
[(set_attr "type" "jmpreg")
|
||||||
|
(set_attr "length" "12")])
|
||||||
|
|
||||||
(define_insn "nop"
|
(define_insn "nop"
|
||||||
[(unspec [(const_int 0)] UNSPEC_NOP)]
|
[(unspec [(const_int 0)] UNSPEC_NOP)]
|
||||||
""
|
""
|
||||||
|
|
|
@ -700,3 +700,8 @@ Use the given offset for addressing the stack-protector guard.
|
||||||
|
|
||||||
TargetVariable
|
TargetVariable
|
||||||
long rs6000_stack_protector_guard_offset = 0
|
long rs6000_stack_protector_guard_offset = 0
|
||||||
|
|
||||||
|
;; -mno-speculate-indirect-jumps adds deliberate misprediction to indirect
|
||||||
|
;; branches via the CTR.
|
||||||
|
mspeculate-indirect-jumps
|
||||||
|
Target Undocumented Var(rs6000_speculate_indirect_jumps) Init(1) Save
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
2018-01-17 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
Backport from mainline
|
||||||
|
2018-01-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
* gcc.target/powerpc/safe-indirect-jump-1.c: New file.
|
||||||
|
* gcc.target/powerpc/safe-indirect-jump-2.c: New file.
|
||||||
|
* gcc.target/powerpc/safe-indirect-jump-3.c: New file.
|
||||||
|
* gcc.target/powerpc/safe-indirect-jump-4.c: New file.
|
||||||
|
* gcc.target/powerpc/safe-indirect-jump-5.c: New file.
|
||||||
|
* gcc.target/powerpc/safe-indirect-jump-6.c: New file.
|
||||||
|
|
||||||
|
Backport from mainline
|
||||||
|
2018-01-17 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.
|
||||||
|
|
||||||
2018-01-17 Harald Anlauf <anlauf@gmx.de>
|
2018-01-17 Harald Anlauf <anlauf@gmx.de>
|
||||||
|
|
||||||
Backport from mainline
|
Backport from mainline
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* { dg-do compile { target { lp64 } } } */
|
||||||
|
/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
|
||||||
|
|
||||||
|
/* Test for deliberate misprediction of indirect calls. */
|
||||||
|
|
||||||
|
extern int (*f)();
|
||||||
|
|
||||||
|
int bar ()
|
||||||
|
{
|
||||||
|
return (*f) ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* { dg-final { scan-assembler "crset eq" } } */
|
||||||
|
/* { dg-final { scan-assembler "beqctrl-" } } */
|
|
@ -0,0 +1,33 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-mno-speculate-indirect-jumps" } */
|
||||||
|
|
||||||
|
/* Test for deliberate misprediction of computed goto. */
|
||||||
|
|
||||||
|
int bar (int);
|
||||||
|
int baz (int);
|
||||||
|
int spaz (int);
|
||||||
|
|
||||||
|
int foo (int x)
|
||||||
|
{
|
||||||
|
static void *labptr[] = { &&lab0, &&lab1, &&lab2 };
|
||||||
|
|
||||||
|
if (x < 0 || x > 2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
goto *labptr[x];
|
||||||
|
|
||||||
|
lab0:
|
||||||
|
return bar (x);
|
||||||
|
|
||||||
|
lab1:
|
||||||
|
return baz (x) + 1;
|
||||||
|
|
||||||
|
lab2:
|
||||||
|
return spaz (x) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The following assumes CR7 as the first chosen volatile. */
|
||||||
|
|
||||||
|
/* { dg-final { scan-assembler "crset 30" } } */
|
||||||
|
/* { dg-final { scan-assembler "beqctr- 7" } } */
|
||||||
|
/* { dg-final { scan-assembler "b ." } } */
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-mno-speculate-indirect-jumps" } */
|
||||||
|
|
||||||
|
/* Test for deliberate misprediction of jump tables. */
|
||||||
|
|
||||||
|
void bar (void);
|
||||||
|
|
||||||
|
int foo (int x)
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
|
||||||
|
switch (x)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
a = -1;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
a = x * x;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
a = x + 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
a = x + x;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
a = x << 3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
a = x >> 1;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
a = x;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
a = 0;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
a = x * x + x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bar();
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The following assumes CR7 as the first chosen volatile. */
|
||||||
|
|
||||||
|
/* { dg-final { scan-assembler "crset 30" } } */
|
||||||
|
/* { dg-final { scan-assembler "beqctr- 7" } } */
|
||||||
|
/* { dg-final { scan-assembler "b ." } } */
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
|
||||||
|
|
||||||
|
/* Test for deliberate misprediction of indirect calls for ELFv2. */
|
||||||
|
|
||||||
|
int (*f)();
|
||||||
|
|
||||||
|
int __attribute__((noinline)) bar ()
|
||||||
|
{
|
||||||
|
return (*f) ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int g ()
|
||||||
|
{
|
||||||
|
return 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
f = &g;
|
||||||
|
if (bar () != 26)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-additional-options "-mno-speculate-indirect-jumps -Wno-pedantic" } */
|
||||||
|
|
||||||
|
/* Test for deliberate misprediction of computed goto. */
|
||||||
|
|
||||||
|
int __attribute__((noinline)) bar (int i)
|
||||||
|
{
|
||||||
|
return 1960 + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__((noinline)) baz (int i)
|
||||||
|
{
|
||||||
|
return i * i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__((noinline)) spaz (int i)
|
||||||
|
{
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int foo (int x)
|
||||||
|
{
|
||||||
|
static void *labptr[] = { &&lab0, &&lab1, &&lab2 };
|
||||||
|
|
||||||
|
if (x < 0 || x > 2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
goto *labptr[x];
|
||||||
|
|
||||||
|
lab0:
|
||||||
|
return bar (x);
|
||||||
|
|
||||||
|
lab1:
|
||||||
|
return baz (x) + 1;
|
||||||
|
|
||||||
|
lab2:
|
||||||
|
return spaz (x) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
if (foo (0) != 1960)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (1) != 2)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (2) != 1)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (3) != -1)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
|
||||||
|
|
||||||
|
/* Test for deliberate misprediction of jump tables. */
|
||||||
|
|
||||||
|
void __attribute__((noinline)) bar ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int foo (int x)
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
|
||||||
|
switch (x)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
a = -1;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
a = x * x + 3;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
a = x + 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
a = x + x;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
a = x << 3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
a = x >> 1;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
a = x;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
a = 0;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
a = x * x + x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bar();
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
if (foo (0) != 3)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (1) != 2)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (2) != 4)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (3) != 24)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (4) != 2)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (5) != 5)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (6) != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (7) != 56)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
if (foo (8) != -1)
|
||||||
|
__builtin_abort ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -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-" } } */
|
|
@ -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 ." } } */
|
Loading…
Reference in New Issue