From 440285200265eca0e148cb838f83fa7cbc37c640 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 2 Jun 2022 22:08:51 -0700 Subject: [PATCH] [RISCV] Reduce scalar load/store isel patterns to a single ComplexPattern. NFCI Previously we had 3 different isel patterns for every scalar load store instruction. This reduces them to a single ComplexPattern that returns the Base and Offset. Or an offset of 0 if there was no offset identified I've done a similar thing for the 2 isel patterns that match add/or with FrameIndex and immediate. Using the offset of 0, I was also able to remove the custom handler for FrameIndex. Happy to split that to another patch. We might be able to enhance in the future to remove the post-isel peephole or the special handling for ADD with constant added by D126576. A nice side effect is that this removes nearly 3000 bytes from the isel table. Differential Revision: https://reviews.llvm.org/D126932 --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 61 ++++++++++++++++++--- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h | 3 +- llvm/lib/Target/RISCV/RISCVInstrInfo.td | 28 +++------- llvm/lib/Target/RISCV/RISCVInstrInfoA.td | 8 +-- 4 files changed, 66 insertions(+), 34 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index b6606161c491..6ddb75337bb9 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -691,13 +691,6 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { 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 @@ bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( 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 @@ bool RISCVDAGToDAGISel::SelectBaseAddr(SDValue Addr, SDValue &Base) { 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/RISCVISelDAGToDAG.h b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h index 8ddc5c32a3da..d4eadb5f1b3e 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h @@ -45,8 +45,9 @@ public: 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/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 5034e380c9ae..f6f85ab9a6bd 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -367,8 +367,10 @@ def uimm6gt32 : ImmLeaf; +def FrameAddrRegImm : ComplexPattern; def BaseAddr : ComplexPattern; +def AddrRegImm : ComplexPattern; // Return the negation of an immediate value. def NegImm : SDNodeXForm /// Predicates -def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ - return isOrEquivalentToAdd(N); -}]>; def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{ return cast(N->getOperand(1))->getVT().bitsLE(MVT::i32); }]>; @@ -1205,10 +1204,8 @@ def PseudoAddTPRel : Pseudo<(outs GPR:$rd), /// 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 @@ def PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs /// 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 @@ defm : LdPat; 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 index eaef8cdc2fb8..dd4b174d7e62 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td @@ -45,12 +45,8 @@ multiclass AMO_rr_aq_rl funct5, bits<3> funct3, string opcodestr> { 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)>; } //===----------------------------------------------------------------------===//