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 "VE.h" 14 #include "VETargetMachine.h" 15 #include "llvm/CodeGen/MachineRegisterInfo.h" 16 #include "llvm/CodeGen/SelectionDAGISel.h" 17 #include "llvm/IR/Intrinsics.h" 18 #include "llvm/Support/Debug.h" 19 #include "llvm/Support/ErrorHandling.h" 20 #include "llvm/Support/raw_ostream.h" 21 using namespace llvm; 22 23 //===----------------------------------------------------------------------===// 24 // Instruction Selector Implementation 25 //===----------------------------------------------------------------------===// 26 27 /// Convert a DAG integer condition code to a VE ICC condition. 28 inline static VECC::CondCode intCondCode2Icc(ISD::CondCode CC) { 29 switch (CC) { 30 default: 31 llvm_unreachable("Unknown integer condition code!"); 32 case ISD::SETEQ: 33 return VECC::CC_IEQ; 34 case ISD::SETNE: 35 return VECC::CC_INE; 36 case ISD::SETLT: 37 return VECC::CC_IL; 38 case ISD::SETGT: 39 return VECC::CC_IG; 40 case ISD::SETLE: 41 return VECC::CC_ILE; 42 case ISD::SETGE: 43 return VECC::CC_IGE; 44 case ISD::SETULT: 45 return VECC::CC_IL; 46 case ISD::SETULE: 47 return VECC::CC_ILE; 48 case ISD::SETUGT: 49 return VECC::CC_IG; 50 case ISD::SETUGE: 51 return VECC::CC_IGE; 52 } 53 } 54 55 /// Convert a DAG floating point condition code to a VE FCC condition. 56 inline static VECC::CondCode fpCondCode2Fcc(ISD::CondCode CC) { 57 switch (CC) { 58 default: 59 llvm_unreachable("Unknown fp condition code!"); 60 case ISD::SETFALSE: 61 return VECC::CC_AF; 62 case ISD::SETEQ: 63 case ISD::SETOEQ: 64 return VECC::CC_EQ; 65 case ISD::SETNE: 66 case ISD::SETONE: 67 return VECC::CC_NE; 68 case ISD::SETLT: 69 case ISD::SETOLT: 70 return VECC::CC_L; 71 case ISD::SETGT: 72 case ISD::SETOGT: 73 return VECC::CC_G; 74 case ISD::SETLE: 75 case ISD::SETOLE: 76 return VECC::CC_LE; 77 case ISD::SETGE: 78 case ISD::SETOGE: 79 return VECC::CC_GE; 80 case ISD::SETO: 81 return VECC::CC_NUM; 82 case ISD::SETUO: 83 return VECC::CC_NAN; 84 case ISD::SETUEQ: 85 return VECC::CC_EQNAN; 86 case ISD::SETUNE: 87 return VECC::CC_NENAN; 88 case ISD::SETULT: 89 return VECC::CC_LNAN; 90 case ISD::SETUGT: 91 return VECC::CC_GNAN; 92 case ISD::SETULE: 93 return VECC::CC_LENAN; 94 case ISD::SETUGE: 95 return VECC::CC_GENAN; 96 case ISD::SETTRUE: 97 return VECC::CC_AT; 98 } 99 } 100 101 /// getImmVal - get immediate representation of integer value 102 inline static uint64_t getImmVal(const ConstantSDNode *N) { 103 return N->getSExtValue(); 104 } 105 106 /// getFpImmVal - get immediate representation of floating point value 107 inline static uint64_t getFpImmVal(const ConstantFPSDNode *N) { 108 const APInt &Imm = N->getValueAPF().bitcastToAPInt(); 109 uint64_t Val = Imm.getZExtValue(); 110 if (Imm.getBitWidth() == 32) { 111 // Immediate value of float place places at higher bits on VE. 112 Val <<= 32; 113 } 114 return Val; 115 } 116 117 //===--------------------------------------------------------------------===// 118 /// VEDAGToDAGISel - VE specific code to select VE machine 119 /// instructions for SelectionDAG operations. 120 /// 121 namespace { 122 class VEDAGToDAGISel : public SelectionDAGISel { 123 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can 124 /// make the right decision when generating code for different targets. 125 const VESubtarget *Subtarget; 126 127 public: 128 explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {} 129 130 bool runOnMachineFunction(MachineFunction &MF) override { 131 Subtarget = &MF.getSubtarget<VESubtarget>(); 132 return SelectionDAGISel::runOnMachineFunction(MF); 133 } 134 135 void Select(SDNode *N) override; 136 137 // Complex Pattern Selectors. 138 bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 139 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 140 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 141 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 142 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset); 143 bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset); 144 145 StringRef getPassName() const override { 146 return "VE DAG->DAG Pattern Instruction Selection"; 147 } 148 149 // Include the pieces autogenerated from the target description. 150 #include "VEGenDAGISel.inc" 151 152 private: 153 SDNode *getGlobalBaseReg(); 154 155 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index); 156 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset); 157 }; 158 } // end anonymous namespace 159 160 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index, 161 SDValue &Offset) { 162 if (Addr.getOpcode() == ISD::FrameIndex) 163 return false; 164 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 165 Addr.getOpcode() == ISD::TargetGlobalAddress || 166 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 167 return false; // direct calls. 168 169 SDValue LHS, RHS; 170 if (matchADDRri(Addr, LHS, RHS)) { 171 if (matchADDRrr(LHS, Base, Index)) { 172 Offset = RHS; 173 return true; 174 } 175 // Return false to try selectADDRrii. 176 return false; 177 } 178 if (matchADDRrr(Addr, LHS, RHS)) { 179 // If the input is a pair of a frame-index and a register, move a 180 // frame-index to LHS. This generates MI with following operands. 181 // %dest, #FI, %reg, offset 182 // In the eliminateFrameIndex, above MI is converted to the following. 183 // %dest, %fp, %reg, fi_offset + offset 184 if (isa<FrameIndexSDNode>(RHS)) 185 std::swap(LHS, RHS); 186 187 if (matchADDRri(RHS, Index, Offset)) { 188 Base = LHS; 189 return true; 190 } 191 if (matchADDRri(LHS, Base, Offset)) { 192 Index = RHS; 193 return true; 194 } 195 Base = LHS; 196 Index = RHS; 197 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 198 return true; 199 } 200 return false; // Let the reg+imm(=0) pattern catch this! 201 } 202 203 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index, 204 SDValue &Offset) { 205 if (matchADDRri(Addr, Base, Offset)) { 206 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 207 return true; 208 } 209 210 Base = Addr; 211 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 212 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 213 return true; 214 } 215 216 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index, 217 SDValue &Offset) { 218 // Prefer ADDRrii. 219 return false; 220 } 221 222 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index, 223 SDValue &Offset) { 224 if (isa<FrameIndexSDNode>(Addr)) 225 return false; 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 (isa<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 (isa<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 340 // Late eliminate the LEGALAVL wrapper 341 case VEISD::LEGALAVL: 342 ReplaceNode(N, N->getOperand(0).getNode()); 343 return; 344 345 // Lower (broadcast 1) and (broadcast 0) to VM[P]0 346 case VEISD::VEC_BROADCAST: { 347 MVT SplatResTy = N->getSimpleValueType(0); 348 if (SplatResTy.getVectorElementType() != MVT::i1) 349 break; 350 351 // Constant non-zero broadcast. 352 auto BConst = dyn_cast<ConstantSDNode>(N->getOperand(0)); 353 if (!BConst) 354 break; 355 bool BCTrueMask = (BConst->getSExtValue() != 0); 356 if (!BCTrueMask) 357 break; 358 359 // Packed or non-packed. 360 SDValue New; 361 if (SplatResTy.getVectorNumElements() == StandardVectorWidth) { 362 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VM0, 363 MVT::v256i1); 364 } else if (SplatResTy.getVectorNumElements() == PackedVectorWidth) { 365 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VMP0, 366 MVT::v512i1); 367 } else 368 break; 369 370 // Replace. 371 ReplaceNode(N, New.getNode()); 372 return; 373 } 374 375 case VEISD::GLOBAL_BASE_REG: 376 ReplaceNode(N, getGlobalBaseReg()); 377 return; 378 } 379 380 SelectCode(N); 381 } 382 383 SDNode *VEDAGToDAGISel::getGlobalBaseReg() { 384 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF); 385 return CurDAG 386 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout())) 387 .getNode(); 388 } 389 390 /// createVEISelDag - This pass converts a legalized DAG into a 391 /// VE-specific DAG, ready for instruction scheduling. 392 /// 393 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) { 394 return new VEDAGToDAGISel(TM); 395 } 396