From 3fb192d2c7fd3ac8080d335d62ac9ad6754cd36f Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Mon, 11 Jul 2005 16:11:28 +0000 Subject: [PATCH] bfin.md (define_attr "type"): Add "sync". * config/bfin/bfin.md (define_attr "type"): Add "sync". (define_insn_reservation "alu"): Likewise. (csync, ssync): Now of type sync. * config/bfin/bfin.h (TARGET_DEFAULT): Defaults to -mcsync-anomaly -mspecld-anomaly. * config/bfin/bfin.opt (mcsync): Remove. (mcsync-anomaly, mspecld-anomaly): Add. * config/bfin/bfin.c: Include "insn-codes.h". (bfin_reorg): Extend to handle the CSYNC anomaly as well. (TARGET_DEFAULT_TARGET_FLAGS): New. * doc/invoke.texi: Document -mcsync-anomaly, -mspecld-anomaly. From-SVN: r101880 --- gcc/ChangeLog | 14 +++++ gcc/config/bfin/bfin.c | 120 +++++++++++++++++++++++++++++++++------ gcc/config/bfin/bfin.h | 2 +- gcc/config/bfin/bfin.md | 8 +-- gcc/config/bfin/bfin.opt | 11 +++- gcc/doc/invoke.texi | 24 ++++++-- 6 files changed, 148 insertions(+), 31 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7199ddd7012..b5147ab56ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2005-07-11 Bernd Schmidt + + * config/bfin/bfin.md (define_attr "type"): Add "sync". + (define_insn_reservation "alu"): Likewise. + (csync, ssync): Now of type sync. + * config/bfin/bfin.h (TARGET_DEFAULT): Defaults to + -mcsync-anomaly -mspecld-anomaly. + * config/bfin/bfin.opt (mcsync): Remove. + (mcsync-anomaly, mspecld-anomaly): Add. + * config/bfin/bfin.c: Include "insn-codes.h". + (bfin_reorg): Extend to handle the CSYNC anomaly as well. + (TARGET_DEFAULT_TARGET_FLAGS): New. + * doc/invoke.texi: Document -mcsync-anomaly, -mspecld-anomaly. + 2005-07-11 Steven Bosscher * basic-block.h: Give the BB flags enum a name, bb_flags. diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 1b43e1fbae7..5be76bbec5a 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -28,6 +28,7 @@ #include "hard-reg-set.h" #include "real.h" #include "insn-config.h" +#include "insn-codes.h" #include "conditions.h" #include "insn-flags.h" #include "output.h" @@ -2470,9 +2471,11 @@ bfin_reorg (void) rtx insn, last_condjump = NULL_RTX; int cycles_since_jump = INT_MAX; - if (! TARGET_CSYNC) + if (! TARGET_SPECLD_ANOMALY || ! TARGET_CSYNC_ANOMALY) return; + /* First pass: find predicted-false branches; if something after them + needs nops, insert them or change the branch to predict true. */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { rtx pat; @@ -2500,29 +2503,109 @@ bfin_reorg (void) else if (INSN_P (insn)) { enum attr_type type = get_attr_type (insn); + int delay_needed = 0; if (cycles_since_jump < INT_MAX) cycles_since_jump++; - if (type == TYPE_MCLD && cycles_since_jump < 3) + if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY) + { + rtx pat = single_set (insn); + if (may_trap_p (SET_SRC (pat))) + delay_needed = 3; + } + else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY) + delay_needed = 4; + + if (delay_needed > cycles_since_jump) + { + rtx pat; + int num_clobbers; + rtx *op = recog_data.operand; + + delay_needed -= cycles_since_jump; + + extract_insn (last_condjump); + if (optimize_size) + { + pat = gen_cbranch_predicted_taken (op[0], op[1], op[2], + op[3]); + cycles_since_jump = INT_MAX; + } + else + /* Do not adjust cycles_since_jump in this case, so that + we'll increase the number of NOPs for a subsequent insn + if necessary. */ + pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3], + GEN_INT (delay_needed)); + PATTERN (last_condjump) = pat; + INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers); + } + } + } + /* Second pass: for predicted-true branches, see if anything at the + branch destination needs extra nops. */ + if (! TARGET_CSYNC_ANOMALY) + return; + + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + if (JUMP_P (insn) + && any_condjump_p (insn) + && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken + || cbranch_predicted_taken_p (insn))) + { + rtx target = JUMP_LABEL (insn); + rtx label = target; + cycles_since_jump = 0; + for (; target && cycles_since_jump < 3; target = NEXT_INSN (target)) { rtx pat; - pat = single_set (insn); - if (may_trap_p (SET_SRC (pat))) - { - int num_clobbers; - rtx *op = recog_data.operand; + if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target)) + continue; - extract_insn (last_condjump); - if (optimize_size) - pat = gen_cbranch_predicted_taken (op[0], op[1], op[2], - op[3]); - else - pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3], - GEN_INT (3 - cycles_since_jump)); - PATTERN (last_condjump) = pat; - INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers); - cycles_since_jump = INT_MAX; + pat = PATTERN (target); + if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER + || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC + || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0) + continue; + + if (INSN_P (target)) + { + enum attr_type type = get_attr_type (target); + int delay_needed = 0; + if (cycles_since_jump < INT_MAX) + cycles_since_jump++; + + if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY) + delay_needed = 2; + + if (delay_needed > cycles_since_jump) + { + rtx prev = prev_real_insn (label); + delay_needed -= cycles_since_jump; + if (dump_file) + fprintf (dump_file, "Adding %d nops after %d\n", + delay_needed, INSN_UID (label)); + if (JUMP_P (prev) + && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops) + { + rtx x; + HOST_WIDE_INT v; + + if (dump_file) + fprintf (dump_file, + "Reducing nops on insn %d.\n", + INSN_UID (prev)); + x = PATTERN (prev); + x = XVECEXP (x, 0, 1); + v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed; + XVECEXP (x, 0, 0) = GEN_INT (v); + } + while (delay_needed-- > 0) + emit_insn_after (gen_nop (), label); + break; + } } } } @@ -2792,4 +2875,7 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, #undef TARGET_HANDLE_OPTION #define TARGET_HANDLE_OPTION bfin_handle_option +#undef TARGET_DEFAULT_TARGET_FLAGS +#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT + struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index 830222d509e..7ced865f997 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -48,7 +48,7 @@ extern int target_flags; /* Generate DSP instructions, like DSP halfword loads */ #define TARGET_DSP (1) -#define TARGET_DEFAULT MASK_CSYNC +#define TARGET_DEFAULT (MASK_SPECLD_ANOMALY | MASK_CSYNC_ANOMALY) /* Maximum number of library ids we permit */ #define MAX_LIBRARY_ID 255 diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 76d6e13d89a..be430c8c6ba 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -125,7 +125,7 @@ (UNSPEC_VOLATILE_SSYNC 2)]) (define_attr "type" - "move,mvi,mcld,mcst,dsp32,mult,alu0,shft,brcc,br,call,misc,compare,dummy" + "move,mvi,mcld,mcst,dsp32,mult,alu0,shft,brcc,br,call,misc,sync,compare,dummy" (const_string "misc")) ;; Scheduling definitions @@ -135,7 +135,7 @@ (define_cpu_unit "core" "bfin") (define_insn_reservation "alu" 1 - (eq_attr "type" "move,mvi,mcst,dsp32,alu0,shft,brcc,br,call,misc,compare") + (eq_attr "type" "move,mvi,mcst,dsp32,alu0,shft,brcc,br,call,misc,sync,compare") "core") (define_insn_reservation "imul" 3 @@ -1931,13 +1931,13 @@ [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_CSYNC)] "" "csync;" - [(set_attr "type" "misc")]) + [(set_attr "type" "sync")]) (define_insn "ssync" [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_SSYNC)] "" "ssync;" - [(set_attr "type" "misc")]) + [(set_attr "type" "sync")]) ;;; Vector instructions diff --git a/gcc/config/bfin/bfin.opt b/gcc/config/bfin/bfin.opt index da5fd59d08f..43f56c4d624 100644 --- a/gcc/config/bfin/bfin.opt +++ b/gcc/config/bfin/bfin.opt @@ -27,9 +27,14 @@ mlow64k Target Report Mask(LOW_64K) Program is entirely located in low 64k of memory -mcsync -Target Report Mask(CSYNC) -Avoid speculative loads by inserting CSYNC or equivalent +mcsync-anomaly +Target Report Mask(CSYNC_ANOMALY) +Work around a hardware anomaly by adding a number of NOPs before a +CSYNC or SSYNC instruction. + +mspecld-anomaly +Target Report Mask(SPECLD_ANOMALY) +Avoid speculative loads to work around a hardware anomaly. mid-shared-library Target Report Mask(ID_SHARED_LIBRARY) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index fb9c64d84d0..8fa98600472 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -414,8 +414,9 @@ Objective-C and Objective-C++ Dialects}. -mcall-prologues -mno-tablejump -mtiny-stack -mint8} @emph{Blackfin Options} -@gccoptlist{-momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer -mcsync @gol --mno-csync -mlow-64k -mno-low64k -mid-shared-library @gol +@gccoptlist{-momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer @gol +-mspecld-anomaly -mno-specld-anomaly -mcsync-anomaly -mno-csync-anomaly @gol +-mlow-64k -mno-low64k -mid-shared-library @gol -mno-id-shared-library -mshared-library-id=@var{n} @gol -mlong-calls -mno-long-calls} @@ -7403,16 +7404,27 @@ makes an extra register available in leaf functions. The option @option{-fomit-frame-pointer} removes the frame pointer for all functions which might make debugging harder. -@item -mcsync -@opindex mcsync +@item -mspecld-anomaly +@opindex mspecld-anomaly When enabled, the compiler will ensure that the generated code does not contain speculative loads after jump instructions. This option is enabled by default. -@item -mno-csync -@opindex mno-csync +@item -mno-specld-anomaly +@opindex mno-specld-anomaly Don't generate extra code to prevent speculative loads from occurring. +@item -mcsync-anomaly +@opindex mspecld-anomaly +When enabled, the compiler will ensure that the generated code does not +contain CSYNC or SSYNC instructions too soon after conditional branches. +This option is enabled by default. + +@item -mno-csync-anomaly +@opindex mno-specld-anomaly +Don't generate extra code to prevent CSYNC or SSYNC instructions from +occurring too soon after a conditional branch. + @item -mlow-64k @opindex mlow-64k When enabled, the compiler is free to take advantage of the knowledge that