17
17
#include " llvm/ADT/SmallVector.h"
18
18
#include " llvm/CodeGen/MachineBasicBlock.h"
19
19
#include " llvm/CodeGen/MachineFunctionPass.h"
20
+ #include " llvm/CodeGen/MachineRegisterInfo.h"
21
+ #include " llvm/CodeGen/TargetRegisterInfo.h"
20
22
21
23
using namespace llvm ;
22
24
@@ -108,8 +110,30 @@ static bool ChangesStreamingMode(const MachineInstr *MI) {
108
110
MI->getOperand (0 ).getImm () == AArch64SVCR::SVCRSMZA;
109
111
}
110
112
113
+ static bool isSVERegOp (const TargetRegisterInfo &TRI,
114
+ const MachineRegisterInfo &MRI,
115
+ const MachineOperand &MO) {
116
+ if (!MO.isReg ())
117
+ return false ;
118
+
119
+ Register R = MO.getReg ();
120
+ if (R.isPhysical ())
121
+ return llvm::any_of (TRI.subregs_inclusive (R), [](const MCPhysReg &SR) {
122
+ return AArch64::ZPRRegClass.contains (SR) ||
123
+ AArch64::PPRRegClass.contains (SR);
124
+ });
125
+
126
+ const TargetRegisterClass *RC = MRI.getRegClass (R);
127
+ return TRI.getCommonSubClass (&AArch64::ZPRRegClass, RC) ||
128
+ TRI.getCommonSubClass (&AArch64::PPRRegClass, RC);
129
+ }
130
+
111
131
bool SMEPeepholeOpt::optimizeStartStopPairs (MachineBasicBlock &MBB,
112
132
bool &HasRemainingSMChange) const {
133
+ const MachineRegisterInfo &MRI = MBB.getParent ()->getRegInfo ();
134
+ const TargetRegisterInfo &TRI =
135
+ *MBB.getParent ()->getSubtarget ().getRegisterInfo ();
136
+
113
137
SmallVector<MachineInstr *, 4 > ToBeRemoved;
114
138
115
139
bool Changed = false ;
@@ -129,33 +153,6 @@ bool SMEPeepholeOpt::optimizeStartStopPairs(MachineBasicBlock &MBB,
129
153
// tracking.
130
154
for (MachineInstr &MI : make_early_inc_range (MBB)) {
131
155
switch (MI.getOpcode ()) {
132
- default :
133
- Reset ();
134
- break ;
135
- case AArch64::COPY: {
136
- // Permit copies of 32 and 64-bit registers.
137
- if (!MI.getOperand (1 ).isReg ()) {
138
- Reset ();
139
- break ;
140
- }
141
- Register Reg = MI.getOperand (1 ).getReg ();
142
- if (!AArch64::GPR32RegClass.contains (Reg) &&
143
- !AArch64::GPR64RegClass.contains (Reg))
144
- Reset ();
145
- break ;
146
- }
147
- case AArch64::ADJCALLSTACKDOWN:
148
- case AArch64::ADJCALLSTACKUP:
149
- case AArch64::ANDXri:
150
- case AArch64::ADDXri:
151
- // We permit these as they don't generate SVE/NEON instructions.
152
- break ;
153
- case AArch64::VGRestorePseudo:
154
- case AArch64::VGSavePseudo:
155
- // When the smstart/smstop are removed, we should also remove
156
- // the pseudos that save/restore the VG value for CFI info.
157
- ToBeRemoved.push_back (&MI);
158
- break ;
159
156
case AArch64::MSRpstatesvcrImm1:
160
157
case AArch64::MSRpstatePseudo: {
161
158
if (!Prev)
@@ -174,8 +171,50 @@ bool SMEPeepholeOpt::optimizeStartStopPairs(MachineBasicBlock &MBB,
174
171
Reset ();
175
172
Prev = &MI;
176
173
}
174
+ continue ;
175
+ }
176
+ default :
177
+ if (!Prev)
178
+ // Avoid doing expensive checks when Prev is nullptr.
179
+ continue ;
177
180
break ;
178
181
}
182
+
183
+ // Test if the instructions in between the start/stop sequence are agnostic
184
+ // of streaming mode. If not, the algorithm should reset.
185
+ switch (MI.getOpcode ()) {
186
+ default :
187
+ Reset ();
188
+ break ;
189
+ case AArch64::COALESCER_BARRIER_FPR16:
190
+ case AArch64::COALESCER_BARRIER_FPR32:
191
+ case AArch64::COALESCER_BARRIER_FPR64:
192
+ case AArch64::COALESCER_BARRIER_FPR128:
193
+ case AArch64::COPY:
194
+ // These instructions should be safe when executed on their own, but
195
+ // the code remains conservative when SVE registers are used. There may
196
+ // exist subtle cases where executing a COPY in a different mode results
197
+ // in different behaviour, even if we can't yet come up with any
198
+ // concrete example/test-case.
199
+ if (isSVERegOp (TRI, MRI, MI.getOperand (0 )) ||
200
+ isSVERegOp (TRI, MRI, MI.getOperand (1 )))
201
+ Reset ();
202
+ break ;
203
+ case AArch64::ADJCALLSTACKDOWN:
204
+ case AArch64::ADJCALLSTACKUP:
205
+ case AArch64::ANDXri:
206
+ case AArch64::ADDXri:
207
+ // We permit these as they don't generate SVE/NEON instructions.
208
+ break ;
209
+ case AArch64::VGRestorePseudo:
210
+ case AArch64::VGSavePseudo:
211
+ // When the smstart/smstop are removed, we should also remove
212
+ // the pseudos that save/restore the VG value for CFI info.
213
+ ToBeRemoved.push_back (&MI);
214
+ break ;
215
+ case AArch64::MSRpstatesvcrImm1:
216
+ case AArch64::MSRpstatePseudo:
217
+ llvm_unreachable (" Should have been handled" );
179
218
}
180
219
}
181
220
0 commit comments