diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp')
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 175 |
1 files changed, 100 insertions, 75 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index c97b14a254cd..cfec46d23d65 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -689,10 +689,16 @@ bool RISCVDAGToDAGISel::trySignedBitfieldInsertInMask(SDNode *Node) { if (!isShiftedMask_32(C1) || isInt<12>(C1)) return false; + // INSBI will clobber the input register in N0. Bail out if we need a copy to + // preserve this value. + SDValue N0 = Node->getOperand(0); + if (!N0.hasOneUse()) + return false; + // If C1 is a shifted mask (but can't be formed as an ORI), // use a bitfield insert of -1. // Transform (or x, C1) - // -> (qc.insbi x, width, shift) + // -> (qc.insbi x, -1, width, shift) const unsigned Leading = llvm::countl_zero((uint32_t)C1); const unsigned Trailing = llvm::countr_zero((uint32_t)C1); const unsigned Width = 32 - Leading - Trailing; @@ -705,7 +711,7 @@ bool RISCVDAGToDAGISel::trySignedBitfieldInsertInMask(SDNode *Node) { SDLoc DL(Node); MVT VT = Node->getSimpleValueType(0); - SDValue Ops[] = {CurDAG->getSignedTargetConstant(-1, DL, VT), + SDValue Ops[] = {N0, CurDAG->getSignedTargetConstant(-1, DL, VT), CurDAG->getTargetConstant(Width, DL, VT), CurDAG->getTargetConstant(Trailing, DL, VT)}; SDNode *BitIns = CurDAG->getMachineNode(RISCV::QC_INSBI, DL, VT, Ops); @@ -2842,56 +2848,6 @@ static bool isWorthFoldingAdd(SDValue Add) { return true; } -bool RISCVDAGToDAGISel::SelectAddrRegRegScale(SDValue Addr, - unsigned MaxShiftAmount, - SDValue &Base, SDValue &Index, - SDValue &Scale) { - EVT VT = Addr.getSimpleValueType(); - auto UnwrapShl = [this, VT, MaxShiftAmount](SDValue N, SDValue &Index, - SDValue &Shift) { - uint64_t ShiftAmt = 0; - Index = N; - - if (N.getOpcode() == ISD::SHL && isa<ConstantSDNode>(N.getOperand(1))) { - // Only match shifts by a value in range [0, MaxShiftAmount]. - if (N.getConstantOperandVal(1) <= MaxShiftAmount) { - Index = N.getOperand(0); - ShiftAmt = N.getConstantOperandVal(1); - } - } - - Shift = CurDAG->getTargetConstant(ShiftAmt, SDLoc(N), VT); - return ShiftAmt != 0; - }; - - if (Addr.getOpcode() == ISD::ADD) { - if (auto *C1 = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { - SDValue AddrB = Addr.getOperand(0); - if (AddrB.getOpcode() == ISD::ADD && - UnwrapShl(AddrB.getOperand(0), Index, Scale) && - !isa<ConstantSDNode>(AddrB.getOperand(1)) && - isInt<12>(C1->getSExtValue())) { - // (add (add (shl A C2) B) C1) -> (add (add B C1) (shl A C2)) - SDValue C1Val = - CurDAG->getTargetConstant(C1->getZExtValue(), SDLoc(Addr), VT); - Base = SDValue(CurDAG->getMachineNode(RISCV::ADDI, SDLoc(Addr), VT, - AddrB.getOperand(1), C1Val), - 0); - return true; - } - } else if (UnwrapShl(Addr.getOperand(0), Index, Scale)) { - Base = Addr.getOperand(1); - return true; - } else { - UnwrapShl(Addr.getOperand(1), Index, Scale); - Base = Addr.getOperand(0); - return true; - } - } - - return false; -} - bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset) { if (SelectAddrFrameIndex(Addr, Base, Offset)) @@ -2908,7 +2864,7 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base, if (CurDAG->isBaseWithConstantOffset(Addr)) { int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue(); - if (isInt<12>(CVal) && isInt<12>(CVal)) { + if (isInt<12>(CVal)) { Base = Addr.getOperand(0); if (Base.getOpcode() == RISCVISD::ADD_LO) { SDValue LoOperand = Base.getOperand(1); @@ -2942,8 +2898,7 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base, // Handle ADD with large immediates. if (Addr.getOpcode() == ISD::ADD && isa<ConstantSDNode>(Addr.getOperand(1))) { int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue(); - assert(!(isInt<12>(CVal) && isInt<12>(CVal)) && - "simm12 not already handled?"); + assert(!isInt<12>(CVal) && "simm12 not already handled?"); // Handle immediates in the range [-4096,-2049] or [2048, 4094]. We can use // an ADDI for part of the offset and fold the rest into the load/store. @@ -2984,12 +2939,11 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base, return true; } -/// Similar to SelectAddrRegImm, except that the offset restricted for -/// unsinged nine bits. +/// Similar to SelectAddrRegImm, except that the offset is restricted to uimm9. bool RISCVDAGToDAGISel::SelectAddrRegImm9(SDValue Addr, SDValue &Base, SDValue &Offset) { - if (SelectAddrFrameIndex(Addr, Base, Offset)) - return true; + // FIXME: Support FrameIndex. Need to teach eliminateFrameIndex that only + // a 9-bit immediate can be folded. SDLoc DL(Addr); MVT VT = Addr.getSimpleValueType(); @@ -2999,8 +2953,8 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm9(SDValue Addr, SDValue &Base, if (isUInt<9>(CVal)) { Base = Addr.getOperand(0); - if (auto *FIN = dyn_cast<FrameIndexSDNode>(Base)) - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT); + // FIXME: Support FrameIndex. Need to teach eliminateFrameIndex that only + // a 9-bit immediate can be folded. Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT); return true; } @@ -3078,6 +3032,80 @@ bool RISCVDAGToDAGISel::SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, return true; } +bool RISCVDAGToDAGISel::SelectAddrRegRegScale(SDValue Addr, + unsigned MaxShiftAmount, + SDValue &Base, SDValue &Index, + SDValue &Scale) { + if (Addr.getOpcode() != ISD::ADD) + return false; + SDValue LHS = Addr.getOperand(0); + SDValue RHS = Addr.getOperand(1); + + EVT VT = Addr.getSimpleValueType(); + auto SelectShl = [this, VT, MaxShiftAmount](SDValue N, SDValue &Index, + SDValue &Shift) { + if (N.getOpcode() != ISD::SHL || !isa<ConstantSDNode>(N.getOperand(1))) + return false; + + // Only match shifts by a value in range [0, MaxShiftAmount]. + unsigned ShiftAmt = N.getConstantOperandVal(1); + if (ShiftAmt > MaxShiftAmount) + return false; + + Index = N.getOperand(0); + Shift = CurDAG->getTargetConstant(ShiftAmt, SDLoc(N), VT); + return true; + }; + + if (auto *C1 = dyn_cast<ConstantSDNode>(RHS)) { + // (add (add (shl A C2) B) C1) -> (add (add B C1) (shl A C2)) + if (LHS.getOpcode() == ISD::ADD && + !isa<ConstantSDNode>(LHS.getOperand(1)) && + isInt<12>(C1->getSExtValue())) { + if (SelectShl(LHS.getOperand(1), Index, Scale)) { + SDValue C1Val = CurDAG->getTargetConstant(*C1->getConstantIntValue(), + SDLoc(Addr), VT); + Base = SDValue(CurDAG->getMachineNode(RISCV::ADDI, SDLoc(Addr), VT, + LHS.getOperand(0), C1Val), + 0); + return true; + } + + // Add is commutative so we need to check both operands. + if (SelectShl(LHS.getOperand(0), Index, Scale)) { + SDValue C1Val = CurDAG->getTargetConstant(*C1->getConstantIntValue(), + SDLoc(Addr), VT); + Base = SDValue(CurDAG->getMachineNode(RISCV::ADDI, SDLoc(Addr), VT, + LHS.getOperand(1), C1Val), + 0); + return true; + } + } + + // Don't match add with constants. + // FIXME: Is this profitable for large constants that have 0s in the lower + // 12 bits that we can materialize with LUI? + return false; + } + + // Try to match a shift on the RHS. + if (SelectShl(RHS, Index, Scale)) { + Base = LHS; + return true; + } + + // Try to match a shift on the LHS. + if (SelectShl(LHS, Index, Scale)) { + Base = RHS; + return true; + } + + Base = LHS; + Index = RHS; + Scale = CurDAG->getTargetConstant(0, SDLoc(Addr), VT); + return true; +} + bool RISCVDAGToDAGISel::SelectAddrRegReg(SDValue Addr, SDValue &Base, SDValue &Offset) { if (Addr.getOpcode() != ISD::ADD) @@ -3776,21 +3804,18 @@ bool RISCVDAGToDAGISel::hasAllNBitUsers(SDNode *Node, unsigned Bits, // Select a constant that can be represented as (sign_extend(imm5) << imm2). bool RISCVDAGToDAGISel::selectSimm5Shl2(SDValue N, SDValue &Simm5, SDValue &Shl2) { - if (auto *C = dyn_cast<ConstantSDNode>(N)) { - int64_t Offset = C->getSExtValue(); - unsigned Shift; - for (Shift = 0; Shift < 4; Shift++) - if (isInt<5>(Offset >> Shift) && ((Offset % (1LL << Shift)) == 0)) - break; - - // Constant cannot be encoded. - if (Shift == 4) - return false; + auto *C = dyn_cast<ConstantSDNode>(N); + if (!C) + return false; - EVT Ty = N->getValueType(0); - Simm5 = CurDAG->getSignedTargetConstant(Offset >> Shift, SDLoc(N), Ty); - Shl2 = CurDAG->getTargetConstant(Shift, SDLoc(N), Ty); - return true; + int64_t Offset = C->getSExtValue(); + for (unsigned Shift = 0; Shift < 4; Shift++) { + if (isInt<5>(Offset >> Shift) && ((Offset % (1LL << Shift)) == 0)) { + EVT VT = N->getValueType(0); + Simm5 = CurDAG->getSignedTargetConstant(Offset >> Shift, SDLoc(N), VT); + Shl2 = CurDAG->getTargetConstant(Shift, SDLoc(N), VT); + return true; + } } return false; |
