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 /// Convert a DAG integer condition code to a VE ICC condition. 27 inline static VECC::CondCode intCondCode2Icc(ISD::CondCode CC) { 28 switch (CC) { 29 default: 30 llvm_unreachable("Unknown integer condition code!"); 31 case ISD::SETEQ: 32 return VECC::CC_IEQ; 33 case ISD::SETNE: 34 return VECC::CC_INE; 35 case ISD::SETLT: 36 return VECC::CC_IL; 37 case ISD::SETGT: 38 return VECC::CC_IG; 39 case ISD::SETLE: 40 return VECC::CC_ILE; 41 case ISD::SETGE: 42 return VECC::CC_IGE; 43 case ISD::SETULT: 44 return VECC::CC_IL; 45 case ISD::SETULE: 46 return VECC::CC_ILE; 47 case ISD::SETUGT: 48 return VECC::CC_IG; 49 case ISD::SETUGE: 50 return VECC::CC_IGE; 51 } 52 } 53 54 /// Convert a DAG floating point condition code to a VE FCC condition. 55 inline static VECC::CondCode fpCondCode2Fcc(ISD::CondCode CC) { 56 switch (CC) { 57 default: 58 llvm_unreachable("Unknown fp condition code!"); 59 case ISD::SETFALSE: 60 return VECC::CC_AF; 61 case ISD::SETEQ: 62 case ISD::SETOEQ: 63 return VECC::CC_EQ; 64 case ISD::SETNE: 65 case ISD::SETONE: 66 return VECC::CC_NE; 67 case ISD::SETLT: 68 case ISD::SETOLT: 69 return VECC::CC_L; 70 case ISD::SETGT: 71 case ISD::SETOGT: 72 return VECC::CC_G; 73 case ISD::SETLE: 74 case ISD::SETOLE: 75 return VECC::CC_LE; 76 case ISD::SETGE: 77 case ISD::SETOGE: 78 return VECC::CC_GE; 79 case ISD::SETO: 80 return VECC::CC_NUM; 81 case ISD::SETUO: 82 return VECC::CC_NAN; 83 case ISD::SETUEQ: 84 return VECC::CC_EQNAN; 85 case ISD::SETUNE: 86 return VECC::CC_NENAN; 87 case ISD::SETULT: 88 return VECC::CC_LNAN; 89 case ISD::SETUGT: 90 return VECC::CC_GNAN; 91 case ISD::SETULE: 92 return VECC::CC_LENAN; 93 case ISD::SETUGE: 94 return VECC::CC_GENAN; 95 case ISD::SETTRUE: 96 return VECC::CC_AT; 97 } 98 } 99 100 /// getImmVal - get immediate representation of integer value 101 inline static uint64_t getImmVal(const ConstantSDNode *N) { 102 return N->getSExtValue(); 103 } 104 105 /// getFpImmVal - get immediate representation of floating point value 106 inline static uint64_t getFpImmVal(const ConstantFPSDNode *N) { 107 const APInt &Imm = N->getValueAPF().bitcastToAPInt(); 108 uint64_t Val = Imm.getZExtValue(); 109 if (Imm.getBitWidth() == 32) { 110 // Immediate value of float place places at higher bits on VE. 111 Val <<= 32; 112 } 113 return Val; 114 } 115 116 //===--------------------------------------------------------------------===// 117 /// VEDAGToDAGISel - VE specific code to select VE machine 118 /// instructions for SelectionDAG operations. 119 /// 120 namespace { 121 class VEDAGToDAGISel : public SelectionDAGISel { 122 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can 123 /// make the right decision when generating code for different targets. 124 const VESubtarget *Subtarget; 125 126 public: 127 explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {} 128 129 bool runOnMachineFunction(MachineFunction &MF) override { 130 Subtarget = &MF.getSubtarget<VESubtarget>(); 131 return SelectionDAGISel::runOnMachineFunction(MF); 132 } 133 134 void Select(SDNode *N) override; 135 136 // Complex Pattern Selectors. 137 bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 138 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 139 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 140 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 141 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset); 142 bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset); 143 144 StringRef getPassName() const override { 145 return "VE DAG->DAG Pattern Instruction Selection"; 146 } 147 148 // Include the pieces autogenerated from the target description. 149 #include "VEGenDAGISel.inc" 150 151 private: 152 SDNode *getGlobalBaseReg(); 153 154 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index); 155 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset); 156 }; 157 } // end anonymous namespace 158 159 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index, 160 SDValue &Offset) { 161 if (Addr.getOpcode() == ISD::FrameIndex) 162 return false; 163 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 164 Addr.getOpcode() == ISD::TargetGlobalAddress || 165 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 166 return false; // direct calls. 167 168 SDValue LHS, RHS; 169 if (matchADDRri(Addr, LHS, RHS)) { 170 if (matchADDRrr(LHS, Base, Index)) { 171 Offset = RHS; 172 return true; 173 } 174 // Return false to try selectADDRrii. 175 return false; 176 } 177 if (matchADDRrr(Addr, LHS, RHS)) { 178 // If the input is a pair of a frame-index and a register, move a 179 // frame-index to LHS. This generates MI with following operands. 180 // %dest, #FI, %reg, offset 181 // In the eliminateFrameIndex, above MI is converted to the following. 182 // %dest, %fp, %reg, fi_offset + offset 183 if (dyn_cast<FrameIndexSDNode>(RHS)) 184 std::swap(LHS, RHS); 185 186 if (matchADDRri(RHS, Index, Offset)) { 187 Base = LHS; 188 return true; 189 } 190 if (matchADDRri(LHS, Base, Offset)) { 191 Index = RHS; 192 return true; 193 } 194 Base = LHS; 195 Index = RHS; 196 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 197 return true; 198 } 199 return false; // Let the reg+imm(=0) pattern catch this! 200 } 201 202 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index, 203 SDValue &Offset) { 204 if (matchADDRri(Addr, Base, Offset)) { 205 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 206 return true; 207 } 208 209 Base = Addr; 210 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 211 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 212 return true; 213 } 214 215 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index, 216 SDValue &Offset) { 217 // Prefer ADDRrii. 218 return false; 219 } 220 221 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index, 222 SDValue &Offset) { 223 if (dyn_cast<FrameIndexSDNode>(Addr)) { 224 return false; 225 } 226 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 227 Addr.getOpcode() == ISD::TargetGlobalAddress || 228 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 229 return false; // direct calls. 230 231 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) { 232 if (isInt<32>(CN->getSExtValue())) { 233 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 234 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 235 Offset = 236 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 237 return true; 238 } 239 } 240 return false; 241 } 242 243 bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base, 244 SDValue &Offset) { 245 if (matchADDRri(Addr, Base, Offset)) 246 return true; 247 248 Base = Addr; 249 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 250 return true; 251 } 252 253 bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base, 254 SDValue &Offset) { 255 if (dyn_cast<FrameIndexSDNode>(Addr)) 256 return false; 257 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 258 Addr.getOpcode() == ISD::TargetGlobalAddress || 259 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 260 return false; // direct calls. 261 262 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) { 263 if (isInt<32>(CN->getSExtValue())) { 264 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 265 Offset = 266 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 267 return true; 268 } 269 } 270 return false; 271 } 272 273 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) { 274 if (dyn_cast<FrameIndexSDNode>(Addr)) 275 return false; 276 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 277 Addr.getOpcode() == ISD::TargetGlobalAddress || 278 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 279 return false; // direct calls. 280 281 if (Addr.getOpcode() == ISD::ADD) { 282 ; // Nothing to do here. 283 } else if (Addr.getOpcode() == ISD::OR) { 284 // We want to look through a transform in InstCombine and DAGCombiner that 285 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'. 286 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1))) 287 return false; 288 } else { 289 return false; 290 } 291 292 if (Addr.getOperand(0).getOpcode() == VEISD::Lo || 293 Addr.getOperand(1).getOpcode() == VEISD::Lo) 294 return false; // Let the LEASL patterns catch this! 295 296 Base = Addr.getOperand(0); 297 Index = Addr.getOperand(1); 298 return true; 299 } 300 301 bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) { 302 auto AddrTy = Addr->getValueType(0); 303 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 304 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); 305 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 306 return true; 307 } 308 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 309 Addr.getOpcode() == ISD::TargetGlobalAddress || 310 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 311 return false; // direct calls. 312 313 if (CurDAG->isBaseWithConstantOffset(Addr)) { 314 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1)); 315 if (isInt<32>(CN->getSExtValue())) { 316 if (FrameIndexSDNode *FIN = 317 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 318 // Constant offset from frame ref. 319 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); 320 } else { 321 Base = Addr.getOperand(0); 322 } 323 Offset = 324 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 325 return true; 326 } 327 } 328 return false; 329 } 330 331 void VEDAGToDAGISel::Select(SDNode *N) { 332 SDLoc dl(N); 333 if (N->isMachineOpcode()) { 334 N->setNodeId(-1); 335 return; // Already selected. 336 } 337 338 switch (N->getOpcode()) { 339 case VEISD::GLOBAL_BASE_REG: 340 ReplaceNode(N, getGlobalBaseReg()); 341 return; 342 } 343 344 SelectCode(N); 345 } 346 347 SDNode *VEDAGToDAGISel::getGlobalBaseReg() { 348 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF); 349 return CurDAG 350 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout())) 351 .getNode(); 352 } 353 354 /// createVEISelDag - This pass converts a legalized DAG into a 355 /// VE-specific DAG, ready for instruction scheduling. 356 /// 357 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) { 358 return new VEDAGToDAGISel(TM); 359 } 360