Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Line
Count
Source (jump to first uncovered line)
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 "MCTargetDesc/RISCVMCTargetDesc.h"
14
#include "RISCV.h"
15
#include "RISCVTargetMachine.h"
16
#include "Utils/RISCVMatInt.h"
17
#include "llvm/CodeGen/MachineFrameInfo.h"
18
#include "llvm/CodeGen/SelectionDAGISel.h"
19
#include "llvm/Support/Debug.h"
20
#include "llvm/Support/MathExtras.h"
21
#include "llvm/Support/raw_ostream.h"
22
using namespace llvm;
23
24
#define DEBUG_TYPE "riscv-isel"
25
26
// RISCV-specific code to select RISCV machine instructions for
27
// SelectionDAG operations.
28
namespace {
29
class RISCVDAGToDAGISel final : public SelectionDAGISel {
30
  const RISCVSubtarget *Subtarget;
31
32
public:
33
  explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine)
34
329
      : SelectionDAGISel(TargetMachine) {}
35
36
3.36k
  StringRef getPassName() const override {
37
3.36k
    return "RISCV DAG->DAG Pattern Instruction Selection";
38
3.36k
  }
39
40
3.36k
  bool runOnMachineFunction(MachineFunction &MF) override {
41
3.36k
    Subtarget = &MF.getSubtarget<RISCVSubtarget>();
42
3.36k
    return SelectionDAGISel::runOnMachineFunction(MF);
43
3.36k
  }
44
45
  void PostprocessISelDAG() override;
46
47
  void Select(SDNode *Node) override;
48
49
  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
50
                                    std::vector<SDValue> &OutOps) override;
51
52
  bool SelectAddrFI(SDValue Addr, SDValue &Base);
53
54
// Include the pieces autogenerated from the target description.
55
#include "RISCVGenDAGISel.inc"
56
57
private:
58
  void doPeepholeLoadStoreADDI();
59
};
60
}
61
62
3.98k
void RISCVDAGToDAGISel::PostprocessISelDAG() {
63
3.98k
  doPeepholeLoadStoreADDI();
64
3.98k
}
65
66
static SDNode *selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm,
67
741
                         MVT XLenVT) {
68
741
  RISCVMatInt::InstSeq Seq;
69
741
  RISCVMatInt::generateInstSeq(Imm, XLenVT == MVT::i64, Seq);
70
741
71
741
  SDNode *Result;
72
741
  SDValue SrcReg = CurDAG->getRegister(RISCV::X0, XLenVT);
73
1.05k
  for (RISCVMatInt::Inst &Inst : Seq) {
74
1.05k
    SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, XLenVT);
75
1.05k
    if (Inst.Opc == RISCV::LUI)
76
134
      Result = CurDAG->getMachineNode(RISCV::LUI, DL, XLenVT, SDImm);
77
925
    else
78
925
      Result = CurDAG->getMachineNode(Inst.Opc, DL, XLenVT, SrcReg, SDImm);
79
1.05k
80
1.05k
    // Only the first instruction has X0 as its source.
81
1.05k
    SrcReg = SDValue(Result, 0);
82
1.05k
  }
83
741
84
741
  return Result;
