// 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) {}
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"
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();
+}
+
#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)
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);
#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) {
// 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
}
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,
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
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);
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;
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),
; 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>
; 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>
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}