Line data Source code
1 : /* gimplify_reg_info is used during gimplification while walking over
2 : operands and their corresponding constraints of asm statements in order to
3 : detect errors.
4 :
5 : m_alt_output is a mapping describing which registers are potentially used in
6 : which alternative over all outputs. Similarly for m_alt_input but over all
7 : inputs.
8 :
9 : m_early_clobbered_alt is a mapping describing which register is early
10 : clobbered in which alternative over all outputs.
11 :
12 : m_early_clobbered_output is the counter part to the prior one, i.e., it
13 : is a mapping describing which register is early clobbered in which operand
14 : over all alternatives.
15 :
16 : m_reg_asm_output is the set of registers (including register pairs) used for
17 : register asm output operands.
18 :
19 : m_reg_asm_input similar as m_reg_asm_output but for inputs. */
20 :
21 : #include "regs.h"
22 :
23 : class gimplify_reg_info
24 : {
25 : HARD_REG_SET *m_buf;
26 : HARD_REG_SET *m_alt_output;
27 : HARD_REG_SET *m_alt_input;
28 : HARD_REG_SET *m_early_clobbered_alt;
29 : HARD_REG_SET *m_early_clobbered_output;
30 : HARD_REG_SET m_reg_asm_output;
31 : HARD_REG_SET m_reg_asm_input;
32 : const unsigned m_num_alternatives;
33 : const unsigned m_num_outputs;
34 : /* Member m_clobbered describes all the registers marked as clobbered in an
35 : asm statement, i.e., this is the clobbers list of an extended asm
36 :
37 : asm asm-qualifiers ( AssemblerTemplate
38 : : OutputOperands
39 : [ : InputOperands
40 : [ : Clobbers ] ])
41 :
42 : and is not to be confused with the early clobbers sets. */
43 : HARD_REG_SET m_clobbered;
44 :
45 : /* Return the first overlapping register of REGS and REGNO:MODE or -1. */
46 2215 : int test (const HARD_REG_SET ®s, int regno) const
47 : {
48 2215 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
49 :
50 2215 : if (TEST_HARD_REG_BIT (regs, regno))
51 : return regno;
52 :
53 2207 : int end_regno = end_hard_regno (mode, regno);
54 2210 : while (++regno < end_regno)
55 3 : if (TEST_HARD_REG_BIT (regs, regno))
56 : return regno;
57 :
58 : return -1;
59 : }
60 :
61 : public:
62 : tree operand;
63 :
64 97480 : gimplify_reg_info (unsigned num_alternatives,
65 : unsigned num_outputs)
66 97480 : : m_num_alternatives{num_alternatives}
67 97480 : , m_num_outputs{num_outputs}
68 : {
69 389920 : CLEAR_HARD_REG_SET (m_reg_asm_output);
70 292440 : CLEAR_HARD_REG_SET (m_reg_asm_input);
71 97480 : CLEAR_HARD_REG_SET (m_clobbered);
72 :
73 : /* If there are no alternatives, then there are no outputs/inputs and there
74 : is nothing to do on our end. Thus, we are dealing most likely with a
75 : basic asm. */
76 97480 : if (num_alternatives == 0)
77 : return;
78 :
79 30836 : unsigned buf_size = num_alternatives * 3 + num_outputs;
80 30836 : m_buf = new HARD_REG_SET[buf_size];
81 183164 : for (unsigned i = 0; i < buf_size; ++i)
82 304656 : CLEAR_HARD_REG_SET (m_buf[i]);
83 30836 : m_alt_output = &m_buf[0];
84 30836 : m_alt_input = &m_buf[num_alternatives];
85 30836 : m_early_clobbered_alt = &m_buf[num_alternatives * 2];
86 30836 : if (num_outputs > 0)
87 25137 : m_early_clobbered_output = &m_buf[num_alternatives * 3];
88 : else
89 5699 : m_early_clobbered_output = nullptr;
90 : }
91 :
92 97480 : ~gimplify_reg_info ()
93 : {
94 97480 : if (m_num_alternatives > 0)
95 30836 : delete[] m_buf;
96 97480 : }
97 :
98 99 : void set_output (unsigned alt, int regno)
99 : {
100 99 : gcc_checking_assert (alt < m_num_alternatives);
101 99 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
102 99 : add_to_hard_reg_set (&m_alt_output[alt], mode, regno);
103 99 : }
104 :
105 98 : void set_input (unsigned alt, int regno)
106 : {
107 98 : gcc_checking_assert (alt < m_num_alternatives);
108 98 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
109 98 : add_to_hard_reg_set (&m_alt_input[alt], mode, regno);
110 98 : }
111 :
112 1045 : int test_alt_output (unsigned alt, int regno) const
113 : {
114 1045 : gcc_checking_assert (alt < m_num_alternatives);
115 1045 : return test (m_alt_output[alt], regno);
116 : }
117 :
118 972 : int test_alt_input (unsigned alt, int regno) const
119 : {
120 972 : gcc_checking_assert (alt < m_num_alternatives);
121 972 : return test (m_alt_input[alt], regno);
122 : }
123 :
124 945 : void set_reg_asm_output (int regno)
125 : {
126 945 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
127 945 : add_to_hard_reg_set (&m_reg_asm_output, mode, regno);
128 945 : }
129 :
130 99 : int test_reg_asm_output (int regno) const
131 : {
132 99 : return test (m_reg_asm_output, regno);
133 : }
134 :
135 867 : void set_reg_asm_input (int regno)
136 : {
137 867 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
138 867 : add_to_hard_reg_set (&m_reg_asm_input, mode, regno);
139 867 : }
140 :
141 99 : int test_reg_asm_input (int regno) const
142 : {
143 99 : return test (m_reg_asm_input, regno);
144 : }
145 :
146 26 : void set_early_clobbered (unsigned alt, unsigned output, int regno)
147 : {
148 26 : gcc_checking_assert (alt < m_num_alternatives);
149 26 : gcc_checking_assert (output < m_num_outputs);
150 26 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
151 26 : add_to_hard_reg_set (&m_early_clobbered_alt[alt], mode, regno);
152 26 : add_to_hard_reg_set (&m_early_clobbered_output[output], mode, regno);
153 26 : }
154 :
155 275 : bool test_early_clobbered_alt (unsigned alt, int regno) const
156 : {
157 275 : gcc_checking_assert (alt < m_num_alternatives);
158 275 : return TEST_HARD_REG_BIT (m_early_clobbered_alt[alt], regno);
159 : }
160 :
161 667 : bool is_early_clobbered_in_any_output_unequal (unsigned operand,
162 : int regno) const
163 : {
164 667 : gcc_checking_assert (operand < m_num_outputs);
165 1497 : for (unsigned op = 0; op < m_num_outputs; ++op)
166 832 : if (op != operand
167 832 : && TEST_HARD_REG_BIT (m_early_clobbered_output[op], regno))
168 : return true;
169 : return false;
170 : }
171 :
172 41262 : void set_clobbered (int regno)
173 : {
174 41262 : SET_HARD_REG_BIT (m_clobbered, regno);
175 41262 : }
176 :
177 197 : bool is_clobbered (int regno) const
178 : {
179 197 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
180 197 : return overlaps_hard_reg_set_p (m_clobbered, mode, regno);
181 : }
182 : };
|