]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/epiphany/resolve-sw-modes.c
Update copyright years.
[thirdparty/gcc.git] / gcc / config / epiphany / resolve-sw-modes.c
CommitLineData
feeeff5c 1/* Mode switching cleanup pass for the EPIPHANY cpu.
8d9254fc 2 Copyright (C) 2000-2020 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
8fcc61f8
RS
21#define IN_TARGET_CODE 1
22
feeeff5c
JR
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
c7131fb2
AM
26#include "backend.h"
27#include "rtl.h"
28#include "df.h"
4d0cdd0c 29#include "memmodel.h"
feeeff5c 30#include "tm_p.h"
feeeff5c 31#include "insn-config.h"
feeeff5c
JR
32#include "emit-rtl.h"
33#include "recog.h"
e11c4407 34#include "cfgrtl.h"
feeeff5c
JR
35#include "insn-attr-common.h"
36#include "tree-pass.h"
37
be55bfe6
TS
38namespace {
39
40const pass_data pass_data_resolve_sw_modes =
41{
42 RTL_PASS, /* type */
43 "resolve_sw_modes", /* name */
44 OPTGROUP_NONE, /* optinfo_flags */
be55bfe6
TS
45 TV_MODE_SWITCH, /* tv_id */
46 0, /* properties_required */
47 0, /* properties_provided */
48 0, /* properties_destroyed */
49 0, /* todo_flags_start */
3bea341f 50 TODO_df_finish, /* todo_flags_finish */
be55bfe6
TS
51};
52
53class pass_resolve_sw_modes : public rtl_opt_pass
54{
55public:
56 pass_resolve_sw_modes(gcc::context *ctxt)
57 : rtl_opt_pass(pass_data_resolve_sw_modes, ctxt)
58 {}
59
60 /* opt_pass methods: */
61 virtual bool gate (function *) { return optimize; }
62 virtual unsigned int execute (function *);
63
64}; // class pass_resolve_sw_modes
65
feeeff5c
JR
66/* Clean-up after mode switching:
67 Check for mode setting insns that have FP_MODE_ROUND_UNKNOWN.
68 If only one rounding mode is required, select that one.
69 Else we have to choose one to use in this mode setting insn and
70 insert new mode setting insns on the edges where the other mode
71 becomes unambigous. */
72
be55bfe6
TS
73unsigned
74pass_resolve_sw_modes::execute (function *fun)
feeeff5c
JR
75{
76 basic_block bb;
bcfba653
DM
77 rtx_insn *insn;
78 rtx src;
9771b263 79 vec<basic_block> todo;
feeeff5c
JR
80 sbitmap pushed;
81 bool need_commit = false;
82 bool finalize_fp_sets = (MACHINE_FUNCTION (cfun)->unknown_mode_sets == 0);
83
be55bfe6
TS
84 todo.create (last_basic_block_for_fn (fun));
85 pushed = sbitmap_alloc (last_basic_block_for_fn (fun));
f61e445a 86 bitmap_clear (pushed);
feeeff5c
JR
87 if (!finalize_fp_sets)
88 {
89 df_note_add_problem ();
90 df_analyze ();
91 }
be55bfe6 92 FOR_EACH_BB_FN (bb, fun)
feeeff5c
JR
93 FOR_BB_INSNS (bb, insn)
94 {
95 enum attr_fp_mode selected_mode;
96
97 if (!NONJUMP_INSN_P (insn)
98 || recog_memoized (insn) != CODE_FOR_set_fp_mode)
99 continue;
100 src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
101 if (finalize_fp_sets)
102 {
103 SET_SRC (XVECEXP (PATTERN (insn), 0, 2)) = copy_rtx (src);
104 if (REG_P (src))
105 df_insn_rescan (insn);
106 continue;
107 }
108 if (REG_P (src)
109 || XINT (XVECEXP (XEXP (src, 0), 0, 0), 0) != FP_MODE_ROUND_UNKNOWN)
110 continue;
111 if (find_regno_note (insn, REG_UNUSED, FP_TRUNCATE_REGNUM))
112 selected_mode = FP_MODE_ROUND_NEAREST;
113 else if (find_regno_note (insn, REG_UNUSED, FP_NEAREST_REGNUM))
114 selected_mode = FP_MODE_ROUND_TRUNC;
115 else
116 {
117 /* We could get more fancy in the selection of the mode by
118 checking the total frequency of the affected edges. */
119 selected_mode = (enum attr_fp_mode) epiphany_normal_fp_rounding;
120
9771b263 121 todo.quick_push (bb);
d7c028c0 122 bitmap_set_bit (pushed, bb->index);
feeeff5c
JR
123 }
124 XVECEXP (XEXP (src, 0), 0, 0) = GEN_INT (selected_mode);
125 SET_SRC (XVECEXP (PATTERN (insn), 0, 1)) = copy_rtx (src);
126 SET_SRC (XVECEXP (PATTERN (insn), 0, 2)) = copy_rtx (src);
127 df_insn_rescan (insn);
128 }
9771b263 129 while (todo.length ())
feeeff5c 130 {
9771b263 131 basic_block bb = todo.pop ();
feeeff5c
JR
132 int selected_reg, jilted_reg;
133 enum attr_fp_mode jilted_mode;
134 edge e;
135 edge_iterator ei;
136
d7c028c0
LC
137 bitmap_set_bit (pushed, bb->index);
138 bitmap_set_bit (pushed, bb->index);
feeeff5c
JR
139
140 if (epiphany_normal_fp_rounding == FP_MODE_ROUND_NEAREST)
141 {
142 selected_reg = FP_NEAREST_REGNUM;
143 jilted_reg = FP_TRUNCATE_REGNUM;
144 jilted_mode = FP_MODE_ROUND_TRUNC;
145 }
146 else
147 {
148 selected_reg = FP_TRUNCATE_REGNUM;
149 jilted_reg = FP_NEAREST_REGNUM;
150 jilted_mode = FP_MODE_ROUND_NEAREST;
151 }
152
153 FOR_EACH_EDGE (e, ei, bb->succs)
154 {
155 basic_block succ = e->dest;
bcfba653 156 rtx_insn *seq;
feeeff5c
JR
157
158 if (!REGNO_REG_SET_P (DF_LIVE_IN (succ), jilted_reg))
159 continue;
160 if (REGNO_REG_SET_P (DF_LIVE_IN (succ), selected_reg))
161 {
d7c028c0 162 if (bitmap_bit_p (pushed, succ->index))
feeeff5c 163 continue;
9771b263 164 todo.quick_push (succ);
d7c028c0 165 bitmap_set_bit (pushed, bb->index);
feeeff5c
JR
166 continue;
167 }
168 start_sequence ();
169 emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN,
504279ae
RS
170 jilted_mode, FP_MODE_NONE,
171 reg_class_contents[NO_REGS]);
feeeff5c
JR
172 seq = get_insns ();
173 end_sequence ();
174 need_commit = true;
175 insert_insn_on_edge (seq, e);
176 }
177 }
9771b263 178 todo.release ();
feeeff5c
JR
179 sbitmap_free (pushed);
180 if (need_commit)
181 commit_edge_insertions ();
182 return 0;
183}
184
27a4cd48
DM
185} // anon namespace
186
187rtl_opt_pass *
188make_pass_resolve_sw_modes (gcc::context *ctxt)
189{
190 return new pass_resolve_sw_modes (ctxt);
191}