Message ID | 20171127095715.5938-4-cederman@gaisler.com |
---|---|
State | New |
Headers | show |
Series | Workarounds for UT699, UT700, and GR712RC errata | expand |
> 2017-11-17 Daniel Cederman <cederman@gaisler.com> > > * 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 > UT700. > * config/sparc/sync.md (atomic_compare_and_swap_leon3_1): Make > instruction referable in atomic_insns_p. OK for mainline and 7 branch, thanks.
> @@ -1024,6 +1040,31 @@ sparc_do_work_around_errata (void) > emit_insn_before (gen_nop (), target); > } > > + /* Insert a NOP between load instruction and atomic > + instruction. Insert a NOP at branch target if load > + in delay slot and atomic instruction at branch target. */ > + if (sparc_fix_ut700 > + && NONJUMP_INSN_P (insn) > + && (set = single_set (insn)) != NULL_RTX > + && MEM_P (SET_SRC (set)) > + && REG_P (SET_DEST (set))) Any particular reason to use MEM_P instead of mem_ref here? It looks like there is also a case for the b2bst workaround (only loads are concerned). If no, I'll make the changes along with more cosmetic fixes.
> Any particular reason to use MEM_P instead of mem_ref here? It looks like > there is also a case for the b2bst workaround (only loads are concerned). No, there was no particular reason. mem_ref seems like a better choice if it detects more types of loads. /Daniel C
> No, there was no particular reason. mem_ref seems like a better choice > if it detects more types of loads. Right, it's supposed to detect all types of loads. Here's what I have installed on the mainline and 7 branch. 2017-12-04 Eric Botcazou <ebotcazou@adacore.com> * config/sparc/sparc.c (sparc_do_work_around_errata): Use mem_ref instead of MEM_P in a couple more places. Fix formatting issues.
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 51045db..401dfcb 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -970,6 +970,22 @@ fpop_insn_p (rtx_insn *insn) } } +/* True if INSN is an atomic instruction. */ + +static bool +atomic_insn_for_leon3_p (rtx_insn *insn) +{ + switch (INSN_CODE (insn)) + { + case CODE_FOR_swapsi: + case CODE_FOR_ldstub: + case CODE_FOR_atomic_compare_and_swap_leon3_1: + 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 @@ -1024,6 +1040,31 @@ sparc_do_work_around_errata (void) emit_insn_before (gen_nop (), target); } + /* Insert a NOP between load instruction and atomic + instruction. Insert a NOP at branch target if load + in delay slot and atomic instruction at branch target. */ + if (sparc_fix_ut700 + && NONJUMP_INSN_P (insn) + && (set = single_set (insn)) != NULL_RTX + && MEM_P (SET_SRC (set)) + && REG_P (SET_DEST (set))) + { + if (jump) + { + rtx_insn *target = next_active_insn (JUMP_LABEL_AS_INSN (jump)); + if (target + && atomic_insn_for_leon3_p (target)) + emit_insn_before (gen_nop (), target); + } + + next = next_active_insn (insn); + if (!next) + break; + + if (atomic_insn_for_leon3_p (next)) + insert_nop = true; + } + /* Look for either of these two sequences: Sequence A: diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md index ead7c77..43c66e9 100644 --- a/gcc/config/sparc/sync.md +++ b/gcc/config/sparc/sync.md @@ -212,7 +212,7 @@ "cas<modesuffix>\t%1, %2, %0" [(set_attr "type" "multi")]) -(define_insn "*atomic_compare_and_swap_leon3_1" +(define_insn "atomic_compare_and_swap_leon3_1" [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "mem_noofs_operand" "+w")) (set (match_dup 1)