diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h @@ -45,8 +45,9 @@ bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector &OutOps) override; - bool SelectAddrFI(SDValue Addr, SDValue &Base); + bool SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset); bool SelectBaseAddr(SDValue Addr, SDValue &Base); + bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset); bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt); bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) { diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -691,13 +691,6 @@ ReplaceNode(Node, selectImm(CurDAG, DL, VT, Imm, *Subtarget)); return; } - case ISD::FrameIndex: { - SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT); - int FI = cast(Node)->getIndex(); - SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); - ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm)); - return; - } case ISD::ADD: { // Try to select ADD + immediate used as memory addresses to // (ADDI (ADD X, Imm-Lo12), Lo12) if it will allow the ADDI to be removed by @@ -1861,11 +1854,31 @@ return true; } -bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { +// Select a frame index and an optional immediate offset from an ADD or OR. +bool RISCVDAGToDAGISel::SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, + SDValue &Offset) { if (auto *FIN = dyn_cast(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT()); + Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Subtarget->getXLenVT()); return true; } + + // TODO: Use SelectionDAG::isBaseWithConstantOffset. + if (Addr.getOpcode() == ISD::ADD || + (Addr.getOpcode() == ISD::OR && isOrEquivalentToAdd(Addr.getNode()))) { + if (auto *FIN = dyn_cast(Addr.getOperand(0))) { + if (auto *CN = dyn_cast(Addr.getOperand(1))) { + if (isInt<12>(CN->getSExtValue())) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), + Subtarget->getXLenVT()); + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), + Subtarget->getXLenVT()); + return true; + } + } + } + } + return false; } @@ -1879,6 +1892,38 @@ return true; } +bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::ADD) { + if (auto *CN = dyn_cast(Addr.getOperand(1))) { + if (isInt<12>(CN->getSExtValue())) { + SelectBaseAddr(Addr.getOperand(0), Base); + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), + Subtarget->getXLenVT()); + return true; + } + } + } else if (Addr.getOpcode() == ISD::OR) { + // We might be able to treat this OR as an ADD. + // TODO: Use SelectionDAG::isBaseWithConstantOffset. + if (auto *FIN = dyn_cast(Addr.getOperand(0))) { + if (auto *CN = dyn_cast(Addr.getOperand(1))) { + if (isInt<12>(CN->getSExtValue()) && + isOrEquivalentToAdd(Addr.getNode())) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), + Subtarget->getXLenVT()); + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), + Subtarget->getXLenVT()); + return true; + } + } + } + } + + Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Subtarget->getXLenVT()); + return SelectBaseAddr(Addr, Base); +} + bool RISCVDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt) { // Shift instructions on RISCV only read the lower 5 or 6 bits of the shift diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -367,8 +367,10 @@ // Addressing modes. // Necessary because a frameindex can't be matched directly in a pattern. -def AddrFI : ComplexPattern; +def FrameAddrRegImm : ComplexPattern; def BaseAddr : ComplexPattern; +def AddrRegImm : ComplexPattern; // Return the negation of an immediate value. def NegImm : SDNodeXForm; def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{ return cast(N->getOperand(1))->getVT().bitsLE(MVT::i32); }]>; @@ -1205,10 +1204,8 @@ /// FrameIndex calculations -def : Pat<(add (XLenVT AddrFI:$Rs), simm12:$imm12), - (ADDI (XLenVT AddrFI:$Rs), simm12:$imm12)>; -def : Pat<(IsOrAdd (XLenVT AddrFI:$Rs), simm12:$imm12), - (ADDI (XLenVT AddrFI:$Rs), simm12:$imm12)>; +def : Pat<(FrameAddrRegImm GPR:$rs1, simm12:$imm12), + (ADDI GPR:$rs1, simm12:$imm12)>; /// Setcc @@ -1397,11 +1394,8 @@ /// Loads multiclass LdPat { - def : Pat<(vt (LoadOp BaseAddr:$rs1)), (Inst BaseAddr:$rs1, 0)>; - def : Pat<(vt (LoadOp (add BaseAddr:$rs1, simm12:$imm12))), - (Inst BaseAddr:$rs1, simm12:$imm12)>; - def : Pat<(vt (LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12))), - (Inst AddrFI:$rs1, simm12:$imm12)>; + def : Pat<(vt (LoadOp (AddrRegImm GPR:$rs1, simm12:$imm12))), + (Inst GPR:$rs1, simm12:$imm12)>; } defm : LdPat; @@ -1416,12 +1410,8 @@ multiclass StPat { - def : Pat<(StoreOp (vt StTy:$rs2), BaseAddr:$rs1), - (Inst StTy:$rs2, BaseAddr:$rs1, 0)>; - def : Pat<(StoreOp (vt StTy:$rs2), (add BaseAddr:$rs1, simm12:$imm12)), - (Inst StTy:$rs2, BaseAddr:$rs1, simm12:$imm12)>; - def : Pat<(StoreOp (vt StTy:$rs2), (IsOrAdd AddrFI:$rs1, simm12:$imm12)), - (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; + def : Pat<(StoreOp (vt StTy:$rs2), (AddrRegImm GPR:$rs1, simm12:$imm12)), + (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>; } defm : StPat; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td @@ -45,12 +45,8 @@ multiclass AtomicStPat { - def : Pat<(StoreOp BaseAddr:$rs1, (vt StTy:$rs2)), - (Inst StTy:$rs2, BaseAddr:$rs1, 0)>; - def : Pat<(StoreOp (add BaseAddr:$rs1, simm12:$imm12), (vt StTy:$rs2)), - (Inst StTy:$rs2, BaseAddr:$rs1, simm12:$imm12)>; - def : Pat<(StoreOp (IsOrAdd AddrFI:$rs1, simm12:$imm12), (vt StTy:$rs2)), - (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; + def : Pat<(StoreOp (AddrRegImm GPR:$rs1, simm12:$imm12), (vt StTy:$rs2)), + (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>; } //===----------------------------------------------------------------------===//