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" 14 #include "MCTargetDesc/RISCVMCTargetDesc.h" 15 #include "Utils/RISCVMatInt.h" 16 #include "llvm/CodeGen/MachineFrameInfo.h" 17 #include "llvm/Support/Debug.h" 18 #include "llvm/Support/MathExtras.h" 19 #include "llvm/Support/raw_ostream.h" 20 21 using namespace llvm; 22 23 #define DEBUG_TYPE "riscv-isel" 24 25 void RISCVDAGToDAGISel::PostprocessISelDAG() { 26 doPeepholeLoadStoreADDI(); 27 } 28 29 static SDNode *selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm, 30 MVT XLenVT) { 31 RISCVMatInt::InstSeq Seq; 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 61 void RISCVDAGToDAGISel::Select(SDNode *Node) { 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()) { 80 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(Node), 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 } 123 case RISCVISD::READ_CYCLE_WIDE: 124 assert(!Subtarget->is64Bit() && "READ_CYCLE_WIDE is only used on riscv32"); 125 126 ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ReadCycleWide, DL, MVT::i32, 127 MVT::i32, MVT::Other, 128 Node->getOperand(0))); 129 return; 130 } 131 132 // Select the default instruction. 133 SelectCode(Node); 134 } 135 136 bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( 137 const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { 138 switch (ConstraintID) { 139 case InlineAsm::Constraint_m: 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; 144 case InlineAsm::Constraint_A: 145 OutOps.push_back(Op); 146 return false; 147 default: 148 break; 149 } 150 151 return true; 152 } 153 154 bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { 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() { 166 SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode()); 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. 256 FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) { 257 return new RISCVDAGToDAGISel(TM); 258 } 259