]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/epiphany/resolve-sw-modes.c
c-opts.c (c_common_post_options): For -freestanding...
[thirdparty/gcc.git] / gcc / config / epiphany / resolve-sw-modes.c
CommitLineData
feeeff5c 1/* Mode switching cleanup pass for the EPIPHANY cpu.
23a5b65a 2 Copyright (C) 2000-2014 Free Software Foundation, Inc.
feeeff5c
JR
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"
30#include "basic-block.h"
31#include "df.h"
32#include "rtl.h"
33#include "insn-config.h"
34#include "insn-codes.h"
35#include "emit-rtl.h"
36#include "recog.h"
37#include "function.h"
38#include "insn-attr-common.h"
39#include "tree-pass.h"
40
be55bfe6
TS
41namespace {
42
43const pass_data pass_data_resolve_sw_modes =
44{
45 RTL_PASS, /* type */
46 "resolve_sw_modes", /* name */
47 OPTGROUP_NONE, /* optinfo_flags */
48 true, /* has_execute */
49 TV_MODE_SWITCH, /* tv_id */
50 0, /* properties_required */
51 0, /* properties_provided */
52 0, /* properties_destroyed */
53 0, /* todo_flags_start */
54 ( TODO_df_finish | TODO_verify_rtl_sharing | 0 ), /* todo_flags_finish */
55};
56
57class pass_resolve_sw_modes : public rtl_opt_pass
58{
59public:
60 pass_resolve_sw_modes(gcc::context *ctxt)
61 : rtl_opt_pass(pass_data_resolve_sw_modes, ctxt)
62 {}
63
64 /* opt_pass methods: */
65 virtual bool gate (function *) { return optimize; }
66 virtual unsigned int execute (function *);
67
68}; // class pass_resolve_sw_modes
69
feeeff5c
JR
70/* Clean-up after mode switching:
71 Check for mode setting insns that have FP_MODE_ROUND_UNKNOWN.
72 If only one rounding mode is required, select that one.
73 Else we have to choose one to use in this mode setting insn and
74 insert new mode setting insns on the edges where the other mode
75 becomes unambigous. */
76
be55bfe6
TS
77unsigned
78pass_resolve_sw_modes::execute (function *fun)
feeeff5c
JR
79{
80 basic_block bb;
81 rtx insn, src;
9771b263 82 vec<basic_block> todo;
feeeff5c
JR
83 sbitmap pushed;
84 bool need_commit = false;
85 bool finalize_fp_sets = (MACHINE_FUNCTION (cfun)->unknown_mode_sets == 0);
86
be55bfe6
TS
87 todo.create (last_basic_block_for_fn (fun));
88 pushed = sbitmap_alloc (last_basic_block_for_fn (fun));
f61e445a 89 bitmap_clear (pushed);
feeeff5c
JR
90 if (!finalize_fp_sets)
91 {
92 df_note_add_problem ();
93 df_analyze ();
94 }
be55bfe6 95 FOR_EACH_BB_FN (bb, fun)
feeeff5c
JR
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
9771b263 124 todo.quick_push (bb);
d7c028c0 125 bitmap_set_bit (pushed, bb->index);
feeeff5c
JR
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 }
9771b263 132 while (todo.length ())
feeeff5c 133 {
9771b263 134 basic_block bb = todo.pop ();
feeeff5c
JR
135 int selected_reg, jilted_reg;
136 enum attr_fp_mode jilted_mode;
137 edge e;
138 edge_iterator ei;
139
d7c028c0
LC
140 bitmap_set_bit (pushed, bb->index);
141 bitmap_set_bit (pushed, bb->index);
feeeff5c
JR
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 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 {
d7c028c0 165 if (bitmap_bit_p (pushed, succ->index))
feeeff5c 166 continue;
9771b263 167 todo.quick_push (succ);
d7c028c0 168 bitmap_set_bit (pushed, bb->index);
feeeff5c
JR
169 continue;
170 }
171 start_sequence ();
172 emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN,
173 jilted_mode, NULL);
174 seq = get_insns ();
175 end_sequence ();
176 need_commit = true;
177 insert_insn_on_edge (seq, e);
178 }
179 }
9771b263 180 todo.release ();
feeeff5c
JR
181 sbitmap_free (pushed);
182 if (need_commit)
183 commit_edge_insertions ();
184 return 0;
185}
186
27a4cd48
DM
187} // anon namespace
188
189rtl_opt_pass *
190make_pass_resolve_sw_modes (gcc::context *ctxt)
191{
192 return new pass_resolve_sw_modes (ctxt);
193}