Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/XCore/XCoreISelDAGToDAG.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file defines an instruction selector for the XCore target.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "XCore.h"
15
#include "XCoreTargetMachine.h"
16
#include "llvm/CodeGen/MachineFrameInfo.h"
17
#include "llvm/CodeGen/MachineFunction.h"
18
#include "llvm/CodeGen/MachineInstrBuilder.h"
19
#include "llvm/CodeGen/MachineRegisterInfo.h"
20
#include "llvm/CodeGen/SelectionDAG.h"
21
#include "llvm/CodeGen/SelectionDAGISel.h"
22
#include "llvm/IR/CallingConv.h"
23
#include "llvm/IR/Constants.h"
24
#include "llvm/IR/DerivedTypes.h"
25
#include "llvm/IR/Function.h"
26
#include "llvm/IR/Intrinsics.h"
27
#include "llvm/IR/LLVMContext.h"
28
#include "llvm/Support/Debug.h"
29
#include "llvm/Support/ErrorHandling.h"
30
#include "llvm/Support/raw_ostream.h"
31
#include "llvm/Target/TargetLowering.h"
32
using namespace llvm;
33
34
/// XCoreDAGToDAGISel - XCore specific code to select XCore machine
35
/// instructions for SelectionDAG operations.
36
///
37
namespace {
38
  class XCoreDAGToDAGISel : public SelectionDAGISel {
39
40
  public:
41
    XCoreDAGToDAGISel(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel)
42
69
      : SelectionDAGISel(TM, OptLevel) {}
43
44
    void Select(SDNode *N) override;
45
    bool tryBRIND(SDNode *N);
46
47
    /// getI32Imm - Return a target constant with the specified value, of type
48
    /// i32.
49
47
    inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
50
47
      return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
51
47
    }
52
53
135
    inline bool immMskBitp(SDNode *inN) const {
54
135
      ConstantSDNode *N = cast<ConstantSDNode>(inN);
55
135
      uint32_t value = (uint32_t)N->getZExtValue();
56
135
      if (
!isMask_32(value)135
) {
57
105
        return false;
58
105
      }
59
30
      int msksize = 32 - countLeadingZeros(value);
60
30
      return (msksize >= 1 && msksize <= 8) ||
61
30
              
msksize == 161
||
msksize == 240
||
msksize == 320
;
62
135
    }
63
64
    // Complex Pattern Selectors.
65
    bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
66
67
    bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
68
                                      std::vector<SDValue> &OutOps) override;
69
70
0
    StringRef getPassName() const override {
71
0
      return "XCore DAG->DAG Pattern Instruction Selection";
72
0
    }
73
74
    // Include the pieces autogenerated from the target description.
75
  #include "XCoreGenDAGISel.inc"
76
  };
77
}  // end anonymous namespace
78
79
/// createXCoreISelDag - This pass converts a legalized DAG into a
80
/// XCore-specific DAG, ready for instruction scheduling.
81
///
82
FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM,
83
69
                                       CodeGenOpt::Level OptLevel) {
84
69
  return new XCoreDAGToDAGISel(TM, OptLevel);
85
69
}
86
87
bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base,
88
226
                                       SDValue &Offset) {
89
226
  FrameIndexSDNode *FIN = nullptr;
90
226
  if (
(FIN = dyn_cast<FrameIndexSDNode>(Addr))226
) {
91
40
    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
92
40
    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
93
40
    return true;
94
40
  }
95
186
  
if (186
Addr.getOpcode() == ISD::ADD186
) {
96
109
    ConstantSDNode *CN = nullptr;
97
109
    if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
98
23
      && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
99
109
      && 
(CN->getSExtValue() % 4 == 0 && 23
CN->getSExtValue() >= 023
)) {
100
21
      // Constant positive word offset from frame index
101
21
      Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
102
21
      Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr),
103
21
                                         MVT::i32);
104
21
      return true;
105
21
    }
106
165
  }
107
165
  return false;
108
165
}
109
110
bool XCoreDAGToDAGISel::
111
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
112
2
                             std::vector<SDValue> &OutOps) {
113
2
  SDValue Reg;
114
2
  switch (ConstraintID) {
115
0
  default: return true;
116
2
  case InlineAsm::Constraint_m: // Memory.
117
2
    switch (Op.getOpcode()) {
118
0
    default: return true;
119
1
    case XCoreISD::CPRelativeWrapper:
120
1
      Reg = CurDAG->getRegister(XCore::CP, MVT::i32);
121
1
      break;
122
1
    case XCoreISD::DPRelativeWrapper:
123
1
      Reg = CurDAG->getRegister(XCore::DP, MVT::i32);
124
1
      break;
125
2
    }
126
2
  }
127
2
  OutOps.push_back(Reg);
128
2
  OutOps.push_back(Op.getOperand(0));
129
2
  return false;
130
2
}
131
132
3.68k
void XCoreDAGToDAGISel::Select(SDNode *N) {
133
3.68k
  SDLoc dl(N);
134
3.68k
  switch (N->getOpcode()) {
135
3.53k
  default: break;
136
128
  case ISD::Constant: {
137
128
    uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue();
138
128
    if (
immMskBitp(N)128
) {
139
23
      // Transformation function: get the size of a mask
140
23
      // Look for the first non-zero bit
141
23
      SDValue MskSize = getI32Imm(32 - countLeadingZeros((uint32_t)Val), dl);
142
23
      ReplaceNode(N, CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
143
23
                                            MVT::i32, MskSize));
144
23
      return;
145
23
    }
146
105
    else 
if (105
!isUInt<16>(Val)105
) {
147
10
      SDValue CPIdx = CurDAG->getTargetConstantPool(
148
10
          ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
149
10
          getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
150
10
      SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32,
151
10
                                            MVT::Other, CPIdx,
152
10
                                            CurDAG->getEntryNode());
153
10
      MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
154
10
      MemOp[0] =
155
10
          MF->getMachineMemOperand(MachinePointerInfo::getConstantPool(*MF),
156
10
                                   MachineMemOperand::MOLoad, 4, 4);
157
10
      cast<MachineSDNode>(node)->setMemRefs(MemOp, MemOp + 1);
158
10
      ReplaceNode(N, node);
159
10
      return;
160
10
    }
161
95
    break;
162
95
  }
163
5
  case XCoreISD::LADD: {
164
5
    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
165
5
                        N->getOperand(2) };
166
5
    ReplaceNode(N, CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32,
167
5
                                          MVT::i32, Ops));
