diff options
author | Daniel Cederman <cederman@gaisler.com> | 2017-11-29 15:15:48 +0000 |
---|---|---|
committer | Daniel Hellstrom <danielh@gcc.gnu.org> | 2017-11-29 16:15:48 +0100 |
commit | dcacda0cc1c9ecd23c15e8403e8025129502fed9 (patch) | |
tree | e20f603705106c0bdc0546ee661b6c279d4ba2ea | |
parent | f7300fff74becf365cdadd23c9447521da852e84 (diff) | |
download | gcc-dcacda0cc1c9ecd23c15e8403e8025129502fed9.zip gcc-dcacda0cc1c9ecd23c15e8403e8025129502fed9.tar.gz gcc-dcacda0cc1c9ecd23c15e8403e8025129502fed9.tar.bz2 |
[SPARC] Errata workaround for GRLIB-TN-0012
This patch provides a workaround for the errata described in GRLIB-TN-0012.
If the workaround is enabled it will:
* Prevent any floating-point operation from being placed in the
delay slot of an annulled integer branch.
* Place a NOP at the branch target of an integer branch if it is
a floating-point operation or a floating-point branch.
It is applicable to GR712RC.
2017-11-29 Daniel Cederman <cederman@gaisler.com>
gcc/
* config/sparc/sparc.c (fpop_insn_p): New function.
(sparc_do_work_around_errata): Insert NOP instructions to
prevent sequences that could trigger the TN-0012 errata for
GR712RC.
(pass_work_around_errata::gate): Also test sparc_fix_gr712rc.
* config/sparc/sparc.md (fix_gr712rc): New attribute.
(in_branch_annul_delay): Prevent floating-point instructions
in delay slot of annulled integer branch.
From-SVN: r255234
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 57 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 21 |
3 files changed, 84 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 003b6b1..390a0b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2017-11-29 Daniel Cederman <cederman@gaisler.com> + + * config/sparc/sparc.c (fpop_insn_p): New function. + (sparc_do_work_around_errata): Insert NOP instructions to + prevent sequences that could trigger the TN-0012 errata for + GR712RC. + (pass_work_around_errata::gate): Also test sparc_fix_gr712rc. + * config/sparc/sparc.md (fix_gr712rc): New attribute. + (in_branch_annul_delay): Prevent floating-point instructions + in delay slot of annulled integer branch. + 2017-11-29 Richard Biener <rguenther@suse.de> PR tree-optimization/83202 diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index a9945e2..3208165 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -945,6 +945,31 @@ mem_ref (rtx x) return NULL_RTX; } +/* True if INSN is a floating-point instruction. */ + +static bool +fpop_insn_p (rtx_insn *insn) +{ + if (GET_CODE (PATTERN (insn)) != SET) + return false; + + switch (get_attr_type (insn)) + { + case TYPE_FPMOVE: + case TYPE_FPCMOVE: + case TYPE_FP: + case TYPE_FPCMP: + case TYPE_FPMUL: + case TYPE_FPDIVS: + case TYPE_FPSQRTS: + case TYPE_FPDIVD: + case TYPE_FPSQRTD: + return true; + default: + return false; + } +} + /* We use a machine specific pass to enable workarounds for errata. We need to have the (essentially) final form of the insn stream in order @@ -970,11 +995,34 @@ sparc_do_work_around_errata (void) { bool insert_nop = false; rtx set; + rtx_insn *jump; + rtx_sequence *seq; /* Look into the instruction in a delay slot. */ - if (NONJUMP_INSN_P (insn)) - if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn))) - insn = seq->insn (1); + if (NONJUMP_INSN_P (insn) + && (seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))) + { + jump = seq->insn (0); + insn = seq->insn (1); + } + else if (JUMP_P (insn)) + jump = insn; + else + jump = NULL; + + /* Place a NOP at the branch target of an integer branch if it is + a floating-point operation or a floating-point branch. */ + if (sparc_fix_gr712rc + && jump != NULL_RTX + && get_attr_branch_type (jump) == BRANCH_TYPE_ICC) + { + rtx_insn *target = next_active_insn (JUMP_LABEL_AS_INSN (jump)); + if (target + && (fpop_insn_p (target) + || ((JUMP_P (target) + && get_attr_branch_type (target) == BRANCH_TYPE_FCC)))) + emit_insn_before (gen_nop (), target); + } /* Look for either of these two sequences: @@ -1303,7 +1351,8 @@ public: /* opt_pass methods: */ virtual bool gate (function *) { - return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst; + return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst + || sparc_fix_gr712rc; } virtual unsigned int execute (function *) diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index d9cbd4f..c6f3b61 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -430,6 +430,10 @@ (symbol_ref "(sparc_fix_b2bst != 0 ? FIX_B2BST_TRUE : FIX_B2BST_FALSE)")) +(define_attr "fix_gr712rc" "false,true" + (symbol_ref "(sparc_fix_gr712rc != 0 + ? FIX_GR712RC_TRUE : FIX_GR712RC_FALSE)")) + ;; Length (in # of insns). ;; Beware that setting a length greater or equal to 3 for conditional branches ;; has a side-effect (see output_cbranch and output_v9branch). @@ -590,6 +594,15 @@ (const_string "true") ] (const_string "false"))) +(define_attr "in_integer_branch_annul_delay" "false,true" + (cond [(and (eq_attr "fix_gr712rc" "true") + (eq_attr "type" "fp,fpcmp,fpmove,fpcmove,fpmul, + fpdivs,fpsqrts,fpdivd,fpsqrtd")) + (const_string "false") + (eq_attr "in_branch_delay" "true") + (const_string "true") + ] (const_string "false"))) + (define_delay (eq_attr "type" "call") [(eq_attr "in_call_delay" "true") (nil) (nil)]) @@ -599,9 +612,15 @@ (define_delay (eq_attr "type" "return") [(eq_attr "in_return_delay" "true") (nil) (nil)]) -(define_delay (eq_attr "type" "branch") +(define_delay (and (eq_attr "type" "branch") + (not (eq_attr "branch_type" "icc"))) [(eq_attr "in_branch_delay" "true") (nil) (eq_attr "in_branch_delay" "true")]) +(define_delay (and (eq_attr "type" "branch") + (eq_attr "branch_type" "icc")) + [(eq_attr "in_branch_delay" "true") (nil) + (eq_attr "in_integer_branch_annul_delay" "true")]) + (define_delay (eq_attr "type" "uncond_branch") [(eq_attr "in_branch_delay" "true") (nil) (nil)]) |