LLVM: lib/Target/CSKY/CSKYInstrInfo.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

19

20#define DEBUG_TYPE "csky-instr-info"

21

22using namespace llvm;

23

24#define GET_INSTRINFO_CTOR_DTOR

25#include "CSKYGenInstrInfo.inc"

26

28 : CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) {

33}

34

37

39 "Unknown conditional branch");

43}

44

49 bool AllowModify) const {

50 TBB = FBB = nullptr;

52

53

55 if (I == MBB.end() || !isUnpredicatedTerminator(*I))

56 return false;

57

58

59

61 int NumTerminators = 0;

62 for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);

63 J++) {

64 NumTerminators++;

65 if (J->getDesc().isUnconditionalBranch() ||

66 J->getDesc().isIndirectBranch()) {

67 FirstUncondOrIndirectBr = J.getReverse();

68 }

69 }

70

71

72

73 if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {

74 while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {

75 std::next(FirstUncondOrIndirectBr)->eraseFromParent();

76 NumTerminators--;

77 }

78 I = FirstUncondOrIndirectBr;

79 }

80

81

82 if (I->getDesc().isIndirectBranch())

83 return true;

84

85

86 if (NumTerminators > 2)

87 return true;

88

89

90 if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {

92 return false;

93 }

94

95

96 if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {

98 return false;

99 }

100

101

102 if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&

103 I->getDesc().isUnconditionalBranch()) {

106 return false;

107 }

108

109

110 return true;

111}

112

114 int *BytesRemoved) const {

115 if (BytesRemoved)

116 *BytesRemoved = 0;

119 return 0;

120

121 if (I->getDesc().isUnconditionalBranch() &&

122 I->getDesc().isConditionalBranch())

123 return 0;

124

125

126 if (BytesRemoved)

128 I->eraseFromParent();

129

131

133 return 1;

134 --I;

135 if (I->getDesc().isConditionalBranch())

136 return 1;

137

138

139 if (BytesRemoved)

141 I->eraseFromParent();

142 return 2;

143}

144

147 assert(MI.getDesc().isBranch() && "Unexpected opcode!");

148

149 int NumOp = MI.getNumExplicitOperands();

150 assert(MI.getOperand(NumOp - 1).isMBB() && "Expected MBB!");

151 return MI.getOperand(NumOp - 1).getMBB();

152}

153

157 if (BytesAdded)

158 *BytesAdded = 0;

159

160

161 assert(TBB && "insertBranch must not be told to insert a fallthrough");

163 "CSKY branch conditions have two components!");

164

165

166 if (Cond.empty()) {

168 if (BytesAdded)

170 return 1;

171 }

172

173

174 unsigned Opc = Cond[0].getImm();

176 if (BytesAdded)

178

179

180 if (!FBB)

181 return 1;

182

183

185 if (BytesAdded)

187 return 2;

188}

189

191 switch (Opcode) {

192 default:

194 case CSKY::BT32:

195 return CSKY::BF32;

196 case CSKY::BT16:

197 return CSKY::BF16;

198 case CSKY::BF32:

199 return CSKY::BT32;

200 case CSKY::BF16:

201 return CSKY::BT16;

202 case CSKY::BHZ32:

203 return CSKY::BLSZ32;

204 case CSKY::BHSZ32:

205 return CSKY::BLZ32;

206 case CSKY::BLZ32:

207 return CSKY::BHSZ32;

208 case CSKY::BLSZ32:

209 return CSKY::BHZ32;

210 case CSKY::BNEZ32:

211 return CSKY::BEZ32;

212 case CSKY::BEZ32:

213 return CSKY::BNEZ32;

214 }

215}

216

219 assert((Cond.size() == 2) && "Invalid branch condition!");

221 return false;

222}

223

228 if (!isInt<32>(Val))

230

232

235 DstReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);

236

237 if (isUInt<16>(Val)) {

239 .addImm(Val & 0xFFFF)

241 } else if (isShiftedUInt<16, 16>(Val)) {

243 .addImm((Val >> 16) & 0xFFFF)

245 } else {

247 .addImm((Val >> 16) & 0xFFFF)

251 .addImm(Val & 0xFFFF)

253 }

254

255 } else {

256 DstReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);

257 if (isUInt<8>(Val)) {

261 } else if (isUInt<16>(Val)) {

263 .addImm((Val >> 8) & 0xFF)

269 if ((Val & 0xFF) != 0)

274 } else if (isUInt<24>(Val)) {

276 .addImm((Val >> 16) & 0xFF)

282 if (((Val >> 8) & 0xFF) != 0)

285 .addImm((Val >> 8) & 0xFF)

291 if ((Val & 0xFF) != 0)

296 } else {

298 .addImm((Val >> 24) & 0xFF)

304 if (((Val >> 16) & 0xFF) != 0)

307 .addImm((Val >> 16) & 0xFF)

313 if (((Val >> 8) & 0xFF) != 0)

316 .addImm((Val >> 8) & 0xFF)

322 if ((Val & 0xFF) != 0)

327 }

328 }

329

330 return DstReg;

331}

332

