Go to the documentation of this file.
64 #define DEBUG_TYPE "aarch64-copyelim"
66 STATISTIC(NumCopiesRemoved,
"Number of copies removed.");
103 return "AArch64 Redundant Copy Elimination";
110 "AArch64 redundant copy elimination pass",
false,
false)
124 bool AArch64RedundantCopyElimination::knownRegValInBlock(
127 unsigned Opc = CondBr.getOpcode();
131 if (((Opc == AArch64::CBZW || Opc == AArch64::CBZX) &&
132 MBB == CondBr.getOperand(1).getMBB()) ||
133 ((Opc == AArch64::CBNZW || Opc == AArch64::CBNZX) &&
134 MBB != CondBr.getOperand(1).getMBB())) {
136 KnownRegs.push_back(
RegImm(CondBr.getOperand(0).getReg(), 0));
141 if (Opc != AArch64::Bcc)
157 "Conditional branch not in predecessor block!");
158 if (CondBr == PredMBB->
begin())
163 DomBBClobberedRegs.
clear();
164 DomBBUsedRegs.
clear();
171 switch (PredI.getOpcode()) {
176 case AArch64::ADDSWri:
177 case AArch64::ADDSXri:
181 case AArch64::SUBSWri:
182 case AArch64::SUBSXri: {
184 if (!PredI.getOperand(1).isReg())
186 MCPhysReg DstReg = PredI.getOperand(0).getReg();
187 MCPhysReg SrcReg = PredI.getOperand(1).getReg();
194 if (PredI.getOperand(2).isImm() && DomBBClobberedRegs.
available(SrcReg) &&
197 int32_t KnownImm = PredI.getOperand(2).getImm();
198 int32_t
Shift = PredI.getOperand(3).getImm();
201 KnownImm = -KnownImm;
203 KnownRegs.push_back(
RegImm(SrcReg, KnownImm));
209 if (DstReg == AArch64::WZR || DstReg == AArch64::XZR)
214 if (!DomBBClobberedRegs.
available(DstReg))
218 KnownRegs.push_back(
RegImm(DstReg, 0));
224 case AArch64::ADCSWr:
225 case AArch64::ADCSXr:
226 case AArch64::ADDSWrr:
227 case AArch64::ADDSWrs:
228 case AArch64::ADDSWrx:
229 case AArch64::ADDSXrr:
230 case AArch64::ADDSXrs:
231 case AArch64::ADDSXrx:
232 case AArch64::ADDSXrx64:
233 case AArch64::ANDSWri:
234 case AArch64::ANDSWrr:
235 case AArch64::ANDSWrs:
236 case AArch64::ANDSXri:
237 case AArch64::ANDSXrr:
238 case AArch64::ANDSXrs:
239 case AArch64::BICSWrr:
240 case AArch64::BICSWrs:
241 case AArch64::BICSXrs:
242 case AArch64::BICSXrr:
243 case AArch64::SBCSWr:
244 case AArch64::SBCSXr:
245 case AArch64::SUBSWrr:
246 case AArch64::SUBSWrs:
247 case AArch64::SUBSWrx:
248 case AArch64::SUBSXrr:
249 case AArch64::SUBSXrs:
250 case AArch64::SUBSXrx:
251 case AArch64::SUBSXrx64: {
252 MCPhysReg DstReg = PredI.getOperand(0).getReg();
253 if (DstReg == AArch64::WZR || DstReg == AArch64::XZR)
258 if (!DomBBClobberedRegs.
available(DstReg))
263 KnownRegs.push_back(
RegImm(DstReg, 0));
269 if (PredI.definesRegister(AArch64::NZCV))
291 if (CondBr == PredMBB->
end())
302 bool SeenFirstUse =
false;
310 if (!knownRegValInBlock(*Itr,
MBB, KnownRegs, FirstUse))
314 OptBBClobberedRegs.
clear();
315 OptBBUsedRegs.
clear();
319 for (
auto PredI = Itr;; --PredI) {
320 if (FirstUse == PredI)
323 if (PredI->isCopy()) {
324 MCPhysReg CopyDstReg = PredI->getOperand(0).getReg();
325 MCPhysReg CopySrcReg = PredI->getOperand(1).getReg();
326 for (
auto &KnownReg : KnownRegs) {
327 if (!OptBBClobberedRegs.
available(KnownReg.Reg))
331 if (CopySrcReg == KnownReg.Reg &&
332 OptBBClobberedRegs.
available(CopyDstReg)) {
333 KnownRegs.push_back(
RegImm(CopyDstReg, KnownReg.Imm));
340 if (CopyDstReg == KnownReg.Reg &&
341 OptBBClobberedRegs.
available(CopySrcReg)) {
342 KnownRegs.push_back(
RegImm(CopySrcReg, KnownReg.Imm));
351 if (PredI == PredMBB->
begin())
358 return !OptBBClobberedRegs.
available(KnownReg.Reg);
364 }
while (Itr != PredMBB->
begin() && Itr->isTerminator());
367 if (KnownRegs.empty())
370 bool Changed =
false;
378 bool RemovedMI =
false;
379 bool IsCopy =
MI->isCopy();
380 bool IsMoveImm =
MI->isMoveImmediate();
381 if (IsCopy || IsMoveImm) {
384 int64_t SrcImm = IsMoveImm ?
MI->getOperand(1).getImm() : 0;
386 ((IsCopy && (SrcReg == AArch64::XZR || SrcReg == AArch64::WZR)) ||
388 for (
RegImm &KnownReg : KnownRegs) {
389 if (KnownReg.Reg != DefReg &&
394 if (IsCopy && KnownReg.Imm != 0)
400 if (KnownReg.Imm != SrcImm)
407 return !O.isDead() && O.isReg() && O.isDef() &&
408 O.getReg() != CmpReg;
423 MI->eraseFromParent();
427 UsedKnownRegs.
insert(KnownReg.Reg);
439 for (
unsigned RI = 0; RI < KnownRegs.size();)
440 if (
MI->modifiesRegister(KnownRegs[RI].Reg,
TRI)) {
441 std::swap(KnownRegs[RI], KnownRegs[KnownRegs.size() - 1]);
442 KnownRegs.pop_back();
450 if (KnownRegs.empty())
465 LLVM_DEBUG(
dbgs() <<
"Clearing kill flags.\n\tFirstUse: " << *FirstUse
466 <<
"\tLastChange: " << *LastChange);
475 bool AArch64RedundantCopyElimination::runOnMachineFunction(
489 bool Changed =
false;
496 return new AArch64RedundantCopyElimination();
unsigned succ_size() const
pred_iterator pred_begin()
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static void accumulateUsedDefed(const MachineInstr &MI, LiveRegUnits &ModifiedRegUnits, LiveRegUnits &UsedRegUnits, const TargetRegisterInfo *TRI)
For a machine instruction MI, adds all register units used in UsedRegUnits and defined or clobbered i...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Reg
All possible values of the reg field in the ModR/M byte.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
bool available(MCPhysReg Reg) const
Returns true if no part of physical register Reg is live.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Properties which a MachineFunction may have at a given point in time.
unsigned const TargetRegisterInfo * TRI
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned pred_size() const
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
MachineOperand class - Representation of each machine instruction operand.
MachineFunctionProperties & set(Property P)
INITIALIZE_PASS(AArch64RedundantCopyElimination, "aarch64-copyelim", "AArch64 redundant copy elimination pass", false, false) bool AArch64RedundantCopyElimination
It's possible to determine the value of a register based on a dominating condition.
STATISTIC(NumFunctions, "Total number of functions")
A set of register units used to track register liveness.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
FunctionPass * createAArch64RedundantCopyEliminationPass()
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void init(const TargetRegisterInfo &TRI)
Initialize and clear the set.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
StringRef - Represent a constant reference to a string, i.e.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
void initializeAArch64RedundantCopyEliminationPass(PassRegistry &)
Function & getFunction()
Return the LLVM function that this machine code represents.
static bool optimizeBlock(BasicBlock &BB, bool &ModifiedDT, const TargetTransformInfo &TTI, const DataLayout &DL, DomTreeUpdater *DTU)
bool isSuperRegister(MCRegister RegA, MCRegister RegB) const
Returns true if RegB is a super-register of RegA.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
A SetVector that performs no allocations if smaller than a certain size.
void clear()
Clears the set.
FunctionPass class - This class is used to implement most global optimizations.