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 /// convMImmVal - Convert a mimm integer immediate value to target immediate. 117 inline static uint64_t convMImmVal(uint64_t Val) { 118 if (Val == 0) 119 return 0; // (0)1 120 if (Val & (1UL << 63)) 121 return countLeadingOnes(Val); // (m)1 122 return countLeadingZeros(Val) | 0x40; // (m)0 123 } 124 125 //===--------------------------------------------------------------------===// 126 /// VEDAGToDAGISel - VE specific code to select VE machine 127 /// instructions for SelectionDAG operations. 128 /// 129 namespace { 130 class VEDAGToDAGISel : public SelectionDAGISel { 131 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can 132 /// make the right decision when generating code for different targets. 133 const VESubtarget *Subtarget; 134 135 public: 136 explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {} 137 138 bool runOnMachineFunction(MachineFunction &MF) override { 139 Subtarget = &MF.getSubtarget<VESubtarget>(); 140 return SelectionDAGISel::runOnMachineFunction(MF); 141 } 142 143 void Select(SDNode *N) override; 144 145 // Complex Pattern Selectors. 146 bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 147 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 148 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 149 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset); 150 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset); 151 152 StringRef getPassName() const override { 153 return "VE DAG->DAG Pattern Instruction Selection"; 154 } 155 156 // Include the pieces autogenerated from the target description. 157 #include "VEGenDAGISel.inc" 158 159 private: 160 SDNode *getGlobalBaseReg(); 161 162 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index); 163 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset); 164 }; 165 } // end anonymous namespace 166 167 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index, 168 SDValue &Offset) { 169 if (Addr.getOpcode() == ISD::FrameIndex) 170 return false; 171 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 172 Addr.getOpcode() == ISD::TargetGlobalAddress || 173 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 174 return false; // direct calls. 175 176 SDValue LHS, RHS; 177 if (matchADDRri(Addr, LHS, RHS)) { 178 if (matchADDRrr(LHS, Base, Index)) { 179 Offset = RHS; 180 return true; 181 } 182 // Return false to try selectADDRrii. 183 return false; 184 } 185 if (matchADDRrr(Addr, LHS, RHS)) { 186 // If the input is a pair of a frame-index and a register, move a 187 // frame-index to LHS. This generates MI with following operands. 188 // %dest, #FI, %reg, offset 189 // In the eliminateFrameIndex, above MI is converted to the following. 190 // %dest, %fp, %reg, fi_offset + offset 191 if (dyn_cast<FrameIndexSDNode>(RHS)) 192 std::swap(LHS, RHS); 193 194 if (matchADDRri(RHS, Index, Offset)) { 195 Base = LHS; 196 return true; 197 } 198 if (matchADDRri(LHS, Base, Offset)) { 199 Index = RHS; 200 return true; 201 } 202 Base = LHS; 203 Index = RHS; 204 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 205 return true; 206 } 207 return false; // Let the reg+imm(=0) pattern catch this! 208 } 209 210 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index, 211 SDValue &Offset) { 212 if (matchADDRri(Addr, Base, Offset)) { 213 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 214 return true; 215 } 216 217 Base = Addr; 218 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 219 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 220 return true; 221 } 222 223 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index, 224 SDValue &Offset) { 225 // Prefer ADDRrii. 226 return false; 227 } 228 229 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index, 230 SDValue &Offset) { 231 if (dyn_cast<FrameIndexSDNode>(Addr)) { 232 return false; 233 } 234 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 235 Addr.getOpcode() == ISD::TargetGlobalAddress || 236 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 237 return false; // direct calls. 238 239 if (ConstantSDNode *CN = cast<ConstantSDNode>(Addr)) { 240 if (isInt<32>(CN->getSExtValue())) { 241 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 242 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 243 Offset = 244 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 245 return true; 246 } 247 } 248 return false; 249 } 250 251 bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base, 252 SDValue &Offset) { 253 if (matchADDRri(Addr, Base, Offset)) 254 return true; 255 256 Base = Addr; 257 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 258 return true; 259 } 260 261 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) { 262 if (dyn_cast<FrameIndexSDNode>(Addr)) 263 return false; 264 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 265 Addr.getOpcode() == ISD::TargetGlobalAddress || 266 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 267 return false; // direct calls. 268 269 if (Addr.getOpcode() == ISD::ADD) { 270 ; // Nothing to do here. 271 } else if (Addr.getOpcode() == ISD::OR) { 272 // We want to look through a transform in InstCombine and DAGCombiner that 273 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'. 274 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1))) 275 return false; 276 } else { 277 return false; 278 } 279 280 if (Addr.getOperand(0).getOpcode() == VEISD::Lo || 281 Addr.getOperand(1).getOpcode() == VEISD::Lo) 282 return false; // Let the LEASL patterns catch this! 283 284 Base = Addr.getOperand(0); 285 Index = Addr.getOperand(1); 286 return true; 287 } 288 289 bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) { 290 auto AddrTy = Addr->getValueType(0); 291 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 292 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); 293 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 294 return true; 295 } 296 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 297 Addr.getOpcode() == ISD::TargetGlobalAddress || 298 Addr.getOpcode() == ISD::TargetGlobalTLSAddress) 299 return false; // direct calls. 300 301 if (CurDAG->isBaseWithConstantOffset(Addr)) { 302 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1)); 303 if (isInt<32>(CN->getSExtValue())) { 304 if (FrameIndexSDNode *FIN = 305 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 306 // Constant offset from frame ref. 307 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy); 308 } else { 309 Base = Addr.getOperand(0); 310 } 311 Offset = 312 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32); 313 return true; 314 } 315 } 316 return false; 317 } 318 319 void VEDAGToDAGISel::Select(SDNode *N) { 320 SDLoc dl(N); 321 if (N->isMachineOpcode()) { 322 N->setNodeId(-1); 323 return; // Already selected. 324 } 325 326 switch (N->getOpcode()) { 327 case VEISD::GLOBAL_BASE_REG: 328 ReplaceNode(N, getGlobalBaseReg()); 329 return; 330 } 331 332 SelectCode(N); 333 } 334 335 SDNode *VEDAGToDAGISel::getGlobalBaseReg() { 336 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF); 337 return CurDAG 338 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout())) 339 .getNode(); 340 } 341 342 /// createVEISelDag - This pass converts a legalized DAG into a 343 /// VE-specific DAG, ready for instruction scheduling. 344 /// 345 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) { 346 return new VEDAGToDAGISel(TM); 347 } 348