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 (isa<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 (isa<FrameIndexSDNode>(Addr)) 224 return false; 225 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 226 Addr.getOpcode() == ISD::TargetGlobalAddress || 227 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 228 return false; // direct calls. 229 230 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) { 231 if (isInt<32>(CN->getSExtValue())) { 232 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 233 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 234 Offset = 235 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 236 return true; 237 } 238 } 239 return false; 240 } 241 242 bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base, 243 SDValue &Offset) { 244 if (matchADDRri(Addr, Base, Offset)) 245 return true; 246 247 Base = Addr; 248 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 249 return true; 250 } 251 252 bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base, 253 SDValue &Offset) { 254 if (isa<FrameIndexSDNode>(Addr)) 255 return false; 256 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 257 Addr.getOpcode() == ISD::TargetGlobalAddress || 258 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 259 return false; // direct calls. 260 261 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) { 262 if (isInt<32>(CN->getSExtValue())) { 263 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 264 Offset = 265 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 266 return true; 267 } 268 } 269 return false; 270 } 271 272 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) { 273 if (isa<FrameIndexSDNode>(Addr)) 274 return false; 275 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 276 Addr.getOpcode() == ISD::TargetGlobalAddress || 277 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 278 return false; // direct calls. 279 280 if (Addr.getOpcode() == ISD::ADD) { 281 ; // Nothing to do here. 282 } else if (Addr.getOpcode() == ISD::OR) { 283 // We want to look through a transform in InstCombine and DAGCombiner that 284 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'. 285 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1))) 286 return false; 287 } else { 288 return false; 289 } 290 291 if (Addr.getOperand(0).getOpcode() == VEISD::Lo || 292 Addr.getOperand(1).getOpcode() == VEISD::Lo) 293 return false; // Let the LEASL patterns catch this! 294 295 Base = Addr.getOperand(0); 296 Index = Addr.getOperand(1); 297 return true; 298 } 299 300 bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) { 301 auto AddrTy = Addr->getValueType(0); 302 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 303 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); 304 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 305 return true; 306 } 307 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 308 Addr.getOpcode() == ISD::TargetGlobalAddress || 309 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 310 return false; // direct calls. 311 312 if (CurDAG->isBaseWithConstantOffset(Addr)) { 313 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1)); 314 if (isInt<32>(CN->getSExtValue())) { 315 if (FrameIndexSDNode *FIN = 316 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 317 // Constant offset from frame ref. 318 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); 319 } else { 320 Base = Addr.getOperand(0); 321 } 322 Offset = 323 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 324 return true; 325 } 326 } 327 return false; 328 } 329 330 void VEDAGToDAGISel::Select(SDNode *N) { 331 SDLoc dl(N); 332 if (N->isMachineOpcode()) { 333 N->setNodeId(-1); 334 return; // Already selected. 335 } 336 337 switch (N->getOpcode()) { 338 case VEISD::GLOBAL_BASE_REG: 339 ReplaceNode(N, getGlobalBaseReg()); 340 return; 341 } 342 343 SelectCode(N); 344 } 345 346 SDNode *VEDAGToDAGISel::getGlobalBaseReg() { 347 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF); 348 return CurDAG 349 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout())) 350 .getNode(); 351 } 352 353 /// createVEISelDag - This pass converts a legalized DAG into a 354 /// VE-specific DAG, ready for instruction scheduling. 355 /// 356 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) { 357 return new VEDAGToDAGISel(TM); 358 } 359