]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/epiphany/resolve-sw-modes.c
Zero-initialize pass_manager
[thirdparty/gcc.git] / gcc / config / epiphany / resolve-sw-modes.c
CommitLineData
feeeff5c 1/* Mode switching cleanup pass for the EPIPHANY cpu.
d1e082c2 2 Copyright (C) 2000-2013 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
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. */
47
48static bool
49gate_resolve_sw_modes (void)
50{
51 return optimize;
52}
53
54static unsigned
55resolve_sw_modes (void)
56{
57 basic_block bb;
58 rtx insn, src;
9771b263 59 vec<basic_block> todo;
feeeff5c
JR
60 sbitmap pushed;
61 bool need_commit = false;
62 bool finalize_fp_sets = (MACHINE_FUNCTION (cfun)->unknown_mode_sets == 0);
63
9771b263 64 todo.create (last_basic_block);
feeeff5c 65 pushed = sbitmap_alloc (last_basic_block);
f61e445a 66 bitmap_clear (pushed);
feeeff5c
JR
67 if (!finalize_fp_sets)
68 {
69 df_note_add_problem ();
70 df_analyze ();
71 }
72 FOR_EACH_BB (bb)
73 FOR_BB_INSNS (bb, insn)
74 {
75 enum attr_fp_mode selected_mode;
76
77 if (!NONJUMP_INSN_P (insn)
78 || recog_memoized (insn) != CODE_FOR_set_fp_mode)
79 continue;
80 src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
81 if (finalize_fp_sets)
82 {
83 SET_SRC (XVECEXP (PATTERN (insn), 0, 2)) = copy_rtx (src);
84 if (REG_P (src))
85 df_insn_rescan (insn);
86 continue;
87 }
88 if (REG_P (src)
89 || XINT (XVECEXP (XEXP (src, 0), 0, 0), 0) != FP_MODE_ROUND_UNKNOWN)
90 continue;
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;
95 else
96 {
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;
100
9771b263 101 todo.quick_push (bb);
d7c028c0 102 bitmap_set_bit (pushed, bb->index);
feeeff5c
JR
103 }
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);
108 }
9771b263 109 while (todo.length ())
feeeff5c 110 {
9771b263 111 basic_block bb = todo.pop ();
feeeff5c
JR
112 int selected_reg, jilted_reg;
113 enum attr_fp_mode jilted_mode;
114 edge e;
115 edge_iterator ei;
116
d7c028c0
LC
117 bitmap_set_bit (pushed, bb->index);
118 bitmap_set_bit (pushed, bb->index);
feeeff5c
JR
119
120 if (epiphany_normal_fp_rounding == FP_MODE_ROUND_NEAREST)
121 {
122 selected_reg = FP_NEAREST_REGNUM;
123 jilted_reg = FP_TRUNCATE_REGNUM;
124 jilted_mode = FP_MODE_ROUND_TRUNC;
125 }
126 else
127 {
128 selected_reg = FP_TRUNCATE_REGNUM;
129 jilted_reg = FP_NEAREST_REGNUM;
130 jilted_mode = FP_MODE_ROUND_NEAREST;
131 }
132
133 FOR_EACH_EDGE (e, ei, bb->succs)
134 {
135 basic_block succ = e->dest;
136 rtx seq;
137
138 if (!REGNO_REG_SET_P (DF_LIVE_IN (succ), jilted_reg))
139 continue;
140 if (REGNO_REG_SET_P (DF_LIVE_IN (succ), selected_reg))
141 {
d7c028c0 142 if (bitmap_bit_p (pushed, succ->index))
feeeff5c 143 continue;
9771b263 144 todo.quick_push (succ);
d7c028c0 145 bitmap_set_bit (pushed, bb->index);
feeeff5c
JR
146 continue;
147 }
148 start_sequence ();
149 emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN,
150 jilted_mode, NULL);
151 seq = get_insns ();
152 end_sequence ();
153 need_commit = true;
154 insert_insn_on_edge (seq, e);
155 }
156 }
9771b263 157 todo.release ();
feeeff5c
JR
158 sbitmap_free (pushed);
159 if (need_commit)
160 commit_edge_insertions ();
161 return 0;
162}
163
164struct rtl_opt_pass pass_resolve_sw_modes =
165{
166 {
167 RTL_PASS,
168 "resolve_sw_modes", /* name */
53750ab0 169 OPTGROUP_NONE, /* optinfo_flags */
feeeff5c
JR
170 gate_resolve_sw_modes, /* gate */
171 resolve_sw_modes, /* execute */
172 NULL, /* sub */
173 NULL, /* next */
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 */
182 }
183};