cl::desc("Disable the peephole optimizer"));
static cl::opt<bool>
-DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(true),
+DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(false),
cl::desc("Disable advanced copy optimization"));
STATISTIC(NumReuse, "Number of extension results reused");
namespace {
class PeepholeOptimizer : public MachineFunctionPass {
- const TargetMachine *TM;
+ MachineFunction *MF;
const TargetInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
MachineRegisterInfo *MRI;
MachineDominatorTree *DT; // Machine dominator tree
/// \brief Check whether \p MI is a copy like instruction that is
/// not recognized by the register coalescer.
bool isUncoalescableCopy(const MachineInstr &MI) {
- return MI.isBitcast() || (!DisableAdvCopyOpt &&
- MI.isRegSequenceLike());
+ return MI.isBitcast() ||
+ (!DisableAdvCopyOpt &&
+ (MI.isRegSequenceLike() || MI.isInsertSubregLike() ||
+ MI.isExtractSubregLike()));
}
};
// Ensure DstReg can get a register class that actually supports
// sub-registers. Don't change the class until we commit.
const TargetRegisterClass *DstRC = MRI->getRegClass(DstReg);
- DstRC = TM->getSubtargetImpl()->getRegisterInfo()->getSubClassWithSubReg(
- DstRC, SubIdx);
+ DstRC = TRI->getSubClassWithSubReg(DstRC, SubIdx);
if (!DstRC)
return false;
// If UseSrcSubIdx is Set, SubIdx also applies to SrcReg, and only uses of
// SrcReg:SubIdx should be replaced.
bool UseSrcSubIdx =
- TM->getSubtargetImpl()->getRegisterInfo()->getSubClassWithSubReg(
- MRI->getRegClass(SrcReg), SubIdx) != nullptr;
+ TRI->getSubClassWithSubReg(MRI->getRegClass(SrcReg), SubIdx) != nullptr;
// The source has other uses. See if we can replace the other uses with use of
// the result of the extension.
unsigned Src;
unsigned SrcSubReg;
bool ShouldRewrite = false;
- const TargetRegisterInfo &TRI = *TM->getSubtargetImpl()->getRegisterInfo();
// Follow the chain of copies until we reach the top of the use-def chain
// or find a more suitable source.
const TargetRegisterClass *SrcRC = MRI->getRegClass(Src);
// If this source does not incur a cross register bank copy, use it.
- ShouldRewrite = shareSameRegisterFile(TRI, DefRC, DefSubReg, SrcRC,
+ ShouldRewrite = shareSameRegisterFile(*TRI, DefRC, DefSubReg, SrcRC,
SrcSubReg);
} while (!ShouldRewrite);
if (!findNextSource(NewSrc, NewSubReg) || SrcReg == NewSrc)
continue;
// Rewrite source.
- Changed |= CpyRewriter->RewriteCurrentSource(NewSrc, NewSubReg);
+ if (CpyRewriter->RewriteCurrentSource(NewSrc, NewSubReg)) {
+ // We may have extended the live-range of NewSrc, account for that.
+ MRI->clearKillFlags(NewSrc);
+ Changed = true;
+ }
}
// TODO: We could have a clean-up method to tidy the instruction.
// E.g., v0 = INSERT_SUBREG v1, v1.sub0, sub0
return false;
}
-bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
- if (skipOptnoneFunction(*MF.getFunction()))
+bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &mf) {
+ if (skipOptnoneFunction(*mf.getFunction()))
return false;
DEBUG(dbgs() << "********** PEEPHOLE OPTIMIZER **********\n");
- DEBUG(dbgs() << "********** Function: " << MF.getName() << '\n');
+ DEBUG(dbgs() << "********** Function: " << mf.getName() << '\n');
if (DisablePeephole)
return false;
- TM = &MF.getTarget();
- TII = TM->getSubtargetImpl()->getInstrInfo();
- MRI = &MF.getRegInfo();
+ MF = &mf;
+ TII = MF->getSubtarget().getInstrInfo();
+ TRI = MF->getSubtarget().getRegisterInfo();
+ MRI = &MF->getRegInfo();
DT = Aggressive ? &getAnalysis<MachineDominatorTree>() : nullptr;
bool Changed = false;
- for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
+ for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) {
MachineBasicBlock *MBB = &*I;
bool SeenMoveImm = false;
return false;
}
-/// Extract the inputs from INSERT_SUBREG.
-/// INSERT_SUBREG vreg0:sub0, vreg1:sub1, sub3 would produce:
-/// - BaseReg: vreg0:sub0
-/// - InsertedReg: vreg1:sub1, sub3
-static void
-getInsertSubregInputs(const MachineInstr &MI,
- TargetInstrInfo::RegSubRegPair &BaseReg,
- TargetInstrInfo::RegSubRegPairAndIdx &InsertedReg) {
- assert(MI.isInsertSubreg() && "Instruction do not have the proper type");
-
- // We are looking at:
- // Def = INSERT_SUBREG v0, v1, sub0.
- const MachineOperand &MOBaseReg = MI.getOperand(1);
- const MachineOperand &MOInsertedReg = MI.getOperand(2);
- const MachineOperand &MOSubIdx = MI.getOperand(3);
- assert(MOSubIdx.isImm() &&
- "One of the subindex of the reg_sequence is not an immediate");
- BaseReg.Reg = MOBaseReg.getReg();
- BaseReg.SubReg = MOBaseReg.getSubReg();
-
- InsertedReg.Reg = MOInsertedReg.getReg();
- InsertedReg.SubReg = MOInsertedReg.getSubReg();
- InsertedReg.SubIdx = (unsigned)MOSubIdx.getImm();
-}
-
bool ValueTracker::getNextSourceFromInsertSubreg(unsigned &SrcReg,
unsigned &SrcSubReg) {
- assert(Def->isInsertSubreg() && "Invalid definition");
+ assert((Def->isInsertSubreg() || Def->isInsertSubregLike()) &&
+ "Invalid definition");
+
if (Def->getOperand(DefIdx).getSubReg())
// If we are composing subreg, bails out.
// Same remark as getNextSourceFromRegSequence.
// I.e., this may be turned into an assert.
return false;
+ if (!TII)
+ // We could handle the REG_SEQUENCE here, but we do not want to
+ // duplicate the code from the generic TII.
+ return false;
+
TargetInstrInfo::RegSubRegPair BaseReg;
TargetInstrInfo::RegSubRegPairAndIdx InsertedReg;
- assert(DefIdx == 0 && "Invalid definition");
- getInsertSubregInputs(*Def, BaseReg, InsertedReg);
+ if (!TII->getInsertSubregInputs(*Def, DefIdx, BaseReg, InsertedReg))
+ return false;
// We are looking at:
// Def = INSERT_SUBREG v0, v1, sub1
return true;
}
-/// Extract the inputs from EXTRACT_SUBREG.
-/// EXTRACT_SUBREG vreg1:sub1, sub0, would produce:
-/// - vreg1:sub1, sub0
-static void
-getExtractSubregInputs(const MachineInstr &MI,
- TargetInstrInfo::RegSubRegPairAndIdx &InputReg) {
- assert(MI.isExtractSubreg() && "Instruction do not have the proper type");
- // We are looking at:
- // Def = EXTRACT_SUBREG v0.sub1, sub0.
- const MachineOperand &MOReg = MI.getOperand(1);
- const MachineOperand &MOSubIdx = MI.getOperand(2);
- assert(MOSubIdx.isImm() &&
- "The subindex of the extract_subreg is not an immediate");
-
- InputReg.Reg = MOReg.getReg();
- InputReg.SubReg = MOReg.getSubReg();
- InputReg.SubIdx = (unsigned)MOSubIdx.getImm();
-}
-
bool ValueTracker::getNextSourceFromExtractSubreg(unsigned &SrcReg,
unsigned &SrcSubReg) {
- assert(Def->isExtractSubreg() && "Invalid definition");
+ assert((Def->isExtractSubreg() ||
+ Def->isExtractSubregLike()) && "Invalid definition");
// We are looking at:
// Def = EXTRACT_SUBREG v0, sub0
if (DefSubReg)
return false;
+ if (!TII)
+ // We could handle the EXTRACT_SUBREG here, but we do not want to
+ // duplicate the code from the generic TII.
+ return false;
+
TargetInstrInfo::RegSubRegPairAndIdx ExtractSubregInputReg;
- assert(DefIdx == 0 && "Invalid definition");
- getExtractSubregInputs(*Def, ExtractSubregInputReg);
+ if (!TII->getExtractSubregInputs(*Def, DefIdx, ExtractSubregInputReg))
+ return false;
// Bails if we have to compose sub registers.
// Likewise, if v0.subreg != 0, we would have to compose v0.subreg with sub0.
return false;
if (Def->isRegSequence() || Def->isRegSequenceLike())
return getNextSourceFromRegSequence(SrcReg, SrcSubReg);
- if (Def->isInsertSubreg())
+ if (Def->isInsertSubreg() || Def->isInsertSubregLike())
return getNextSourceFromInsertSubreg(SrcReg, SrcSubReg);
- if (Def->isExtractSubreg())
+ if (Def->isExtractSubreg() || Def->isExtractSubregLike())
return getNextSourceFromExtractSubreg(SrcReg, SrcSubReg);
if (Def->isSubregToReg())
return getNextSourceFromSubregToReg(SrcReg, SrcSubReg);