1 //===-- CSKYInstrInfo.h - CSKY Instruction Information --------*- C++ -*---===// 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 contains the CSKY implementation of the TargetInstrInfo class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CSKYInstrInfo.h" 14 #include "CSKYConstantPoolValue.h" 15 #include "CSKYMachineFunctionInfo.h" 16 #include "CSKYTargetMachine.h" 17 #include "llvm/MC/MCContext.h" 18 19 #define DEBUG_TYPE "csky-instr-info" 20 21 using namespace llvm; 22 23 #define GET_INSTRINFO_CTOR_DTOR 24 #include "CSKYGenInstrInfo.inc" 25 26 CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget &STI) 27 : CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) { 28 } 29 30 static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target, 31 SmallVectorImpl<MachineOperand> &Cond) { 32 // Block ends with fall-through condbranch. 33 assert(LastInst.getDesc().isConditionalBranch() && 34 "Unknown conditional branch"); 35 Target = LastInst.getOperand(1).getMBB(); 36 Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode())); 37 Cond.push_back(LastInst.getOperand(0)); 38 } 39 40 bool CSKYInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 41 MachineBasicBlock *&TBB, 42 MachineBasicBlock *&FBB, 43 SmallVectorImpl<MachineOperand> &Cond, 44 bool AllowModify) const { 45 TBB = FBB = nullptr; 46 Cond.clear(); 47 48 // If the block has no terminators, it just falls into the block after it. 49 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); 50 if (I == MBB.end() || !isUnpredicatedTerminator(*I)) 51 return false; 52 53 // Count the number of terminators and find the first unconditional or 54 // indirect branch. 55 MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end(); 56 int NumTerminators = 0; 57 for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J); 58 J++) { 59 NumTerminators++; 60 if (J->getDesc().isUnconditionalBranch() || 61 J->getDesc().isIndirectBranch()) { 62 FirstUncondOrIndirectBr = J.getReverse(); 63 } 64 } 65 66 // If AllowModify is true, we can erase any terminators after 67 // FirstUncondOrIndirectBR. 68 if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) { 69 while (std::next(FirstUncondOrIndirectBr) != MBB.end()) { 70 std::next(FirstUncondOrIndirectBr)->eraseFromParent(); 71 NumTerminators--; 72 } 73 I = FirstUncondOrIndirectBr; 74 } 75 76 // We can't handle blocks that end in an indirect branch. 77 if (I->getDesc().isIndirectBranch()) 78 return true; 79 80 // We can't handle blocks with more than 2 terminators. 81 if (NumTerminators > 2) 82 return true; 83 84 // Handle a single unconditional branch. 85 if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) { 86 TBB = getBranchDestBlock(*I); 87 return false; 88 } 89 90 // Handle a single conditional branch. 91 if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) { 92 parseCondBranch(*I, TBB, Cond); 93 return false; 94 } 95 96 // Handle a conditional branch followed by an unconditional branch. 97 if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() && 98 I->getDesc().isUnconditionalBranch()) { 99 parseCondBranch(*std::prev(I), TBB, Cond); 100 FBB = getBranchDestBlock(*I); 101 return false; 102 } 103 104 // Otherwise, we can't handle this. 105 return true; 106 } 107 108 unsigned CSKYInstrInfo::removeBranch(MachineBasicBlock &MBB, 109 int *BytesRemoved) const { 110 if (BytesRemoved) 111 *BytesRemoved = 0; 112 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); 113 if (I == MBB.end()) 114 return 0; 115 116 if (!I->getDesc().isUnconditionalBranch() && 117 !I->getDesc().isConditionalBranch()) 118 return 0; 119 120 // Remove the branch. 121 if (BytesRemoved) 122 *BytesRemoved += getInstSizeInBytes(*I); 123 I->eraseFromParent(); 124 125 I = MBB.end(); 126 127 if (I == MBB.begin()) 128 return 1; 129 --I; 130 if (!I->getDesc().isConditionalBranch()) 131 return 1; 132 133 // Remove the branch. 134 if (BytesRemoved) 135 *BytesRemoved += getInstSizeInBytes(*I); 136 I->eraseFromParent(); 137 return 2; 138 } 139 140 MachineBasicBlock * 141 CSKYInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { 142 assert(MI.getDesc().isBranch() && "Unexpected opcode!"); 143 // The branch target is always the last operand. 144 int NumOp = MI.getNumExplicitOperands(); 145 assert(MI.getOperand(NumOp - 1).isMBB() && "Expected MBB!"); 146 return MI.getOperand(NumOp - 1).getMBB(); 147 } 148 149 unsigned CSKYInstrInfo::insertBranch( 150 MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, 151 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const { 152 if (BytesAdded) 153 *BytesAdded = 0; 154 155 // Shouldn't be a fall through. 156 assert(TBB && "insertBranch must not be told to insert a fallthrough"); 157 assert((Cond.size() == 2 || Cond.size() == 0) && 158 "CSKY branch conditions have two components!"); 159 160 // Unconditional branch. 161 if (Cond.empty()) { 162 MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(TBB); 163 if (BytesAdded) 164 *BytesAdded += getInstSizeInBytes(MI); 165 return 1; 166 } 167 168 // Either a one or two-way conditional branch. 169 unsigned Opc = Cond[0].getImm(); 170 MachineInstr &CondMI = *BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).addMBB(TBB); 171 if (BytesAdded) 172 *BytesAdded += getInstSizeInBytes(CondMI); 173 174 // One-way conditional branch. 175 if (!FBB) 176 return 1; 177 178 // Two-way conditional branch. 179 MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(FBB); 180 if (BytesAdded) 181 *BytesAdded += getInstSizeInBytes(MI); 182 return 2; 183 } 184 185 static unsigned getOppositeBranchOpc(unsigned Opcode) { 186 switch (Opcode) { 187 default: 188 llvm_unreachable("Unknown conditional branch!"); 189 case CSKY::BT32: 190 return CSKY::BF32; 191 case CSKY::BT16: 192 return CSKY::BF16; 193 case CSKY::BF32: 194 return CSKY::BT32; 195 case CSKY::BF16: 196 return CSKY::BT16; 197 case CSKY::BHZ32: 198 return CSKY::BLSZ32; 199 case CSKY::BHSZ32: 200 return CSKY::BLZ32; 201 case CSKY::BLZ32: 202 return CSKY::BHSZ32; 203 case CSKY::BLSZ32: 204 return CSKY::BHZ32; 205 case CSKY::BNEZ32: 206 return CSKY::BEZ32; 207 case CSKY::BEZ32: 208 return CSKY::BNEZ32; 209 } 210 } 211 212 bool CSKYInstrInfo::reverseBranchCondition( 213 SmallVectorImpl<MachineOperand> &Cond) const { 214 assert((Cond.size() == 2) && "Invalid branch condition!"); 215 Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm())); 216 return false; 217 } 218 219 Register CSKYInstrInfo::movImm(MachineBasicBlock &MBB, 220 MachineBasicBlock::iterator MBBI, 221 const DebugLoc &DL, int64_t Val, 222 MachineInstr::MIFlag Flag) const { 223 assert(isUInt<32>(Val) && "should be uint32"); 224 225 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 226 227 Register DstReg; 228 if (STI.hasE2()) { 229 DstReg = MRI.createVirtualRegister(&CSKY::GPRRegClass); 230 231 if (isUInt<16>(Val)) { 232 BuildMI(MBB, MBBI, DL, get(CSKY::MOVI32), DstReg) 233 .addImm(Val & 0xFFFF) 234 .setMIFlags(Flag); 235 } else if (isShiftedUInt<16, 16>(Val)) { 236 BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg) 237 .addImm((Val >> 16) & 0xFFFF) 238 .setMIFlags(Flag); 239 } else { 240 BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg) 241 .addImm((Val >> 16) & 0xFFFF) 242 .setMIFlags(Flag); 243 BuildMI(MBB, MBBI, DL, get(CSKY::ORI32), DstReg) 244 .addReg(DstReg) 245 .addImm(Val & 0xFFFF) 246 .setMIFlags(Flag); 247 } 248 249 } else { 250 DstReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass); 251 if (isUInt<8>(Val)) { 252 BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) 253 .addImm(Val & 0xFF) 254 .setMIFlags(Flag); 255 } else if (isUInt<16>(Val)) { 256 BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) 257 .addImm((Val >> 8) & 0xFF) 258 .setMIFlags(Flag); 259 BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 260 .addReg(DstReg) 261 .addImm(8) 262 .setMIFlags(Flag); 263 if ((Val & 0xFF) != 0) 264 BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 265 .addReg(DstReg) 266 .addImm(Val & 0xFF) 267 .setMIFlags(Flag); 268 } else if (isUInt<24>(Val)) { 269 BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) 270 .addImm((Val >> 16) & 0xFF) 271 .setMIFlags(Flag); 272 BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 273 .addReg(DstReg) 274 .addImm(8) 275 .setMIFlags(Flag); 276 if (((Val >> 8) & 0xFF) != 0) 277 BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 278 .addReg(DstReg) 279 .addImm((Val >> 8) & 0xFF) 280 .setMIFlags(Flag); 281 BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 282 .addReg(DstReg) 283 .addImm(8) 284 .setMIFlags(Flag); 285 if ((Val & 0xFF) != 0) 286 BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 287 .addReg(DstReg) 288 .addImm(Val & 0xFF) 289 .setMIFlags(Flag); 290 } else { 291 BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) 292 .addImm((Val >> 24) & 0xFF) 293 .setMIFlags(Flag); 294 BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 295 .addReg(DstReg) 296 .addImm(8) 297 .setMIFlags(Flag); 298 if (((Val >> 16) & 0xFF) != 0) 299 BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 300 .addReg(DstReg) 301 .addImm((Val >> 16) & 0xFF) 302 .setMIFlags(Flag); 303 BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 304 .addReg(DstReg) 305 .addImm(8) 306 .setMIFlags(Flag); 307 if (((Val >> 8) & 0xFF) != 0) 308 BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 309 .addReg(DstReg) 310 .addImm((Val >> 8) & 0xFF) 311 .setMIFlags(Flag); 312 BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) 313 .addReg(DstReg) 314 .addImm(8) 315 .setMIFlags(Flag); 316 if ((Val & 0xFF) != 0) 317 BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) 318 .addReg(DstReg) 319 .addImm(Val & 0xFF) 320 .setMIFlags(Flag); 321 } 322 } 323 324 return DstReg; 325 } 326 327 unsigned CSKYInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, 328 int &FrameIndex) const { 329 switch (MI.getOpcode()) { 330 default: 331 return 0; 332 case CSKY::LD16B: 333 case CSKY::LD16H: 334 case CSKY::LD16W: 335 case CSKY::LD32B: 336 case CSKY::LD32BS: 337 case CSKY::LD32H: 338 case CSKY::LD32HS: 339 case CSKY::LD32W: 340 case CSKY::RESTORE_CARRY: 341 break; 342 } 343 344 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && 345 MI.getOperand(2).getImm() == 0) { 346 FrameIndex = MI.getOperand(1).getIndex(); 347 return MI.getOperand(0).getReg(); 348 } 349 350 return 0; 351 } 352 353 unsigned CSKYInstrInfo::isStoreToStackSlot(const MachineInstr &MI, 354 int &FrameIndex) const { 355 switch (MI.getOpcode()) { 356 default: 357 return 0; 358 case CSKY::ST16B: 359 case CSKY::ST16H: 360 case CSKY::ST16W: 361 case CSKY::ST32B: 362 case CSKY::ST32H: 363 case CSKY::ST32W: 364 case CSKY::SPILL_CARRY: 365 break; 366 } 367 368 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && 369 MI.getOperand(2).getImm() == 0) { 370 FrameIndex = MI.getOperand(1).getIndex(); 371 return MI.getOperand(0).getReg(); 372 } 373 374 return 0; 375 } 376 377 void CSKYInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 378 MachineBasicBlock::iterator I, 379 Register SrcReg, bool IsKill, int FI, 380 const TargetRegisterClass *RC, 381 const TargetRegisterInfo *TRI) const { 382 DebugLoc DL; 383 if (I != MBB.end()) 384 DL = I->getDebugLoc(); 385 386 MachineFunction &MF = *MBB.getParent(); 387 CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 388 MachineFrameInfo &MFI = MF.getFrameInfo(); 389 390 unsigned Opcode = 0; 391 392 if (CSKY::GPRRegClass.hasSubClassEq(RC)) { 393 Opcode = CSKY::ST32W; // Optimize for 16bit 394 } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) { 395 Opcode = CSKY::SPILL_CARRY; 396 CFI->setSpillsCR(); 397 } else { 398 llvm_unreachable("Unknown RegisterClass"); 399 } 400 401 MachineMemOperand *MMO = MF.getMachineMemOperand( 402 MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, 403 MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 404 405 BuildMI(MBB, I, DL, get(Opcode)) 406 .addReg(SrcReg, getKillRegState(IsKill)) 407 .addFrameIndex(FI) 408 .addImm(0) 409 .addMemOperand(MMO); 410 } 411 412 void CSKYInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 413 MachineBasicBlock::iterator I, 414 Register DestReg, int FI, 415 const TargetRegisterClass *RC, 416 const TargetRegisterInfo *TRI) const { 417 DebugLoc DL; 418 if (I != MBB.end()) 419 DL = I->getDebugLoc(); 420 421 MachineFunction &MF = *MBB.getParent(); 422 CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 423 MachineFrameInfo &MFI = MF.getFrameInfo(); 424 425 unsigned Opcode = 0; 426 427 if (CSKY::GPRRegClass.hasSubClassEq(RC)) { 428 Opcode = CSKY::LD32W; 429 } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) { 430 Opcode = CSKY::RESTORE_CARRY; 431 CFI->setSpillsCR(); 432 } else { 433 llvm_unreachable("Unknown RegisterClass"); 434 } 435 436 MachineMemOperand *MMO = MF.getMachineMemOperand( 437 MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, 438 MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 439 440 BuildMI(MBB, I, DL, get(Opcode), DestReg) 441 .addFrameIndex(FI) 442 .addImm(0) 443 .addMemOperand(MMO); 444 } 445 446 void CSKYInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 447 MachineBasicBlock::iterator I, 448 const DebugLoc &DL, MCRegister DestReg, 449 MCRegister SrcReg, bool KillSrc) const { 450 451 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 452 453 if (CSKY::GPRRegClass.contains(SrcReg) && 454 CSKY::CARRYRegClass.contains(DestReg)) { 455 if (STI.hasE2()) { 456 BuildMI(MBB, I, DL, get(CSKY::BTSTI32), DestReg) 457 .addReg(SrcReg, getKillRegState(KillSrc)) 458 .addImm(0); 459 } else { 460 assert(SrcReg < CSKY::R8); 461 BuildMI(MBB, I, DL, get(CSKY::BTSTI16), DestReg) 462 .addReg(SrcReg, getKillRegState(KillSrc)) 463 .addImm(0); 464 } 465 return; 466 } 467 468 if (CSKY::CARRYRegClass.contains(SrcReg) && 469 CSKY::GPRRegClass.contains(DestReg)) { 470 471 if (STI.hasE2()) { 472 BuildMI(MBB, I, DL, get(CSKY::MVC32), DestReg) 473 .addReg(SrcReg, getKillRegState(KillSrc)); 474 } else { 475 assert(DestReg < CSKY::R16); 476 assert(DestReg < CSKY::R8); 477 BuildMI(MBB, I, DL, get(CSKY::MOVI16), DestReg).addImm(0); 478 BuildMI(MBB, I, DL, get(CSKY::ADDC16)) 479 .addReg(DestReg, RegState::Define) 480 .addReg(SrcReg, RegState::Define) 481 .addReg(DestReg, getKillRegState(true)) 482 .addReg(DestReg, getKillRegState(true)) 483 .addReg(SrcReg, getKillRegState(true)); 484 BuildMI(MBB, I, DL, get(CSKY::BTSTI16)) 485 .addReg(SrcReg, RegState::Define | getDeadRegState(KillSrc)) 486 .addReg(DestReg) 487 .addImm(0); 488 } 489 return; 490 } 491 492 unsigned Opcode = 0; 493 if (CSKY::GPRRegClass.contains(DestReg, SrcReg)) 494 Opcode = CSKY::MOV32; 495 else { 496 LLVM_DEBUG(dbgs() << "src = " << SrcReg << ", dst = " << DestReg); 497 LLVM_DEBUG(I->dump()); 498 llvm_unreachable("Unknown RegisterClass"); 499 } 500 501 BuildMI(MBB, I, DL, get(Opcode), DestReg) 502 .addReg(SrcReg, getKillRegState(KillSrc)); 503 } 504 505 Register CSKYInstrInfo::getGlobalBaseReg(MachineFunction &MF) const { 506 CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 507 MachineConstantPool *MCP = MF.getConstantPool(); 508 MachineRegisterInfo &MRI = MF.getRegInfo(); 509 510 Register GlobalBaseReg = CFI->getGlobalBaseReg(); 511 if (GlobalBaseReg != 0) 512 return GlobalBaseReg; 513 514 // Insert a pseudo instruction to set the GlobalBaseReg into the first 515 // MBB of the function 516 MachineBasicBlock &FirstMBB = MF.front(); 517 MachineBasicBlock::iterator MBBI = FirstMBB.begin(); 518 DebugLoc DL; 519 520 CSKYConstantPoolValue *CPV = CSKYConstantPoolSymbol::Create( 521 Type::getInt32Ty(MF.getFunction().getContext()), "_GLOBAL_OFFSET_TABLE_", 522 0, CSKYCP::ADDR); 523 524 unsigned CPI = MCP->getConstantPoolIndex(CPV, Align(4)); 525 526 MachineMemOperand *MO = 527 MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF), 528 MachineMemOperand::MOLoad, 4, Align(4)); 529 BuildMI(FirstMBB, MBBI, DL, get(CSKY::LRW32), CSKY::R28) 530 .addConstantPoolIndex(CPI) 531 .addMemOperand(MO); 532 533 GlobalBaseReg = MRI.createVirtualRegister(&CSKY::GPRRegClass); 534 BuildMI(FirstMBB, MBBI, DL, get(TargetOpcode::COPY), GlobalBaseReg) 535 .addReg(CSKY::R28); 536 537 CFI->setGlobalBaseReg(GlobalBaseReg); 538 return GlobalBaseReg; 539 } 540 541 unsigned CSKYInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { 542 switch (MI.getOpcode()) { 543 default: 544 return MI.getDesc().getSize(); 545 case CSKY::CONSTPOOL_ENTRY: 546 return MI.getOperand(2).getImm(); 547 case CSKY::SPILL_CARRY: 548 case CSKY::RESTORE_CARRY: 549 case CSKY::PseudoTLSLA32: 550 return 8; 551 case TargetOpcode::INLINEASM_BR: 552 case TargetOpcode::INLINEASM: { 553 const MachineFunction *MF = MI.getParent()->getParent(); 554 const char *AsmStr = MI.getOperand(0).getSymbolName(); 555 return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); 556 } 557 } 558 } 559