334 int &FrameIndex) const {

335 switch (MI.getOpcode()) {

336 default:

337 return 0;

338 case CSKY::LD16B:

339 case CSKY::LD16H:

340 case CSKY::LD16W:

341 case CSKY::LD32B:

342 case CSKY::LD32BS:

343 case CSKY::LD32H:

344 case CSKY::LD32HS:

345 case CSKY::LD32W:

346 case CSKY::FLD_S:

347 case CSKY::FLD_D:

348 case CSKY::f2FLD_S:

349 case CSKY::f2FLD_D:

350 case CSKY::RESTORE_CARRY:

351 break;

352 }

353

354 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&

355 MI.getOperand(2).getImm() == 0) {

356 FrameIndex = MI.getOperand(1).getIndex();

357 return MI.getOperand(0).getReg();

358 }

359

360 return 0;

361}

362

364 int &FrameIndex) const {

365 switch (MI.getOpcode()) {

366 default:

367 return 0;

368 case CSKY::ST16B:

369 case CSKY::ST16H:

370 case CSKY::ST16W:

371 case CSKY::ST32B:

372 case CSKY::ST32H:

373 case CSKY::ST32W:

374 case CSKY::FST_S:

375 case CSKY::FST_D:

376 case CSKY::f2FST_S:

377 case CSKY::f2FST_D:

378 case CSKY::SPILL_CARRY:

379 break;

380 }

381

382 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&

383 MI.getOperand(2).getImm() == 0) {

384 FrameIndex = MI.getOperand(1).getIndex();

385 return MI.getOperand(0).getReg();

386 }

387

388 return 0;

389}

390

393 Register SrcReg, bool IsKill, int FI,

399 DL = I->getDebugLoc();

400

404

405 unsigned Opcode = 0;

406

407 if (CSKY::GPRRegClass.hasSubClassEq(RC)) {

408 Opcode = CSKY::ST32W;

409 } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {

410 Opcode = CSKY::SPILL_CARRY;

412 } else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC))

413 Opcode = CSKY::FST_S;

414 else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC))

415 Opcode = CSKY::FST_D;

416 else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC))

417 Opcode = CSKY::f2FST_S;

418 else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC))

419 Opcode = CSKY::f2FST_D;

420 else {

422 }

423

426 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));

427

433}

434

443 DL = I->getDebugLoc();

444

448

449 unsigned Opcode = 0;

450

451 if (CSKY::GPRRegClass.hasSubClassEq(RC)) {

452 Opcode = CSKY::LD32W;

453 } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {

454 Opcode = CSKY::RESTORE_CARRY;

456 } else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC))

457 Opcode = CSKY::FLD_S;

458 else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC))

459 Opcode = CSKY::FLD_D;

460 else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC))

461 Opcode = CSKY::f2FLD_S;

462 else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC))

463 Opcode = CSKY::f2FLD_D;

464 else {

466 }

467

470 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));

471

476}

477

482 bool RenamableDest, bool RenamableSrc) const {

483 if (CSKY::GPRRegClass.contains(SrcReg) &&

484 CSKY::CARRYRegClass.contains(DestReg)) {

489 } else {

490 assert(SrcReg < CSKY::R8);

494 }

495 return;

496 }

497

498 if (CSKY::CARRYRegClass.contains(SrcReg) &&

499 CSKY::GPRRegClass.contains(DestReg)) {

500

504 } else {

505 assert(DestReg < CSKY::R16);

506 assert(DestReg < CSKY::R8);

518 }

519 return;

520 }

521

522 unsigned Opcode = 0;

523 if (CSKY::GPRRegClass.contains(DestReg, SrcReg))

524 Opcode = STI.hasE2() ? CSKY::MOV32 : CSKY::MOV16;

525 else if (v2sf && CSKY::sFPR32RegClass.contains(DestReg, SrcReg))

526 Opcode = CSKY::FMOV_S;

527 else if (v3sf && CSKY::FPR32RegClass.contains(DestReg, SrcReg))

528 Opcode = CSKY::f2FMOV_S;

529 else if (v2df && CSKY::sFPR64RegClass.contains(DestReg, SrcReg))

530 Opcode = CSKY::FMOV_D;

531 else if (v3df && CSKY::FPR64RegClass.contains(DestReg, SrcReg))

532 Opcode = CSKY::f2FMOV_D;

533 else if (v2sf && CSKY::sFPR32RegClass.contains(SrcReg) &&

534 CSKY::GPRRegClass.contains(DestReg))

535 Opcode = CSKY::FMFVRL;

536 else if (v3sf && CSKY::FPR32RegClass.contains(SrcReg) &&

537 CSKY::GPRRegClass.contains(DestReg))

538 Opcode = CSKY::f2FMFVRL;

539 else if (v2df && CSKY::sFPR64RegClass.contains(SrcReg) &&

540 CSKY::GPRRegClass.contains(DestReg))

541 Opcode = CSKY::FMFVRL_D;

542 else if (v3df && CSKY::FPR64RegClass.contains(SrcReg) &&

543 CSKY::GPRRegClass.contains(DestReg))

