LLVM  11.0.0git
RISCVISelDAGToDAG.cpp
Go to the documentation of this file.
1 //===-- RISCVISelDAGToDAG.cpp - A dag to dag inst selector for RISCV ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines an instruction selector for the RISCV target.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "RISCVISelDAGToDAG.h"
15 #include "Utils/RISCVMatInt.h"
17 #include "llvm/Support/Debug.h"
20 
21 using namespace llvm;
22 
23 #define DEBUG_TYPE "riscv-isel"
24 
26  doPeepholeLoadStoreADDI();
27 }
28 
29 static SDNode *selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm,
30  MVT XLenVT) {
32  RISCVMatInt::generateInstSeq(Imm, XLenVT == MVT::i64, Seq);
33 
34  SDNode *Result = nullptr;
35  SDValue SrcReg = CurDAG->getRegister(RISCV::X0, XLenVT);
36  for (RISCVMatInt::Inst &Inst : Seq) {
37  SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, XLenVT);
38  if (Inst.Opc == RISCV::LUI)
39  Result = CurDAG->getMachineNode(RISCV::LUI, DL, XLenVT, SDImm);
40  else
41  Result = CurDAG->getMachineNode(Inst.Opc, DL, XLenVT, SrcReg, SDImm);
42 
43  // Only the first instruction has X0 as its source.
44  SrcReg = SDValue(Result, 0);
45  }
46 
47  return Result;
48 }
49 
50 // Returns true if the Node is an ISD::AND with a constant argument. If so,
51 // set Mask to that constant value.
52 static bool isConstantMask(SDNode *Node, uint64_t &Mask) {
53  if (Node->getOpcode() == ISD::AND &&
54  Node->getOperand(1).getOpcode() == ISD::Constant) {
55  Mask = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
56  return true;
57  }
58  return false;
59 }
60 
62  // If we have a custom node, we have already selected.
63  if (Node->isMachineOpcode()) {
64  LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
65  Node->setNodeId(-1);
66  return;
67  }
68 
69  // Instruction Selection not handled by the auto-generated tablegen selection
70  // should be handled here.
71  unsigned Opcode = Node->getOpcode();
72  MVT XLenVT = Subtarget->getXLenVT();
73  SDLoc DL(Node);
74  EVT VT = Node->getValueType(0);
75 
76  switch (Opcode) {
77  case ISD::Constant: {
78  auto ConstNode = cast<ConstantSDNode>(Node);
79  if (VT == XLenVT && ConstNode->isNullValue()) {
81  RISCV::X0, XLenVT);
82  ReplaceNode(Node, New.getNode());
83  return;
84  }
85  int64_t Imm = ConstNode->getSExtValue();
86  if (XLenVT == MVT::i64) {
87  ReplaceNode(Node, selectImm(CurDAG, SDLoc(Node), Imm, XLenVT));
88  return;
89  }
90  break;
91  }
92  case ISD::FrameIndex: {
93  SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT);
94  int FI = cast<FrameIndexSDNode>(Node)->getIndex();
95  SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
96  ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm));
97  return;
98  }
99  case ISD::SRL: {
100  if (!Subtarget->is64Bit())
101  break;
102  SDValue Op0 = Node->getOperand(0);
103  SDValue Op1 = Node->getOperand(1);
104  uint64_t Mask;
105  // Match (srl (and val, mask), imm) where the result would be a
106  // zero-extended 32-bit integer. i.e. the mask is 0xffffffff or the result
107  // is equivalent to this (SimplifyDemandedBits may have removed lower bits
108  // from the mask that aren't necessary due to the right-shifting).
109  if (Op1.getOpcode() == ISD::Constant &&
110  isConstantMask(Op0.getNode(), Mask)) {
111  uint64_t ShAmt = cast<ConstantSDNode>(Op1.getNode())->getZExtValue();
112 
113  if ((Mask | maskTrailingOnes<uint64_t>(ShAmt)) == 0xffffffff) {
114  SDValue ShAmtVal =
115  CurDAG->getTargetConstant(ShAmt, SDLoc(Node), XLenVT);
116  CurDAG->SelectNodeTo(Node, RISCV::SRLIW, XLenVT, Op0.getOperand(0),
117  ShAmtVal);
118  return;
119  }
120  }
121  break;
122  }
124  assert(!Subtarget->is64Bit() && "READ_CYCLE_WIDE is only used on riscv32");
125 
126  ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ReadCycleWide, DL, MVT::i32,
128  Node->getOperand(0)));
129  return;
130  }
131 
132  // Select the default instruction.
133  SelectCode(Node);
134 }
135 
137  const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
138  switch (ConstraintID) {
140  // We just support simple memory operands that have a single address
141  // operand and need no special handling.
142  OutOps.push_back(Op);
143  return false;
145  OutOps.push_back(Op);
146  return false;
147  default:
148  break;
149  }
150 
151  return true;
152 }
153 
155  if (auto FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
156  Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT());
157  return true;
158  }
159  return false;
160 }
161 
162 // Merge an ADDI into the offset of a load/store instruction where possible.
163 // (load (add base, off), 0) -> (load base, off)
164 // (store val, (add base, off)) -> (store val, base, off)
165 void RISCVDAGToDAGISel::doPeepholeLoadStoreADDI() {
167  ++Position;
168 
169  while (Position != CurDAG->allnodes_begin()) {
170  SDNode *N = &*--Position;
171  // Skip dead nodes and any non-machine opcodes.
172  if (N->use_empty() || !N->isMachineOpcode())
173  continue;
174 
175  int OffsetOpIdx;
176  int BaseOpIdx;
177 
178  // Only attempt this optimisation for I-type loads and S-type stores.
179  switch (N->getMachineOpcode()) {
180  default:
181  continue;
182  case RISCV::LB:
183  case RISCV::LH:
184  case RISCV::LW:
185  case RISCV::LBU:
186  case RISCV::LHU:
187  case RISCV::LWU:
188  case RISCV::LD:
189  case RISCV::FLW:
190  case RISCV::FLD:
191  BaseOpIdx = 0;
192  OffsetOpIdx = 1;
193  break;
194  case RISCV::SB:
195  case RISCV::SH:
196  case RISCV::SW:
197  case RISCV::SD:
198  case RISCV::FSW:
199  case RISCV::FSD:
200  BaseOpIdx = 1;
201  OffsetOpIdx = 2;
202  break;
203  }
204 
205  // Currently, the load/store offset must be 0 to be considered for this
206  // peephole optimisation.
207  if (!isa<ConstantSDNode>(N->getOperand(OffsetOpIdx)) ||
208  N->getConstantOperandVal(OffsetOpIdx) != 0)
209  continue;
210 
211  SDValue Base = N->getOperand(BaseOpIdx);
212 
213  // If the base is an ADDI, we can merge it in to the load/store.
214  if (!Base.isMachineOpcode() || Base.getMachineOpcode() != RISCV::ADDI)
215  continue;
216 
217  SDValue ImmOperand = Base.getOperand(1);
218 
219  if (auto Const = dyn_cast<ConstantSDNode>(ImmOperand)) {
220  ImmOperand = CurDAG->getTargetConstant(
221  Const->getSExtValue(), SDLoc(ImmOperand), ImmOperand.getValueType());
222  } else if (auto GA = dyn_cast<GlobalAddressSDNode>(ImmOperand)) {
223  ImmOperand = CurDAG->getTargetGlobalAddress(
224  GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(),
225  GA->getOffset(), GA->getTargetFlags());
226  } else if (auto CP = dyn_cast<ConstantPoolSDNode>(ImmOperand)) {
227  ImmOperand = CurDAG->getTargetConstantPool(
228  CP->getConstVal(), ImmOperand.getValueType(), CP->getAlign(),
229  CP->getOffset(), CP->getTargetFlags());
230  } else {
231  continue;
232  }
233 
234  LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: ");
235  LLVM_DEBUG(Base->dump(CurDAG));
236  LLVM_DEBUG(dbgs() << "\nN: ");
237  LLVM_DEBUG(N->dump(CurDAG));
238  LLVM_DEBUG(dbgs() << "\n");
239 
240  // Modify the offset operand of the load/store.
241  if (BaseOpIdx == 0) // Load
242  CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand,
243  N->getOperand(2));
244  else // Store
245  CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0),
246  ImmOperand, N->getOperand(3));
247 
248  // The add-immediate may now be dead, in which case remove it.
249  if (Base.getNode()->use_empty())
250  CurDAG->RemoveDeadNode(Base.getNode());
251  }
252 }
253 
254 // This pass converts a legalized DAG into a RISCV-specific DAG, ready
255 // for instruction scheduling.
257  return new RISCVDAGToDAGISel(TM);
258 }
static bool isConstantMask(SDNode *Node, uint64_t &Mask)
SDNode * SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT)
These are used for target selectors to mutate the specified node to have the specified return type...
EVT getValueType() const
Return the ValueType of the referenced return value.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=None, int Offset=0, unsigned TargetFlags=0)
Definition: SelectionDAG.h:669
void setNodeId(int Id)
Set unique node id.
SDNode * getNode() const
get the SDNode which holds the desired result
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode...
void Select(SDNode *Node) override
Main hook for targets to transform nodes into machine nodes.
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s), MachineInstr opcode, and operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:486
std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:80
Position
Position to insert a new instruction relative to an existing instruction.
FunctionPass * createRISCVISelDag(RISCVTargetMachine &TM)
SDValue getTargetFrameIndex(int FI, EVT VT)
Definition: SelectionDAG.h:658
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:607
Machine Value Type.
This instruction implements an extending load to FP stack slots.
bool isMachineOpcode() const
const SDValue & getOperand(unsigned Num) const
bool SelectAddrFI(SDValue Addr, SDValue &Base)
unsigned getMachineOpcode() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:281
void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
Extended Value Type.
Definition: ValueTypes.h:35
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
bool use_empty() const
Return true if there are no uses of this node.
void dump() const
Dump this node, for debugging.
Iterator for intrusive lists based on ilist_node.
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
Definition: SelectionDAG.h:653
SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:223
static SDNode * selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm, MVT XLenVT)
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:883
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
allnodes_const_iterator allnodes_begin() const
Definition: SelectionDAG.h:463
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine)
void PostprocessISelDAG() override
PostprocessISelDAG() - This hook allows the target to hack on the graph right after selection...
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:550
void generateInstSeq(int64_t Val, bool IsRV64, InstSeq &Res)
Definition: RISCVMatInt.cpp:19
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
Definition: SelectionDAG.h:733
#define N
unsigned getOpcode() const
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
Definition: SelectionDAG.h:483
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
SDValue getRegister(unsigned Reg, EVT VT)
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
const SDValue & getOperand(unsigned i) const
#define LLVM_DEBUG(X)
Definition: Debug.h:122
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...