[SPARC] Errata workaround for GRLIB-TN-0013

This patch provides a workaround for the errata described in GRLIB-TN-0013.

If the workaround is enabled it will:

* Prevent div and sqrt instructions in the delay slot.

* Insert NOPs to prevent the sequence (div/sqrt) -> (two or three floating
  point operations or loads) -> (div/sqrt).

* Not insert NOPs if any of the floating point operations have a dependency
  on the destination register of the first (div/sqrt).

* Not insert NOPs if one of the floating point operations is a (div/sqrt).

* Insert NOPs to prevent (div/sqrt) followed by a branch.

It is applicable to GR712RC, UT700, and UT699.

Backport from mainline
2017-11-29  Daniel Cederman  <cederman@gaisler.com>

gcc/
	* config/sparc/sparc.c (fpop_reg_depend_p): New function.
	(div_sqrt_insn_p): New function.
	(sparc_do_work_around_errata): Insert NOP instructions to
	prevent sequences that could trigger the TN-0013 errata for
	certain LEON3 processors.
	(pass_work_around_errata::gate): Also test sparc_fix_lost_divsqrt.
	(sparc_option_override): Set sparc_fix_lost_divsqrt appropriately.
	* config/sparc/sparc.md (fix_lost_divsqrt): New attribute.
	(in_branch_delay): Prevent div and sqrt in delay slot if
	fix_lost_divsqrt.
	* config/sparc/sparc.opt (sparc_fix_lost_divsqrt): New variable.

From-SVN: r255243
This commit is contained in:
Daniel Cederman 2017-11-29 17:01:45 +00:00 committed by Daniel Hellstrom
parent 304d27a099
commit dc363a5558
4 changed files with 138 additions and 2 deletions

View File

@ -1,5 +1,21 @@
2017-11-29 Daniel Cederman <cederman@gaisler.com>
Backport from mainline
* config/sparc/sparc.c (fpop_reg_depend_p): New function.
(div_sqrt_insn_p): New function.
(sparc_do_work_around_errata): Insert NOP instructions to
prevent sequences that could trigger the TN-0013 errata for
certain LEON3 processors.
(pass_work_around_errata::gate): Also test sparc_fix_lost_divsqrt.
(sparc_option_override): Set sparc_fix_lost_divsqrt appropriately.
* config/sparc/sparc.md (fix_lost_divsqrt): New attribute.
(in_branch_delay): Prevent div and sqrt in delay slot if
fix_lost_divsqrt.
* config/sparc/sparc.opt (sparc_fix_lost_divsqrt): New variable.
2017-11-29 Daniel Cederman <cederman@gaisler.com>
Backport from mainline
* config/sparc/sparc.c (atomic_insn_p): New function.
(sparc_do_work_around_errata): Insert NOP instructions to
prevent sequences that could trigger the TN-0010 errata for

View File

