diff options
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZISelLowering.cpp')
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 180 |
1 files changed, 58 insertions, 122 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 944284d0fb8..0003c290bd7 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -31,17 +31,6 @@ using namespace llvm; #define DEBUG_TYPE "systemz-lower" namespace { -// Represents a sequence for extracting a 0/1 value from an IPM result: -// (((X ^ XORValue) + AddValue) >> Bit) -struct IPMConversion { - IPMConversion(unsigned xorValue, int64_t addValue, unsigned bit) - : XORValue(xorValue), AddValue(addValue), Bit(bit) {} - - int64_t XORValue; - int64_t AddValue; - unsigned Bit; -}; - // Represents information about a comparison. struct Comparison { Comparison(SDValue Op0In, SDValue Op1In) @@ -517,7 +506,9 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, setOperationAction(ISD::VAEND, MVT::Other, Expand); // Codes for which we want to perform some z-specific combinations. + setTargetDAGCombine(ISD::ZERO_EXTEND); setTargetDAGCombine(ISD::SIGN_EXTEND); + setTargetDAGCombine(ISD::SIGN_EXTEND_INREG); setTargetDAGCombine(ISD::STORE); setTargetDAGCombine(ISD::EXTRACT_VECTOR_ELT); setTargetDAGCombine(ISD::FP_ROUND); @@ -1699,73 +1690,6 @@ static unsigned CCMaskForCondCode(ISD::CondCode CC) { #undef CONV } -// Return a sequence for getting a 1 from an IPM result when CC has a -// value in CCMask and a 0 when CC has a value in CCValid & ~CCMask. -// The handling of CC values outside CCValid doesn't matter. -static IPMConversion getIPMConversion(unsigned CCValid, unsigned CCMask) { - // Deal with cases where the result can be taken directly from a bit - // of the IPM result. - if (CCMask == (CCValid & (SystemZ::CCMASK_1 | SystemZ::CCMASK_3))) - return IPMConversion(0, 0, SystemZ::IPM_CC); - if (CCMask == (CCValid & (SystemZ::CCMASK_2 | SystemZ::CCMASK_3))) - return IPMConversion(0, 0, SystemZ::IPM_CC + 1); - - // Deal with cases where we can add a value to force the sign bit - // to contain the right value. Putting the bit in 31 means we can - // use SRL rather than RISBG(L), and also makes it easier to get a - // 0/-1 value, so it has priority over the other tests below. - // - // These sequences rely on the fact that the upper two bits of the - // IPM result are zero. - uint64_t TopBit = uint64_t(1) << 31; - if (CCMask == (CCValid & SystemZ::CCMASK_0)) - return IPMConversion(0, -(1 << SystemZ::IPM_CC), 31); - if (CCMask == (CCValid & (SystemZ::CCMASK_0 | SystemZ::CCMASK_1))) - return IPMConversion(0, -(2 << SystemZ::IPM_CC), 31); - if (CCMask == (CCValid & (SystemZ::CCMASK_0 - | SystemZ::CCMASK_1 - | SystemZ::CCMASK_2))) - return IPMConversion(0, -(3 << SystemZ::IPM_CC), 31); - if (CCMask == (CCValid & SystemZ::CCMASK_3)) - return IPMConversion(0, TopBit - (3 << SystemZ::IPM_CC), 31); - if (CCMask == (CCValid & (SystemZ::CCMASK_1 - | SystemZ::CCMASK_2 - | SystemZ::CCMASK_3))) - return IPMConversion(0, TopBit - (1 << SystemZ::IPM_CC), 31); - - // Next try inverting the value and testing a bit. 0/1 could be - // handled this way too, but we dealt with that case above. - if (CCMask == (CCValid & (SystemZ::CCMASK_0 | SystemZ::CCMASK_2))) - return IPMConversion(-1, 0, SystemZ::IPM_CC); - - // Handle cases where adding a value forces a non-sign bit to contain - // the right value. - if (CCMask == (CCValid & (SystemZ::CCMASK_1 | SystemZ::CCMASK_2))) - return IPMConversion(0, 1 << SystemZ::IPM_CC, SystemZ::IPM_CC + 1); - if (CCMask == (CCValid & (SystemZ::CCMASK_0 | SystemZ::CCMASK_3))) - return IPMConversion(0, -(1 << SystemZ::IPM_CC), SystemZ::IPM_CC + 1); - - // The remaining cases are 1, 2, 0/1/3 and 0/2/3. All these are - // can be done by inverting the low CC bit and applying one of the - // sign-based extractions above. - if (CCMask == (CCValid & SystemZ::CCMASK_1)) - return IPMConversion(1 << SystemZ::IPM_CC, -(1 << SystemZ::IPM_CC), 31); - if (CCMask == (CCValid & SystemZ::CCMASK_2)) - return IPMConversion(1 << SystemZ::IPM_CC, - TopBit - (3 << SystemZ::IPM_CC), 31); - if (CCMask == (CCValid & (SystemZ::CCMASK_0 - | SystemZ::CCMASK_1 - | SystemZ::CCMASK_3))) - return IPMConversion(1 << SystemZ::IPM_CC, -(3 << SystemZ::IPM_CC), 31); - if (CCMask == (CCValid & (SystemZ::CCMASK_0 - | SystemZ::CCMASK_2 - | SystemZ::CCMASK_3))) - return IPMConversion(1 << SystemZ::IPM_CC, - TopBit - (1 << SystemZ::IPM_CC), 31); - - llvm_unreachable("Unexpected CC combination"); -} - // If C can be converted to a comparison against zero, adjust the operands // as necessary. static void adjustZeroCmp(SelectionDAG &DAG, const SDLoc &DL, Comparison &C) { @@ -2388,24 +2312,11 @@ static void lowerGR128Binary(SelectionDAG &DAG, const SDLoc &DL, EVT VT, // in CCValid, so other values can be ignored. static SDValue emitSETCC(SelectionDAG &DAG, const SDLoc &DL, SDValue Glue, unsigned CCValid, unsigned CCMask) { - IPMConversion Conversion = getIPMConversion(CCValid, CCMask); - SDValue Result = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, Glue); - - if (Conversion.XORValue) - Result = DAG.getNode(ISD::XOR, DL, MVT::i32, Result, - DAG.getConstant(Conversion.XORValue, DL, MVT::i32)); - - if (Conversion.AddValue) - Result = DAG.getNode(ISD::ADD, DL, MVT::i32, Result, - DAG.getConstant(Conversion.AddValue, DL, MVT::i32)); - - // The SHR/AND sequence should get optimized to an RISBG. - Result = DAG.getNode(ISD::SRL, DL, MVT::i32, Result, - DAG.getConstant(Conversion.Bit, DL, MVT::i32)); - if (Conversion.Bit != 31) - Result = DAG.getNode(ISD::AND, DL, MVT::i32, Result, - DAG.getConstant(1, DL, MVT::i32)); - return Result; + 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 }; + return DAG.getNode(SystemZISD::SELECT_CCMASK, DL, MVT::i32, Ops); } // Return the SystemISD vector comparison operation for CC, or 0 if it cannot @@ -2620,35 +2531,10 @@ SDValue SystemZTargetLowering::lowerSELECT_CC(SDValue Op, } SDValue Glue = emitCmp(DAG, DL, C); - - // Special case for handling -1/0 results. The shifts we use here - // should get optimized with the IPM conversion sequence. - auto *TrueC = dyn_cast<ConstantSDNode>(TrueOp); - auto *FalseC = dyn_cast<ConstantSDNode>(FalseOp); - if (TrueC && FalseC) { - int64_t TrueVal = TrueC->getSExtValue(); - int64_t FalseVal = FalseC->getSExtValue(); - if ((TrueVal == -1 && FalseVal == 0) || (TrueVal == 0 && FalseVal == -1)) { - // Invert the condition if we want -1 on false. - if (TrueVal == 0) - C.CCMask ^= C.CCValid; - SDValue Result = emitSETCC(DAG, DL, Glue, C.CCValid, C.CCMask); - EVT VT = Op.getValueType(); - // Extend the result to VT. Upper bits are ignored. - if (!is32Bit(VT)) - Result = DAG.getNode(ISD::ANY_EXTEND, DL, VT, Result); - // Sign-extend from the low bit. - SDValue ShAmt = DAG.getConstant(VT.getSizeInBits() - 1, DL, MVT::i32); - SDValue Shl = DAG.getNode(ISD::SHL, DL, VT, Result, ShAmt); - return DAG.getNode(ISD::SRA, DL, VT, Shl, ShAmt); - } - } - SDValue Ops[] = {TrueOp, FalseOp, DAG.getConstant(C.CCValid, DL, MVT::i32), DAG.getConstant(C.CCMask, DL, MVT::i32), Glue}; - SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); - return DAG.getNode(SystemZISD::SELECT_CCMASK, DL, VTs, Ops); + return DAG.getNode(SystemZISD::SELECT_CCMASK, DL, Op.getValueType(), Ops); } SDValue SystemZTargetLowering::lowerGlobalAddress(GlobalAddressSDNode *Node, @@ -5174,6 +5060,54 @@ SDValue SystemZTargetLowering::combineTruncateExtract( return SDValue(); } +SDValue SystemZTargetLowering::combineZERO_EXTEND( + SDNode *N, DAGCombinerInfo &DCI) const { + // Convert (zext (select_ccmask C1, C2)) into (select_ccmask C1', C2') + SelectionDAG &DAG = DCI.DAG; + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + if (N0.getOpcode() == SystemZISD::SELECT_CCMASK) { + auto *TrueOp = dyn_cast<ConstantSDNode>(N0.getOperand(0)); + auto *FalseOp = dyn_cast<ConstantSDNode>(N0.getOperand(1)); + if (TrueOp && FalseOp) { + SDLoc DL(N0); + SDValue Ops[] = { DAG.getConstant(TrueOp->getZExtValue(), DL, VT), + DAG.getConstant(FalseOp->getZExtValue(), DL, VT), + N0.getOperand(2), N0.getOperand(3), N0.getOperand(4) }; + SDValue NewSelect = DAG.getNode(SystemZISD::SELECT_CCMASK, DL, VT, Ops); + // If N0 has multiple uses, change other uses as well. + if (!N0.hasOneUse()) { + SDValue TruncSelect = + DAG.getNode(ISD::TRUNCATE, DL, N0.getValueType(), NewSelect); + DCI.CombineTo(N0.getNode(), TruncSelect); + } + return NewSelect; + } + } + return SDValue(); +} + +SDValue SystemZTargetLowering::combineSIGN_EXTEND_INREG( + SDNode *N, DAGCombinerInfo &DCI) const { + // Convert (sext_in_reg (setcc LHS, RHS, COND), i1) + // and (sext_in_reg (any_extend (setcc LHS, RHS, COND)), i1) + // into (select_cc LHS, RHS, -1, 0, COND) + SelectionDAG &DAG = DCI.DAG; + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + EVT EVT = cast<VTSDNode>(N->getOperand(1))->getVT(); + if (N0.hasOneUse() && N0.getOpcode() == ISD::ANY_EXTEND) + N0 = N0.getOperand(0); + if (EVT == MVT::i1 && N0.hasOneUse() && N0.getOpcode() == ISD::SETCC) { + SDLoc DL(N0); + SDValue Ops[] = { N0.getOperand(0), N0.getOperand(1), + DAG.getConstant(-1, DL, VT), DAG.getConstant(0, DL, VT), + N0.getOperand(2) }; + return DAG.getNode(ISD::SELECT_CC, DL, VT, Ops); + } + return SDValue(); +} + SDValue SystemZTargetLowering::combineSIGN_EXTEND( SDNode *N, DAGCombinerInfo &DCI) const { // Convert (sext (ashr (shl X, C1), C2)) to @@ -5479,7 +5413,9 @@ SDValue SystemZTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { switch(N->getOpcode()) { default: break; + case ISD::ZERO_EXTEND: return combineZERO_EXTEND(N, DCI); case ISD::SIGN_EXTEND: return combineSIGN_EXTEND(N, DCI); + case ISD::SIGN_EXTEND_INREG: return combineSIGN_EXTEND_INREG(N, DCI); case SystemZISD::MERGE_HIGH: case SystemZISD::MERGE_LOW: return combineMERGE(N, DCI); case ISD::STORE: return combineSTORE(N, DCI); |