544 Opcode = CSKY::f2FMFVRL_D;

545 else if (v2sf && CSKY::GPRRegClass.contains(SrcReg) &&

546 CSKY::sFPR32RegClass.contains(DestReg))

547 Opcode = CSKY::FMTVRL;

548 else if (v3sf && CSKY::GPRRegClass.contains(SrcReg) &&

549 CSKY::FPR32RegClass.contains(DestReg))

550 Opcode = CSKY::f2FMTVRL;

551 else if (v2df && CSKY::GPRRegClass.contains(SrcReg) &&

552 CSKY::sFPR64RegClass.contains(DestReg))

553 Opcode = CSKY::FMTVRL_D;

554 else if (v3df && CSKY::GPRRegClass.contains(SrcReg) &&

555 CSKY::FPR64RegClass.contains(DestReg))

556 Opcode = CSKY::f2FMTVRL_D;

557 else {

558 LLVM_DEBUG(dbgs() << "src = " << SrcReg << ", dst = " << DestReg);

561 }

562

565}

566

571

573 if (GlobalBaseReg != 0)

574 return GlobalBaseReg;

575

576

577

581

585

586 unsigned CPI = MCP->getConstantPoolIndex(CPV, Align(4));

587

594

595 GlobalBaseReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);

596 BuildMI(FirstMBB, MBBI, DL, get(TargetOpcode::COPY), GlobalBaseReg)

598

600 return GlobalBaseReg;

601}

602

604 switch (MI.getOpcode()) {

605 default:

606 return MI.getDesc().getSize();

607 case CSKY::CONSTPOOL_ENTRY:

608 return MI.getOperand(2).getImm();

609 case CSKY::SPILL_CARRY:

610 case CSKY::RESTORE_CARRY:

611 case CSKY::PseudoTLSLA32:

612 return 8;

613 case TargetOpcode::INLINEASM_BR:

614 case TargetOpcode::INLINEASM: {

616 const char *AsmStr = MI.getOperand(0).getSymbolName();

618 }

619 }

620}

unsigned const MachineRegisterInfo * MRI

static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

MachineBasicBlock MachineBasicBlock::iterator MBBI

static unsigned getOppositeBranchOpc(unsigned Opcode)

unsigned const TargetRegisterInfo * TRI

const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB

const SmallVectorImpl< MachineOperand > & Cond

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

static CSKYConstantPoolSymbol * Create(Type *Ty, const char *S, unsigned PCAdjust, CSKYCP::CSKYCPModifier Modifier)

CSKYConstantPoolValue - CSKY specific constantpool value.

unsigned getInstSizeInBytes(const MachineInstr &MI) const override

void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool IsKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override

unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override

unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override

void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override

const CSKYSubtarget & STI

MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override

bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override

Register movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, uint64_t Val, MachineInstr::MIFlag Flag=MachineInstr::NoFlags) const

CSKYInstrInfo(CSKYSubtarget &STI)

Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override

Register getGlobalBaseReg(MachineFunction &MF) const

bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override

Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override

void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override

Register getGlobalBaseReg() const

void setGlobalBaseReg(Register Reg)

bool hasFPUv2SingleFloat() const

bool hasFPUv3SingleFloat() const

bool hasFPUv2DoubleFloat() const

bool hasFPUv3DoubleFloat() const

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

bool isConditionalBranch() const

Return true if this is a branch which may fall through to the next instruction or may transfer contro...

Wrapper class representing physical registers. Should be passed by value.

iterator getLastNonDebugInstr(bool SkipPseudoOp=true)

Returns an iterator to the last non-debug instruction in the basic block, or end().

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...

The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.

MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)

getMachineMemOperand - Allocate a new MachineMemOperand.

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

MachineConstantPool * getConstantPool()

getConstantPool - Return the constant pool object for the current function.

const MachineBasicBlock & front() const

const TargetMachine & getTarget() const

getTarget - Return the target machine this machine code is compiled with

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addFrameIndex(int Idx) const

const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const

const MachineInstrBuilder & setMIFlags(unsigned Flags) const

const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const

reverse_iterator getReverse() const

Get a reverse iterator to the same node.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const MCInstrDesc & getDesc() const

Returns the target instruction descriptor of this MachineInstr.

const MachineOperand & getOperand(unsigned i) const

A description of a memory reference used in the backend.

@ MOLoad

The memory access reads data.

@ MOStore

The memory access writes data.

MachineBasicBlock * getMBB() const

static MachineOperand CreateImm(int64_t Val)

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

Wrapper class representing virtual and physical registers.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

const MCAsmInfo * getMCAsmInfo() const

Return target specific asm information.

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

Target - Wrapper for Target specific information.

static IntegerType * getInt32Ty(LLVMContext &C)

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ Define

Register definition.

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

unsigned getDeadRegState(bool B)

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

unsigned getKillRegState(bool B)

This struct is a compact representation of a valid (non-zero power of two) alignment.

static MachinePointerInfo getConstantPool(MachineFunction &MF)

Return a MachinePointerInfo record that refers to the constant pool.

static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)

Return a MachinePointerInfo record that refers to the specified FrameIndex.