]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/epiphany/resolve-sw-modes.c
gimple-predict.h: New file.
[thirdparty/gcc.git] / gcc / config / epiphany / resolve-sw-modes.c
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.
4
5 This file is part of GCC.
6
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)
10 any later version.
11
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.
16
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/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "cfghooks.h"
26 #include "rtl.h"
27 #include "df.h"
28 #include "tm_p.h"
29 #include "cfgrtl.h"
30 #include "cfganal.h"
31 #include "lcm.h"
32 #include "cfgbuild.h"
33 #include "cfgcleanup.h"
34 #include "insn-config.h"
35 #include "insn-codes.h"
36 #include "emit-rtl.h"
37 #include "recog.h"
38 #include "insn-attr-common.h"
39 #include "tree-pass.h"
40
41 namespace {
42
43 const pass_data pass_data_resolve_sw_modes =
44 {
45 RTL_PASS, /* type */
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 */
54 };
55
56 class pass_resolve_sw_modes : public rtl_opt_pass
57 {
58 public:
59 pass_resolve_sw_modes(gcc::context *ctxt)
60 : rtl_opt_pass(pass_data_resolve_sw_modes, ctxt)
61 {}
62
63 /* opt_pass methods: */
64 virtual bool gate (function *) { return optimize; }
65 virtual unsigned int execute (function *);
66
67 }; // class pass_resolve_sw_modes
68
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. */
75
76 unsigned
77 pass_resolve_sw_modes::execute (function *fun)
78 {
79 basic_block bb;
80 rtx_insn *insn;
81 rtx src;
82 vec<basic_block> todo;
83 sbitmap pushed;
84 bool need_commit = false;
85 bool finalize_fp_sets = (MACHINE_FUNCTION (cfun)->unknown_mode_sets == 0);
86
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)
91 {
92 df_note_add_problem ();
93 df_analyze ();
94 }
95 FOR_EACH_BB_FN (bb, fun)
96 FOR_BB_INSNS (bb, insn)
97 {
98 enum attr_fp_mode selected_mode;
99
100 if (!NONJUMP_INSN_P (insn)
101 || recog_memoized (insn) != CODE_FOR_set_fp_mode)
102 continue;
103 src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
104 if (finalize_fp_sets)
105 {
106 SET_SRC (XVECEXP (PATTERN (insn), 0, 2)) = copy_rtx (src);
107 if (REG_P (src))
108 df_insn_rescan (insn);
109 continue;
110 }
111 if (REG_P (src)
112 || XINT (XVECEXP (XEXP (src, 0), 0, 0), 0) != FP_MODE_ROUND_UNKNOWN)
113 continue;
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;
118 else
119 {
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;
123
124 todo.quick_push (bb);
125 bitmap_set_bit (pushed, bb->index);
126 }
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);
131 }
132 while (todo.length ())
133 {
134 basic_block bb = todo.pop ();
135 int selected_reg, jilted_reg;
136 enum attr_fp_mode jilted_mode;
137 edge e;
138 edge_iterator ei;
139
140 bitmap_set_bit (pushed, bb->index);
141 bitmap_set_bit (pushed, bb->index);
142
143 if (epiphany_normal_fp_rounding == FP_MODE_ROUND_NEAREST)
144 {
145 selected_reg = FP_NEAREST_REGNUM;
146 jilted_reg = FP_TRUNCATE_REGNUM;
147 jilted_mode = FP_MODE_ROUND_TRUNC;
148 }
149 else
150 {
151 selected_reg = FP_TRUNCATE_REGNUM;
152 jilted_reg = FP_NEAREST_REGNUM;
153 jilted_mode = FP_MODE_ROUND_NEAREST;
154 }
155
156 FOR_EACH_EDGE (e, ei, bb->succs)
157 {
158 basic_block succ = e->dest;
159 rtx_insn *seq;
160
161 if (!REGNO_REG_SET_P (DF_LIVE_IN (succ), jilted_reg))
162 continue;
163 if (REGNO_REG_SET_P (DF_LIVE_IN (succ), selected_reg))
164 {
165 if (bitmap_bit_p (pushed, succ->index))
166 continue;
167 todo.quick_push (succ);
168 bitmap_set_bit (pushed, bb->index);
169 continue;
170 }
171 start_sequence ();
172 emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN,
173 jilted_mode, FP_MODE_NONE, NULL);
174 seq = get_insns ();
175 end_sequence ();
176 need_commit = true;
177 insert_insn_on_edge (seq, e);
178 }
179 }
180 todo.release ();
181 sbitmap_free (pushed);
182 if (need_commit)
183 commit_edge_insertions ();
184 return 0;
185 }
186
187 } // anon namespace
188
189 rtl_opt_pass *
190 make_pass_resolve_sw_modes (gcc::context *ctxt)
191 {
192 return new pass_resolve_sw_modes (ctxt);
193 }