]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/epiphany/resolve-sw-modes.c
2014-10-27 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / config / epiphany / resolve-sw-modes.c
CommitLineData
d19f5793 1/* Mode switching cleanup pass for the EPIPHANY cpu.
3aea1f79 2 Copyright (C) 2000-2014 Free Software Foundation, Inc.
d19f5793 3 Contributed by Embecosm on behalf of Adapteva, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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 "machmode.h"
25#include "tm.h"
26#include "hard-reg-set.h"
27#include "tm_p.h"
28#include "vec.h"
29#include "sbitmap.h"
94ea8568 30#include "predict.h"
31#include "hashtab.h"
32#include "hash-set.h"
33#include "input.h"
34#include "function.h"
35#include "dominance.h"
36#include "cfg.h"
37#include "cfgrtl.h"
38#include "cfganal.h"
39#include "lcm.h"
40#include "cfgbuild.h"
41#include "cfgcleanup.h"
d19f5793 42#include "basic-block.h"
43#include "df.h"
44#include "rtl.h"
45#include "insn-config.h"
46#include "insn-codes.h"
47#include "emit-rtl.h"
48#include "recog.h"
d19f5793 49#include "insn-attr-common.h"
50#include "tree-pass.h"
51
65b0537f 52namespace {
53
54const pass_data pass_data_resolve_sw_modes =
55{
56 RTL_PASS, /* type */
57 "resolve_sw_modes", /* name */
58 OPTGROUP_NONE, /* optinfo_flags */
65b0537f 59 TV_MODE_SWITCH, /* tv_id */
60 0, /* properties_required */
61 0, /* properties_provided */
62 0, /* properties_destroyed */
63 0, /* todo_flags_start */
8b88439e 64 TODO_df_finish, /* todo_flags_finish */
65b0537f 65};
66
67class pass_resolve_sw_modes : public rtl_opt_pass
68{
69public:
70 pass_resolve_sw_modes(gcc::context *ctxt)
71 : rtl_opt_pass(pass_data_resolve_sw_modes, ctxt)
72 {}
73
74 /* opt_pass methods: */
75 virtual bool gate (function *) { return optimize; }
76 virtual unsigned int execute (function *);
77
78}; // class pass_resolve_sw_modes
79
d19f5793 80/* Clean-up after mode switching:
81 Check for mode setting insns that have FP_MODE_ROUND_UNKNOWN.
82 If only one rounding mode is required, select that one.
83 Else we have to choose one to use in this mode setting insn and
84 insert new mode setting insns on the edges where the other mode
85 becomes unambigous. */
86
65b0537f 87unsigned
88pass_resolve_sw_modes::execute (function *fun)
d19f5793 89{
90 basic_block bb;
34c12ec8 91 rtx_insn *insn;
92 rtx src;
f1f41a6c 93 vec<basic_block> todo;
d19f5793 94 sbitmap pushed;
95 bool need_commit = false;
96 bool finalize_fp_sets = (MACHINE_FUNCTION (cfun)->unknown_mode_sets == 0);
97
65b0537f 98 todo.create (last_basic_block_for_fn (fun));
99 pushed = sbitmap_alloc (last_basic_block_for_fn (fun));
53c5d9d4 100 bitmap_clear (pushed);
d19f5793 101 if (!finalize_fp_sets)
102 {
103 df_note_add_problem ();
104 df_analyze ();
105 }
65b0537f 106 FOR_EACH_BB_FN (bb, fun)
d19f5793 107 FOR_BB_INSNS (bb, insn)
108 {
109 enum attr_fp_mode selected_mode;
110
111 if (!NONJUMP_INSN_P (insn)
112 || recog_memoized (insn) != CODE_FOR_set_fp_mode)
113 continue;
114 src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
115 if (finalize_fp_sets)
116 {
117 SET_SRC (XVECEXP (PATTERN (insn), 0, 2)) = copy_rtx (src);
118 if (REG_P (src))
119 df_insn_rescan (insn);
120 continue;
121 }
122 if (REG_P (src)
123 || XINT (XVECEXP (XEXP (src, 0), 0, 0), 0) != FP_MODE_ROUND_UNKNOWN)
124 continue;
125 if (find_regno_note (insn, REG_UNUSED, FP_TRUNCATE_REGNUM))
126 selected_mode = FP_MODE_ROUND_NEAREST;
127 else if (find_regno_note (insn, REG_UNUSED, FP_NEAREST_REGNUM))
128 selected_mode = FP_MODE_ROUND_TRUNC;
129 else
130 {
131 /* We could get more fancy in the selection of the mode by
132 checking the total frequency of the affected edges. */
133 selected_mode = (enum attr_fp_mode) epiphany_normal_fp_rounding;
134
f1f41a6c 135 todo.quick_push (bb);
08b7917c 136 bitmap_set_bit (pushed, bb->index);
d19f5793 137 }
138 XVECEXP (XEXP (src, 0), 0, 0) = GEN_INT (selected_mode);
139 SET_SRC (XVECEXP (PATTERN (insn), 0, 1)) = copy_rtx (src);
140 SET_SRC (XVECEXP (PATTERN (insn), 0, 2)) = copy_rtx (src);
141 df_insn_rescan (insn);
142 }
f1f41a6c 143 while (todo.length ())
d19f5793 144 {
f1f41a6c 145 basic_block bb = todo.pop ();
d19f5793 146 int selected_reg, jilted_reg;
147 enum attr_fp_mode jilted_mode;
148 edge e;
149 edge_iterator ei;
150
08b7917c 151 bitmap_set_bit (pushed, bb->index);
152 bitmap_set_bit (pushed, bb->index);
d19f5793 153
154 if (epiphany_normal_fp_rounding == FP_MODE_ROUND_NEAREST)
155 {
156 selected_reg = FP_NEAREST_REGNUM;
157 jilted_reg = FP_TRUNCATE_REGNUM;
158 jilted_mode = FP_MODE_ROUND_TRUNC;
159 }
160 else
161 {
162 selected_reg = FP_TRUNCATE_REGNUM;
163 jilted_reg = FP_NEAREST_REGNUM;
164 jilted_mode = FP_MODE_ROUND_NEAREST;
165 }
166
167 FOR_EACH_EDGE (e, ei, bb->succs)
168 {
169 basic_block succ = e->dest;
34c12ec8 170 rtx_insn *seq;
d19f5793 171
172 if (!REGNO_REG_SET_P (DF_LIVE_IN (succ), jilted_reg))
173 continue;
174 if (REGNO_REG_SET_P (DF_LIVE_IN (succ), selected_reg))
175 {
08b7917c 176 if (bitmap_bit_p (pushed, succ->index))
d19f5793 177 continue;
f1f41a6c 178 todo.quick_push (succ);
08b7917c 179 bitmap_set_bit (pushed, bb->index);
d19f5793 180 continue;
181 }
182 start_sequence ();
183 emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN,
7fc0df2f 184 jilted_mode, FP_MODE_NONE, NULL);
d19f5793 185 seq = get_insns ();
186 end_sequence ();
187 need_commit = true;
188 insert_insn_on_edge (seq, e);
189 }
190 }
f1f41a6c 191 todo.release ();
d19f5793 192 sbitmap_free (pushed);
193 if (need_commit)
194 commit_edge_insertions ();
195 return 0;
196}
197
cbe8bda8 198} // anon namespace
199
200rtl_opt_pass *
201make_pass_resolve_sw_modes (gcc::context *ctxt)
202{
203 return new pass_resolve_sw_modes (ctxt);
204}