From 261e2877ebcb3c6139ddcc67992662494232b096 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 11 Jul 2013 09:10:09 +0000 Subject: [PATCH] [SystemZ] Use zeroing form of RISBG for shift-and-AND sequences Extend r186072 to handle shifts and ANDs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186073 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 71 +++++++++++++++++++++++++++--- test/CodeGen/SystemZ/fp-move-02.ll | 4 +- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index 5b1b77b2d56..39589f6d201 100644 --- a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -613,20 +613,81 @@ SDNode *SystemZDAGToDAGISel::tryRISBGForAND(SDNode *N) { unsigned Start, End; ConstantSDNode *MaskNode = dyn_cast(N->getOperand(1).getNode()); - if (!MaskNode - || !isRISBGMask(MaskNode->getZExtValue(), BitSize, Start, End)) + if (!MaskNode) return 0; + SDValue Input = N->getOperand(0); + uint64_t Mask = MaskNode->getZExtValue(); + if (!isRISBGMask(Mask, BitSize, Start, End)) { + APInt KnownZero, KnownOne; + CurDAG->ComputeMaskedBits(Input, KnownZero, KnownOne); + Mask |= KnownZero.getZExtValue(); + if (!isRISBGMask(Mask, BitSize, Start, End)) + return 0; + } + + unsigned Rotate = 0; + if (Input->getOpcode() == ISD::ROTL && BitSize == 64) { + // Any 64-bit rotate left can be merged into the RISBG. + if (ConstantSDNode *CountNode = + dyn_cast(Input.getOperand(1).getNode())) { + Rotate = CountNode->getZExtValue() & (BitSize - 1); + Input = Input->getOperand(0); + } + } else if (Input->getOpcode() == ISD::SHL) { + // Try to convert (and (shl X, count), mask) into + // (and (rotl X, count), mask&(~0<(Input.getOperand(1).getNode())) { + uint64_t Count = CountNode->getZExtValue(); + if (Count > 0 && + Count < BitSize && + isRISBGMask(Mask & (allOnes(BitSize - Count) << Count), + BitSize, Start, End)) { + Rotate = Count; + Input = Input->getOperand(0); + } + } + } else if (Input->getOpcode() == ISD::SRL) { + // Try to convert (and (srl X, count), mask) into + // (and (rotl X, size-count), mask&(~0>>count)), which is similar + // to SLL above. + if (ConstantSDNode *CountNode = + dyn_cast(Input.getOperand(1).getNode())) { + uint64_t Count = CountNode->getZExtValue(); + if (Count > 0 && + Count < BitSize && + isRISBGMask(Mask & allOnes(BitSize - Count), BitSize, Start, End)) { + Rotate = 64 - Count; + Input = Input->getOperand(0); + } + } + } else if (Start <= End && Input->getOpcode() == ISD::SRA) { + // Try to convert (and (sra X, count), mask) into + // (and (rotl X, size-count), mask). The mask must not include + // any sign bits. + if (ConstantSDNode *CountNode = + dyn_cast(Input.getOperand(1).getNode())) { + uint64_t Count = CountNode->getZExtValue(); + if (Count > 0 && Count < BitSize && Start >= 64 - (BitSize - Count)) { + Rotate = 64 - Count; + Input = Input->getOperand(0); + } + } + } + // Prefer register extensions like LLC over RSIBG. - if ((Start == 32 || Start == 48 || Start == 56) && End == 63) + if (Rotate == 0 && (Start == 32 || Start == 48 || Start == 56) && End == 63) return 0; SDValue Ops[5] = { getUNDEF64(SDLoc(N)), - convertTo(SDLoc(N), MVT::i64, N->getOperand(0)), + convertTo(SDLoc(N), MVT::i64, Input), CurDAG->getTargetConstant(Start, MVT::i32), CurDAG->getTargetConstant(End | 128, MVT::i32), - CurDAG->getTargetConstant(0, MVT::i32) + CurDAG->getTargetConstant(Rotate, MVT::i32) }; N = CurDAG->getMachineNode(SystemZ::RISBG, SDLoc(N), MVT::i64, Ops); return convertTo(SDLoc(N), VT, SDValue(N, 0)).getNode(); diff --git a/test/CodeGen/SystemZ/fp-move-02.ll b/test/CodeGen/SystemZ/fp-move-02.ll index a02c8564125..f828b2d1ad4 100644 --- a/test/CodeGen/SystemZ/fp-move-02.ll +++ b/test/CodeGen/SystemZ/fp-move-02.ll @@ -16,7 +16,7 @@ define float @f1(i32 %a) { ; surrounding code. define float @f2(i64 %big) { ; CHECK: f2: -; CHECK: sllg [[REGISTER:%r[0-5]]], %r2, 31 +; CHECK: risbg [[REGISTER:%r[0-5]]], %r2, 0, 159, 31 ; CHECK: ldgr %f0, [[REGISTER]] %shift = lshr i64 %big, 1 %a = trunc i64 %shift to i32 @@ -27,7 +27,7 @@ define float @f2(i64 %big) { ; Another example of the same thing. define float @f3(i64 %big) { ; CHECK: f3: -; CHECK: sllg [[REGISTER:%r[0-5]]], %r2, 2 +; CHECK: risbg [[REGISTER:%r[0-5]]], %r2, 0, 159, 2 ; CHECK: ldgr %f0, [[REGISTER]] %shift = ashr i64 %big, 30 %a = trunc i64 %shift to i32 -- 2.11.0