diff options
author | wschmidt <wschmidt@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-01-18 01:34:10 +0000 |
---|---|---|
committer | wschmidt <wschmidt@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-01-18 01:34:10 +0000 |
commit | d56301ce0da31950df7a9aaeffdf733162f1d304 (patch) | |
tree | bc4a0efb60efeb3bdce939d5b220c830dc3be245 | |
parent | 195ac7b203a48a4f230dc3b977641e9a4e8139db (diff) |
[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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@256832 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 46 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 3 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 263 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.opt | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c | 52 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c | 55 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c | 80 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-8.c | 15 |
13 files changed, 605 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ad7f159045af..51ab249a6b44 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> Backport from mainline diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 323b218d2293..6c5679a12821 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -39223,6 +39223,9 @@ static struct rs6000_opt_var const rs6000_opt_vars[] = { "sched-epilog", offsetof (struct gcc_options, 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", offsetof (struct gcc_options, x_rs6000_gen_cell_microcode), offsetof (struct cl_target_option, x_rs6000_gen_cell_microcode), }, diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index fe6653628c05..6daa7a99cd2c 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -11002,10 +11002,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")) @@ -11090,10 +11115,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 "" "") @@ -11218,11 +11268,22 @@ (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)) (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")) @@ -11230,11 +11291,23 @@ (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)) (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 @@ -11244,22 +11317,44 @@ (match_operand 1 "" "g,g")) (set (reg:P TOC_REGNUM) (unspec [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_ELFv2" + "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps" "b%T0l\;<ptrload> 2,%2(1)" [(set_attr "type" "jmpreg") (set_attr "length" "8")]) +;; Variant with deliberate misprediction. +(define_insn "*call_indirect_elfv2<mode>_nospec" + [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) + (match_operand 1 "" "g,g")) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps" + "crset eq\;beq%T0l-\;<ptrload> 2,%2(1)" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + (define_insn "*call_value_indirect_elfv2<mode>" [(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 [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_ELFv2" + "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps" "b%T1l\;<ptrload> 2,%3(1)" [(set_attr "type" "jmpreg") (set_attr "length" "8")]) +; Variant with deliberate misprediction. +(define_insn "*call_value_indirect_elfv2<mode>_nospec" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) + (match_operand 2 "" "g,g"))) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps" + "crset eq\;beq%T1l-\;<ptrload> 2,%3(1)" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) ;; Call subroutine returning any type. (define_expand "untyped_call" @@ -11436,7 +11531,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); @@ -11446,7 +11547,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 "" "") @@ -11466,7 +11588,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); @@ -11476,7 +11604,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. @@ -12852,16 +13001,35 @@ [(set_attr "type" "jmpreg")]) (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>" [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))] - "" + "rs6000_speculate_indirect_jumps" "@ bctr blr" [(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: (define_expand "tablejump" [(use (match_operand 0 "" "")) @@ -12869,10 +13037,23 @@ "" " { - if (TARGET_32BIT) - emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); + if (rs6000_speculate_indirect_jumps) + { + if (TARGET_32BIT) + emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); + else + emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); + } 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; }") @@ -12882,13 +13063,28 @@ (match_dup 2))) (parallel [(set (pc) (match_dup 3)) (use (label_ref (match_operand 1 "" "")))])] - "TARGET_32BIT" + "TARGET_32BIT && rs6000_speculate_indirect_jumps" " { operands[0] = force_reg (SImode, operands[0]); operands[2] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1])); 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" [(set (match_dup 4) (sign_extend:DI (match_operand:SI 0 "lwa_operand" ""))) @@ -12897,23 +13093,50 @@ (match_dup 2))) (parallel [(set (pc) (match_dup 3)) (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[3] = 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" [(set (pc) (match_operand:P 0 "register_operand" "c,*l")) (use (label_ref (match_operand 1 "" "")))] - "" + "rs6000_speculate_indirect_jumps" "@ bctr blr" [(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" [(unspec [(const_int 0)] UNSPEC_NOP)] "" diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index a232d5749be8..ce0210a5533c 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -700,3 +700,8 @@ Use the given offset for addressing the stack-protector guard. TargetVariable 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d098f41ac392..eb5b8187f96f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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> Backport from mainline diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c new file mode 100644 index 000000000000..d66e9c3cdb9d --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c @@ -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-" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c new file mode 100644 index 000000000000..b51034fa1b0c --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c @@ -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 ." } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c new file mode 100644 index 000000000000..81da127cc17b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c @@ -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 ." } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c new file mode 100644 index 000000000000..ed0000797c93 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c @@ -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; +} diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c new file mode 100644 index 000000000000..5a4cd9a838e6 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c @@ -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; +} diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c new file mode 100644 index 000000000000..a78e468fc707 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c @@ -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; +} diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c new file mode 100644 index 000000000000..d19245e34c4f --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c @@ -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-" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-8.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-8.c new file mode 100644 index 000000000000..be2150e0c148 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-8.c @@ -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 ." } } */ |