diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 178 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 180 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.h | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.td | 12 | ||||
| -rw-r--r-- | llvm/test/CodeGen/SystemZ/branch-07.ll | 8 | ||||
| -rw-r--r-- | llvm/test/CodeGen/SystemZ/setcc-03.ll | 73 | ||||
| -rw-r--r-- | llvm/test/CodeGen/SystemZ/setcc-04.ll | 173 |
7 files changed, 488 insertions, 138 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index ce6f3d37f5c..f12147cf3ea 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -330,6 +330,9 @@ class SystemZDAGToDAGISel : public SelectionDAGISel { // to X. bool storeLoadCanUseBlockBinary(SDNode *N, unsigned I) const; + // Try to expand a boolean SELECT_CCMASK using an IPM sequence. + SDValue expandSelectBoolean(SDNode *Node); + public: SystemZDAGToDAGISel(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel) : SelectionDAGISel(TM, OptLevel) {} @@ -348,6 +351,7 @@ public: void Select(SDNode *Node) override; bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) override; + void PreprocessISelDAG() override; // Include the pieces autogenerated from the target description. #include "SystemZGenDAGISel.inc" @@ -1438,3 +1442,177 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, return true; } + +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; +}; +} // end anonymous namespace + +// 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"); +} + +SDValue SystemZDAGToDAGISel::expandSelectBoolean(SDNode *Node) { + auto *TrueOp = dyn_cast<ConstantSDNode>(Node->getOperand(0)); + auto *FalseOp = dyn_cast<ConstantSDNode>(Node->getOperand(1)); + if (!TrueOp || !FalseOp) + return SDValue(); + if (FalseOp->getZExtValue() != 0) + return SDValue(); + if (TrueOp->getSExtValue() != 1 && TrueOp->getSExtValue() != -1) + return SDValue(); + + auto *CCValidOp = dyn_cast<ConstantSDNode>(Node->getOperand(2)); + auto *CCMaskOp = dyn_cast<ConstantSDNode>(Node->getOperand(3)); + if (!CCValidOp || !CCMaskOp) + return SDValue(); + int CCValid = CCValidOp->getZExtValue(); + int CCMask = CCMaskOp->getZExtValue(); + + SDLoc DL(Node); + SDValue Glue = Node->getOperand(4); + IPMConversion IPM = getIPMConversion(CCValid, CCMask); + SDValue Result = CurDAG->getNode(SystemZISD::IPM, DL, MVT::i32, Glue); + + if (IPM.XORValue) + Result = CurDAG->getNode(ISD::XOR, DL, MVT::i32, Result, + CurDAG->getConstant(IPM.XORValue, DL, MVT::i32)); + + if (IPM.AddValue) + Result = CurDAG->getNode(ISD::ADD, DL, MVT::i32, Result, + CurDAG->getConstant(IPM.AddValue, DL, MVT::i32)); + + EVT VT = Node->getValueType(0); + if (VT == MVT::i32 && IPM.Bit == 31) { + unsigned ShiftOp = TrueOp->getSExtValue() == 1 ? ISD::SRL : ISD::SRA; + Result = CurDAG->getNode(ShiftOp, DL, MVT::i32, Result, + CurDAG->getConstant(IPM.Bit, DL, MVT::i32)); + } else { + if (VT != MVT::i32) + Result = CurDAG->getNode(ISD::ANY_EXTEND, DL, VT, Result); + + if (TrueOp->getSExtValue() == 1) { + // The SHR/AND sequence should get optimized to an RISBG. + Result = CurDAG->getNode(ISD::SRL, DL, VT, Result, + CurDAG->getConstant(IPM.Bit, DL, MVT::i32)); + Result = CurDAG->getNode(ISD::AND, DL, VT, Result, + CurDAG->getConstant(1, DL, VT)); + } else { + // Sign-extend from IPM.Bit using a pair of shifts. + int ShlAmt = VT.getSizeInBits() - 1 - IPM.Bit; + int SraAmt = VT.getSizeInBits() - 1; + Result = CurDAG->getNode(ISD::SHL, DL, VT, Result, + CurDAG->getConstant(ShlAmt, DL, MVT::i32)); + Result = CurDAG->getNode(ISD::SRA, DL, VT, Result, + CurDAG->getConstant(SraAmt, DL, MVT::i32)); + } + } + + return Result; +} + +void SystemZDAGToDAGISel::PreprocessISelDAG() { + bool MadeChange = false; + + for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), + E = CurDAG->allnodes_end(); + I != E;) { + SDNode *N = &*I++; + if (N->use_empty()) + continue; + + SDValue Res; + switch (N->getOpcode()) { + default: break; + case SystemZISD::SELECT_CCMASK: + Res = expandSelectBoolean(N); + break; + } + + if (Res) { + DEBUG(dbgs() << "SystemZ DAG preprocessing replacing:\nOld: "); + DEBUG(N->dump(CurDAG)); + DEBUG(dbgs() << "\nNew: "); + DEBUG(Res.getNode()->dump(CurDAG)); + DEBUG(dbgs() << "\n"); + + CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), Res); + MadeChange = true; + } + } + + if (MadeChange) + CurDAG->RemoveDeadNodes(); +} + 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); diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index 589ab9f602c..a74ca69c08b 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -571,7 +571,9 @@ private: bool Force) const; SDValue combineTruncateExtract(const SDLoc &DL, EVT TruncVT, SDValue Op, DAGCombinerInfo &DCI) const; + SDValue combineZERO_EXTEND(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineSIGN_EXTEND(SDNode *N, DAGCombinerInfo &DCI) const; + SDValue combineSIGN_EXTEND_INREG(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineMERGE(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineSTORE(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineEXTRACT_VECTOR_ELT(SDNode *N, DAGCombinerInfo &DCI) const; diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index abb804597f4..5c874dea087 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -2131,18 +2131,6 @@ def : Pat<(add GR64:$src1, imm64zx32n:$src2), def : Pat<(sub GR64:$src1, (azextloadi32 bdxaddr20only:$addr)), (SLGF GR64:$src1, bdxaddr20only:$addr)>; -// Optimize sign-extended 1/0 selects to -1/0 selects. This is important -// for vector legalization. -def : Pat<(sra (shl (i32 (z_select_ccmask 1, 0, imm32zx4:$valid, imm32zx4:$cc)), - (i32 31)), - (i32 31)), - (Select32 (LHI -1), (LHI 0), imm32zx4:$valid, imm32zx4:$cc)>; -def : Pat<(sra (shl (i64 (anyext (i32 (z_select_ccmask 1, 0, imm32zx4:$valid, - imm32zx4:$cc)))), - (i32 63)), - (i32 63)), - (Select64 (LGHI -1), (LGHI 0), imm32zx4:$valid, imm32zx4:$cc)>; - // Avoid generating 2 XOR instructions. (xor (and x, y), y) is // equivalent to (and (xor x, -1), y) def : Pat<(and (xor GR64:$x, (i64 -1)), GR64:$y), diff --git a/llvm/test/CodeGen/SystemZ/branch-07.ll b/llvm/test/CodeGen/SystemZ/branch-07.ll index 857c9cb17ad..bac607133a8 100644 --- a/llvm/test/CodeGen/SystemZ/branch-07.ll +++ b/llvm/test/CodeGen/SystemZ/branch-07.ll @@ -129,8 +129,8 @@ define void @f9(i64 %a, i64 %b, <2 x i64> *%dest) { ; CHECK-LABEL: f9: ; CHECK: ipm [[REG:%r[0-5]]] ; CHECK: afi [[REG]], -268435456 -; CHECK: risbg [[REG2:%r[0-5]]], [[REG]], 63, 191, 33 -; CHECK: lcgr {{%r[0-5]}}, [[REG2]] +; CHECK: sllg [[REG2:%r[0-5]]], [[REG]], 32 +; CHECK: srag {{%r[0-5]}}, [[REG2]], 63 ; CHECK: br %r14 %avec = bitcast i64 %a to <2 x i32> %bvec = bitcast i64 %b to <2 x i32> @@ -145,8 +145,8 @@ define void @f10(i64 %a, i64 %b, <2 x i64> *%dest) { ; CHECK-LABEL: f10: ; CHECK: ipm [[REG:%r[0-5]]] ; CHECK: afi [[REG]], 1879048192 -; CHECK: risbg [[REG2:%r[0-5]]], [[REG]], 63, 191, 33 -; CHECK: lcgr {{%r[0-5]}}, [[REG2]] +; CHECK: sllg [[REG2:%r[0-5]]], [[REG]], 32 +; CHECK: srag {{%r[0-5]}}, [[REG2]], 63 ; CHECK: br %r14 %avec = bitcast i64 %a to <2 x i32> %bvec = bitcast i64 %b to <2 x i32> diff --git a/llvm/test/CodeGen/SystemZ/setcc-03.ll b/llvm/test/CodeGen/SystemZ/setcc-03.ll new file mode 100644 index 00000000000..0a125f02aac --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/setcc-03.ll @@ -0,0 +1,73 @@ +; Test SETCC with an i32 result for every integer condition. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s + +; Test CC in { 0 }, with 3 don't care. +define i64 @f1(i32 %a, i32 %b) { +; CHECK-LABEL: f1: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -268435456 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = icmp eq i32 %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 1 }, with 3 don't care. +define i64 @f2(i32 %a, i32 %b) { +; CHECK-LABEL: f2: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 36 +; CHECK: br %r14 + %cond = icmp slt i32 %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 0, 1 }, with 3 don't care. +define i64 @f3(i32 %a, i32 %b) { +; CHECK-LABEL: f3: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -536870912 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = icmp sle i32 %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 2 }, with 3 don't care. +define i64 @f4(i32 %a, i32 %b) { +; CHECK-LABEL: f4: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 35 +; CHECK: br %r14 + %cond = icmp sgt i32 %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 0, 2 }, with 3 don't care. +define i64 @f5(i32 %a, i32 %b) { +; CHECK-LABEL: f5: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 4294967295 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 36 +; CHECK: br %r14 + %cond = icmp sge i32 %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 1, 2 }, with 3 don't care. +define i64 @f6(i32 %a, i32 %b) { +; CHECK-LABEL: f6: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], 1879048192 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = icmp ne i32 %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} diff --git a/llvm/test/CodeGen/SystemZ/setcc-04.ll b/llvm/test/CodeGen/SystemZ/setcc-04.ll new file mode 100644 index 00000000000..91ea11e850a --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/setcc-04.ll @@ -0,0 +1,173 @@ +; Test SETCC with an i64 result for every floating-point condition. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s + +; Test CC in { 0 } +define i64 @f1(float %a, float %b) { +; CHECK-LABEL: f1: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -268435456 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = fcmp oeq float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 1 } +define i64 @f2(float %a, float %b) { +; CHECK-LABEL: f2: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 268435456 +; CHECK-NEXT: afi [[REG]], -268435456 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = fcmp olt float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 0, 1 } +define i64 @f3(float %a, float %b) { +; CHECK-LABEL: f3: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -536870912 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = fcmp ole float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 2 } +define i64 @f4(float %a, float %b) { +; CHECK-LABEL: f4: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 268435456 +; CHECK-NEXT: afi [[REG]], 1342177280 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = fcmp ogt float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 0, 2 } +define i64 @f5(float %a, float %b) { +; CHECK-LABEL: f5: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 4294967295 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 36 +; CHECK: br %r14 + %cond = fcmp oge float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 1, 2 } +define i64 @f6(float %a, float %b) { +; CHECK-LABEL: f6: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], 268435456 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 35 +; CHECK: br %r14 + %cond = fcmp one float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 0, 1, 2 } +define i64 @f7(float %a, float %b) { +; CHECK-LABEL: f7: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -805306368 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = fcmp ord float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 3 } +define i64 @f8(float %a, float %b) { +; CHECK-LABEL: f8: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], 1342177280 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = fcmp uno float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 0, 3 } +define i64 @f9(float %a, float %b) { +; CHECK-LABEL: f9: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], -268435456 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 35 +; CHECK: br %r14 + %cond = fcmp ueq float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 1, 3 } +define i64 @f10(float %a, float %b) { +; CHECK-LABEL: f10: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 36 +; CHECK: br %r14 + %cond = fcmp ult float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 0, 1, 3 } +define i64 @f11(float %a, float %b) { +; CHECK-LABEL: f11: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 268435456 +; CHECK-NEXT: afi [[REG]], -805306368 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = fcmp ule float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 2, 3 } +define i64 @f12(float %a, float %b) { +; CHECK-LABEL: f12: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 35 +; CHECK: br %r14 + %cond = fcmp ugt float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 0, 2, 3 } +define i64 @f13(float %a, float %b) { +; CHECK-LABEL: f13: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: xilf [[REG]], 268435456 +; CHECK-NEXT: afi [[REG]], 1879048192 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = fcmp uge float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} + +; Test CC in { 1, 2, 3 } +define i64 @f14(float %a, float %b) { +; CHECK-LABEL: f14: +; CHECK: ipm [[REG:%r[0-5]]] +; CHECK-NEXT: afi [[REG]], 1879048192 +; CHECK-NEXT: risbg %r2, [[REG]], 63, 191, 33 +; CHECK: br %r14 + %cond = fcmp une float %a, %b + %res = zext i1 %cond to i64 + ret i64 %res +} |

