annotate gcc/config/aarch64/aarch64-speculation.cc @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1 /* Speculation tracking and mitigation (e.g. CVE 2017-5753) for AArch64.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2018-2020 Free Software Foundation, Inc.
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
3 Contributed by ARM Ltd.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
4
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
5 This file is part of GCC.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
6
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
8 under the terms of the GNU General Public License as published by
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
10 any later version.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
11
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
13 WITHOUT ANY WARRANTY; without even the implied warranty of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
15 General Public License for more details.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
16
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
20
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
21 #include "config.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
22 #include "system.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
23 #include "coretypes.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
24 #include "target.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
25 #include "rtl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
26 #include "tree-pass.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
27 #include "profile-count.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
28 #include "backend.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
29 #include "cfgbuild.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
30 #include "print-rtl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
31 #include "cfgrtl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
32 #include "function.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
33 #include "basic-block.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
34 #include "memmodel.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
35 #include "emit-rtl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
36 #include "insn-attr.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
37 #include "df.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
38 #include "tm_p.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
39 #include "insn-config.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
40 #include "recog.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
41
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
42 /* This pass scans the RTL just before the final branch
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
43 re-organisation pass. The aim is to identify all places where
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
44 there is conditional control flow and to insert code that tracks
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
45 any speculative execution of a conditional branch.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
46
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
47 To do this we reserve a call-clobbered register (so that it can be
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
48 initialized very early in the function prologue) that can then be
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
49 updated each time there is a conditional branch. At each such
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
50 branch we then generate a code sequence that uses conditional
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
51 select operations that are not subject to speculation themselves
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
52 (we ignore for the moment situations where that might not always be
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
53 strictly true). For example, a branch sequence such as:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
54
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
55 B.EQ <dst>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
56 ...
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
57 <dst>:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
58
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
59 is transformed to:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
60
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
61 B.EQ <dst>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
62 CSEL tracker, tracker, XZr, ne
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
63 ...
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
64 <dst>:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
65 CSEL tracker, tracker, XZr, eq
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
66
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
67 Since we start with the tracker initialized to all bits one, if at any
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
68 time the predicted control flow diverges from the architectural program
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
69 behavior, then the tracker will become zero (but not otherwise).
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
70
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
71 The tracker value can be used at any time at which a value needs
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
72 guarding against incorrect speculation. This can be done in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
73 several ways, but they all amount to the same thing. For an
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
74 untrusted address, or an untrusted offset to a trusted address, we
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
75 can simply mask the address with the tracker with the untrusted
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
76 value. If the CPU is not speculating, or speculating correctly,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
77 then the value will remain unchanged, otherwise it will be clamped
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
78 to zero. For more complex scenarios we can compare the tracker
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
79 against zero and use the flags to form a new selection with an
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
80 alternate safe value.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
81
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
82 On implementations where the data processing instructions may
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
83 themselves produce speculative values, the architecture requires
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
84 that a CSDB instruction will resolve such data speculation, so each
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
85 time we use the tracker for protecting a vulnerable value we also
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
86 emit a CSDB: we do not need to do that each time the tracker itself
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
87 is updated.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
88
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
89 At function boundaries, we need to communicate the speculation
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
90 tracking state with the caller or the callee. This is tricky
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
91 because there is no register available for such a purpose without
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
92 creating a new ABI. We deal with this by relying on the principle
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
93 that in all real programs the stack pointer, SP will never be NULL
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
94 at a function boundary; we can thus encode the speculation state in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
95 SP by clearing SP if the speculation tracker itself is NULL. After
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
96 the call we recover the tracking state back from SP into the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
97 tracker register. The results is that a function call sequence is
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
98 transformed to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
99
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
100 MOV tmp, SP
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
101 AND tmp, tmp, tracker
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
102 MOV SP, tmp
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
103 BL <callee>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
104 CMP SP, #0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
105 CSETM tracker, ne
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
106
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
107 The additional MOV instructions in the pre-call sequence are needed
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
108 because SP cannot be used directly with the AND instruction.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
109
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
110 The code inside a function body uses the post-call sequence in the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
111 prologue to establish the tracker and the pre-call sequence in the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
112 epilogue to re-encode the state for the return.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
113
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
114 The code sequences have the nice property that if called from, or
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
115 calling a function that does not track speculation then the stack pointer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
116 will always be non-NULL and hence the tracker will be initialized to all
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
117 bits one as we need: we lose the ability to fully track speculation in that
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
118 case, but we are still architecturally safe.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
119
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
120 Tracking speculation in this way is quite expensive, both in code
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
121 size and execution time. We employ a number of tricks to try to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
122 limit this:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
123
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
124 1) Simple leaf functions with no conditional branches (or use of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
125 the tracker) do not need to establish a new tracker: they simply
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
126 carry the tracking state through SP for the duration of the call.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
127 The same is also true for leaf functions that end in a tail-call.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
128
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
129 2) Back-to-back function calls in a single basic block also do not
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
130 need to re-establish the tracker between the calls. Again, we can
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
131 carry the tracking state in SP for this period of time unless the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
132 tracker value is needed at that point in time.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
133
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
134 We run the pass just before the final branch reorganization pass so
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
135 that we can handle most of the conditional branch cases using the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
136 standard edge insertion code. The reorg pass will hopefully clean
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
137 things up for afterwards so that the results aren't too
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
138 horrible. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
139
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
140 /* Generate a code sequence to clobber SP if speculating incorreclty. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
141 static rtx_insn *
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
142 aarch64_speculation_clobber_sp ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
143 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
144 rtx sp = gen_rtx_REG (DImode, SP_REGNUM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
145 rtx tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
146 rtx scratch = gen_rtx_REG (DImode, SPECULATION_SCRATCH_REGNUM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
147
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
148 start_sequence ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
149 emit_insn (gen_rtx_SET (scratch, sp));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
150 emit_insn (gen_anddi3 (scratch, scratch, tracker));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
151 emit_insn (gen_rtx_SET (sp, scratch));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
152 rtx_insn *seq = get_insns ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
153 end_sequence ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
154 return seq;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
155 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
156
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
157 /* Generate a code sequence to establish the tracker variable from the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
158 contents of SP. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
159 static rtx_insn *
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
160 aarch64_speculation_establish_tracker ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
161 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
162 rtx sp = gen_rtx_REG (DImode, SP_REGNUM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
163 rtx tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
164 start_sequence ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
165 rtx cc = aarch64_gen_compare_reg (EQ, sp, const0_rtx);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
166 emit_insn (gen_cstoredi_neg (tracker,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
167 gen_rtx_NE (CCmode, cc, const0_rtx), cc));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
168 rtx_insn *seq = get_insns ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
169 end_sequence ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
170 return seq;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
171 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
172
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
173 /* Main speculation tracking pass. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
174 unsigned int
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
175 aarch64_do_track_speculation ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
176 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
177 basic_block bb;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
178 bool needs_tracking = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
179 bool need_second_pass = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
180 rtx_insn *insn;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
181 int fixups_pending = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
182
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
183 FOR_EACH_BB_FN (bb, cfun)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
184 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
185 insn = BB_END (bb);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
186
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
187 if (dump_file)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
188 fprintf (dump_file, "Basic block %d:\n", bb->index);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
189
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
190 while (insn != BB_HEAD (bb)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
191 && NOTE_P (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
192 insn = PREV_INSN (insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
193
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
194 if (control_flow_insn_p (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
195 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
196 if (any_condjump_p (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
197 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
198 if (dump_file)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
199 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
200 fprintf (dump_file, " condjump\n");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
201 dump_insn_slim (dump_file, insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
202 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
203
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
204 rtx src = SET_SRC (pc_set (insn));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
205
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
206 /* Check for an inverted jump, where the fall-through edge
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
207 appears first. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
208 bool inverted = GET_CODE (XEXP (src, 2)) != PC;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
209 /* The other edge must be the PC (we assume that we don't
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
210 have conditional return instructions). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
211 gcc_assert (GET_CODE (XEXP (src, 1 + !inverted)) == PC);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
212
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
213 rtx cond = copy_rtx (XEXP (src, 0));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
214 gcc_assert (COMPARISON_P (cond)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
215 && REG_P (XEXP (cond, 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
216 && REGNO (XEXP (cond, 0)) == CC_REGNUM
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
217 && XEXP (cond, 1) == const0_rtx);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
218 rtx branch_tracker = gen_speculation_tracker (copy_rtx (cond));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
219 rtx fallthru_tracker = gen_speculation_tracker_rev (cond);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
220 if (inverted)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
221 std::swap (branch_tracker, fallthru_tracker);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
222
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
223 insert_insn_on_edge (branch_tracker, BRANCH_EDGE (bb));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
224 insert_insn_on_edge (fallthru_tracker, FALLTHRU_EDGE (bb));
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
225 needs_tracking = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
226 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
227 else if (GET_CODE (PATTERN (insn)) == RETURN)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
228 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
229 /* If we already know we'll need a second pass, don't put
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
230 out the return sequence now, or we might end up with
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
231 two copies. Instead, we'll do all return statements
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
232 during the second pass. However, if this is the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
233 first return insn we've found and we already
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
234 know that we'll need to emit the code, we can save a
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
235 second pass by emitting the code now. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
236 if (needs_tracking && ! need_second_pass)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
237 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
238 rtx_insn *seq = aarch64_speculation_clobber_sp ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
239 emit_insn_before (seq, insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
240 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
241 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
242 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
243 fixups_pending++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
244 need_second_pass = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
245 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
246 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
247 else if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
248 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
249 rtx_insn *seq = aarch64_speculation_clobber_sp ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
250 emit_insn_before (seq, insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
251 needs_tracking = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
252 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
253 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
254 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
255 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
256 if (dump_file)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
257 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
258 fprintf (dump_file, " other\n");
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
259 dump_insn_slim (dump_file, insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
260 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
261 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
262 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
263
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
264 FOR_EACH_BB_FN (bb, cfun)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
265 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
266 rtx_insn *end = BB_END (bb);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
267 rtx_insn *call_insn = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
268
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
269 if (bb->flags & BB_NON_LOCAL_GOTO_TARGET)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
270 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
271 rtx_insn *label = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
272 /* For non-local goto targets we have to recover the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
273 speculation state from SP. Find the last code label at
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
274 the head of the block and place the fixup sequence after
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
275 that. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
276 for (insn = BB_HEAD (bb); insn != end; insn = NEXT_INSN (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
277 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
278 if (LABEL_P (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
279 label = insn;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
280 /* Never put anything before the basic block note. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
281 if (NOTE_INSN_BASIC_BLOCK_P (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
282 label = insn;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
283 if (INSN_P (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
284 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
285 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
286
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
287 gcc_assert (label);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
288 emit_insn_after (aarch64_speculation_establish_tracker (), label);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
289 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
290
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
291 /* Scan the insns looking for calls. We need to pass the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
292 speculation tracking state encoded in to SP. After a call we
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
293 restore the speculation tracking into the tracker register.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
294 To avoid unnecessary transfers we look for two or more calls
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
295 within a single basic block and eliminate, where possible,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
296 any redundant operations. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
297 for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
298 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
299 if (NONDEBUG_INSN_P (insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
300 && recog_memoized (insn) >= 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
301 && (get_attr_speculation_barrier (insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
302 == SPECULATION_BARRIER_TRUE))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
303 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
304 if (call_insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
305 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
306 /* This instruction requires the speculation
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
307 tracking to be in the tracker register. If there
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
308 was an earlier call in this block, we need to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
309 copy the speculation tracking back there. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
310 emit_insn_after (aarch64_speculation_establish_tracker (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
311 call_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
312 call_insn = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
313 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
314
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
315 needs_tracking = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
316 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
317
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
318 if (CALL_P (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
319 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
320 bool tailcall
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
321 = (SIBLING_CALL_P (insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
322 || find_reg_note (insn, REG_NORETURN, NULL_RTX));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
323
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
324 /* Tailcalls are like returns, we can eliminate the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
325 transfer between the tracker register and SP if we
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
326 know that this function does not itself need
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
327 tracking. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
328 if (tailcall && (need_second_pass || !needs_tracking))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
329 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
330 /* Don't clear call_insn if it is set - needs_tracking
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
331 will be true in that case and so we will end
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
332 up putting out mitigation sequences. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
333 fixups_pending++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
334 need_second_pass = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
335 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
336 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
337
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
338 needs_tracking = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
339
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
340 /* We always need a transfer before the first call in a BB. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
341 if (!call_insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
342 emit_insn_before (aarch64_speculation_clobber_sp (), insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
343
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
344 /* Tail-calls and no-return calls don't need any post-call
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
345 reestablishment of the tracker. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
346 if (! tailcall)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
347 call_insn = insn;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
348 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
349 call_insn = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
350 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
351
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
352 if (insn == end)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
353 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
354 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
355
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
356 if (call_insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
357 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
358 rtx_insn *seq = aarch64_speculation_establish_tracker ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
359
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
360 /* Handle debug insns at the end of the BB. Put the extra
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
361 insns after them. This ensures that we have consistent
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
362 behaviour for the placement of the extra insns between
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
363 debug and non-debug builds. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
364 for (insn = call_insn;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
365 insn != end && DEBUG_INSN_P (NEXT_INSN (insn));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
366 insn = NEXT_INSN (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
367 ;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
368
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
369 if (insn == end)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
370 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
371 edge e = find_fallthru_edge (bb->succs);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
372 /* We need to be very careful about some calls that
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
373 appear at the end of a basic block. If the call
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
374 involves exceptions, then the compiler may depend on
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
375 this being the last instruction in the block. The
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
376 easiest way to handle this is to commit the new
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
377 instructions on the fall-through edge and to let
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
378 commit_edge_insertions clean things up for us.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
379
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
380 Sometimes, eg with OMP, there may not even be an
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
381 outgoing edge after the call. In that case, there's
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
382 not much we can do, presumably the compiler has
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
383 decided that the call can never return in this
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
384 context. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
385 if (e)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
386 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
387 /* We need to set the location lists explicitly in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
388 this case. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
389 if (! INSN_P (seq))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
390 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
391 start_sequence ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
392 emit_insn (seq);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
393 seq = get_insns ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
394 end_sequence ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
395 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
396
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
397 for (rtx_insn *list = seq; list; list = NEXT_INSN (list))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
398 INSN_LOCATION (list) = INSN_LOCATION (call_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
399
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
400 insert_insn_on_edge (seq, e);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
401 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
402 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
403 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
404 emit_insn_after (seq, call_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
405 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
406 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
407
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
408 if (needs_tracking)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
409 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
410 if (need_second_pass)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
411 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
412 /* We found a return instruction before we found out whether
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
413 or not we need to emit the tracking code, but we now
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
414 know we do. Run quickly over the basic blocks and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
415 fix up the return insns. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
416 FOR_EACH_BB_FN (bb, cfun)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
417 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
418 insn = BB_END (bb);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
419
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
420 while (insn != BB_HEAD (bb)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
421 && NOTE_P (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
422 insn = PREV_INSN (insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
423
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
424 if ((control_flow_insn_p (insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
425 && GET_CODE (PATTERN (insn)) == RETURN)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
426 || (CALL_P (insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
427 && (SIBLING_CALL_P (insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
428 || find_reg_note (insn, REG_NORETURN, NULL_RTX))))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
429 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
430 rtx_insn *seq = aarch64_speculation_clobber_sp ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
431 emit_insn_before (seq, insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
432 fixups_pending--;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
433 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
434 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
435 gcc_assert (fixups_pending == 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
436 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
437
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
438 /* Set up the initial value of the tracker, using the incoming SP. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
439 insert_insn_on_edge (aarch64_speculation_establish_tracker (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
440 single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
441 commit_edge_insertions ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
442 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
443
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
444 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
445 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
446
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
447 namespace {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
448
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
449 const pass_data pass_data_aarch64_track_speculation =
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
450 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
451 RTL_PASS, /* type. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
452 "speculation", /* name. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
453 OPTGROUP_NONE, /* optinfo_flags. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
454 TV_MACH_DEP, /* tv_id. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
455 0, /* properties_required. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
456 0, /* properties_provided. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
457 0, /* properties_destroyed. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
458 0, /* todo_flags_start. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
459 0 /* todo_flags_finish. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
460 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
461
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
462 class pass_track_speculation : public rtl_opt_pass
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
463 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
464 public:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
465 pass_track_speculation(gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
466 : rtl_opt_pass(pass_data_aarch64_track_speculation, ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
467 {}
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
468
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
469 /* opt_pass methods: */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
470 virtual bool gate (function *)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
471 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
472 return aarch64_track_speculation;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
473 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
474
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
475 virtual unsigned int execute (function *)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
476 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
477 return aarch64_do_track_speculation ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
478 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
479 }; // class pass_track_speculation.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
480 } // anon namespace.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
481
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
482 /* Create a new pass instance. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
483 rtl_opt_pass *
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
484 make_pass_track_speculation (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
485 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
486 return new pass_track_speculation (ctxt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
487 }