85
741
}
86
87
// Returns true if the Node is an ISD::AND with a constant argument. If so,
88
// set Mask to that constant value.
89
30
static bool isConstantMask(SDNode *Node, uint64_t &Mask) {
90
30
  if (Node->getOpcode() == ISD::AND &&
91
30
      
Node->getOperand(1).getOpcode() == ISD::Constant12
) {
92
12
    Mask = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
93
12
    return true;
94
12
  }
95
18
  return false;
96
18
}
97
98
66.4k
void RISCVDAGToDAGISel::Select(SDNode *Node) {
99
66.4k
  // If we have a custom node, we have already selected.
100
66.4k
  if (Node->isMachineOpcode()) {
101
560
    LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
102
560
    Node->setNodeId(-1);
103
560
    return;
104
560
  }
105
65.8k
106
65.8k
  // Instruction Selection not handled by the auto-generated tablegen selection
107
65.8k
  // should be handled here.
108
65.8k
  unsigned Opcode = Node->getOpcode();
109
65.8k
  MVT XLenVT = Subtarget->getXLenVT();
110
65.8k
  SDLoc DL(Node);
111
65.8k
  EVT VT = Node->getValueType(0);
112
65.8k
113
65.8k
  switch (Opcode) {
114
65.8k
  case ISD::Constant: {
115
2.61k
    auto ConstNode = cast<ConstantSDNode>(Node);
116
2.61k
    if (VT == XLenVT && ConstNode->isNullValue()) {
117
597
      SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(Node),
118
597
                                           RISCV::X0, XLenVT);
119
597
      ReplaceNode(Node, New.getNode());
120
597
      return;
121
597
    }
122
2.02k
    int64_t Imm = ConstNode->getSExtValue();
123
2.02k
    if (XLenVT == MVT::i64) {
124
741
      ReplaceNode(Node, selectImm(CurDAG, SDLoc(Node), Imm, XLenVT));
125
741
      return;
126
741
    }
127
1.27k
    break;
128
1.27k
  }
129
1.27k
  case ISD::FrameIndex: {
130
422
    SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT);
131
422
    int FI = cast<FrameIndexSDNode>(Node)->getIndex();
132
422
    SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
133
422
    ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm));
134
422
    return;
135
1.27k
  }
136
1.27k
  case ISD::SRL: {
137
247
    if (!Subtarget->is64Bit())
138
206
      break;
139
41
    SDValue Op0 = Node->getOperand(0);
140
41
    SDValue Op1 = Node->getOperand(1);
141
41
    uint64_t Mask;
142
41
    // Match (srl (and val, mask), imm) where the result would be a
143
41
    // zero-extended 32-bit integer. i.e. the mask is 0xffffffff or the result
144
41
    // is equivalent to this (SimplifyDemandedBits may have removed lower bits
145
41
    // from the mask that aren't necessary due to the right-shifting).
146
41
    if (Op1.getOpcode() == ISD::Constant &&
147
41
        
isConstantMask(Op0.getNode(), Mask)30
) {
148
12
      uint64_t ShAmt = cast<ConstantSDNode>(Op1.getNode())->getZExtValue();
149
12
150
12
      if ((Mask | maskTrailingOnes<uint64_t>(ShAmt)) == 0xffffffff) {
151
10
        SDValue ShAmtVal =
152
10
            CurDAG->getTargetConstant(ShAmt, SDLoc(Node), XLenVT);
153
10
        CurDAG->SelectNodeTo(Node, RISCV::SRLIW, XLenVT, Op0.getOperand(0),
154
10
                             ShAmtVal);
155
10
        return;
156
10
      }
157
31
    }
158
31
    break;
159
31
  }
160
31
  case RISCVISD::READ_CYCLE_WIDE:
161
1
    assert(!Subtarget->is64Bit() && "READ_CYCLE_WIDE is only used on riscv32");
162
1
163
1
    ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ReadCycleWide, DL, MVT::i32,
164
1
                                             MVT::i32, MVT::Other,
165
1
                                             Node->getOperand(0)));
166
1
    return;
167
64.1k
  }
168
64.1k
169
64.1k
  // Select the default instruction.
170
64.1k
  SelectCode(Node);
171
64.1k
}
172
173
bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand(
174
4
    const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
175
4
  switch (ConstraintID) {
176
4
  case InlineAsm::Constraint_i:
177
4
  case InlineAsm::Constraint_m:
178
4
    // We just support simple memory operands that have a single address
179
4
    // operand and need no special handling.
180
4
    OutOps.push_back(Op);
181
4
    return false;
182
4
  default:
183
0
    break;
184
0
  }
185
0
186
0
  return true;
187
0
}
188
189
8.20k
bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) {
190
8.20k
  if (auto FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
191
1.85k
    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT());
192
1.85k
    return true;
193
1.85k
  }
194
6.34k
  return false;
195
6.34k
}
196
197
// Merge an ADDI into the offset of a load/store instruction where possible.
198
// (load (add base, off), 0) -> (load base, off)
199
// (store val, (add base, off)) -> (store val, base, off)
200
3.98k
void RISCVDAGToDAGISel::doPeepholeLoadStoreADDI() {
201
3.98k
  SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode());
202
3.98k
  ++Position;
