Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/Lanai/LanaiISelDAGToDAG.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===//
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 Lanai target.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "LanaiAluCode.h"
14
#include "LanaiMachineFunctionInfo.h"
15
#include "LanaiRegisterInfo.h"
16
#include "LanaiSubtarget.h"
17
#include "LanaiTargetMachine.h"
18
#include "llvm/CodeGen/MachineConstantPool.h"
19
#include "llvm/CodeGen/MachineFrameInfo.h"
20
#include "llvm/CodeGen/MachineFunction.h"
21
#include "llvm/CodeGen/MachineInstrBuilder.h"
22
#include "llvm/CodeGen/MachineRegisterInfo.h"
23
#include "llvm/CodeGen/SelectionDAGISel.h"
24
#include "llvm/IR/CFG.h"
25
#include "llvm/IR/GlobalValue.h"
26
#include "llvm/IR/Instructions.h"
27
#include "llvm/IR/Intrinsics.h"
28
#include "llvm/IR/Type.h"
29
#include "llvm/Support/Debug.h"
30
#include "llvm/Support/ErrorHandling.h"
31
#include "llvm/Support/raw_ostream.h"
32
#include "llvm/Target/TargetMachine.h"
33
34
using namespace llvm;
35
36
#define DEBUG_TYPE "lanai-isel"
37
38
//===----------------------------------------------------------------------===//
39
// Instruction Selector Implementation
40
//===----------------------------------------------------------------------===//
41
42
//===----------------------------------------------------------------------===//
43
// LanaiDAGToDAGISel - Lanai specific code to select Lanai machine
44
// instructions for SelectionDAG operations.
45
//===----------------------------------------------------------------------===//
46
namespace {
47
48
class LanaiDAGToDAGISel : public SelectionDAGISel {
49
public:
50
  explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine)
51
22
      : SelectionDAGISel(TargetMachine) {}
52
53
92
  bool runOnMachineFunction(MachineFunction &MF) override {
54
92
    return SelectionDAGISel::runOnMachineFunction(MF);
55
92
  }
56
57
  // Pass Name
58
92
  StringRef getPassName() const override {
59
92
    return "Lanai DAG->DAG Pattern Instruction Selection";
60
92
  }
61
62
  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
63
                                    std::vector<SDValue> &OutOps) override;
64
65
private:
66
// Include the pieces autogenerated from the target description.
67
#include "LanaiGenDAGISel.inc"
68
69
  // Instruction Selection not handled by the auto-generated tablgen
70
  void Select(SDNode *N) override;
71
72
  // Support functions for the opcodes of Instruction Selection
73
  // not handled by the auto-generated tablgen
74
  void selectFrameIndex(SDNode *N);
75
76
  // Complex Pattern for address selection.
77
  bool selectAddrRi(SDValue Addr, SDValue &Base, SDValue &Offset,
78
                    SDValue &AluOp);
79
  bool selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, SDValue &AluOp);
80
  bool selectAddrSls(SDValue Addr, SDValue &Offset);
81
  bool selectAddrSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
82
                      SDValue &AluOp);
83
84
  // getI32Imm - Return a target constant with the specified value, of type i32.
85
0
  inline SDValue getI32Imm(unsigned Imm, const SDLoc &DL) {
86
0
    return CurDAG->getTargetConstant(Imm, DL, MVT::i32);
87
0
  }
88
89
private:
90
  bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
91
                        SDValue &AluOp, bool RiMode);
92
};
93
94
0
bool canBeRepresentedAsSls(const ConstantSDNode &CN) {
95
0
  // Fits in 21-bit signed immediate and two low-order bits are zero.
96
0
  return isInt<21>(CN.getSExtValue()) && ((CN.getSExtValue() & 0x3) == 0);
97
0
}
98
99
} // namespace
100
101
// Helper functions for ComplexPattern used on LanaiInstrInfo
102
// Used on Lanai Load/Store instructions.
103
1
bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) {
104
1
  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
105
0
    SDLoc DL(Addr);
106
0
    // Loading from a constant address.
107
0
    if (canBeRepresentedAsSls(*CN)) {
108
0
      int32_t Imm = CN->getSExtValue();
109
0
      Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
110
0
      return true;
111
0
    }
112
1
  }
