Go to the documentation of this file.
49 #define DEBUG_TYPE "aarch64-simd-scalar"
55 cl::desc(
"Force use of AdvSIMD scalar instructions everywhere"),
58 STATISTIC(NumScalarInsnsUsed,
"Number of scalar instructions used");
59 STATISTIC(NumCopiesDeleted,
"Number of cross-class copies deleted");
60 STATISTIC(NumCopiesInserted,
"Number of cross-class copies inserted");
62 #define AARCH64_ADVSIMD_NAME "AdvSIMD Scalar Operation Optimization"
110 return AArch64::GPR64RegClass.contains(
Reg);
132 if (
MI->getOpcode() == AArch64::FMOVDXr ||
133 MI->getOpcode() == AArch64::FMOVXDr)
134 return &
MI->getOperand(1);
137 if (
MI->getOpcode() == AArch64::UMOVvi64 &&
MI->getOperand(2).getImm() == 0) {
139 return &
MI->getOperand(1);
143 if (
MI->getOpcode() == AArch64::COPY) {
144 if (
isFPR64(
MI->getOperand(0).getReg(),
MI->getOperand(0).getSubReg(),
146 isGPR64(
MI->getOperand(1).getReg(),
MI->getOperand(1).getSubReg(),
MRI))
147 return &
MI->getOperand(1);
148 if (isGPR64(
MI->getOperand(0).getReg(),
MI->getOperand(0).getSubReg(),
150 isFPR64(
MI->getOperand(1).getReg(),
MI->getOperand(1).getSubReg(),
152 SubReg =
MI->getOperand(1).getSubReg();
153 return &
MI->getOperand(1);
169 case AArch64::ADDXrr:
170 return AArch64::ADDv1i64;
171 case AArch64::SUBXrr:
172 return AArch64::SUBv1i64;
173 case AArch64::ANDXrr:
174 return AArch64::ANDv8i8;
175 case AArch64::EORXrr:
176 return AArch64::EORv8i8;
177 case AArch64::ORRXrr:
178 return AArch64::ORRv8i8;
185 unsigned Opc =
MI.getOpcode();
201 unsigned NumNewCopies = 3;
202 unsigned NumRemovableCopies = 0;
204 Register OrigSrc0 =
MI.getOperand(1).getReg();
205 Register OrigSrc1 =
MI.getOperand(2).getReg();
219 ++NumRemovableCopies;
231 ++NumRemovableCopies;
240 bool AllUsesAreCopies =
true;
247 ++NumRemovableCopies;
253 else if (
Use->getOpcode() == AArch64::INSERT_SUBREG ||
254 Use->getOpcode() == AArch64::INSvi64gpr)
257 AllUsesAreCopies =
false;
261 if (AllUsesAreCopies)
266 if (NumNewCopies <= NumRemovableCopies)
275 unsigned Dst,
unsigned Src,
bool IsKill) {
277 TII->get(AArch64::COPY), Dst)
287 void AArch64AdvSIMDScalar::transformInstruction(
MachineInstr &
MI) {
291 unsigned OldOpc =
MI.getOpcode();
293 assert(OldOpc != NewOpc &&
"transform an instruction to itself?!");
296 Register OrigSrc0 =
MI.getOperand(1).getReg();
297 Register OrigSrc1 =
MI.getOperand(2).getReg();
298 unsigned Src0 = 0, SubReg0;
299 unsigned Src1 = 0, SubReg1;
300 bool KillSrc0 =
false, KillSrc1 =
false;
310 KillSrc0 = MOSrc0->
isKill();
314 assert(MOSrc0 &&
"Can't delete copy w/o a valid original source!");
315 Def->eraseFromParent();
329 KillSrc1 = MOSrc1->
isKill();
333 assert(MOSrc1 &&
"Can't delete copy w/o a valid original source!");
334 Def->eraseFromParent();
372 MI.eraseFromParent();
374 ++NumScalarInsnsUsed;
379 bool Changed =
false;
382 transformInstruction(
MI);
391 bool Changed =
false;
402 if (processMachineBasicBlock(&
MBB))
410 return new AArch64AdvSIMDScalar();
static def_instr_iterator def_instr_end()
static cl::opt< bool > TransformAll("aarch64-simd-scalar-force-all", cl::desc("Force use of AdvSIMD scalar instructions everywhere"), cl::init(false), cl::Hidden)
This is an optimization pass for GlobalISel generic memory operations.
static use_instr_nodbg_iterator use_instr_nodbg_end()
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual const TargetInstrInfo * getInstrInfo() const
return AArch64::GPR64RegClass contains(Reg)
void setIsKill(bool Val=true)
def_instr_iterator def_instr_begin(Register RegNo) const
Reg
All possible values of the reg field in the ModR/M byte.
defusechain_iterator - This class provides iterator support for machine operands in the function that...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
static MachineOperand * getSrcFromCopy(MachineInstr *MI, const MachineRegisterInfo *MRI, unsigned &SubReg)
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
TargetInstrInfo - Interface to description of machine instruction set.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Represent the analysis usage information of a pass.
const HexagonInstrInfo * TII
MachineOperand class - Representation of each machine instruction operand.
bool hasSuperClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
STATISTIC(NumFunctions, "Total number of functions")
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
static MachineInstr * insertCopy(const TargetInstrInfo *TII, MachineInstr &MI, unsigned Dst, unsigned Src, bool IsKill)
void initializeAArch64AdvSIMDScalarPass(PassRegistry &)
initializer< Ty > init(const Ty &Val)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Register getReg() const
getReg - Returns the register number.
static bool isTransformable(const MachineInstr &MI)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
StringRef - Represent a constant reference to a string, i.e.
bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
static bool isFPR64(unsigned Reg, unsigned SubReg, const MachineRegisterInfo *MRI)
Function & getFunction()
Return the LLVM function that this machine code represents.
static bool isProfitableToTransform(const Loop &L, const BranchInst *BI)
#define AARCH64_ADVSIMD_NAME
unsigned getKillRegState(bool B)
FunctionPass * createAArch64AdvSIMDScalar()
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
INITIALIZE_PASS(AArch64AdvSIMDScalar, "aarch64-simd-scalar", AARCH64_ADVSIMD_NAME, false, false) static bool isGPR64(unsigned Reg
static unsigned getTransformOpcode(unsigned Opc)
FunctionPass class - This class is used to implement most global optimizations.
A Use represents the edge between a Value definition and its users.