168
5
    return;
169
95
  }
170
4
  case XCoreISD::LSUB: {
171
4
    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
172
4
                        N->getOperand(2) };
173
4
    ReplaceNode(N, CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32,
174
4
                                          MVT::i32, Ops));
175
4
    return;
176
95
  }
177
1
  case XCoreISD::MACCU: {
178
1
    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
179
1
                      N->getOperand(2), N->getOperand(3) };
180
1
    ReplaceNode(N, CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32,
181
1
                                          MVT::i32, Ops));
182
1
    return;
183
95
  }
184
3
  case XCoreISD::MACCS: {
185
3
    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
186
3
                      N->getOperand(2), N->getOperand(3) };
187
3
    ReplaceNode(N, CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32,
188
3
                                          MVT::i32, Ops));
189
3
    return;
190
95
  }
191
11
  case XCoreISD::LMUL: {
192
11
    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
193
11
                      N->getOperand(2), N->getOperand(3) };
194
11
    ReplaceNode(N, CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32,
195
11
                                          MVT::i32, Ops));
196
11
    return;
197
95
  }
198
1
  case XCoreISD::CRC8: {
199
1
    SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) };
200
1
    ReplaceNode(N, CurDAG->getMachineNode(XCore::CRC8_l4r, dl, MVT::i32,
201
1
                                          MVT::i32, Ops));
202
1
    return;
203
95
  }
204
3
  case ISD::BRIND:
205
3
    if (tryBRIND(N))
206
1
      return;
207
2
    break;
208
3.62k
  // Other cases are autogenerated.
209
3.62k
  }
210
3.62k
  SelectCode(N);
211
3.62k
}
212
213
/// Given a chain return a new chain where any appearance of Old is replaced
214
/// by New. There must be at most one instruction between Old and Chain and
215
/// this instruction must be a TokenFactor. Returns an empty SDValue if
216
/// these conditions don't hold.
217
static SDValue
218
replaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New)
219
1
{
220
1
  if (Chain == Old)
221
1
    return New;
222
0
  
if (0
Chain->getOpcode() != ISD::TokenFactor0
)
223
0
    return SDValue();
224
0
  SmallVector<SDValue, 8> Ops;
225
0
  bool found = false;
226
0
  for (unsigned i = 0, e = Chain->getNumOperands(); 
i != e0
;
++i0
) {
227
0
    if (
Chain->getOperand(i) == Old0
) {
228
0
      Ops.push_back(New);
229
0
      found = true;
230
0
    } else {
231
0
      Ops.push_back(Chain->getOperand(i));
232
0
    }
233
0
  }
234
0
  if (!found)
235
0
    return SDValue();
236
0
  return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops);
237
0
}
238
239
3
bool XCoreDAGToDAGISel::tryBRIND(SDNode *N) {
240
3
  SDLoc dl(N);
241
3
  // (brind (int_xcore_checkevent (addr)))
242
3
  SDValue Chain = N->getOperand(0);
243
3
  SDValue Addr = N->getOperand(1);
244
3
  if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN)
245
1
    return false;
246
2
  unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue();
247
2
  if (IntNo != Intrinsic::xcore_checkevent)
248
1
    return false;
249
1
  SDValue nextAddr = Addr->getOperand(2);
250
1
  SDValue CheckEventChainOut(Addr.getNode(), 1);
251
1
  if (
!CheckEventChainOut.use_empty()1
) {
252
1
    // If the chain out of the checkevent intrinsic is an operand of the
253
1
    // indirect branch or used in a TokenFactor which is the operand of the
254
1
    // indirect branch then build a new chain which uses the chain coming into
255
1
    // the checkevent intrinsic instead.
256
1
    SDValue CheckEventChainIn = Addr->getOperand(0);
257
1
    SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut,
258
1
                                      CheckEventChainIn);
259
1
    if (!NewChain.getNode())
260
0
      return false;
261
1
    Chain = NewChain;
262
1
  }
263
1
  // Enable events on the thread using setsr 1 and then disable them immediately
264
1
  // after with clrsr 1. If any resources owned by the thread are ready an event
265
1
  // will be taken. If no resource is ready we branch to the address which was
266
1
  // the operand to the checkevent intrinsic.
267
1
  SDValue constOne = getI32Imm(1, dl);
268
1
  SDValue Glue =
269
1
    SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue,
270
1
                                   constOne, Chain), 0);
271
1
  Glue =
272
1
    SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue,
273
1
                                   constOne, Glue), 0);
274
1
  if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper &&
275
1
      
nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress1
) {
276
1
    CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other,
277
1
                         nextAddr->getOperand(0), Glue);
278
1
    return true;
279
1
  }
280
0
  CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue);
281
0
  return true;
282
0
}