1 /* Mode switching cleanup pass for the EPIPHANY cpu.
2 Copyright (C) 2000-2013 Free Software Foundation, Inc.
3 Contributed by Embecosm on behalf of Adapteva, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
26 #include "hard-reg-set.h"
30 #include "basic-block.h"
33 #include "insn-config.h"
34 #include "insn-codes.h"
38 #include "insn-attr-common.h"
39 #include "tree-pass.h"
41 /* Clean-up after mode switching:
42 Check for mode setting insns that have FP_MODE_ROUND_UNKNOWN.
43 If only one rounding mode is required, select that one.
44 Else we have to choose one to use in this mode setting insn and
45 insert new mode setting insns on the edges where the other mode
46 becomes unambigous. */
49 gate_resolve_sw_modes (void)
55 resolve_sw_modes (void)
59 vec
<basic_block
> todo
;
61 bool need_commit
= false;
62 bool finalize_fp_sets
= (MACHINE_FUNCTION (cfun
)->unknown_mode_sets
== 0);
64 todo
.create (last_basic_block
);
65 pushed
= sbitmap_alloc (last_basic_block
);
66 bitmap_clear (pushed
);
67 if (!finalize_fp_sets
)
69 df_note_add_problem ();
73 FOR_BB_INSNS (bb
, insn
)
75 enum attr_fp_mode selected_mode
;
77 if (!NONJUMP_INSN_P (insn
)
78 || recog_memoized (insn
) != CODE_FOR_set_fp_mode
)
80 src
= SET_SRC (XVECEXP (PATTERN (insn
), 0, 0));
83 SET_SRC (XVECEXP (PATTERN (insn
), 0, 2)) = copy_rtx (src
);
85 df_insn_rescan (insn
);
89 || XINT (XVECEXP (XEXP (src
, 0), 0, 0), 0) != FP_MODE_ROUND_UNKNOWN
)
91 if (find_regno_note (insn
, REG_UNUSED
, FP_TRUNCATE_REGNUM
))
92 selected_mode
= FP_MODE_ROUND_NEAREST
;
93 else if (find_regno_note (insn
, REG_UNUSED
, FP_NEAREST_REGNUM
))
94 selected_mode
= FP_MODE_ROUND_TRUNC
;
97 /* We could get more fancy in the selection of the mode by
98 checking the total frequency of the affected edges. */
99 selected_mode
= (enum attr_fp_mode
) epiphany_normal_fp_rounding
;
101 todo
.quick_push (bb
);
102 bitmap_set_bit (pushed
, bb
->index
);
104 XVECEXP (XEXP (src
, 0), 0, 0) = GEN_INT (selected_mode
);
105 SET_SRC (XVECEXP (PATTERN (insn
), 0, 1)) = copy_rtx (src
);
106 SET_SRC (XVECEXP (PATTERN (insn
), 0, 2)) = copy_rtx (src
);
107 df_insn_rescan (insn
);
109 while (todo
.length ())
111 basic_block bb
= todo
.pop ();
112 int selected_reg
, jilted_reg
;
113 enum attr_fp_mode jilted_mode
;
117 bitmap_set_bit (pushed
, bb
->index
);
118 bitmap_set_bit (pushed
, bb
->index
);
120 if (epiphany_normal_fp_rounding
== FP_MODE_ROUND_NEAREST
)
122 selected_reg
= FP_NEAREST_REGNUM
;
123 jilted_reg
= FP_TRUNCATE_REGNUM
;
124 jilted_mode
= FP_MODE_ROUND_TRUNC
;
128 selected_reg
= FP_TRUNCATE_REGNUM
;
129 jilted_reg
= FP_NEAREST_REGNUM
;
130 jilted_mode
= FP_MODE_ROUND_NEAREST
;
133 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
135 basic_block succ
= e
->dest
;
138 if (!REGNO_REG_SET_P (DF_LIVE_IN (succ
), jilted_reg
))
140 if (REGNO_REG_SET_P (DF_LIVE_IN (succ
), selected_reg
))
142 if (bitmap_bit_p (pushed
, succ
->index
))
144 todo
.quick_push (succ
);
145 bitmap_set_bit (pushed
, bb
->index
);
149 emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
,
154 insert_insn_on_edge (seq
, e
);
158 sbitmap_free (pushed
);
160 commit_edge_insertions ();
164 struct rtl_opt_pass pass_resolve_sw_modes
=
168 "resolve_sw_modes", /* name */
169 OPTGROUP_NONE
, /* optinfo_flags */
170 gate_resolve_sw_modes
, /* gate */
171 resolve_sw_modes
, /* execute */
174 0, /* static_pass_number */
175 TV_MODE_SWITCH
, /* tv_id */
176 0, /* properties_required */
177 0, /* properties_provided */
178 0, /* properties_destroyed */
179 0, /* todo_flags_start */
180 TODO_df_finish
| TODO_verify_rtl_sharing
|
181 0 /* todo_flags_finish */