[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
This commit is contained in:
parent
f7300fff74
commit
dcacda0cc1
@ -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
|
||||
|
@ -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 *)
|
||||
|
@ -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)])
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user