1 //===-- VEISelDAGToDAG.cpp - A dag to dag inst selector for VE ------------===//
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 VE target.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "VETargetMachine.h"
14 #include "llvm/CodeGen/MachineRegisterInfo.h"
15 #include "llvm/CodeGen/SelectionDAGISel.h"
16 #include "llvm/IR/Intrinsics.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
20 using namespace llvm;
21 
22 //===----------------------------------------------------------------------===//
23 // Instruction Selector Implementation
24 //===----------------------------------------------------------------------===//
25 
26 //===--------------------------------------------------------------------===//
27 /// VEDAGToDAGISel - VE specific code to select VE machine
28 /// instructions for SelectionDAG operations.
29 ///
30 namespace {
31 class VEDAGToDAGISel : public SelectionDAGISel {
32   /// Subtarget - Keep a pointer to the VE Subtarget around so that we can
33   /// make the right decision when generating code for different targets.
34   const VESubtarget *Subtarget;
35 
36 public:
37   explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {}
38 
39   bool runOnMachineFunction(MachineFunction &MF) override {
40     Subtarget = &MF.getSubtarget<VESubtarget>();
41     return SelectionDAGISel::runOnMachineFunction(MF);
42   }
43 
44   void Select(SDNode *N) override;
45 
46   // Complex Pattern Selectors.
47   bool SelectADDRrr(SDValue N, SDValue &R1, SDValue &R2);
48   bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
49 
50   StringRef getPassName() const override {
51     return "VE DAG->DAG Pattern Instruction Selection";
52   }
53 
54   // Include the pieces autogenerated from the target description.
55 #include "VEGenDAGISel.inc"
56 };
57 } // end anonymous namespace
58 
59 bool VEDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) {
60   if (Addr.getOpcode() == ISD::FrameIndex)
61     return false;
62   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
63       Addr.getOpcode() == ISD::TargetGlobalAddress ||
64       Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
65     return false; // direct calls.
66 
67   if (Addr.getOpcode() == ISD::ADD) {
68     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
69       if (isInt<13>(CN->getSExtValue()))
70         return false; // Let the reg+imm pattern catch this!
71     if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||
72         Addr.getOperand(1).getOpcode() == VEISD::Lo)
73       return false; // Let the reg+imm pattern catch this!
74     R1 = Addr.getOperand(0);
75     R2 = Addr.getOperand(1);
76     return true;
77   }
78 
79   return false; // Let the reg+imm pattern catch this!
80 }
81 
82 bool VEDAGToDAGISel::SelectADDRri(SDValue Addr, SDValue &Base,
83                                   SDValue &Offset) {
84   auto AddrTy = Addr->getValueType(0);
85   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
86     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
87     Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
88     return true;
89   }
90   if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
91       Addr.getOpcode() == ISD::TargetGlobalAddress ||
92       Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
93     return false; // direct calls.
94 
95   if (CurDAG->isBaseWithConstantOffset(Addr)) {
96     ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));
97     if (isInt<13>(CN->getSExtValue())) {
98       if (FrameIndexSDNode *FIN =
99               dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
100         // Constant offset from frame ref.
101         Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
102       } else {
103         Base = Addr.getOperand(0);
104       }
105       Offset =
106           CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
107       return true;
108     }
109   }
110   Base = Addr;
111   Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
112   return true;
113 }
114 
115 void VEDAGToDAGISel::Select(SDNode *N) {
116   SDLoc dl(N);
117   if (N->isMachineOpcode()) {
118     N->setNodeId(-1);
119     return; // Already selected.
120   }
121 
122   SelectCode(N);
123 }
124 
125 /// createVEISelDag - This pass converts a legalized DAG into a
126 /// VE-specific DAG, ready for instruction scheduling.
127 ///
128 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) {
129   return new VEDAGToDAGISel(TM);
130 }
131