//===-- AArch64A53Fix835769.cpp -------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // This pass changes code to work around Cortex-A53 erratum 835769. // It works around it by inserting a nop instruction in code sequences that // in some circumstances may trigger the erratum. // It inserts a nop instruction between a sequence of the following 2 classes // of instructions: // instr 1: mem-instr (including loads, stores and prefetches). // instr 2: non-SIMD integer multiply-accumulate writing 64-bit X registers. //===----------------------------------------------------------------------===// #include "AArch64.h" #include "AArch64Subtarget.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" usingnamespacellvm; #define DEBUG_TYPE … STATISTIC(NumNopsAdded, "Number of Nops added to work around erratum 835769"); //===----------------------------------------------------------------------===// // Helper functions // Is the instruction a match for the instruction that comes first in the // sequence of instructions that can trigger the erratum? static bool isFirstInstructionInSequence(MachineInstr *MI) { … } // Is the instruction a match for the instruction that comes second in the // sequence that can trigger the erratum? static bool isSecondInstructionInSequence(MachineInstr *MI) { … } //===----------------------------------------------------------------------===// namespace { class AArch64A53Fix835769 : public MachineFunctionPass { … }; char AArch64A53Fix835769::ID = …; } // end anonymous namespace INITIALIZE_PASS(…) //===----------------------------------------------------------------------===// bool AArch64A53Fix835769::runOnMachineFunction(MachineFunction &F) { … } // Return the block that was fallen through to get to MBB, if any, // otherwise nullptr. static MachineBasicBlock *getBBFallenThrough(MachineBasicBlock *MBB, const TargetInstrInfo *TII) { … } // Iterate through fallen through blocks trying to find a previous non-pseudo if // there is one, otherwise return nullptr. Only look for instructions in // previous blocks, not the current block, since we only use this to look at // previous blocks. static MachineInstr *getLastNonPseudo(MachineBasicBlock &MBB, const TargetInstrInfo *TII) { … } static void insertNopBeforeInstruction(MachineBasicBlock &MBB, MachineInstr* MI, const TargetInstrInfo *TII) { … } bool AArch64A53Fix835769::runOnBasicBlock(MachineBasicBlock &MBB) { … } // Factory function used by AArch64TargetMachine to add the pass to // the passmanager. FunctionPass *llvm::createAArch64A53Fix835769() { … }