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 /// ARCDAGToDAGISel - ARC specific code to select ARC machine
36 /// instructions for SelectionDAG operations.
39 class ARCDAGToDAGISel
: public SelectionDAGISel
{
41 ARCDAGToDAGISel(ARCTargetMachine
&TM
, CodeGenOpt::Level OptLevel
)
42 : SelectionDAGISel(TM
, OptLevel
) {}
44 void Select(SDNode
*N
) override
;
46 // Complex Pattern Selectors.
47 bool SelectFrameADDR_ri(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
48 bool SelectAddrModeS9(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
49 bool SelectAddrModeImm(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
50 bool SelectAddrModeFar(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
51 bool SelectCMOVPred(SDValue N
, SDValue
&Pred
, SDValue
&Reg
) {
52 const ConstantSDNode
*CN
= cast
<ConstantSDNode
>(N
);
53 Pred
= CurDAG
->getTargetConstant(CN
->getZExtValue(), SDLoc(N
), MVT::i32
);
54 Reg
= CurDAG
->getRegister(ARC::STATUS32
, MVT::i32
);
58 StringRef
getPassName() const override
{
59 return "ARC DAG->DAG Pattern Instruction Selection";
62 // Include the pieces autogenerated from the target description.
63 #include "ARCGenDAGISel.inc"
66 } // end anonymous namespace
68 /// This pass converts a legalized DAG into a ARC-specific DAG, ready for
69 /// instruction scheduling.
70 FunctionPass
*llvm::createARCISelDag(ARCTargetMachine
&TM
,
71 CodeGenOpt::Level OptLevel
) {
72 return new ARCDAGToDAGISel(TM
, OptLevel
);
75 bool ARCDAGToDAGISel::SelectAddrModeImm(SDValue Addr
, SDValue
&Base
,
77 if (Addr
.getOpcode() == ARCISD::GAWRAPPER
) {
78 Base
= Addr
.getOperand(0);
79 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
85 bool ARCDAGToDAGISel::SelectAddrModeS9(SDValue Addr
, SDValue
&Base
,
87 if (Addr
.getOpcode() == ARCISD::GAWRAPPER
) {
91 if (Addr
.getOpcode() != ISD::ADD
&& Addr
.getOpcode() != ISD::SUB
&&
92 !CurDAG
->isBaseWithConstantOffset(Addr
)) {
93 if (Addr
.getOpcode() == ISD::FrameIndex
) {
95 int FI
= cast
<FrameIndexSDNode
>(Addr
)->getIndex();
96 Base
= CurDAG
->getTargetFrameIndex(
97 FI
, TLI
->getPointerTy(CurDAG
->getDataLayout()));
101 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
105 if (ConstantSDNode
*RHS
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1))) {
106 int32_t RHSC
= RHS
->getSExtValue();
107 if (Addr
.getOpcode() == ISD::SUB
)
110 // Do we need more than 9 bits to encode?
113 Base
= Addr
.getOperand(0);
114 if (Base
.getOpcode() == ISD::FrameIndex
) {
115 int FI
= cast
<FrameIndexSDNode
>(Base
)->getIndex();
116 Base
= CurDAG
->getTargetFrameIndex(
117 FI
, TLI
->getPointerTy(CurDAG
->getDataLayout()));
119 Offset
= CurDAG
->getTargetConstant(RHSC
, SDLoc(Addr
), MVT::i32
);
123 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
127 bool ARCDAGToDAGISel::SelectAddrModeFar(SDValue Addr
, SDValue
&Base
,
129 if (SelectAddrModeS9(Addr
, Base
, Offset
))
131 if (Addr
.getOpcode() == ARCISD::GAWRAPPER
) {
134 if (ConstantSDNode
*RHS
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1))) {
135 int32_t RHSC
= RHS
->getSExtValue();
136 if (Addr
.getOpcode() == ISD::SUB
)
138 Base
= Addr
.getOperand(0);
139 Offset
= CurDAG
->getTargetConstant(RHSC
, SDLoc(Addr
), MVT::i32
);
145 // Is this a legal frame index addressing expression.
146 bool ARCDAGToDAGISel::SelectFrameADDR_ri(SDValue Addr
, SDValue
&Base
,
148 FrameIndexSDNode
*FIN
= nullptr;
149 if ((FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
))) {
150 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i32
);
151 Offset
= CurDAG
->getTargetConstant(0, SDLoc(Addr
), MVT::i32
);
154 if (Addr
.getOpcode() == ISD::ADD
) {
155 ConstantSDNode
*CN
= nullptr;
156 if ((FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0))) &&
157 (CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1))) &&
158 (CN
->getSExtValue() % 4 == 0 && CN
->getSExtValue() >= 0)) {
159 // Constant positive word offset from frame index
160 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i32
);
162 CurDAG
->getTargetConstant(CN
->getSExtValue(), SDLoc(Addr
), MVT::i32
);
169 void ARCDAGToDAGISel::Select(SDNode
*N
) {
170 switch (N
->getOpcode()) {
171 case ISD::Constant
: {
172 uint64_t CVal
= cast
<ConstantSDNode
>(N
)->getZExtValue();
173 ReplaceNode(N
, CurDAG
->getMachineNode(
174 isInt
<12>(CVal
) ? ARC::MOV_rs12
: ARC::MOV_rlimm
,
176 CurDAG
->getTargetConstant(CVal
, SDLoc(N
), MVT::i32
)));