@ -914,6 +914,39 @@ mem_ref (rtx x)
return NULL_RTX;
}
/* True if any of INSN's source register(s) is REG. */
static bool
insn_uses_reg_p (rtx_insn *insn, unsigned int reg)
{
extract_insn (insn);
return ((REG_P (recog_data.operand[1])
&& REGNO (recog_data.operand[1]) == reg)
|| (recog_data.n_operands == 3
&& REG_P (recog_data.operand[2])
&& REGNO (recog_data.operand[2]) == reg));
}
/* True if INSN is a floating-point division or square-root. */
static bool
div_sqrt_insn_p (rtx_insn *insn)
{
if (GET_CODE (PATTERN (insn)) != SET)
return false;
switch (get_attr_type (insn))
{
case TYPE_FPDIVS:
case TYPE_FPSQRTS:
case TYPE_FPDIVD:
case TYPE_FPSQRTD:
return true;
default:
return false;
}
}
/* True if INSN is a floating-point instruction. */
static bool
@ -1034,6 +1067,79 @@ sparc_do_work_around_errata (void)
insert_nop = true;
}
/* Look for sequences that could trigger the GRLIB-TN-0013 errata. */
if (sparc_fix_lost_divsqrt
&& NONJUMP_INSN_P (insn)
&& div_sqrt_insn_p (insn))
{
int i;
int fp_found = 0;
rtx_insn *after;
const unsigned int dest_reg = REGNO (SET_DEST (single_set (insn)));
next = next_active_insn (insn);
if (!next)
break;
for (after = next, i = 0; i < 4; i++)
{
/* Count floating-point operations. */
if (i != 3 && fpop_insn_p (after))
{
/* If the insn uses the destination register of
the div/sqrt, then it cannot be problematic. */
if (insn_uses_reg_p (after, dest_reg))
break;
fp_found++;
}
/* Count floating-point loads. */
if (i != 3
&& (set = single_set (after)) != NULL_RTX
&& REG_P (SET_DEST (set))
&& REGNO (SET_DEST (set)) > 31)
{
/* If the insn uses the destination register of
the div/sqrt, then it cannot be problematic. */
if (REGNO (SET_DEST (set)) == dest_reg)
break;
fp_found++;
}
/* Check if this is a problematic sequence. */
if (i > 1
&& fp_found >= 2
&& div_sqrt_insn_p (after))
{
/* If this is the short version of the problematic
sequence we add two NOPs in a row to also prevent
the long version. */
if (i == 2)
emit_insn_before (gen_nop (), next);
insert_nop = true;
break;
}
/* No need to scan past a second div/sqrt. */
if (div_sqrt_insn_p (after))
break;
/* Insert NOP before branch. */
if (i < 3
&& (!NONJUMP_INSN_P (after)
|| GET_CODE (PATTERN (after)) == SEQUENCE))
{
insert_nop = true;
break;
}
after = next_active_insn (after);
if (!after)
break;
}
}
/* Look for either of these two sequences:
Sequence A:
@ -1362,7 +1468,7 @@ public:
virtual bool gate (function *)
{
return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst
|| sparc_fix_gr712rc || sparc_fix_ut700;
|| sparc_fix_gr712rc || sparc_fix_ut700 || sparc_fix_lost_divsqrt;
}
virtual unsigned int execute (function *)
@ -1732,9 +1838,12 @@ sparc_option_override (void)
if (!(target_flags_explicit & MASK_LRA))
target_flags |= MASK_LRA;
/* Enable the back-to-back store errata workaround for LEON3FT. */
/* Enable applicable errata workarounds for LEON3FT. */
if (sparc_fix_ut699 || sparc_fix_ut700 || sparc_fix_gr712rc)
{
sparc_fix_b2bst = 1;
sparc_fix_lost_divsqrt = 1;
}
/* Disable FsMULd for the UT699 since it doesn't work correctly. */
if (sparc_fix_ut699)

View File

@ -430,6 +430,10 @@
(symbol_ref "(sparc_fix_b2bst != 0
? FIX_B2BST_TRUE : FIX_B2BST_FALSE)"))
(define_attr "fix_lost_divsqrt" "false,true"
(symbol_ref "(sparc_fix_lost_divsqrt != 0
? FIX_LOST_DIVSQRT_TRUE : FIX_LOST_DIVSQRT_FALSE)"))
(define_attr "fix_gr712rc" "false,true"
(symbol_ref "(sparc_fix_gr712rc != 0
? FIX_GR712RC_TRUE : FIX_GR712RC_FALSE)"))
@ -581,6 +585,9 @@
(define_attr "in_branch_delay" "false,true"
(cond [(eq_attr "type" "uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi")
(const_string "false")
(and (eq_attr "fix_lost_divsqrt" "true")
(eq_attr "type" "fpdivs,fpsqrts,fpdivd,fpsqrtd"))
(const_string "false")
(and (eq_attr "fix_b2bst" "true") (eq_attr "type" "store,fpstore"))
(const_string "false")
(and (eq_attr "fix_ut699" "true") (eq_attr "type" "load,sload"))

View File

@ -253,6 +253,10 @@ Enable workarounds for the errata of the GR712RC processor.
TargetVariable
unsigned int sparc_fix_b2bst
;; Enable workaround for GRLIB-TN-0013 errata
TargetVariable
unsigned int sparc_fix_lost_divsqrt
Mask(LONG_DOUBLE_128)
;; Use 128-bit long double