diff options
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZISelLowering.cpp')
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 286 |
1 files changed, 192 insertions, 94 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index bf5a28cdf4a..ab314e1f311 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1662,9 +1662,9 @@ static bool isIntrinsicWithCC(SDValue Op, unsigned &Opcode, unsigned &CCValid) { } } -// Emit an intrinsic with chain with a glued value instead of its CC result. -static SDValue emitIntrinsicWithChainAndGlue(SelectionDAG &DAG, SDValue Op, - unsigned Opcode) { +// Emit an intrinsic with chain and an explicit CC register result. +static SDNode *emitIntrinsicWithCCAndChain(SelectionDAG &DAG, SDValue Op, + unsigned Opcode) { // Copy all operands except the intrinsic ID. unsigned NumOps = Op.getNumOperands(); SmallVector<SDValue, 6> Ops; @@ -1674,17 +1674,17 @@ static SDValue emitIntrinsicWithChainAndGlue(SelectionDAG &DAG, SDValue Op, Ops.push_back(Op.getOperand(I)); assert(Op->getNumValues() == 2 && "Expected only CC result and chain"); - SDVTList RawVTs = DAG.getVTList(MVT::Other, MVT::Glue); + SDVTList RawVTs = DAG.getVTList(MVT::i32, MVT::Other); SDValue Intr = DAG.getNode(Opcode, SDLoc(Op), RawVTs, Ops); SDValue OldChain = SDValue(Op.getNode(), 1); - SDValue NewChain = SDValue(Intr.getNode(), 0); + SDValue NewChain = SDValue(Intr.getNode(), 1); DAG.ReplaceAllUsesOfValueWith(OldChain, NewChain); - return Intr; + return Intr.getNode(); } -// Emit an intrinsic with a glued value instead of its CC result. -static SDValue emitIntrinsicWithGlue(SelectionDAG &DAG, SDValue Op, - unsigned Opcode) { +// Emit an intrinsic with an explicit CC register result. +static SDNode *emitIntrinsicWithCC(SelectionDAG &DAG, SDValue Op, + unsigned Opcode) { // Copy all operands except the intrinsic ID. unsigned NumOps = Op.getNumOperands(); SmallVector<SDValue, 6> Ops; @@ -1692,11 +1692,8 @@ static SDValue emitIntrinsicWithGlue(SelectionDAG &DAG, SDValue Op, for (unsigned I = 1; I < NumOps; ++I) Ops.push_back(Op.getOperand(I)); - if (Op->getNumValues() == 1) - return DAG.getNode(Opcode, SDLoc(Op), MVT::Glue, Ops); - assert(Op->getNumValues() == 2 && "Expected exactly one non-CC result"); - SDVTList RawVTs = DAG.getVTList(Op->getValueType(0), MVT::Glue); - return DAG.getNode(Opcode, SDLoc(Op), RawVTs, Ops); + SDValue Intr = DAG.getNode(Opcode, SDLoc(Op), Op->getVTList(), Ops); + return Intr.getNode(); } // CC is a comparison that will be implemented using an integer or @@ -2310,29 +2307,28 @@ static Comparison getCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, // Emit the comparison instruction described by C. static SDValue emitCmp(SelectionDAG &DAG, const SDLoc &DL, Comparison &C) { if (!C.Op1.getNode()) { - SDValue Op; + SDNode *Node; switch (C.Op0.getOpcode()) { case ISD::INTRINSIC_W_CHAIN: - Op = emitIntrinsicWithChainAndGlue(DAG, C.Op0, C.Opcode); - break; + Node = emitIntrinsicWithCCAndChain(DAG, C.Op0, C.Opcode); + return SDValue(Node, 0); case ISD::INTRINSIC_WO_CHAIN: - Op = emitIntrinsicWithGlue(DAG, C.Op0, C.Opcode); - break; + Node = emitIntrinsicWithCC(DAG, C.Op0, C.Opcode); + return SDValue(Node, Node->getNumValues() - 1); default: llvm_unreachable("Invalid comparison operands"); } - return SDValue(Op.getNode(), Op->getNumValues() - 1); } if (C.Opcode == SystemZISD::ICMP) - return DAG.getNode(SystemZISD::ICMP, DL, MVT::Glue, C.Op0, C.Op1, + return DAG.getNode(SystemZISD::ICMP, DL, MVT::i32, C.Op0, C.Op1, DAG.getConstant(C.ICmpType, DL, MVT::i32)); if (C.Opcode == SystemZISD::TM) { bool RegisterOnly = (bool(C.CCMask & SystemZ::CCMASK_TM_MIXED_MSB_0) != bool(C.CCMask & SystemZ::CCMASK_TM_MIXED_MSB_1)); - return DAG.getNode(SystemZISD::TM, DL, MVT::Glue, C.Op0, C.Op1, + return DAG.getNode(SystemZISD::TM, DL, MVT::i32, C.Op0, C.Op1, DAG.getConstant(RegisterOnly, DL, MVT::i32)); } - return DAG.getNode(C.Opcode, DL, MVT::Glue, C.Op0, C.Op1); + return DAG.getNode(C.Opcode, DL, MVT::i32, C.Op0, C.Op1); } // Implement a 32-bit *MUL_LOHI operation by extending both operands to @@ -2363,15 +2359,15 @@ static void lowerGR128Binary(SelectionDAG &DAG, const SDLoc &DL, EVT VT, Odd = DAG.getTargetExtractSubreg(SystemZ::odd128(Is32Bit), DL, VT, Result); } -// Return an i32 value that is 1 if the CC value produced by Glue is +// Return an i32 value that is 1 if the CC value produced by CCReg is // in the mask CCMask and 0 otherwise. CC is known to have a value // in CCValid, so other values can be ignored. -static SDValue emitSETCC(SelectionDAG &DAG, const SDLoc &DL, SDValue Glue, +static SDValue emitSETCC(SelectionDAG &DAG, const SDLoc &DL, SDValue CCReg, unsigned CCValid, unsigned CCMask) { SDValue Ops[] = { DAG.getConstant(1, DL, MVT::i32), DAG.getConstant(0, DL, MVT::i32), DAG.getConstant(CCValid, DL, MVT::i32), - DAG.getConstant(CCMask, DL, MVT::i32), Glue }; + DAG.getConstant(CCMask, DL, MVT::i32), CCReg }; return DAG.getNode(SystemZISD::SELECT_CCMASK, DL, MVT::i32, Ops); } @@ -2521,8 +2517,8 @@ SDValue SystemZTargetLowering::lowerSETCC(SDValue Op, return lowerVectorSETCC(DAG, DL, VT, CC, CmpOp0, CmpOp1); Comparison C(getCmp(DAG, CmpOp0, CmpOp1, CC, DL)); - SDValue Glue = emitCmp(DAG, DL, C); - return emitSETCC(DAG, DL, Glue, C.CCValid, C.CCMask); + SDValue CCReg = emitCmp(DAG, DL, C); + return emitSETCC(DAG, DL, CCReg, C.CCValid, C.CCMask); } SDValue SystemZTargetLowering::lowerBR_CC(SDValue Op, SelectionDAG &DAG) const { @@ -2533,10 +2529,10 @@ SDValue SystemZTargetLowering::lowerBR_CC(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); Comparison C(getCmp(DAG, CmpOp0, CmpOp1, CC, DL)); - SDValue Glue = emitCmp(DAG, DL, C); + SDValue CCReg = emitCmp(DAG, DL, C); return DAG.getNode(SystemZISD::BR_CCMASK, DL, Op.getValueType(), Op.getOperand(0), DAG.getConstant(C.CCValid, DL, MVT::i32), - DAG.getConstant(C.CCMask, DL, MVT::i32), Dest, Glue); + DAG.getConstant(C.CCMask, DL, MVT::i32), Dest, CCReg); } // Return true if Pos is CmpOp and Neg is the negative of CmpOp, @@ -2586,9 +2582,9 @@ SDValue SystemZTargetLowering::lowerSELECT_CC(SDValue Op, return getAbsolute(DAG, DL, FalseOp, C.CCMask & SystemZ::CCMASK_CMP_GT); } - SDValue Glue = emitCmp(DAG, DL, C); + SDValue CCReg = emitCmp(DAG, DL, C); SDValue Ops[] = {TrueOp, FalseOp, DAG.getConstant(C.CCValid, DL, MVT::i32), - DAG.getConstant(C.CCMask, DL, MVT::i32), Glue}; + DAG.getConstant(C.CCMask, DL, MVT::i32), CCReg}; return DAG.getNode(SystemZISD::SELECT_CCMASK, DL, Op.getValueType(), Ops); } @@ -3454,16 +3450,16 @@ SDValue SystemZTargetLowering::lowerATOMIC_CMP_SWAP(SDValue Op, EVT NarrowVT = Node->getMemoryVT(); EVT WideVT = NarrowVT == MVT::i64 ? MVT::i64 : MVT::i32; if (NarrowVT == WideVT) { - SDVTList Tys = DAG.getVTList(WideVT, MVT::Other, MVT::Glue); + SDVTList Tys = DAG.getVTList(WideVT, MVT::i32, MVT::Other); SDValue Ops[] = { ChainIn, Addr, CmpVal, SwapVal }; SDValue AtomicOp = DAG.getMemIntrinsicNode(SystemZISD::ATOMIC_CMP_SWAP, DL, Tys, Ops, NarrowVT, MMO); - SDValue Success = emitSETCC(DAG, DL, AtomicOp.getValue(2), + SDValue Success = emitSETCC(DAG, DL, AtomicOp.getValue(1), SystemZ::CCMASK_CS, SystemZ::CCMASK_CS_EQ); DAG.ReplaceAllUsesOfValueWith(Op.getValue(0), AtomicOp.getValue(0)); DAG.ReplaceAllUsesOfValueWith(Op.getValue(1), Success); - DAG.ReplaceAllUsesOfValueWith(Op.getValue(2), AtomicOp.getValue(1)); + DAG.ReplaceAllUsesOfValueWith(Op.getValue(2), AtomicOp.getValue(2)); return SDValue(); } @@ -3488,17 +3484,17 @@ SDValue SystemZTargetLowering::lowerATOMIC_CMP_SWAP(SDValue Op, DAG.getConstant(0, DL, WideVT), BitShift); // Construct the ATOMIC_CMP_SWAPW node. - SDVTList VTList = DAG.getVTList(WideVT, MVT::Other, MVT::Glue); + SDVTList VTList = DAG.getVTList(WideVT, MVT::i32, MVT::Other); SDValue Ops[] = { ChainIn, AlignedAddr, CmpVal, SwapVal, BitShift, NegBitShift, DAG.getConstant(BitSize, DL, WideVT) }; SDValue AtomicOp = DAG.getMemIntrinsicNode(SystemZISD::ATOMIC_CMP_SWAPW, DL, VTList, Ops, NarrowVT, MMO); - SDValue Success = emitSETCC(DAG, DL, AtomicOp.getValue(2), + SDValue Success = emitSETCC(DAG, DL, AtomicOp.getValue(1), SystemZ::CCMASK_ICMP, SystemZ::CCMASK_CMP_EQ); DAG.ReplaceAllUsesOfValueWith(Op.getValue(0), AtomicOp.getValue(0)); DAG.ReplaceAllUsesOfValueWith(Op.getValue(1), Success); - DAG.ReplaceAllUsesOfValueWith(Op.getValue(2), AtomicOp.getValue(1)); + DAG.ReplaceAllUsesOfValueWith(Op.getValue(2), AtomicOp.getValue(2)); return SDValue(); } @@ -3555,12 +3551,10 @@ SDValue SystemZTargetLowering::lowerPREFETCH(SDValue Op, Node->getMemoryVT(), Node->getMemOperand()); } -// Return an i32 that contains the value of CC immediately after After, -// whose final operand must be MVT::Glue. -static SDValue getCCResult(SelectionDAG &DAG, SDNode *After) { - SDLoc DL(After); - SDValue Glue = SDValue(After, After->getNumValues() - 1); - SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, Glue); +// Convert condition code in CCReg to an i32 value. +static SDValue getCCResult(SelectionDAG &DAG, SDValue CCReg) { + SDLoc DL(CCReg); + SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg); return DAG.getNode(ISD::SRL, DL, MVT::i32, IPM, DAG.getConstant(SystemZ::IPM_CC, DL, MVT::i32)); } @@ -3571,8 +3565,8 @@ SystemZTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, unsigned Opcode, CCValid; if (isIntrinsicWithCCAndChain(Op, Opcode, CCValid)) { assert(Op->getNumValues() == 2 && "Expected only CC result and chain"); - SDValue Glued = emitIntrinsicWithChainAndGlue(DAG, Op, Opcode); - SDValue CC = getCCResult(DAG, Glued.getNode()); + SDNode *Node = emitIntrinsicWithCCAndChain(DAG, Op, Opcode); + SDValue CC = getCCResult(DAG, SDValue(Node, 0)); DAG.ReplaceAllUsesOfValueWith(SDValue(Op.getNode(), 0), CC); return SDValue(); } @@ -3585,13 +3579,12 @@ SystemZTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { unsigned Opcode, CCValid; if (isIntrinsicWithCC(Op, Opcode, CCValid)) { - SDValue Glued = emitIntrinsicWithGlue(DAG, Op, Opcode); - SDValue CC = getCCResult(DAG, Glued.getNode()); + SDNode *Node = emitIntrinsicWithCC(DAG, Op, Opcode); if (Op->getNumValues() == 1) - return CC; + return getCCResult(DAG, SDValue(Node, 0)); assert(Op->getNumValues() == 2 && "Expected a CC and non-CC result"); - return DAG.getNode(ISD::MERGE_VALUES, SDLoc(Op), Op->getVTList(), Glued, - CC); + return DAG.getNode(ISD::MERGE_VALUES, SDLoc(Op), Op->getVTList(), + SDValue(Node, 0), getCCResult(DAG, SDValue(Node, 1))); } unsigned Id = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); @@ -4828,19 +4821,19 @@ SystemZTargetLowering::LowerOperationWrapper(SDNode *N, } case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: { SDLoc DL(N); - SDVTList Tys = DAG.getVTList(MVT::Untyped, MVT::Other, MVT::Glue); + SDVTList Tys = DAG.getVTList(MVT::Untyped, MVT::i32, MVT::Other); SDValue Ops[] = { N->getOperand(0), N->getOperand(1), lowerI128ToGR128(DAG, N->getOperand(2)), lowerI128ToGR128(DAG, N->getOperand(3)) }; MachineMemOperand *MMO = cast<AtomicSDNode>(N)->getMemOperand(); SDValue Res = DAG.getMemIntrinsicNode(SystemZISD::ATOMIC_CMP_SWAP_128, DL, Tys, Ops, MVT::i128, MMO); - SDValue Success = emitSETCC(DAG, DL, Res.getValue(2), + SDValue Success = emitSETCC(DAG, DL, Res.getValue(1), SystemZ::CCMASK_CS, SystemZ::CCMASK_CS_EQ); Success = DAG.getZExtOrTrunc(Success, DL, N->getValueType(1)); Results.push_back(lowerGR128ToI128(DAG, Res)); Results.push_back(Success); - Results.push_back(Res.getValue(1)); + Results.push_back(Res.getValue(2)); break; } default: @@ -5465,10 +5458,10 @@ SDValue SystemZTargetLowering::combineSHIFTROT( return SDValue(); } -static bool combineCCMask(SDValue &Glue, int &CCValid, int &CCMask) { +static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) { // We have a SELECT_CCMASK or BR_CCMASK comparing the condition code - // set by the glued instruction using the CCValid / CCMask masks, - // If the glued instruction is itself a (ICMP (SELECT_CCMASK)) testing + // set by the CCReg instruction using the CCValid / CCMask masks, + // If the CCReg instruction is itself a (ICMP (SELECT_CCMASK)) testing // the condition code set by some other instruction, see whether we // can directly use that condition code. bool Invert = false; @@ -5481,15 +5474,13 @@ static bool combineCCMask(SDValue &Glue, int &CCValid, int &CCMask) { else if (CCMask != SystemZ::CCMASK_CMP_EQ) return false; - // Verify that we have an ICMP that is the single user of a SELECT_CCMASK. - SDNode *ICmp = Glue.getNode(); + // Verify that we have an ICMP that is the user of a SELECT_CCMASK. + SDNode *ICmp = CCReg.getNode(); if (ICmp->getOpcode() != SystemZISD::ICMP) return false; SDNode *Select = ICmp->getOperand(0).getNode(); if (Select->getOpcode() != SystemZISD::SELECT_CCMASK) return false; - if (!Select->hasOneUse()) - return false; // Verify that the ICMP compares against one of select values. auto *CompareVal = dyn_cast<ConstantSDNode>(ICmp->getOperand(1)); @@ -5516,25 +5507,8 @@ static bool combineCCMask(SDValue &Glue, int &CCValid, int &CCMask) { if (Invert) CCMask ^= CCValid; - // Return the updated Glue link. - Glue = Select->getOperand(4); - return true; -} - -static bool combineMergeChains(SDValue &Chain, SDValue Glue) { - // We are about to glue an instruction with input chain Chain to the - // instruction Glue. Verify that this would not create an invalid - // topological sort due to intervening chain nodes. - - SDNode *Node = Glue.getNode(); - for (int ResNo = Node->getNumValues() - 1; ResNo >= 0; --ResNo) - if (Node->getValueType(ResNo) == MVT::Other) { - SDValue OutChain = SDValue(Node, ResNo); - // FIXME: We should be able to at least handle an intervening - // TokenFactor node by swapping chains around a bit ... - return Chain == OutChain; - } - + // Return the updated CCReg link. + CCReg = Select->getOperand(4); return true; } @@ -5551,15 +5525,14 @@ SDValue SystemZTargetLowering::combineBR_CCMASK( int CCValidVal = CCValid->getZExtValue(); int CCMaskVal = CCMask->getZExtValue(); SDValue Chain = N->getOperand(0); - SDValue Glue = N->getOperand(4); + SDValue CCReg = N->getOperand(4); - if (combineCCMask(Glue, CCValidVal, CCMaskVal) - && combineMergeChains(Chain, Glue)) + if (combineCCMask(CCReg, CCValidVal, CCMaskVal)) return DAG.getNode(SystemZISD::BR_CCMASK, SDLoc(N), N->getValueType(0), Chain, DAG.getConstant(CCValidVal, SDLoc(N), MVT::i32), DAG.getConstant(CCMaskVal, SDLoc(N), MVT::i32), - N->getOperand(3), Glue); + N->getOperand(3), CCReg); return SDValue(); } @@ -5575,15 +5548,15 @@ SDValue SystemZTargetLowering::combineSELECT_CCMASK( int CCValidVal = CCValid->getZExtValue(); int CCMaskVal = CCMask->getZExtValue(); - SDValue Glue = N->getOperand(4); + SDValue CCReg = N->getOperand(4); - if (combineCCMask(Glue, CCValidVal, CCMaskVal)) + if (combineCCMask(CCReg, CCValidVal, CCMaskVal)) return DAG.getNode(SystemZISD::SELECT_CCMASK, SDLoc(N), N->getValueType(0), N->getOperand(0), N->getOperand(1), DAG.getConstant(CCValidVal, SDLoc(N), MVT::i32), DAG.getConstant(CCMaskVal, SDLoc(N), MVT::i32), - Glue); + CCReg); return SDValue(); } @@ -5951,6 +5924,103 @@ static unsigned forceReg(MachineInstr &MI, MachineOperand &Base, return Reg; } +// The CC operand of MI might be missing a kill marker because there +// were multiple uses of CC, and ISel didn't know which to mark. +// Figure out whether MI should have had a kill marker. +static bool checkCCKill(MachineInstr &MI, MachineBasicBlock *MBB) { + // Scan forward through BB for a use/def of CC. + MachineBasicBlock::iterator miI(std::next(MachineBasicBlock::iterator(MI))); + for (MachineBasicBlock::iterator miE = MBB->end(); miI != miE; ++miI) { + const MachineInstr& mi = *miI; + if (mi.readsRegister(SystemZ::CC)) + return false; + if (mi.definesRegister(SystemZ::CC)) + break; // Should have kill-flag - update below. + } + + // If we hit the end of the block, check whether CC is live into a + // successor. + if (miI == MBB->end()) { + for (auto SI = MBB->succ_begin(), SE = MBB->succ_end(); SI != SE; ++SI) + if ((*SI)->isLiveIn(SystemZ::CC)) + return false; + } + + return true; +} + +// Return true if it is OK for this Select pseudo-opcode to be cascaded +// together with other Select pseudo-opcodes into a single basic-block with +// a conditional jump around it. +static bool isSelectPseudo(MachineInstr &MI) { + switch (MI.getOpcode()) { + case SystemZ::Select32: + case SystemZ::Select64: + case SystemZ::SelectF32: + case SystemZ::SelectF64: + case SystemZ::SelectF128: + case SystemZ::SelectVR32: + case SystemZ::SelectVR64: + case SystemZ::SelectVR128: + return true; + + default: + return false; + } +} + +// Helper function, which inserts PHI functions into SinkMBB: +// %Result(i) = phi [ %FalseValue(i), FalseMBB ], [ %TrueValue(i), TrueMBB ], +// where %FalseValue(i) and %TrueValue(i) are taken from the consequent Selects +// in [MIItBegin, MIItEnd) range. +static void createPHIsForSelects(MachineBasicBlock::iterator MIItBegin, + MachineBasicBlock::iterator MIItEnd, + MachineBasicBlock *TrueMBB, + MachineBasicBlock *FalseMBB, + MachineBasicBlock *SinkMBB) { + MachineFunction *MF = TrueMBB->getParent(); + const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); + + unsigned CCValid = MIItBegin->getOperand(3).getImm(); + unsigned CCMask = MIItBegin->getOperand(4).getImm(); + DebugLoc DL = MIItBegin->getDebugLoc(); + + MachineBasicBlock::iterator SinkInsertionPoint = SinkMBB->begin(); + + // As we are creating the PHIs, we have to be careful if there is more than + // one. Later Selects may reference the results of earlier Selects, but later + // PHIs have to reference the individual true/false inputs from earlier PHIs. + // That also means that PHI construction must work forward from earlier to + // later, and that the code must maintain a mapping from earlier PHI's + // destination registers, and the registers that went into the PHI. + DenseMap<unsigned, std::pair<unsigned, unsigned>> RegRewriteTable; + + for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd; ++MIIt) { + unsigned DestReg = MIIt->getOperand(0).getReg(); + unsigned TrueReg = MIIt->getOperand(1).getReg(); + unsigned FalseReg = MIIt->getOperand(2).getReg(); + + // If this Select we are generating is the opposite condition from + // the jump we generated, then we have to swap the operands for the + // PHI that is going to be generated. + if (MIIt->getOperand(4).getImm() == (CCValid ^ CCMask)) + std::swap(TrueReg, FalseReg); + + if (RegRewriteTable.find(TrueReg) != RegRewriteTable.end()) + TrueReg = RegRewriteTable[TrueReg].first; + + if (RegRewriteTable.find(FalseReg) != RegRewriteTable.end()) + FalseReg = RegRewriteTable[FalseReg].second; + + BuildMI(*SinkMBB, SinkInsertionPoint, DL, TII->get(SystemZ::PHI), DestReg) + .addReg(TrueReg).addMBB(TrueMBB) + .addReg(FalseReg).addMBB(FalseMBB); + + // Add this PHI to the rewrite table. + RegRewriteTable[DestReg] = std::make_pair(TrueReg, FalseReg); + } +} + // Implement EmitInstrWithCustomInserter for pseudo Select* instruction MI. MachineBasicBlock * SystemZTargetLowering::emitSelect(MachineInstr &MI, @@ -5958,17 +6028,37 @@ SystemZTargetLowering::emitSelect(MachineInstr &MI, const SystemZInstrInfo *TII = static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo()); - unsigned DestReg = MI.getOperand(0).getReg(); - unsigned TrueReg = MI.getOperand(1).getReg(); - unsigned FalseReg = MI.getOperand(2).getReg(); unsigned CCValid = MI.getOperand(3).getImm(); unsigned CCMask = MI.getOperand(4).getImm(); DebugLoc DL = MI.getDebugLoc(); + // If we have a sequence of Select* pseudo instructions using the + // same condition code value, we want to expand all of them into + // a single pair of basic blocks using the same condition. + MachineInstr *LastMI = &MI; + MachineBasicBlock::iterator NextMIIt = + std::next(MachineBasicBlock::iterator(MI)); + + if (isSelectPseudo(MI)) + while (NextMIIt != MBB->end() && isSelectPseudo(*NextMIIt) && + NextMIIt->getOperand(3).getImm() == CCValid && + (NextMIIt->getOperand(4).getImm() == CCMask || + NextMIIt->getOperand(4).getImm() == (CCValid ^ CCMask))) { + LastMI = &*NextMIIt; + ++NextMIIt; + } + MachineBasicBlock *StartMBB = MBB; MachineBasicBlock *JoinMBB = splitBlockBefore(MI, MBB); MachineBasicBlock *FalseMBB = emitBlockAfter(StartMBB); + // Unless CC was killed in the last Select instruction, mark it as + // live-in to both FalseMBB and JoinMBB. + if (!LastMI->killsRegister(SystemZ::CC) && !checkCCKill(*LastMI, JoinMBB)) { + FalseMBB->addLiveIn(SystemZ::CC); + JoinMBB->addLiveIn(SystemZ::CC); + } + // StartMBB: // BRC CCMask, JoinMBB // # fallthrough to FalseMBB @@ -5987,11 +6077,12 @@ SystemZTargetLowering::emitSelect(MachineInstr &MI, // %Result = phi [ %FalseReg, FalseMBB ], [ %TrueReg, StartMBB ] // ... MBB = JoinMBB; - BuildMI(*MBB, MI, DL, TII->get(SystemZ::PHI), DestReg) - .addReg(TrueReg).addMBB(StartMBB) - .addReg(FalseReg).addMBB(FalseMBB); + MachineBasicBlock::iterator MIItBegin = MachineBasicBlock::iterator(MI); + MachineBasicBlock::iterator MIItEnd = + std::next(MachineBasicBlock::iterator(LastMI)); + createPHIsForSelects(MIItBegin, MIItEnd, StartMBB, FalseMBB, MBB); - MI.eraseFromParent(); + StartMBB->erase(MIItBegin, MIItEnd); return JoinMBB; } @@ -6053,6 +6144,13 @@ MachineBasicBlock *SystemZTargetLowering::emitCondStore(MachineInstr &MI, MachineBasicBlock *JoinMBB = splitBlockBefore(MI, MBB); MachineBasicBlock *FalseMBB = emitBlockAfter(StartMBB); + // Unless CC was killed in the CondStore instruction, mark it as + // live-in to both FalseMBB and JoinMBB. + if (!MI.killsRegister(SystemZ::CC) && !checkCCKill(MI, JoinMBB)) { + FalseMBB->addLiveIn(SystemZ::CC); + JoinMBB->addLiveIn(SystemZ::CC); + } + // StartMBB: // BRC CCMask, JoinMBB // # fallthrough to FalseMBB |