63#define DEBUG_TYPE "arm-fix-cortex-a57-aes-1742098"
80 return "ARM fix for Cortex-A57 AES Erratum 1742098";
91 struct AESFixupLocation {
108char ARMFixCortexA57AES1742098::ID = 0;
113 "ARM fix for Cortex-A57 AES Erratum 1742098",
false,
117 "ARM fix for Cortex-A57 AES Erratum 1742098",
false,
false)
121bool ARMFixCortexA57AES1742098::isFirstAESPairInstr(
MachineInstr &
MI) {
122 unsigned Opc =
MI.getOpcode();
123 return Opc == ARM::AESD ||
Opc == ARM::AESE;
127 auto CondCodeIsAL = [](MachineInstr &
MI) ->
bool {
128 int CCIdx =
MI.findFirstPredOperandIdx();
131 return MI.getOperand(CCIdx).getImm() == (int64_t)
ARMCC::AL;
134 switch (
MI.getOpcode()) {
173 case ARM::VLDMDDB_UPD:
174 case ARM::VLDMDIA_UPD:
207 case ARM::VLD1LNd32_UPD:
209 case ARM::VLD1LNd8_UPD:
211 case ARM::VLD1LNd16_UPD:
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:
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:
229 case ARM::VLD1DUPq8wb_fixed:
230 case ARM::VLD1DUPq8wb_register:
235 return CondCodeIsAL(
MI);
241bool ARMFixCortexA57AES1742098::runOnMachineFunction(MachineFunction &
F) {
243 auto &STI =
F.getSubtarget<ARMSubtarget>();
246 if (!STI.hasAES() || !STI.fixCortexA57AES1742098())
249 const ARMBaseRegisterInfo *
TRI = STI.getRegisterInfo();
250 const ARMBaseInstrInfo *
TII = STI.getInstrInfo();
252 auto &
RDA = getAnalysis<ReachingDefAnalysis>();
256 analyzeMF(
F,
RDA,
TRI, FixupLocsForFn);
261 for (AESFixupLocation &FixupLoc : FixupLocsForFn) {
262 insertAESFixup(FixupLoc,
TII,
TRI);
269void ARMFixCortexA57AES1742098::analyzeMF(
270 MachineFunction &MF, ReachingDefAnalysis &
RDA,
271 const ARMBaseRegisterInfo *
TRI,
272 SmallVectorImpl<AESFixupLocation> &FixupLocsForFn)
const {
273 unsigned MaxAllowedFixups = 0;
275 for (MachineBasicBlock &
MBB : MF) {
276 for (MachineInstr &
MI :
MBB) {
277 if (!isFirstAESPairInstr(
MI))
282 assert(
MI.getNumExplicitOperands() == 3 &&
MI.getNumExplicitDefs() == 1 &&
283 "Unknown AES Instruction Format. Expected 1 def, 2 uses.");
287 MaxAllowedFixups += 2;
290 for (MachineOperand &MOp :
MI.uses()) {
291 SmallPtrSet<MachineInstr *, 1> AllDefs{};
295 AESFixupLocation NewLoc{&
MBB, &
MI, &MOp};
299 bool IsLiveIn = MF.front().isLiveIn(MOp.getReg());
304 if (!IsLiveIn && AllDefs.
size() == 0) {
306 <<
"Fixup Planned: No Defining Instrs found, not live-in: "
312 auto IsUnsafe = [](MachineInstr *
MI) ->
bool {
313 return !isSafeAESInput(*
MI);
318 if (UnsafeCount == 0) {
330 <<
"Fixup Planned: Live-In (with safe defining instrs): "
332 NewLoc.Block = &MF.front();
333 NewLoc.InsertionPt = &*NewLoc.Block->begin();
334 LLVM_DEBUG(
dbgs() <<
"Moving Fixup for Live-In to immediately before "
335 << *NewLoc.InsertionPt);
346 if (IsLiveIn || UnsafeCount > 1) {
347 LLVM_DEBUG(
dbgs() <<
"Fixup Planned: Multiple unsafe defining instrs "
348 "(including live-ins): "
354 assert(UnsafeCount == 1 && !IsLiveIn &&
355 "At this point, there should be one unsafe defining instrs "
356 "and the defined register should not be a live-in.");
357 SmallPtrSetIterator<MachineInstr *> It =
360 "UnsafeCount == 1 but No Unsafe MachineInstr found.");
361 MachineInstr *
DefMI = *It;
364 dbgs() <<
"Fixup Planned: Found single unsafe defining instrs for "
376 <<
"And immediately before " << *DefIt);
377 NewLoc.Block = DefIt->getParent();
378 NewLoc.InsertionPt = &*DefIt;
386 assert(FixupLocsForFn.
size() <= MaxAllowedFixups &&
387 "Inserted too many fixups for this function.");
388 (void)MaxAllowedFixups;
391void ARMFixCortexA57AES1742098::insertAESFixup(
392 AESFixupLocation &FixupLoc,
const ARMBaseInstrInfo *
TII,
393 const ARMBaseRegisterInfo *
TRI)
const {
394 MachineOperand *OperandToFixup = FixupLoc.MOp;
396 assert(OperandToFixup->
isReg() &&
"OperandToFixup must be a register");
400 <<
" before: " << *FixupLoc.InsertionPt);
414 TII->get(ARM::VORRq))
425 return new ARMFixCortexA57AES1742098();
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefAnalysis & RDA
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()
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.