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 selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 48 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 49 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 50 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 51 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset); 52 53 StringRef getPassName() const override { 54 return "VE DAG->DAG Pattern Instruction Selection"; 55 } 56 57 // Include the pieces autogenerated from the target description. 58 #include "VEGenDAGISel.inc" 59 60 private: 61 SDNode *getGlobalBaseReg(); 62 63 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index); 64 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset); 65 }; 66 } // end anonymous namespace 67 68 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index, 69 SDValue &Offset) { 70 if (Addr.getOpcode() == ISD::FrameIndex) 71 return false; 72 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 73 Addr.getOpcode() == ISD::TargetGlobalAddress || 74 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 75 return false; // direct calls. 76 77 SDValue LHS, RHS; 78 if (matchADDRri(Addr, LHS, RHS)) { 79 if (matchADDRrr(LHS, Base, Index)) { 80 Offset = RHS; 81 return true; 82 } 83 // Return false to try selectADDRrii. 84 return false; 85 } 86 if (matchADDRrr(Addr, LHS, RHS)) { 87 if (matchADDRri(RHS, Index, Offset)) { 88 Base = LHS; 89 return true; 90 } 91 if (matchADDRri(LHS, Base, Offset)) { 92 Index = RHS; 93 return true; 94 } 95 Base = LHS; 96 Index = RHS; 97 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 98 return true; 99 } 100 return false; // Let the reg+imm(=0) pattern catch this! 101 } 102 103 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index, 104 SDValue &Offset) { 105 if (matchADDRri(Addr, Base, Offset)) { 106 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 107 return true; 108 } 109 110 Base = Addr; 111 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 112 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 113 return true; 114 } 115 116 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index, 117 SDValue &Offset) { 118 // Prefer ADDRrii. 119 return false; 120 } 121 122 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index, 123 SDValue &Offset) { 124 if (dyn_cast<FrameIndexSDNode>(Addr)) { 125 return false; 126 } 127 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 128 Addr.getOpcode() == ISD::TargetGlobalAddress || 129 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 130 return false; // direct calls. 131 132 if (ConstantSDNode *CN = cast<ConstantSDNode>(Addr)) { 133 if (isInt<32>(CN->getSExtValue())) { 134 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 135 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 136 Offset = 137 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 138 return true; 139 } 140 } 141 return false; 142 } 143 144 bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base, 145 SDValue &Offset) { 146 if (matchADDRri(Addr, Base, Offset)) 147 return true; 148 149 Base = Addr; 150 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 151 return true; 152 } 153 154 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) { 155 if (dyn_cast<FrameIndexSDNode>(Addr)) 156 return false; 157 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 158 Addr.getOpcode() == ISD::TargetGlobalAddress || 159 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 160 return false; // direct calls. 161 162 if (Addr.getOpcode() == ISD::ADD) { 163 ; // Nothing to do here. 164 } else if (Addr.getOpcode() == ISD::OR) { 165 // We want to look through a transform in InstCombine and DAGCombiner that 166 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'. 167 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1))) 168 return false; 169 } else { 170 return false; 171 } 172 173 if (Addr.getOperand(0).getOpcode() == VEISD::Lo || 174 Addr.getOperand(1).getOpcode() == VEISD::Lo) 175 return false; // Let the LEASL patterns catch this! 176 177 Base = Addr.getOperand(0); 178 Index = Addr.getOperand(1); 179 return true; 180 } 181 182 bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) { 183 auto AddrTy = Addr->getValueType(0); 184 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 185 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); 186 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 187 return true; 188 } 189 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 190 Addr.getOpcode() == ISD::TargetGlobalAddress || 191 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 192 return false; // direct calls. 193 194 if (CurDAG->isBaseWithConstantOffset(Addr)) { 195 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1)); 196 if (isInt<32>(CN->getSExtValue())) { 197 if (FrameIndexSDNode *FIN = 198 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 199 // Constant offset from frame ref. 200 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); 201 } else { 202 Base = Addr.getOperand(0); 203 } 204 Offset = 205 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 206 return true; 207 } 208 } 209 return false; 210 } 211 212 void VEDAGToDAGISel::Select(SDNode *N) { 213 SDLoc dl(N); 214 if (N->isMachineOpcode()) { 215 N->setNodeId(-1); 216 return; // Already selected. 217 } 218 219 switch (N->getOpcode()) { 220 case VEISD::GLOBAL_BASE_REG: 221 ReplaceNode(N, getGlobalBaseReg()); 222 return; 223 } 224 225 SelectCode(N); 226 } 227 228 SDNode *VEDAGToDAGISel::getGlobalBaseReg() { 229 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF); 230 return CurDAG 231 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout())) 232 .getNode(); 233 } 234 235 /// createVEISelDag - This pass converts a legalized DAG into a 236 /// VE-specific DAG, ready for instruction scheduling. 237 /// 238 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) { 239 return new VEDAGToDAGISel(TM); 240 } 241