1 /* Mode switching cleanup pass for the EPIPHANY cpu.
2 Copyright (C) 2000-2015 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"
33 #include "cfgcleanup.h"
34 #include "insn-config.h"
35 #include "insn-codes.h"
38 #include "insn-attr-common.h"
39 #include "tree-pass.h"
43 const pass_data pass_data_resolve_sw_modes
=
46 "resolve_sw_modes", /* name */
47 OPTGROUP_NONE
, /* optinfo_flags */
48 TV_MODE_SWITCH
, /* tv_id */
49 0, /* properties_required */
50 0, /* properties_provided */
51 0, /* properties_destroyed */
52 0, /* todo_flags_start */
53 TODO_df_finish
, /* todo_flags_finish */
56 class pass_resolve_sw_modes
: public rtl_opt_pass
59 pass_resolve_sw_modes(gcc::context
*ctxt
)
60 : rtl_opt_pass(pass_data_resolve_sw_modes
, ctxt
)
63 /* opt_pass methods: */
64 virtual bool gate (function
*) { return optimize
; }
65 virtual unsigned int execute (function
*);
67 }; // class pass_resolve_sw_modes
69 /* Clean-up after mode switching:
70 Check for mode setting insns that have FP_MODE_ROUND_UNKNOWN.
71 If only one rounding mode is required, select that one.
72 Else we have to choose one to use in this mode setting insn and
73 insert new mode setting insns on the edges where the other mode
74 becomes unambigous. */
77 pass_resolve_sw_modes::execute (function
*fun
)
82 vec
<basic_block
> todo
;
84 bool need_commit
= false;
85 bool finalize_fp_sets
= (MACHINE_FUNCTION (cfun
)->unknown_mode_sets
== 0);
87 todo
.create (last_basic_block_for_fn (fun
));
88 pushed
= sbitmap_alloc (last_basic_block_for_fn (fun
));
89 bitmap_clear (pushed
);
90 if (!finalize_fp_sets
)
92 df_note_add_problem ();
95 FOR_EACH_BB_FN (bb
, fun
)
96 FOR_BB_INSNS (bb
, insn
)
98 enum attr_fp_mode selected_mode
;
100 if (!NONJUMP_INSN_P (insn
)
101 || recog_memoized (insn
) != CODE_FOR_set_fp_mode
)
103 src
= SET_SRC (XVECEXP (PATTERN (insn
), 0, 0));
104 if (finalize_fp_sets
)
106 SET_SRC (XVECEXP (PATTERN (insn
), 0, 2)) = copy_rtx (src
);
108 df_insn_rescan (insn
);
112 || XINT (XVECEXP (XEXP (src
, 0), 0, 0), 0) != FP_MODE_ROUND_UNKNOWN
)
114 if (find_regno_note (insn
, REG_UNUSED
, FP_TRUNCATE_REGNUM
))
115 selected_mode
= FP_MODE_ROUND_NEAREST
;
116 else if (find_regno_note (insn
, REG_UNUSED
, FP_NEAREST_REGNUM
))
117 selected_mode
= FP_MODE_ROUND_TRUNC
;
120 /* We could get more fancy in the selection of the mode by
121 checking the total frequency of the affected edges. */
122 selected_mode
= (enum attr_fp_mode
) epiphany_normal_fp_rounding
;
124 todo
.quick_push (bb
);
125 bitmap_set_bit (pushed
, bb
->index
);
127 XVECEXP (XEXP (src
, 0), 0, 0) = GEN_INT (selected_mode
);
128 SET_SRC (XVECEXP (PATTERN (insn
), 0, 1)) = copy_rtx (src
);
129 SET_SRC (XVECEXP (PATTERN (insn
), 0, 2)) = copy_rtx (src
);
130 df_insn_rescan (insn
);
132 while (todo
.length ())
134 basic_block bb
= todo
.pop ();
135 int selected_reg
, jilted_reg
;
136 enum attr_fp_mode jilted_mode
;
140 bitmap_set_bit (pushed
, bb
->index
);
141 bitmap_set_bit (pushed
, bb
->index
);
143 if (epiphany_normal_fp_rounding
== FP_MODE_ROUND_NEAREST
)
145 selected_reg
= FP_NEAREST_REGNUM
;
146 jilted_reg
= FP_TRUNCATE_REGNUM
;
147 jilted_mode
= FP_MODE_ROUND_TRUNC
;
151 selected_reg
= FP_TRUNCATE_REGNUM
;
152 jilted_reg
= FP_NEAREST_REGNUM
;
153 jilted_mode
= FP_MODE_ROUND_NEAREST
;
156 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
158 basic_block succ
= e
->dest
;
161 if (!REGNO_REG_SET_P (DF_LIVE_IN (succ
), jilted_reg
))
163 if (REGNO_REG_SET_P (DF_LIVE_IN (succ
), selected_reg
))
165 if (bitmap_bit_p (pushed
, succ
->index
))
167 todo
.quick_push (succ
);
168 bitmap_set_bit (pushed
, bb
->index
);
172 emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
,
173 jilted_mode
, FP_MODE_NONE
, NULL
);
177 insert_insn_on_edge (seq
, e
);
181 sbitmap_free (pushed
);
183 commit_edge_insertions ();
190 make_pass_resolve_sw_modes (gcc::context
*ctxt
)
192 return new pass_resolve_sw_modes (ctxt
);