// A terminator that isn't a branch can't easily be handled by this
// analysis.
- unsigned ThisCond;
- const MachineOperand *ThisTarget;
- if (!isBranch(I, ThisCond, ThisTarget))
+ if (!I->isBranch())
return true;
// Can't handle indirect branches.
- if (!ThisTarget->isMBB())
+ SystemZII::Branch Branch(getBranchInfo(I));
+ if (!Branch.Target->isMBB())
return true;
- if (ThisCond == SystemZ::CCMASK_ANY) {
+ if (Branch.CCMask == SystemZ::CCMASK_ANY) {
// Handle unconditional branches.
if (!AllowModify) {
- TBB = ThisTarget->getMBB();
+ TBB = Branch.Target->getMBB();
continue;
}
FBB = 0;
// Delete the JMP if it's equivalent to a fall-through.
- if (MBB.isLayoutSuccessor(ThisTarget->getMBB())) {
+ if (MBB.isLayoutSuccessor(Branch.Target->getMBB())) {
TBB = 0;
I->eraseFromParent();
I = MBB.end();
}
// TBB is used to indicate the unconditinal destination.
- TBB = ThisTarget->getMBB();
+ TBB = Branch.Target->getMBB();
continue;
}
if (Cond.empty()) {
// FIXME: add X86-style branch swap
FBB = TBB;
- TBB = ThisTarget->getMBB();
- Cond.push_back(MachineOperand::CreateImm(ThisCond));
+ TBB = Branch.Target->getMBB();
+ Cond.push_back(MachineOperand::CreateImm(Branch.CCMask));
continue;
}
// Only handle the case where all conditional branches branch to the same
// destination.
- if (TBB != ThisTarget->getMBB())
+ if (TBB != Branch.Target->getMBB())
return true;
// If the conditions are the same, we can leave them alone.
unsigned OldCond = Cond[0].getImm();
- if (OldCond == ThisCond)
+ if (OldCond == Branch.CCMask)
continue;
// FIXME: Try combining conditions like X86 does. Should be easy on Z!
--I;
if (I->isDebugValue())
continue;
- unsigned Cond;
- const MachineOperand *Target;
- if (!isBranch(I, Cond, Target))
+ if (!I->isBranch())
break;
- if (!Target->isMBB())
+ if (!getBranchInfo(I).Target->isMBB())
break;
// Remove the branch.
I->eraseFromParent();
return MI->getDesc().getSize();
}
-bool SystemZInstrInfo::isBranch(const MachineInstr *MI, unsigned &Cond,
- const MachineOperand *&Target) const {
+SystemZII::Branch
+SystemZInstrInfo::getBranchInfo(const MachineInstr *MI) const {
switch (MI->getOpcode()) {
case SystemZ::BR:
case SystemZ::J:
case SystemZ::JG:
- Cond = SystemZ::CCMASK_ANY;
- Target = &MI->getOperand(0);
- return true;
+ return SystemZII::Branch(SystemZ::CCMASK_ANY, &MI->getOperand(0));
case SystemZ::BRC:
case SystemZ::BRCL:
- Cond = MI->getOperand(0).getImm();
- Target = &MI->getOperand(1);
- return true;
+ return SystemZII::Branch(MI->getOperand(0).getImm(), &MI->getOperand(1));
default:
- assert(!MI->getDesc().isBranch() && "Unknown branch opcode");
- return false;
+ llvm_unreachable("Unrecognized branch opcode");
}
}
// @GOT (aka @GOTENT)
MO_GOT = (1 << 0)
};
+ // Information about a branch instruction.
+ struct Branch {
+ // CCMASK_<N> is set if the branch should be taken when CC == N.
+ unsigned CCMask;
+
+ // The target of the branch.
+ const MachineOperand *Target;
+
+ Branch(unsigned ccMask, const MachineOperand *target)
+ : CCMask(ccMask), Target(target) {}
+ };
}
class SystemZInstrInfo : public SystemZGenInstrInfo {
// values on which the instruction will branch, and set Target
// to the operand that contains the branch target. This target
// can be a register or a basic block.
- bool isBranch(const MachineInstr *MI, unsigned &Cond,
- const MachineOperand *&Target) const;
+ SystemZII::Branch getBranchInfo(const MachineInstr *MI) const;
// Get the load and store opcodes for a given register class.
void getLoadStoreOpcodes(const TargetRegisterClass *RC,
TerminatorInfo Terminator;
Terminator.Size = TII->getInstSizeInBytes(MI);
if (MI->isConditionalBranch() || MI->isUnconditionalBranch()) {
- Terminator.Branch = MI;
switch (MI->getOpcode()) {
case SystemZ::J:
// Relaxes to JG, which is 2 bytes longer.
- Terminator.TargetBlock = MI->getOperand(0).getMBB()->getNumber();
Terminator.ExtraRelaxSize = 2;
break;
case SystemZ::BRC:
- // Relaxes to BRCL, which is 2 bytes longer. Operand 0 is the
- // condition code mask.
- Terminator.TargetBlock = MI->getOperand(1).getMBB()->getNumber();
+ // Relaxes to BRCL, which is 2 bytes longer.
Terminator.ExtraRelaxSize = 2;
break;
default:
llvm_unreachable("Unrecognized branch instruction");
}
+ Terminator.Branch = MI;
+ Terminator.TargetBlock =
+ TII->getBranchInfo(MI).Target->getMBB()->getNumber();
}
return Terminator;
}