66#define DEBUG_TYPE "arm-fix-cortex-a57-aes-1742098"
82 MachineFunctionProperties::Property::NoVRegs);
86 return "ARM fix for Cortex-A57 AES Erratum 1742098";
97 struct AESFixupLocation {
114char ARMFixCortexA57AES1742098::ID = 0;
119 "ARM fix for Cortex-A57 AES Erratum 1742098",
false,
127bool ARMFixCortexA57AES1742098::isFirstAESPairInstr(
MachineInstr &
MI) {
128 unsigned Opc =
MI.getOpcode();
129 return Opc == ARM::AESD || Opc == ARM::AESE;
134 int CCIdx =
MI.findFirstPredOperandIdx();
137 return MI.getOperand(CCIdx).getImm() == (int64_t)
ARMCC::AL;
140 switch (
MI.getOpcode()) {
179 case ARM::VLDMDDB_UPD:
180 case ARM::VLDMDIA_UPD:
213 case ARM::VLD1LNd32_UPD:
215 case ARM::VLD1LNd8_UPD:
217 case ARM::VLD1LNd16_UPD:
219 case ARM::VLD1DUPd32:
220 case ARM::VLD1DUPd32wb_fixed:
221 case ARM::VLD1DUPd32wb_register:
222 case ARM::VLD1DUPd16:
223 case ARM::VLD1DUPd16wb_fixed:
224 case ARM::VLD1DUPd16wb_register:
226 case ARM::VLD1DUPd8wb_fixed:
227 case ARM::VLD1DUPd8wb_register:
228 case ARM::VLD1DUPq32:
229 case ARM::VLD1DUPq32wb_fixed:
230 case ARM::VLD1DUPq32wb_register:
231 case ARM::VLD1DUPq16:
232 case ARM::VLD1DUPq16wb_fixed:
233 case ARM::VLD1DUPq16wb_register:
235 case ARM::VLD1DUPq8wb_fixed:
236 case ARM::VLD1DUPq8wb_register:
241 return CondCodeIsAL(
MI);
252 if (!STI.hasAES() || !STI.fixCortexA57AES1742098())
258 auto &
RDA = getAnalysis<ReachingDefAnalysis>();
262 analyzeMF(
F,
RDA,
TRI, FixupLocsForFn);
265 bool Changed =
false;
266 LLVM_DEBUG(
dbgs() <<
"Inserting " << FixupLocsForFn.size() <<
" fixup(s)\n");
267 for (AESFixupLocation &FixupLoc : FixupLocsForFn) {
268 insertAESFixup(FixupLoc,
TII,
TRI);
275void ARMFixCortexA57AES1742098::analyzeMF(
279 unsigned MaxAllowedFixups = 0;
283 if (!isFirstAESPairInstr(
MI))
288 assert(
MI.getNumExplicitOperands() == 3 &&
MI.getNumExplicitDefs() == 1 &&
289 "Unknown AES Instruction Format. Expected 1 def, 2 uses.");
293 MaxAllowedFixups += 2;
301 AESFixupLocation NewLoc{&
MBB, &
MI, &MOp};
305 bool IsLiveIn = MF.front().isLiveIn(MOp.getReg());
310 if (!IsLiveIn && AllDefs.size() == 0) {
312 <<
"Fixup Planned: No Defining Instrs found, not live-in: "
319 return !isSafeAESInput(*
MI);
324 if (UnsafeCount == 0) {
336 <<
"Fixup Planned: Live-In (with safe defining instrs): "
338 NewLoc.Block = &MF.front();
339 NewLoc.InsertionPt = &*NewLoc.Block->begin();
340 LLVM_DEBUG(
dbgs() <<
"Moving Fixup for Live-In to immediately before "
341 << *NewLoc.InsertionPt);
352 if (IsLiveIn || UnsafeCount > 1) {
353 LLVM_DEBUG(
dbgs() <<
"Fixup Planned: Multiple unsafe defining instrs "
354 "(including live-ins): "
360 assert(UnsafeCount == 1 && !IsLiveIn &&
361 "At this point, there should be one unsafe defining instrs "
362 "and the defined register should not be a live-in.");
365 assert(It != AllDefs.end() &&
366 "UnsafeCount == 1 but No Unsafe MachineInstr found.");
370 dbgs() <<
"Fixup Planned: Found single unsafe defining instrs for "
382 <<
"And immediately before " << *DefIt);
383 NewLoc.Block = DefIt->getParent();
384 NewLoc.InsertionPt = &*DefIt;
392 assert(FixupLocsForFn.
size() <= MaxAllowedFixups &&
393 "Inserted too many fixups for this function.");
394 (void)MaxAllowedFixups;
397void ARMFixCortexA57AES1742098::insertAESFixup(
402 assert(OperandToFixup->
isReg() &&
"OperandToFixup must be a register");
406 <<
" before: " << *FixupLoc.InsertionPt);
420 TII->get(ARM::VORRq))
431 return new ARMFixCortexA57AES1742098();
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
MachineInstrBuilder MachineInstrBuilder & DefMI
ReachingDefAnalysis & RDA
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
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.
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
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.
bool isRenamable() const
isRenamable - Returns true if this register may be renamed, i.e.
Register getReg() const
getReg - Returns the register number.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
This class provides the reaching def analysis.
void getGlobalReachingDefs(MachineInstr *MI, MCRegister PhysReg, InstSet &Defs) const
Collect all possible definitions of the value stored in PhysReg, which is used by MI.
Wrapper class representing virtual and physical registers.
SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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.
void initializeARMFixCortexA57AES1742098Pass(PassRegistry &)
FunctionPass * createARMFixCortexA57AES1742098Pass()
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.