using namespace llvm;
+#define DEBUG_TYPE "systemz-isel"
+
namespace {
// Used to build addressing modes.
struct SystemZAddressingMode {
errs() << "SystemZAddressingMode " << this << '\n';
errs() << " Base ";
- if (Base.getNode() != 0)
+ if (Base.getNode())
Base.getNode()->dump();
else
errs() << "null\n";
if (hasIndexField()) {
errs() << " Index ";
- if (Index.getNode() != 0)
+ if (Index.getNode())
Index.getNode()->dump();
else
errs() << "null\n";
};
class SystemZDAGToDAGISel : public SelectionDAGISel {
- const SystemZTargetLowering &Lowering;
- const SystemZSubtarget &Subtarget;
+ const SystemZSubtarget *Subtarget;
// Used by SystemZOperands.td to create integer constants.
inline SDValue getImm(const SDNode *Node, uint64_t Imm) const {
}
const SystemZInstrInfo *getInstrInfo() const {
- return getTargetMachine().getInstrInfo();
+ return Subtarget->getInstrInfo();
}
// Try to fold more of the base or index of AM into AM, where IsBase
public:
SystemZDAGToDAGISel(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel)
- : SelectionDAGISel(TM, OptLevel),
- Lowering(*TM.getTargetLowering()),
- Subtarget(*TM.getSubtargetImpl()) { }
+ : SelectionDAGISel(TM, OptLevel) {}
+
+ bool runOnMachineFunction(MachineFunction &MF) override {
+ Subtarget = &MF.getSubtarget<SystemZSubtarget>();
+ return SelectionDAGISel::runOnMachineFunction(MF);
+ }
// Override MachineFunctionPass.
const char *getPassName() const override {
// Override SelectionDAGISel.
SDNode *Select(SDNode *Node) override;
- bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
+ bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
std::vector<SDValue> &OutOps) override;
// Include the pieces autogenerated from the target description.
uint64_t Used = allOnes(Op.getValueType().getSizeInBits());
if (Used != (AndMask | InsertMask)) {
APInt KnownZero, KnownOne;
- CurDAG->ComputeMaskedBits(Op.getOperand(0), KnownZero, KnownOne);
+ CurDAG->computeKnownBits(Op.getOperand(0), KnownZero, KnownOne);
if (Used != (AndMask | InsertMask | KnownZero.getZExtValue()))
return false;
}
// been removed from the mask. See if adding them back in makes the
// mask suitable.
APInt KnownZero, KnownOne;
- CurDAG->ComputeMaskedBits(Input, KnownZero, KnownOne);
+ CurDAG->computeKnownBits(Input, KnownZero, KnownOne);
Mask |= KnownZero.getZExtValue();
if (!refineRxSBGMask(RxSBG, Mask))
return false;
// been removed from the mask. See if adding them back in makes the
// mask suitable.
APInt KnownZero, KnownOne;
- CurDAG->ComputeMaskedBits(Input, KnownZero, KnownOne);
+ CurDAG->computeKnownBits(Input, KnownZero, KnownOne);
Mask &= ~KnownOne.getZExtValue();
if (!refineRxSBGMask(RxSBG, Mask))
return false;
if (RISBG.Input.getOpcode() != ISD::ANY_EXTEND)
Count += 1;
if (Count == 0)
- return 0;
+ return nullptr;
if (Count == 1) {
// Prefer to use normal shift instructions over RISBG, since they can handle
// all cases and are sometimes shorter.
if (N->getOpcode() != ISD::AND)
- return 0;
+ return nullptr;
// Prefer register extensions like LLC over RISBG. Also prefer to start
// out with normal ANDs if one instruction would be enough. We can convert
N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), NewMask);
return SelectCode(N);
}
- return 0;
+ return nullptr;
}
}
unsigned Opcode = SystemZ::RISBG;
+ // Prefer RISBGN if available, since it does not clobber CC.
+ if (Subtarget->hasMiscellaneousExtensions())
+ Opcode = SystemZ::RISBGN;
EVT OpcodeVT = MVT::i64;
- if (VT == MVT::i32 && Subtarget.hasHighWord()) {
+ if (VT == MVT::i32 && Subtarget->hasHighWord()) {
Opcode = SystemZ::RISBMux;
OpcodeVT = MVT::i32;
RISBG.Start &= 31;
// Do nothing if neither operand is suitable.
if (Count[0] == 0 && Count[1] == 0)
- return 0;
+ return nullptr;
// Pick the deepest second operand.
unsigned I = Count[0] > Count[1] ? 0 : 1;
if (Opcode == SystemZ::ROSBG && (RxSBG[I].Mask & 0xff) == 0)
if (auto *Load = dyn_cast<LoadSDNode>(Op0.getNode()))
if (Load->getMemoryVT() == MVT::i8)
- return 0;
+ return nullptr;
// See whether we can avoid an AND in the first operand by converting
// ROSBG to RISBG.
- if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[I].Mask))
+ if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[I].Mask)) {
Opcode = SystemZ::RISBG;
-
+ // Prefer RISBGN if available, since it does not clobber CC.
+ if (Subtarget->hasMiscellaneousExtensions())
+ Opcode = SystemZ::RISBGN;
+ }
+
EVT VT = N->getValueType(0);
SDValue Ops[5] = {
convertTo(SDLoc(N), MVT::i64, Op0),
if (V1 == V2 && End1 == End2)
return false;
- return !AA->alias(AliasAnalysis::Location(V1, End1, Load->getTBAAInfo()),
- AliasAnalysis::Location(V2, End2, Store->getTBAAInfo()));
+ return !AA->alias(AliasAnalysis::Location(V1, End1, Load->getAAInfo()),
+ AliasAnalysis::Location(V2, End2, Store->getAAInfo()));
}
bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const {
if (Node->isMachineOpcode()) {
DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
Node->setNodeId(-1);
- return 0;
+ return nullptr;
}
unsigned Opcode = Node->getOpcode();
- SDNode *ResNode = 0;
+ SDNode *ResNode = nullptr;
switch (Opcode) {
case ISD::OR:
if (Node->getOperand(1).getOpcode() != ISD::Constant)
ResNode = SelectCode(Node);
DEBUG(errs() << "=> ";
- if (ResNode == NULL || ResNode == Node)
+ if (ResNode == nullptr || ResNode == Node)
Node->dump(CurDAG);
else
ResNode->dump(CurDAG);
bool SystemZDAGToDAGISel::
SelectInlineAsmMemoryOperand(const SDValue &Op,
- char ConstraintCode,
+ unsigned ConstraintID,
std::vector<SDValue> &OutOps) {
- assert(ConstraintCode == 'm' && "Unexpected constraint code");
- // Accept addresses with short displacements, which are compatible
- // with Q, R, S and T. But keep the index operand for future expansion.
- SDValue Base, Disp, Index;
- if (!selectBDXAddr(SystemZAddressingMode::FormBD,
- SystemZAddressingMode::Disp12Only,
- Op, Base, Disp, Index))
- return true;
- OutOps.push_back(Base);
- OutOps.push_back(Disp);
- OutOps.push_back(Index);
- return false;
+ switch(ConstraintID) {
+ default:
+ llvm_unreachable("Unexpected asm memory constraint");
+ case InlineAsm::Constraint_i:
+ case InlineAsm::Constraint_m:
+ case InlineAsm::Constraint_Q:
+ case InlineAsm::Constraint_R:
+ case InlineAsm::Constraint_S:
+ case InlineAsm::Constraint_T:
+ // Accept addresses with short displacements, which are compatible
+ // with Q, R, S and T. But keep the index operand for future expansion.
+ SDValue Base, Disp, Index;
+ if (selectBDXAddr(SystemZAddressingMode::FormBD,
+ SystemZAddressingMode::Disp12Only,
+ Op, Base, Disp, Index)) {
+ OutOps.push_back(Base);
+ OutOps.push_back(Disp);
+ OutOps.push_back(Index);
+ return false;
+ }
+ break;
+ }
+ return true;
}