1 //===- ARCISelDAGToDAG.cpp - ARC dag to dag inst selector -------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines an instruction selector for the ARC target.
11 //===----------------------------------------------------------------------===//
14 #include "ARCTargetMachine.h"
15 #include "llvm/CodeGen/MachineFrameInfo.h"
16 #include "llvm/CodeGen/MachineFunction.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/CodeGen/SelectionDAG.h"
20 #include "llvm/CodeGen/SelectionDAGISel.h"
21 #include "llvm/CodeGen/TargetLowering.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/Compiler.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
35 #define DEBUG_TYPE "arc-isel"
36 #define PASS_NAME "ARC DAG->DAG Pattern Instruction Selection"
38 /// ARCDAGToDAGISel - ARC specific code to select ARC machine
39 /// instructions for SelectionDAG operations.
42 class ARCDAGToDAGISel
: public SelectionDAGISel
{
44 ARCDAGToDAGISel() = delete;
46 ARCDAGToDAGISel(ARCTargetMachine
&TM
, CodeGenOptLevel OptLevel
)
47 : SelectionDAGISel(TM
, OptLevel
) {}
49 void Select(SDNode
*N
) override
;
51 // Complex Pattern Selectors.
52 bool SelectFrameADDR_ri(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
53 bool SelectAddrModeS9(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
54 bool SelectAddrModeImm(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
55 bool SelectAddrModeFar(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
57 // Include the pieces autogenerated from the target description.
58 #include "ARCGenDAGISel.inc"
61 class ARCDAGToDAGISelLegacy
: public SelectionDAGISelLegacy
{
64 explicit ARCDAGToDAGISelLegacy(ARCTargetMachine
&TM
, CodeGenOptLevel OptLevel
)
65 : SelectionDAGISelLegacy(
66 ID
, std::make_unique
<ARCDAGToDAGISel
>(TM
, OptLevel
)) {}
69 char ARCDAGToDAGISelLegacy::ID
;
71 } // end anonymous namespace
73 INITIALIZE_PASS(ARCDAGToDAGISelLegacy
, DEBUG_TYPE
, PASS_NAME
, false, false)
75 /// This pass converts a legalized DAG into a ARC-specific DAG, ready for
76 /// instruction scheduling.
77 FunctionPass
*llvm::createARCISelDag(ARCTargetMachine
&TM
,
78 CodeGenOptLevel OptLevel
) {
79 return new ARCDAGToDAGISelLegacy(TM
, OptLevel
);
82 bool ARCDAGToDAGISel::SelectAddrModeImm(SDValue Addr
, SDValue
&Base
,
84 if (Addr
.getOpcode() == ARCISD::GAWRAPPER
) {
85 Base
= Addr
.getOperand(0);
86 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
92 bool ARCDAGToDAGISel::SelectAddrModeS9(SDValue Addr
, SDValue
&Base
,
94 if (Addr
.getOpcode() == ARCISD::GAWRAPPER
) {
98 if (Addr
.getOpcode() != ISD::ADD
&& Addr
.getOpcode() != ISD::SUB
&&
99 !CurDAG
->isBaseWithConstantOffset(Addr
)) {
100 if (Addr
.getOpcode() == ISD::FrameIndex
) {
101 // Match frame index.
102 int FI
= cast
<FrameIndexSDNode
>(Addr
)->getIndex();
103 Base
= CurDAG
->getTargetFrameIndex(
104 FI
, TLI
->getPointerTy(CurDAG
->getDataLayout()));
108 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
112 if (ConstantSDNode
*RHS
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1))) {
113 int32_t RHSC
= RHS
->getSExtValue();
114 if (Addr
.getOpcode() == ISD::SUB
)
117 // Do we need more than 9 bits to encode?
120 Base
= Addr
.getOperand(0);
121 if (Base
.getOpcode() == ISD::FrameIndex
) {
122 int FI
= cast
<FrameIndexSDNode
>(Base
)->getIndex();
123 Base
= CurDAG
->getTargetFrameIndex(
124 FI
, TLI
->getPointerTy(CurDAG
->getDataLayout()));
126 Offset
= CurDAG
->getTargetConstant(RHSC
, SDLoc(Addr
), MVT::i32
);
130 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
134 bool ARCDAGToDAGISel::SelectAddrModeFar(SDValue Addr
, SDValue
&Base
,
136 if (SelectAddrModeS9(Addr
, Base
, Offset
))
138 if (Addr
.getOpcode() == ARCISD::GAWRAPPER
) {
141 if (ConstantSDNode
*RHS
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1))) {
142 int32_t RHSC
= RHS
->getSExtValue();
143 if (Addr
.getOpcode() == ISD::SUB
)
145 Base
= Addr
.getOperand(0);
146 Offset
= CurDAG
->getTargetConstant(RHSC
, SDLoc(Addr
), MVT::i32
);
152 // Is this a legal frame index addressing expression.
153 bool ARCDAGToDAGISel::SelectFrameADDR_ri(SDValue Addr
, SDValue
&Base
,
155 FrameIndexSDNode
*FIN
= nullptr;
156 if ((FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
))) {
157 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i32
);
158 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
161 if (Addr
.getOpcode() == ISD::ADD
) {
162 ConstantSDNode
*CN
= nullptr;
163 if ((FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0))) &&
164 (CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1))) &&
165 (CN
->getSExtValue() % 4 == 0 && CN
->getSExtValue() >= 0)) {
166 // Constant positive word offset from frame index
167 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i32
);
169 CurDAG
->getTargetConstant(CN
->getSExtValue(), SDLoc(Addr
), MVT::i32
);
176 void ARCDAGToDAGISel::Select(SDNode
*N
) {
177 switch (N
->getOpcode()) {
178 case ISD::Constant
: {
179 uint64_t CVal
= N
->getAsZExtVal();
180 ReplaceNode(N
, CurDAG
->getMachineNode(
181 isInt
<12>(CVal
) ? ARC::MOV_rs12
: ARC::MOV_rlimm
,
183 CurDAG
->getTargetConstant(CVal
, SDLoc(N
), MVT::i32
)));