diff options
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp')
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index 59dd46c0697..26af3f4ebcc 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -351,6 +351,7 @@ public: void Select(SDNode *Node) override; bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) override; + bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const override; void PreprocessISelDAG() override; // Include the pieces autogenerated from the target description. @@ -1445,6 +1446,52 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, return true; } +// IsProfitableToFold - Returns true if is profitable to fold the specific +// operand node N of U during instruction selection that starts at Root. +bool +SystemZDAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U, + SDNode *Root) const { + // We want to avoid folding a LOAD into an ICMP node if as a result + // we would be forced to spill the condition code into a GPR. + if (N.getOpcode() == ISD::LOAD && U->getOpcode() == SystemZISD::ICMP) { + if (!N.hasOneUse() || !U->hasOneUse()) + return false; + + // The user of the CC value will usually be a CopyToReg into the + // physical CC register, which in turn is glued and chained to the + // actual instruction that uses the CC value. Bail out if we have + // anything else than that. + SDNode *CCUser = *U->use_begin(); + SDNode *CCRegUser = nullptr; + if (CCUser->getOpcode() == ISD::CopyToReg || + cast<RegisterSDNode>(CCUser->getOperand(1))->getReg() == SystemZ::CC) { + for (auto *U : CCUser->uses()) { + if (CCRegUser == nullptr) + CCRegUser = U; + else if (CCRegUser != U) + return false; + } + } + if (CCRegUser == nullptr) + return false; + + // If the actual instruction is a branch, the only thing that remains to be + // checked is whether the CCUser chain is a predecessor of the load. + if (CCRegUser->isMachineOpcode() && + CCRegUser->getMachineOpcode() == SystemZ::BRC) + return !N->isPredecessorOf(CCUser->getOperand(0).getNode()); + + // Otherwise, the instruction may have multiple operands, and we need to + // verify that none of them are a predecessor of the load. This is exactly + // the same check that would be done by common code if the CC setter were + // glued to the CC user, so simply invoke that check here. + if (!IsLegalToFold(N, U, CCRegUser, OptLevel, false)) + return false; + } + + return true; +} + namespace { // Represents a sequence for extracting a 0/1 value from an IPM result: // (((X ^ XORValue) + AddValue) >> Bit) @@ -1543,9 +1590,9 @@ SDValue SystemZDAGToDAGISel::expandSelectBoolean(SDNode *Node) { int CCMask = CCMaskOp->getZExtValue(); SDLoc DL(Node); - SDValue Glue = Node->getOperand(4); + SDValue CCReg = Node->getOperand(4); IPMConversion IPM = getIPMConversion(CCValid, CCMask); - SDValue Result = CurDAG->getNode(SystemZISD::IPM, DL, MVT::i32, Glue); + SDValue Result = CurDAG->getNode(SystemZISD::IPM, DL, MVT::i32, CCReg); if (IPM.XORValue) Result = CurDAG->getNode(ISD::XOR, DL, MVT::i32, Result, |