aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sh
diff options
context:
space:
mode:
authorChristian Bruel <christian.bruel@st.com>2014-07-02 15:03:14 +0200
committerChristian Bruel <chrbr@gcc.gnu.org>2014-07-02 15:03:14 +0200
commitcbb1e3d98c5f18f82c1b733aa6338fab78fb891b (patch)
treed5f4efb38c4b5345b26af85c0f13b1a9412dd461 /gcc/config/sh
parentb18f1efce09e8cab57d6141754db3456fab938f7 (diff)
downloadgcc-cbb1e3d98c5f18f82c1b733aa6338fab78fb891b.zip
gcc-cbb1e3d98c5f18f82c1b733aa6338fab78fb891b.tar.gz
gcc-cbb1e3d98c5f18f82c1b733aa6338fab78fb891b.tar.bz2
Support mode toggle.
* mode-switching.c (struct bb_info): Add mode_out, mode_in caches. (make_preds_opaque): Delete. (clear_mode_bit, mode_bit_p, set_mode_bit): New macros. (commit_mode_sets): New function. (optimize_mode_switching): Handle current_mode to mode_switching_emit. Process all modes at once. * basic-block.h (pre_edge_lcm_avs): Declare. * lcm.c (pre_edge_lcm_avs): Renamed from pre_edge_lcm. Call clear_aux_for_edges. Fix comments. (pre_edge_lcm): New wrapper function to call pre_edge_lcm_avs. (pre_edge_rev_lcm): Idem. * config/epiphany/epiphany.c (emit_set_fp_mode): Add prev_mode parameter. * config/epiphany/epiphany-protos.h (emit_set_fp_mode): Idem. * config/epiphany/resolve-sw-modes.c (pass_resolve_sw_modes::execute): Idem. * config/i386/i386.c (x96_emit_mode_set): Idem. * config/sh/sh.c (sh_emit_mode_set): Likewise. Handle PR toggle. * config/sh/sh.md (toggle_pr): Defined if TARGET_FPU_SINGLE. (fpscr_toggle) Disallow from delay slot. * target.def (emit_mode_set): Add prev_mode parameter. * doc/tm.texi: Regenerate. From-SVN: r212230
Diffstat (limited to 'gcc/config/sh')
-rw-r--r--gcc/config/sh/sh.c14
-rw-r--r--gcc/config/sh/sh.md10
2 files changed, 15 insertions, 9 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index ac157e4..02468da 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -203,7 +203,7 @@ static void push_regs (HARD_REG_SET *, int);
static int calc_live_regs (HARD_REG_SET *);
static HOST_WIDE_INT rounded_frame_size (int);
static bool sh_frame_pointer_required (void);
-static void sh_emit_mode_set (int, int, HARD_REG_SET);
+static void sh_emit_mode_set (int, int, int, HARD_REG_SET);
static int sh_mode_needed (int, rtx);
static int sh_mode_after (int, int, rtx);
static int sh_mode_entry (int);
@@ -13583,9 +13583,17 @@ sh_try_omit_signzero_extend (rtx extended_op, rtx insn)
static void
sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
- HARD_REG_SET regs_live)
+ int prev_mode, HARD_REG_SET regs_live)
{
- fpscr_set_from_mem (mode, regs_live);
+ if ((TARGET_SH4A_FP || TARGET_SH4_300)
+ && prev_mode != FP_MODE_NONE && prev_mode != mode)
+ {
+ emit_insn (gen_toggle_pr ());
+ if (TARGET_FMOVD)
+ emit_insn (gen_toggle_sz ());
+ }
+ else
+ fpscr_set_from_mem (mode, regs_live);
}
static int
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index d998af9..b5d05f4 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -504,6 +504,7 @@
(define_attr "in_delay_slot" "yes,no"
(cond [(eq_attr "type" "cbranch") (const_string "no")
(eq_attr "type" "pcload,pcload_si") (const_string "no")
+ (eq_attr "type" "fpscr_toggle") (const_string "no")
(eq_attr "needs_delay_slot" "yes") (const_string "no")
(eq_attr "length" "2") (const_string "yes")
] (const_string "no")))
@@ -12239,15 +12240,12 @@ label:
"fschg"
[(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
-;; There's no way we can use it today, since optimize mode switching
-;; doesn't enable us to know from which mode we're switching to the
-;; mode it requests, to tell whether we can use a relative mode switch
-;; (like toggle_pr) or an absolute switch (like loading fpscr from
-;; memory).
+;; Toggle FPU precision PR mode.
+
(define_insn "toggle_pr"
[(set (reg:PSI FPSCR_REG)
(xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
- "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
+ "TARGET_SH4A_FP"
"fpchg"
[(set_attr "type" "fpscr_toggle")])