203
3.98k
204
67.9k
  while (Position != CurDAG->allnodes_begin()) {
205
63.9k
    SDNode *N = &*--Position;
206
63.9k
    // Skip dead nodes and any non-machine opcodes.
207
63.9k
    if (N->use_empty() || 
!N->isMachineOpcode()59.9k
)
208
45.1k
      continue;
209
18.8k
210
18.8k
    int OffsetOpIdx;
211
18.8k
    int BaseOpIdx;
212
18.8k
213
18.8k
    // Only attempt this optimisation for I-type loads and S-type stores.
214
18.8k
    switch (N->getMachineOpcode()) {
215
18.8k
    default:
216
13.1k
      continue;
217
18.8k
    case RISCV::LB:
218
2.54k
    case RISCV::LH:
219
2.54k
    case RISCV::LW:
220
2.54k
    case RISCV::LBU:
221
2.54k
    case RISCV::LHU:
222
2.54k
    case RISCV::LWU:
223
2.54k
    case RISCV::LD:
224
2.54k
    case RISCV::FLW:
225
2.54k
    case RISCV::FLD:
226
2.54k
      BaseOpIdx = 0;
227
2.54k
      OffsetOpIdx = 1;
228
2.54k
      break;
229
3.11k
    case RISCV::SB:
230
3.11k
    case RISCV::SH:
231
3.11k
    case RISCV::SW:
232
3.11k
    case RISCV::SD:
233
3.11k
    case RISCV::FSW:
234
3.11k
    case RISCV::FSD:
235
3.11k
      BaseOpIdx = 1;
236
3.11k
      OffsetOpIdx = 2;
237
3.11k
      break;
238
5.66k
    }
239
5.66k
240
5.66k
    // Currently, the load/store offset must be 0 to be considered for this
241
5.66k
    // peephole optimisation.
242
5.66k
    if (!isa<ConstantSDNode>(N->getOperand(OffsetOpIdx)) ||
243
5.66k
        N->getConstantOperandVal(OffsetOpIdx) != 0)
244
3.39k
      continue;
245
2.27k
246
2.27k
    SDValue Base = N->getOperand(BaseOpIdx);
247
2.27k
248
2.27k
    // If the base is an ADDI, we can merge it in to the load/store.
249
2.27k
    if (!Base.isMachineOpcode() || 
Base.getMachineOpcode() != RISCV::ADDI387
)
250
1.98k
      continue;
251
292
252
292
    SDValue ImmOperand = Base.getOperand(1);
253
292
254
292
    if (auto Const = dyn_cast<ConstantSDNode>(ImmOperand)) {
255
10
      ImmOperand = CurDAG->getTargetConstant(
256
10
          Const->getSExtValue(), SDLoc(ImmOperand), ImmOperand.getValueType());
257
282
    } else if (auto GA = dyn_cast<GlobalAddressSDNode>(ImmOperand)) {
258
193
      ImmOperand = CurDAG->getTargetGlobalAddress(
259
193
          GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(),
260
193
          GA->getOffset(), GA->getTargetFlags());
261
193
    } else {
262
89
      continue;
263
89
    }
264
203
265
203
    LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase:    ");
266
203
    LLVM_DEBUG(Base->dump(CurDAG));
267
203
    LLVM_DEBUG(dbgs() << "\nN: ");
268
203
    LLVM_DEBUG(N->dump(CurDAG));
269
203
    LLVM_DEBUG(dbgs() << "\n");
270
203
271
203
    // Modify the offset operand of the load/store.
272
203
    if (BaseOpIdx == 0) // Load
273
128
      CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand,
274
128
                                 N->getOperand(2));
275
75
    else // Store
276
75
      CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0),
277
75
                                 ImmOperand, N->getOperand(3));
278
203
279
203
    // The add-immediate may now be dead, in which case remove it.
280
203
    if (Base.getNode()->use_empty())
281
80
      CurDAG->RemoveDeadNode(Base.getNode());
282
203
  }
283
3.98k
}
284
285
// This pass converts a legalized DAG into a RISCV-specific DAG, ready
286
// for instruction scheduling.
287
329
FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) {
288
329
  return new RISCVDAGToDAGISel(TM);
289
329
}