113
1
  if (Addr.getOpcode() == ISD::OR &&
114
1
      Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) {
115
1
    Offset = Addr.getOperand(1).getOperand(0);
116
1
    return true;
117
1
  }
118
0
  return false;
119
0
}
120
121
bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base,
122
                                         SDValue &Offset, SDValue &AluOp,
123
71
                                         bool RiMode) {
124
71
  SDLoc DL(Addr);
125
71
126
71
  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
127
0
    if (RiMode) {
128
0
      // Fits in 16-bit signed immediate.
129
0
      if (isInt<16>(CN->getSExtValue())) {
130
0
        int16_t Imm = CN->getSExtValue();
131
0
        Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
132
0
        Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
133
0
        AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
134
0
        return true;
135
0
      }
136
0
      // Allow SLS to match if the constant doesn't fit in 16 bits but can be
137
0
      // represented as an SLS.
138
0
      if (canBeRepresentedAsSls(*CN))
139
0
        return false;
140
0
    } else {
141
0
      // Fits in 10-bit signed immediate.
142
0
      if (isInt<10>(CN->getSExtValue())) {
143
0
        int16_t Imm = CN->getSExtValue();
144
0
        Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
145
0
        Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
146
0
        AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
147
0
        return true;
148
0
      }
149
71
    }
150
0
  }
151
71
152
71
  // if Address is FI, get the TargetFrameIndex.
153
71
  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
154
52
    Base = CurDAG->getTargetFrameIndex(
155
52
        FIN->getIndex(),
156
52
        getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
157
52
    Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
158
52
    AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
159
52
    return true;
160
52
  }
161
19
162
19
  // Skip direct calls
163
19
  if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
164
19
       Addr.getOpcode() == ISD::TargetGlobalAddress))
165
0
    return false;
166
19
167
19
  // Address of the form imm + reg
168
19
  ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
169
19
  if (AluOperator == ISD::ADD) {
170
4
    AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
171
4
    // Addresses of the form FI+const
172
4
    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
173
4
      if ((RiMode && 
isInt<16>(CN->getSExtValue())2
) ||
174
4
          
(2
!RiMode2
&&
isInt<10>(CN->getSExtValue())2
)) {
175
4
        // If the first operand is a FI, get the TargetFI Node
176
4
        if (FrameIndexSDNode *FIN =
177
0
                dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
178
0
          Base = CurDAG->getTargetFrameIndex(
179
0
              FIN->getIndex(),
180
0
              getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
181
4
        } else {
182
4
          Base = Addr.getOperand(0);
183
4
        }
184
4
185
4
        Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32);
186
4
        return true;
187
4
      }
188
15
  }
189
15
190
15
  // Let SLS match SMALL instead of RI.
191
15
  if (AluOperator == ISD::OR && 
RiMode7
&&
192
15
      
Addr.getOperand(1).getOpcode() == LanaiISD::SMALL7
)
193
1
    return false;
194
14
195
14
  Base = Addr;
196
14
  Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
197
14
  AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
198
14
  return true;
199
14
}
200
201
bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base,
202
67
                                     SDValue &Offset, SDValue &AluOp) {
203
67
  return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/true);
204
67
}
205
206
bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base,
207
4
                                       SDValue &Offset, SDValue &AluOp) {
208
4
  return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false);
209
4
}
210
211
bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2,
212
6
                                     SDValue &AluOp) {
213
6
  // if Address is FI, get the TargetFrameIndex.
214
6
  if (Addr.getOpcode() == ISD::FrameIndex)
215
0
    return false;
216
6
217
6
  // Skip direct calls
218
6
  if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
219
6
       Addr.getOpcode() == ISD::TargetGlobalAddress))
220
0
    return false;
221
6
222
6
  // Address of the form OP + OP
223
6
  ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
224
6
  LPAC::AluCode AluCode = LPAC::isdToLanaiAluCode(AluOperator);
