LLVM: lib/Target/ARM/ARMFixCortexA57AES1742098Pass.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
58#include <assert.h>
59#include <stdint.h>
60
61using namespace llvm;
62
63#define DEBUG_TYPE "arm-fix-cortex-a57-aes-1742098"
64
65
66
67namespace {
69public:
70 static char ID;
72
74
77 }
78
79 StringRef getPassName() const override {
80 return "ARM fix for Cortex-A57 AES Erratum 1742098";
81 }
82
83 void getAnalysisUsage(AnalysisUsage &AU) const override {
87 }
88
89private:
90
91 struct AESFixupLocation {
93
96 };
97
101
102 void insertAESFixup(AESFixupLocation &FixupLoc, const ARMBaseInstrInfo *TII,
104
107};
108char ARMFixCortexA57AES1742098::ID = 0;
109
110}
111
113 "ARM fix for Cortex-A57 AES Erratum 1742098", false,
114 false)
117 "ARM fix for Cortex-A57 AES Erratum 1742098", false, false)
118
119
120
121bool ARMFixCortexA57AES1742098::isFirstAESPairInstr(MachineInstr &MI) {
122 unsigned Opc = MI.getOpcode();
123 return Opc == ARM::AESD || Opc == ARM::AESE;
124}
125
126bool ARMFixCortexA57AES1742098::isSafeAESInput(MachineInstr &MI) {
127 auto CondCodeIsAL = [](MachineInstr &MI) -> bool {
128 int CCIdx = MI.findFirstPredOperandIdx();
129 if (CCIdx == -1)
130 return false;
131 return MI.getOperand(CCIdx).getImm() == (int64_t)ARMCC::AL;
132 };
133
134 switch (MI.getOpcode()) {
135
136 default:
137 return false;
138
139 case ARM::AESD:
140 case ARM::AESE:
141 case ARM::AESMC:
142 case ARM::AESIMC:
143
144 return true;
145
146 case ARM::VANDd:
147 case ARM::VANDq:
148 case ARM::VORRd:
149 case ARM::VORRq:
150 case ARM::VEORd:
151 case ARM::VEORq:
152 case ARM::VMVNd:
153 case ARM::VMVNq:
154
155 case ARM::VMOVD:
156
157 case ARM::VMOVDRR:
158
159 case ARM::VMOVv2i64:
160 case ARM::VMOVv1i64:
161 case ARM::VMOVv2f32:
162 case ARM::VMOVv4f32:
163 case ARM::VMOVv2i32:
164 case ARM::VMOVv4i32:
165 case ARM::VMOVv4i16:
166 case ARM::VMOVv8i16:
167 case ARM::VMOVv8i8:
168 case ARM::VMOVv16i8:
169
170
171 case ARM::VLDRD:
172
173 case ARM::VLDMDDB_UPD:
174 case ARM::VLDMDIA_UPD:
175 case ARM::VLDMDIA:
176
177 case ARM::VLD1d64:
178 case ARM::VLD1q64:
179 case ARM::VLD1d32:
180 case ARM::VLD1q32:
181 case ARM::VLD2b32:
182 case ARM::VLD2d32:
183 case ARM::VLD2q32:
184 case ARM::VLD1d16:
185 case ARM::VLD1q16:
186 case ARM::VLD2d16:
187 case ARM::VLD2q16:
188 case ARM::VLD1d8:
189 case ARM::VLD1q8:
190 case ARM::VLD2b8:
191 case ARM::VLD2d8:
192 case ARM::VLD2q8:
193 case ARM::VLD3d32:
194 case ARM::VLD3q32:
195 case ARM::VLD3d16:
196 case ARM::VLD3q16:
197 case ARM::VLD3d8:
198 case ARM::VLD3q8:
199 case ARM::VLD4d32:
200 case ARM::VLD4q32:
201 case ARM::VLD4d16:
202 case ARM::VLD4q16:
203 case ARM::VLD4d8:
204 case ARM::VLD4q8:
205
206 case ARM::VLD1LNd32:
207 case ARM::VLD1LNd32_UPD:
208 case ARM::VLD1LNd8:
209 case ARM::VLD1LNd8_UPD:
210 case ARM::VLD1LNd16:
211 case ARM::VLD1LNd16_UPD:
212
213 case ARM::VLD1DUPd32:
214 case ARM::VLD1DUPd32wb_fixed:
215 case ARM::VLD1DUPd32wb_register:
216 case ARM::VLD1DUPd16:
217 case ARM::VLD1DUPd16wb_fixed:
218 case ARM::VLD1DUPd16wb_register:
219 case ARM::VLD1DUPd8:
220 case ARM::VLD1DUPd8wb_fixed:
221 case ARM::VLD1DUPd8wb_register:
222 case ARM::VLD1DUPq32:
223 case ARM::VLD1DUPq32wb_fixed:
224 case ARM::VLD1DUPq32wb_register:
225 case ARM::VLD1DUPq16:
226 case ARM::VLD1DUPq16wb_fixed:
227 case ARM::VLD1DUPq16wb_register:
228 case ARM::VLD1DUPq8:
229 case ARM::VLD1DUPq8wb_fixed:
230 case ARM::VLD1DUPq8wb_register:
231
232 case ARM::VSETLNi32:
233 case ARM::VSETLNi16:
234 case ARM::VSETLNi8:
235 return CondCodeIsAL(MI);
236 };
237
238 return false;
239}
240
241bool ARMFixCortexA57AES1742098::runOnMachineFunction(MachineFunction &F) {
242 LLVM_DEBUG(dbgs() << "***** ARMFixCortexA57AES1742098 *****\n");
243 auto &STI = F.getSubtarget();
244
245
246 if (!STI.hasAES() || !STI.fixCortexA57AES1742098())
247 return false;
248
249 const ARMBaseRegisterInfo *TRI = STI.getRegisterInfo();
250 const ARMBaseInstrInfo *TII = STI.getInstrInfo();
251
252 auto &RDI = getAnalysis().getRDI();
253
254
256 analyzeMF(F, RDI, TRI, FixupLocsForFn);
257
258
260 LLVM_DEBUG(dbgs() << "Inserting " << FixupLocsForFn.size() << " fixup(s)\n");
261 for (AESFixupLocation &FixupLoc : FixupLocsForFn) {
262 insertAESFixup(FixupLoc, TII, TRI);
264 }
265
267}
268
269void ARMFixCortexA57AES1742098::analyzeMF(
270 MachineFunction &MF, ReachingDefInfo &RDI, const ARMBaseRegisterInfo *TRI,
271 SmallVectorImpl &FixupLocsForFn) const {
272 unsigned MaxAllowedFixups = 0;
273
274 for (MachineBasicBlock &MBB : MF) {
275 for (MachineInstr &MI : MBB) {
276 if (!isFirstAESPairInstr(MI))
277 continue;
278
279
281 assert(MI.getNumExplicitOperands() == 3 && MI.getNumExplicitDefs() == 1 &&
282 "Unknown AES Instruction Format. Expected 1 def, 2 uses.");
283
284
285
286 MaxAllowedFixups += 2;
287
288
289 for (MachineOperand &MOp : MI.uses()) {
290 SmallPtrSet<MachineInstr *, 1> AllDefs{};
292
293
294 AESFixupLocation NewLoc{&MBB, &MI, &MOp};
295
296
297
298 bool IsLiveIn = MF.front().isLiveIn(MOp.getReg());
299
300
301
302
303 if (!IsLiveIn && AllDefs.size() == 0) {
305 << "Fixup Planned: No Defining Instrs found, not live-in: "
308 continue;
309 }
310
311 auto IsUnsafe = [](MachineInstr *MI) -> bool {
312 return !isSafeAESInput(*MI);
313 };
314 size_t UnsafeCount = llvm::count_if(AllDefs, IsUnsafe);
315
316
317 if (UnsafeCount == 0) {
318
319 if (!IsLiveIn) {
320
321 LLVM_DEBUG(dbgs() << "No Fixup: Defining instrs are all safe: "
323 continue;
324 }
325
326
327
329 << "Fixup Planned: Live-In (with safe defining instrs): "
331 NewLoc.Block = &MF.front();
332 NewLoc.InsertionPt = &*NewLoc.Block->begin();
333 LLVM_DEBUG(dbgs() << "Moving Fixup for Live-In to immediately before "
334 << *NewLoc.InsertionPt);
336 continue;
337 }
338
339
340
341
342
343
344
345 if (IsLiveIn || UnsafeCount > 1) {
346 LLVM_DEBUG(dbgs() << "Fixup Planned: Multiple unsafe defining instrs "
347 "(including live-ins): "
350 continue;
351 }
352
353 assert(UnsafeCount == 1 && !IsLiveIn &&
354 "At this point, there should be one unsafe defining instrs "
355 "and the defined register should not be a live-in.");
356 SmallPtrSetIterator<MachineInstr *> It =
359 "UnsafeCount == 1 but No Unsafe MachineInstr found.");
360 MachineInstr *DefMI = *It;
361
363 dbgs() << "Fixup Planned: Found single unsafe defining instrs for "
365
366
367
368
369
370
372 ++DefIt;
375 << "And immediately before " << *DefIt);
376 NewLoc.Block = DefIt->getParent();
377 NewLoc.InsertionPt = &*DefIt;
378 }
379
381 }
382 }
383 }
384
385 assert(FixupLocsForFn.size() <= MaxAllowedFixups &&
386 "Inserted too many fixups for this function.");
387 (void)MaxAllowedFixups;
388}
389
390void ARMFixCortexA57AES1742098::insertAESFixup(
391 AESFixupLocation &FixupLoc, const ARMBaseInstrInfo *TII,
392 const ARMBaseRegisterInfo *TRI) const {
393 MachineOperand *OperandToFixup = FixupLoc.MOp;
394
395 assert(OperandToFixup->isReg() && "OperandToFixup must be a register");
397
399 << " before: " << *FixupLoc.InsertionPt);
400
401
402
403
404
405
406
407
408
409
410
412 BuildMI(*FixupLoc.Block, FixupLoc.InsertionPt, DebugLoc(),
413 TII->get(ARM::VORRq))
418 .addReg(ARM::NoRegister);
419}
420
421
422
424 return new ARMFixCortexA57AES1742098();
425}
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Properties which a MachineFunction may have at a given point in time.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI bool isRenamable() const
isRenamable - Returns true if this register may be renamed, i.e.
Register getReg() const
getReg - Returns the register number.
This class provides the reaching def analysis.
void getGlobalReachingDefs(MachineInstr *MI, Register Reg, InstSet &Defs) const
Collect all possible definitions of the value stored in Reg, which is used by MI.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
StringRef - Represent a constant reference to a string, i.e.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Renamable
Register that may be renamed.
@ Define
Register definition.
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
FunctionPass * createARMFixCortexA57AES1742098Pass()
Definition ARMFixCortexA57AES1742098Pass.cpp:423
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.