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