225
6
  if (AluCode != LPAC::UNKNOWN) {
226
3
    // Skip addresses of the form FI OP const
227
3
    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
228
1
      if (isInt<16>(CN->getSExtValue()))
229
1
        return false;
230
2
231
2
    // Skip addresses with hi/lo operands
232
2
    if (Addr.getOperand(0).getOpcode() == LanaiISD::HI ||
233
2
        
Addr.getOperand(0).getOpcode() == LanaiISD::LO1
||
234
2
        
Addr.getOperand(0).getOpcode() == LanaiISD::SMALL1
||
235
2
        
Addr.getOperand(1).getOpcode() == LanaiISD::HI1
||
236
2
        
Addr.getOperand(1).getOpcode() == LanaiISD::LO1
||
237
2
        
Addr.getOperand(1).getOpcode() == LanaiISD::SMALL1
)
238
2
      return false;
239
0
240
0
    // Addresses of the form register OP register
241
0
    R1 = Addr.getOperand(0);
242
0
    R2 = Addr.getOperand(1);
243
0
    AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32);
244
0
    return true;
245
0
  }
246
3
247
3
  // Skip addresses with zero offset
248
3
  return false;
249
3
}
250
251
bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand(
252
0
    const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
253
0
  SDValue Op0, Op1, AluOp;
254
0
  switch (ConstraintCode) {
255
0
  default:
256
0
    return true;
257
0
  case InlineAsm::Constraint_m: // memory
258
0
    if (!selectAddrRr(Op, Op0, Op1, AluOp) &&
259
0
        !selectAddrRi(Op, Op0, Op1, AluOp))
260
0
      return true;
261
0
    break;
262
0
  }
263
0
264
0
  OutOps.push_back(Op0);
265
0
  OutOps.push_back(Op1);
266
0
  OutOps.push_back(AluOp);
267
0
  return false;
268
0
}
269
270
// Select instructions not customized! Used for
271
// expanded, promoted and normal instructions
272
1.28k
void LanaiDAGToDAGISel::Select(SDNode *Node) {
273
1.28k
  unsigned Opcode = Node->getOpcode();
274
1.28k
275
1.28k
  // If we have a custom node, we already have selected!
276
1.28k
  if (Node->isMachineOpcode()) {
277
0
    LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
278
0
    return;
279
0
  }
280
1.28k
281
1.28k
  // Instruction Selection not handled by the auto-generated tablegen selection
282
1.28k
  // should be handled here.
283
1.28k
  EVT VT = Node->getValueType(0);
284
1.28k
  switch (Opcode) {
285
1.28k
  case ISD::Constant:
286
27
    if (VT == MVT::i32) {
287
27
      ConstantSDNode *ConstNode = cast<ConstantSDNode>(Node);
288
27
      // Materialize zero constants as copies from R0. This allows the coalescer
289
27
      // to propagate these into other instructions.
290
27
      if (ConstNode->isNullValue()) {
291
15
        SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
292
15
                                             SDLoc(Node), Lanai::R0, MVT::i32);
293
15
        return ReplaceNode(Node, New.getNode());
294
15
      }
295
12
      // Materialize all ones constants as copies from R1. This allows the
296
12
      // coalescer to propagate these into other instructions.
297
12
      if (ConstNode->isAllOnesValue()) {
298
0
        SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
299
0
                                             SDLoc(Node), Lanai::R1, MVT::i32);
300
0
        return ReplaceNode(Node, New.getNode());
301
0
      }
302
12
    }
303
12
    break;
304
12
  case ISD::FrameIndex:
305
0
    selectFrameIndex(Node);
306
0
    return;
307
1.25k
  default:
308
1.25k
    break;
309
1.27k
  }
310
1.27k
311
1.27k
  // Select the default instruction
312
1.27k
  SelectCode(Node);
313
1.27k
}
314
315
0
void LanaiDAGToDAGISel::selectFrameIndex(SDNode *Node) {
316
0
  SDLoc DL(Node);
317
0
  SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i32);
318
0
  int FI = cast<FrameIndexSDNode>(Node)->getIndex();
319
0
  EVT VT = Node->getValueType(0);
320
0
  SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
321
0
  unsigned Opc = Lanai::ADD_I_LO;
322
0
  if (Node->hasOneUse()) {
323
0
    CurDAG->SelectNodeTo(Node, Opc, VT, TFI, Imm);
324
0
    return;
325
0
  }
326
0
  ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, VT, TFI, Imm));
327
0
}
328
329
// createLanaiISelDag - This pass converts a legalized DAG into a
330
// Lanai-specific DAG, ready for instruction scheduling.
331
22
FunctionPass *llvm::createLanaiISelDag(LanaiTargetMachine &TM) {
332
22
  return new LanaiDAGToDAGISel(TM);
333
22
}