Go to the documentation of this file.
47 #define DEBUG_TYPE "aarch64-mi-peephole-opt"
63 using OpcodePair = std::pair<unsigned, unsigned>;
65 using SplitAndOpcFunc =
66 std::function<Optional<OpcodePair>(
T,
unsigned,
T &,
T &)>;
88 SplitAndOpcFunc<T> SplitAndOpc, BuildMIFunc BuildInstr);
94 bool visitADDSUB(
unsigned PosOpc,
unsigned NegOpc,
MachineInstr &
MI,
97 bool visitADDSSUBS(OpcodePair PosOpcs, OpcodePair NegOpcs,
MachineInstr &
MI,
100 template <
typename T>
108 return "AArch64 MI Peephole Optimization pass";
123 "AArch64 MI Peephole Optimization",
false,
false)
125 template <typename
T>
127 T UImm =
static_cast<T>(
Imm);
134 if (
Insn.size() == 1)
163 template <
typename T>
164 bool AArch64MIPeepholeOpt::visitAND(
177 return splitTwoPartImm<T>(
180 if (splitBitmaskImm(
Imm,
RegSize, Imm0, Imm1))
181 return std::make_pair(Opc, Opc);
198 bool AArch64MIPeepholeOpt::visitORR(
204 if (
MI.getOperand(3).getImm() != 0)
207 if (
MI.getOperand(1).getReg() != AArch64::WZR)
224 if (SrcMI->
getOpcode() <= TargetOpcode::GENERIC_OP_END)
233 MI.getOperand(0).setReg(DefReg);
241 template <
typename T>
245 if ((
Imm & 0xfff000) == 0 || (
Imm & 0xfff) == 0 ||
246 (
Imm & ~
static_cast<T>(0xffffff)) != 0)
252 if (
Insn.size() == 1)
256 Imm0 = (
Imm >> 12) & 0xfff;
261 template <
typename T>
262 bool AArch64MIPeepholeOpt::visitADDSUB(
278 return splitTwoPartImm<T>(
283 return std::make_pair(PosOpc, PosOpc);
285 return std::make_pair(NegOpc, NegOpc);
304 template <
typename T>
305 bool AArch64MIPeepholeOpt::visitADDSSUBS(
310 return splitTwoPartImm<T>(
325 if (!NZCVUsed || NZCVUsed->C || NZCVUsed->V)
362 SubregToRegMI =
nullptr;
363 if (MovMI->
getOpcode() == TargetOpcode::SUBREG_TO_REG) {
364 SubregToRegMI = MovMI;
370 if (MovMI->
getOpcode() != AArch64::MOVi32imm &&
371 MovMI->
getOpcode() != AArch64::MOVi64imm)
385 template <
typename T>
386 bool AArch64MIPeepholeOpt::splitTwoPartImm(
388 SplitAndOpcFunc<T> SplitAndOpc, BuildMIFunc BuildInstr) {
391 "Invalid RegSize for legal immediate peephole optimization");
395 if (!checkMovImmInstr(
MI, MovMI, SubregToRegMI))
407 if (
auto R = SplitAndOpc(
Imm,
RegSize, Imm0, Imm1))
408 Opcode =
R.getValue();
420 TII->getRegClass(
TII->get(Opcode.first), 0,
TRI, *MF);
422 TII->getRegClass(
TII->get(Opcode.first), 1,
TRI, *MF);
424 (Opcode.first == Opcode.second)
426 :
TII->getRegClass(
TII->get(Opcode.second), 0,
TRI, *MF);
428 (Opcode.first == Opcode.second)
429 ? FirstInstrOperandRC
430 :
TII->getRegClass(
TII->get(Opcode.second), 1,
TRI, *MF);
445 if (DstReg != NewDstReg)
449 BuildInstr(
MI, Opcode, Imm0, Imm1, SrcReg, NewTmpReg, NewDstReg);
453 if (DstReg != NewDstReg) {
455 MI.getOperand(0).setReg(DstReg);
461 ToBeRemoved.
insert(SubregToRegMI);
462 ToBeRemoved.
insert(MovMI);
474 MLI = &getAnalysis<MachineLoopInfo>();
479 bool Changed =
false;
484 switch (
MI.getOpcode()) {
487 case AArch64::ANDWrr:
488 Changed = visitAND<uint32_t>(AArch64::ANDWri,
MI, ToBeRemoved);
490 case AArch64::ANDXrr:
491 Changed = visitAND<uint64_t>(AArch64::ANDXri,
MI, ToBeRemoved);
493 case AArch64::ORRWrs:
494 Changed = visitORR(
MI, ToBeRemoved);
496 case AArch64::ADDWrr:
497 Changed = visitADDSUB<uint32_t>(AArch64::ADDWri, AArch64::SUBWri,
MI,
500 case AArch64::SUBWrr:
501 Changed = visitADDSUB<uint32_t>(AArch64::SUBWri, AArch64::ADDWri,
MI,
504 case AArch64::ADDXrr:
505 Changed = visitADDSUB<uint64_t>(AArch64::ADDXri, AArch64::SUBXri,
MI,
508 case AArch64::SUBXrr:
509 Changed = visitADDSUB<uint64_t>(AArch64::SUBXri, AArch64::ADDXri,
MI,
512 case AArch64::ADDSWrr:
513 Changed = visitADDSSUBS<uint32_t>({AArch64::ADDWri, AArch64::ADDSWri},
514 {AArch64::SUBWri, AArch64::SUBSWri},
517 case AArch64::SUBSWrr:
518 Changed = visitADDSSUBS<uint32_t>({AArch64::SUBWri, AArch64::SUBSWri},
519 {AArch64::ADDWri, AArch64::ADDSWri},
522 case AArch64::ADDSXrr:
523 Changed = visitADDSSUBS<uint64_t>({AArch64::ADDXri, AArch64::ADDSXri},
524 {AArch64::SUBXri, AArch64::SUBSXri},
527 case AArch64::SUBSXrr:
528 Changed = visitADDSSUBS<uint64_t>({AArch64::SUBXri, AArch64::SUBSXri},
529 {AArch64::ADDXri, AArch64::ADDSXri},
537 MI->eraseFromParent();
543 return new AArch64MIPeepholeOpt();
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
This is an optimization pass for GlobalISel generic memory operations.
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
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Optional< UsedNZCV > examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > *CCUseInstrs=nullptr)
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
unsigned const TargetRegisterInfo * TRI
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.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
const MachineOperand & getOperand(unsigned i) const
Represent the analysis usage information of a pass.
const HexagonInstrInfo * TII
static bool splitAddSubImm(T Imm, unsigned RegSize, T &Imm0, T &Imm1)
INITIALIZE_PASS(AArch64MIPeepholeOpt, "aarch64-mi-peephole-opt", "AArch64 MI Peephole Optimization", false, false) template< typename T > static bool splitBitmaskImm(T Imm
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
FunctionPass * createAArch64MIPeepholeOptPass()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
print Print MemDeps of function
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.
bool insert(const value_type &X)
Insert a new element into the SetVector.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
unsigned countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
StringRef - Represent a constant reference to a string, i.e.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
void initializeAArch64MIPeepholeOptPass(PassRegistry &)
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
Function & getFunction()
Return the LLVM function that this machine code represents.
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
A SetVector that performs no allocations if smaller than a certain size.
FunctionPass class - This class is used to implement most global optimizations.
AnalysisUsage & addRequired()
bool isLoopInvariant(MachineInstr &I) const
Returns true if the instruction is loop invariant.