Branch data 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 : 2206 : int test (const HARD_REG_SET ®s, int regno) const
47 : : {
48 : 2206 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
49 : :
50 : 2206 : if (TEST_HARD_REG_BIT (regs, regno))
51 : : return regno;
52 : :
53 : 2197 : int end_regno = end_hard_regno (mode, regno);
54 : 2200 : 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 : 95151 : gimplify_reg_info (unsigned num_alternatives,
65 : : unsigned num_outputs)
66 : 95151 : : m_num_alternatives{num_alternatives}
67 : 95151 : , m_num_outputs{num_outputs}
68 : : {
69 : 380604 : CLEAR_HARD_REG_SET (m_reg_asm_output);
70 : 285453 : CLEAR_HARD_REG_SET (m_reg_asm_input);
71 : 95151 : 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 : 95151 : if (num_alternatives == 0)
77 : : return;
78 : :
79 : 29447 : unsigned buf_size = num_alternatives * 3 + num_outputs;
80 : 29447 : m_buf = new HARD_REG_SET[buf_size];
81 : 175469 : for (unsigned i = 0; i < buf_size; ++i)
82 : 292044 : CLEAR_HARD_REG_SET (m_buf[i]);
83 : 29447 : m_alt_output = &m_buf[0];
84 : 29447 : m_alt_input = &m_buf[num_alternatives];
85 : 29447 : m_early_clobbered_alt = &m_buf[num_alternatives * 2];
86 : 29447 : if (num_outputs > 0)
87 : 24213 : m_early_clobbered_output = &m_buf[num_alternatives * 3];
88 : : else
89 : 5234 : m_early_clobbered_output = nullptr;
90 : : }
91 : :
92 : 95151 : ~gimplify_reg_info ()
93 : : {
94 : 95151 : if (m_num_alternatives > 0)
95 : 29447 : delete[] m_buf;
96 : 95151 : }
97 : :
98 : 96 : void set_output (unsigned alt, int regno)
99 : : {
100 : 96 : gcc_checking_assert (alt < m_num_alternatives);
101 : 96 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
102 : 96 : add_to_hard_reg_set (&m_alt_output[alt], mode, regno);
103 : 96 : }
104 : :
105 : 96 : void set_input (unsigned alt, int regno)
106 : : {
107 : 96 : gcc_checking_assert (alt < m_num_alternatives);
108 : 96 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
109 : 96 : add_to_hard_reg_set (&m_alt_input[alt], mode, regno);
110 : 96 : }
111 : :
112 : 1042 : int test_alt_output (unsigned alt, int regno) const
113 : : {
114 : 1042 : gcc_checking_assert (alt < m_num_alternatives);
115 : 1042 : return test (m_alt_output[alt], regno);
116 : : }
117 : :
118 : 971 : int test_alt_input (unsigned alt, int regno) const
119 : : {
120 : 971 : gcc_checking_assert (alt < m_num_alternatives);
121 : 971 : 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 : 96 : int test_reg_asm_output (int regno) const
131 : : {
132 : 96 : 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 : 97 : int test_reg_asm_input (int regno) const
142 : : {
143 : 97 : 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 : 272 : bool test_early_clobbered_alt (unsigned alt, int regno) const
156 : : {
157 : 272 : gcc_checking_assert (alt < m_num_alternatives);
158 : 272 : 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 : 41248 : void set_clobbered (int regno)
173 : : {
174 : 41248 : SET_HARD_REG_BIT (m_clobbered, regno);
175 : 41248 : }
176 : :
177 : 192 : bool is_clobbered (int regno) const
178 : : {
179 : 192 : machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
180 : 192 : return overlaps_hard_reg_set_p (m_clobbered, mode, regno);
181 : : }
182 : : };
|