65#define DEBUG_TYPE "arm-fix-cortex-a57-aes-1742098"
81 MachineFunctionProperties::Property::NoVRegs);
85 return "ARM fix for Cortex-A57 AES Erratum 1742098";
96 struct AESFixupLocation {
113char ARMFixCortexA57AES1742098::ID = 0;
118 "ARM fix for Cortex-A57 AES Erratum 1742098",
false,
126bool ARMFixCortexA57AES1742098::isFirstAESPairInstr(
MachineInstr &
MI) {
127 unsigned Opc =
MI.getOpcode();
128 return Opc == ARM::AESD || Opc == ARM::AESE;
133 int CCIdx =
MI.findFirstPredOperandIdx();
136 return MI.getOperand(CCIdx).getImm() == (int64_t)
ARMCC::AL;
139 switch (
MI.getOpcode()) {
178 case ARM::VLDMDDB_UPD:
179 case ARM::VLDMDIA_UPD:
212 case ARM::VLD1LNd32_UPD:
214 case ARM::VLD1LNd8_UPD:
216 case ARM::VLD1LNd16_UPD:
218 case ARM::VLD1DUPd32:
219 case ARM::VLD1DUPd32wb_fixed:
220 case ARM::VLD1DUPd32wb_register:
221 case ARM::VLD1DUPd16:
222 case ARM::VLD1DUPd16wb_fixed:
223 case ARM::VLD1DUPd16wb_register:
225 case ARM::VLD1DUPd8wb_fixed:
226 case ARM::VLD1DUPd8wb_register:
227 case ARM::VLD1DUPq32:
228 case ARM::VLD1DUPq32wb_fixed:
229 case ARM::VLD1DUPq32wb_register:
230 case ARM::VLD1DUPq16:
231 case ARM::VLD1DUPq16wb_fixed:
232 case ARM::VLD1DUPq16wb_register:
234 case ARM::VLD1DUPq8wb_fixed:
235 case ARM::VLD1DUPq8wb_register:
240 return CondCodeIsAL(
MI);
251 if (!STI.hasAES() || !STI.fixCortexA57AES1742098())
257 auto &
RDA = getAnalysis<ReachingDefAnalysis>();
261 analyzeMF(
F,
RDA,
TRI, FixupLocsForFn);
264 bool Changed =
false;
265 LLVM_DEBUG(
dbgs() <<
"Inserting " << FixupLocsForFn.size() <<
" fixup(s)\n");
266 for (AESFixupLocation &FixupLoc : FixupLocsForFn) {
267 insertAESFixup(FixupLoc,
TII,
TRI);
274void ARMFixCortexA57AES1742098::analyzeMF(
278 unsigned MaxAllowedFixups = 0;
282 if (!isFirstAESPairInstr(
MI))
287 assert(
MI.getNumExplicitOperands() == 3 &&
MI.getNumExplicitDefs() == 1 &&
288 "Unknown AES Instruction Format. Expected 1 def, 2 uses.");
292 MaxAllowedFixups += 2;
300 AESFixupLocation NewLoc{&
MBB, &
MI, &MOp};
304 bool IsLiveIn = MF.front().isLiveIn(MOp.getReg());
309 if (!IsLiveIn && AllDefs.size() == 0) {
311 <<
"Fixup Planned: No Defining Instrs found, not live-in: "
318 return !isSafeAESInput(*
MI);
323 if (UnsafeCount == 0) {
335 <<
"Fixup Planned: Live-In (with safe defining instrs): "
337 NewLoc.Block = &MF.front();
338 NewLoc.InsertionPt = &*NewLoc.Block->begin();
339 LLVM_DEBUG(
dbgs() <<
"Moving Fixup for Live-In to immediately before "
340 << *NewLoc.InsertionPt);
351 if (IsLiveIn || UnsafeCount > 1) {
352 LLVM_DEBUG(
dbgs() <<
"Fixup Planned: Multiple unsafe defining instrs "
353 "(including live-ins): "
359 assert(UnsafeCount == 1 && !IsLiveIn &&
360 "At this point, there should be one unsafe defining instrs "
361 "and the defined register should not be a live-in.");
364 assert(It != AllDefs.end() &&
365 "UnsafeCount == 1 but No Unsafe MachineInstr found.");
369 dbgs() <<
"Fixup Planned: Found single unsafe defining instrs for "
381 <<
"And immediately before " << *DefIt);
382 NewLoc.Block = DefIt->getParent();
383 NewLoc.InsertionPt = &*DefIt;
391 assert(FixupLocsForFn.
size() <= MaxAllowedFixups &&
392 "Inserted too many fixups for this function.");
393 (void)MaxAllowedFixups;
396void ARMFixCortexA57AES1742098::insertAESFixup(
401 assert(OperandToFixup->
isReg() &&
"OperandToFixup must be a register");
405 <<
" before: " << *FixupLoc.InsertionPt);
419 TII->get(ARM::VORRq))
430 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.