36 #define DEBUG_TYPE "systemz-elim-compare" 38 STATISTIC(BranchOnCounts,
"Number of branch-on-count instructions");
39 STATISTIC(LoadAndTraps,
"Number of load-and-trap instructions");
40 STATISTIC(EliminatedComparisons,
"Number of eliminated comparisons");
41 STATISTIC(FusedComparisons,
"Number of fused compare-and-branch instructions");
48 Reference() =
default;
50 Reference &
operator|=(
const Reference &Other) {
56 explicit operator bool()
const {
return Def ||
Use; }
72 return "SystemZ Comparison Elimination";
93 unsigned ConvOpc = 0);
110 if ((*SI)->isLiveIn(SystemZ::CC))
153 if (
unsigned MOReg = MO.
getReg()) {
154 if (
TRI->regsOverlap(MOReg, Reg)) {
171 return (MI.
getOpcode() == SystemZ::LTEBR ||
193 bool SystemZElimCompare::convertToBRCT(
199 if (Opcode == SystemZ::AHI)
200 BRCT = SystemZ::BRCT;
201 else if (Opcode == SystemZ::AGHI)
202 BRCT = SystemZ::BRCTG;
203 else if (Opcode == SystemZ::AIH)
204 BRCT = SystemZ::BRCTH;
211 if (CCUsers.
size() != 1)
214 if (Branch->
getOpcode() != SystemZ::BRC ||
224 for (++MBBI; MBBI != MBBE; ++MBBI)
225 if (getRegReferences(*MBBI, SrcReg))
238 if (BRCT != SystemZ::BRCTH)
247 bool SystemZElimCompare::convertToLoadAndTrap(
250 unsigned LATOpcode =
TII->getLoadAndTrap(MI.
getOpcode());
255 if (CCUsers.
size() != 1)
258 if (Branch->
getOpcode() != SystemZ::CondTrap ||
268 for (++MBBI; MBBI != MBBE; ++MBBI)
269 if (getRegReferences(*MBBI, SrcReg))
287 bool SystemZElimCompare::convertToLoadAndTest(
293 if (!Opcode || !adjustCCMasksForInstr(MI, Compare, CCUsers, Opcode))
298 for (
const auto &MO : MI.
operands())
312 bool SystemZElimCompare::adjustCCMasksForInstr(
316 int Opcode = (ConvOpc ? ConvOpc : MI.
getOpcode());
318 unsigned MIFlags = Desc.
TSFlags;
328 if (ReusableCCMask == 0)
332 assert((ReusableCCMask & ~CCValues) == 0 &&
"Invalid CCValues");
334 bool MIEquivalentToCmp =
335 (ReusableCCMask == CCValues &&
338 if (!MIEquivalentToCmp) {
341 for (
unsigned int I = 0,
E = CCUsers.
size();
I !=
E; ++
I) {
359 unsigned OutValid = ~ReusableCCMask & CCValid;
360 unsigned OutMask = ~ReusableCCMask & CCMask;
361 if (OutMask != 0 && OutMask != OutValid)
369 for (
unsigned I = 0,
E = AlterMasks.
size();
I !=
E;
I += 2) {
370 AlterMasks[
I]->setImm(CCValues);
371 unsigned CCMask = AlterMasks[
I + 1]->getImm();
372 if (CCMask & ~ReusableCCMask)
373 AlterMasks[
I + 1]->setImm((CCMask & ReusableCCMask) |
374 (CCValues & ~ReusableCCMask));
381 assert(CCDef >= 0 &&
"Couldn't find CC set");
386 bool BeforeCmp =
false;
388 for (++MBBI; MBBI != MBBE; ++MBBI)
389 if (MBBI == Compare) {
397 for (++MBBI; MBBI != MBBE; ++MBBI)
398 MBBI->clearRegisterKills(SystemZ::CC,
TRI);
407 case SystemZ::LTEBRCompare:
408 case SystemZ::LTDBRCompare:
409 case SystemZ::LTXBRCompare:
424 bool SystemZElimCompare::optimizeCompareZero(
436 MBBE = MBB.
rend(); MBBI != MBBE;) {
442 if (!CCRefs.Use && !SrcRefs) {
443 if (convertToBRCT(MI, Compare, CCUsers)) {
447 if (convertToLoadAndTrap(MI, Compare, CCUsers)) {
453 if ((!CCRefs && convertToLoadAndTest(MI, Compare, CCUsers)) ||
454 (!CCRefs.Def && adjustCCMasksForInstr(MI, Compare, CCUsers))) {
455 EliminatedComparisons += 1;
459 SrcRefs |= getRegReferences(MI, SrcReg);
462 CCRefs |= getRegReferences(MI, SystemZ::CC);
463 if (CCRefs.Use && CCRefs.Def)
476 if (convertToLoadAndTest(MI, Compare, CCUsers)) {
477 EliminatedComparisons += 1;
481 if (getRegReferences(MI, SrcReg).Def)
483 if (getRegReferences(MI, SystemZ::CC))
492 bool SystemZElimCompare::fuseCompareOperations(
495 if (CCUsers.
size() != 1)
503 case SystemZ::CondReturn:
506 case SystemZ::CallBCR:
509 case SystemZ::CondTrap:
517 unsigned FusedOpcode =
530 for (++MBBI; MBBI != MBBE; ++MBBI)
531 if (MBBI->modifiesRegister(SrcReg,
TRI) ||
532 (SrcReg2 && MBBI->modifiesRegister(SrcReg2,
TRI)))
538 "Invalid condition-code mask for integer comparison");
544 RegMask = MBBI->getOperand(2).getRegMask();
547 int CCUse = MBBI->findRegisterUseOperandIdx(SystemZ::CC,
false,
TRI);
548 assert(CCUse >= 0 &&
"BRC/BCR must use CC");
560 unsigned SrcNOps = 2;
561 if (FusedOpcode == SystemZ::CLT || FusedOpcode == SystemZ::CLGT)
565 for (
unsigned I = 0;
I < SrcNOps;
I++)
582 for (++MBBI; MBBI != MBBE; ++MBBI) {
583 MBBI->clearRegisterKills(SrcReg,
TRI);
585 MBBI->clearRegisterKills(SrcReg2,
TRI);
587 FusedComparisons += 1;
594 bool Changed =
false;
602 while (MBBI != MBB.
begin()) {
605 (optimizeCompareZero(MI, CCUsers) ||
606 fuseCompareOperations(MI, CCUsers))) {
616 CompleteCCUsers =
true;
629 TRI = &
TII->getRegisterInfo();
631 bool Changed =
false;
633 Changed |= processBlock(MBB);
639 return new SystemZElimCompare(TM);
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand *> MMOs) const
const MachineInstrBuilder & add(const MachineOperand &MO) const
This class represents lattice values for constants.
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
static bool resultTests(MachineInstr &MI, unsigned Reg)
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
void setIsDead(bool Val=true)
iterator_range< mop_iterator > operands()
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const unsigned CCMASK_ICMP
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
A Use represents the edge between a Value definition and its users.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
The access may reference the value stored in memory.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
static bool isCompareZero(MachineInstr &Compare)
virtual const TargetInstrInfo * getInstrInfo() const
bool operator|=(SparseBitVector< ElementSize > &LHS, const SparseBitVector< ElementSize > *RHS)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
static bool isCCLiveOut(MachineBasicBlock &MBB)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
The instances of the Type class are immutable: once they are created, they are never changed...
bool isCompare(QueryType Type=IgnoreBundle) const
Return true if this instruction is a comparison.
static bool preservesValueOf(MachineInstr &MI, unsigned Reg)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
FunctionPass class - This class is used to implement most global optimizations.
bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr fully defines the specified register.
succ_iterator succ_begin()
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
static unsigned getCompareZeroCCMask(unsigned int Flags)
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
const unsigned CCMASK_CMP_EQ
const unsigned CCMASK_CMP_NE
const Function & getFunction() const
Return the LLVM function that this machine code represents.
Target - Wrapper for Target specific information.
int findRegisterDefOperandIdx(unsigned Reg, bool isDead=false, bool Overlap=false, const TargetRegisterInfo *TRI=nullptr) const
Returns the operand index that is a def of the specified register or -1 if it is not found...
bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
const MachineBasicBlock * getParent() const
MachineFunctionProperties & set(Property P)
static unsigned getCompareSourceReg(MachineInstr &Compare)
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
static unsigned getCCValues(unsigned int Flags)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
FunctionPass * createSystemZElimComparePass(SystemZTargetMachine &TM)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
void RemoveOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
static bool isLoadAndTestAsCmp(MachineInstr &MI)
const MachineOperand & getOperand(unsigned i) const
Properties which a MachineFunction may have at a given point in time.