LLVM: lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

19

20using namespace llvm;

21

22#define DEBUG_TYPE "loongarch-isel"

23#define PASS_NAME "LoongArch DAG->DAG Pattern Instruction Selection"

24

26

31

33 false)

34

36

37 if (Node->isMachineOpcode()) {

38 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");

39 Node->setNodeId(-1);

40 return;

41 }

42

43

44

45 unsigned Opcode = Node->getOpcode();

46 MVT GRLenVT = Subtarget->getGRLenVT();

48 MVT VT = Node->getSimpleValueType(0);

49

50 switch (Opcode) {

51 default:

52 break;

55 if (Imm == 0 && VT == GRLenVT) {

56 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,

57 LoongArch::R0, GRLenVT);

58 ReplaceNode(Node, New.getNode());

59 return;

60 }

61 SDNode *Result = nullptr;

62 SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT);

63

65 SDValue SDImm = CurDAG->getSignedTargetConstant(Inst.Imm, DL, GRLenVT);

66 switch (Inst.Opc) {

67 case LoongArch::LU12I_W:

68 Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SDImm);

69 break;

70 case LoongArch::ADDI_W:

71 case LoongArch::ORI:

72 case LoongArch::LU32I_D:

73 case LoongArch::LU52I_D:

74 Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SrcReg, SDImm);

75 break;

76 case LoongArch::BSTRINS_D:

77 Result = CurDAG->getMachineNode(

78 Inst.Opc, DL, GRLenVT,

79 {SrcReg, SrcReg,

80 CurDAG->getSignedTargetConstant(Inst.Imm >> 32, DL, GRLenVT),

81 CurDAG->getTargetConstant(Inst.Imm & 0xFF, DL, GRLenVT)});

82 break;

83 default:

84 llvm_unreachable("unexpected opcode generated by LoongArchMatInt");

85 }

86 SrcReg = SDValue(Result, 0);

87 }

88

89 ReplaceNode(Node, Result);

90 return;

91 }

93 SDValue Imm = CurDAG->getTargetConstant(0, DL, GRLenVT);

95 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);

96 unsigned ADDIOp =

97 Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

98 ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm));

99 return;

100 }

101 case ISD::BITCAST: {

104 CurDAG->RemoveDeadNode(Node);

105 return;

106 }

107 break;

108 }

110

111

113 APInt SplatValue, SplatUndef;

114 unsigned SplatBitSize;

115 bool HasAnyUndefs;

116 unsigned Op = 0;

121

122 if (!Subtarget->hasExtLSX() || (!Is128Vec && !Is256Vec))

123 break;

124 if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,

125 HasAnyUndefs, 8))

126 break;

127

128

130 switch (SplatBitSize) {

131 default:

132 break;

133 case 8:

134 Op = Is256Vec ? LoongArch::PseudoXVREPLI_B : LoongArch::PseudoVREPLI_B;

135 break;

136 case 16:

137 Op = Is256Vec ? LoongArch::PseudoXVREPLI_H : LoongArch::PseudoVREPLI_H;

138 break;

139 case 32:

140 Op = Is256Vec ? LoongArch::PseudoXVREPLI_W : LoongArch::PseudoVREPLI_W;

141 break;

142 case 64:

143 Op = Is256Vec ? LoongArch::PseudoXVREPLI_D : LoongArch::PseudoVREPLI_D;

144 break;

145 }

146

149 SDValue Imm = CurDAG->getTargetConstant(Val, DL, EleType);

150 Res = CurDAG->getMachineNode(Op, DL, ResTy, Imm);

151 ReplaceNode(Node, Res);

152 return;

153 }

154

155

156

157 const auto &TLI =

159 std::pair<bool, uint64_t> ConvertVLDI =

161 if (ConvertVLDI.first) {

162 Op = Is256Vec ? LoongArch::XVLDI : LoongArch::VLDI;

163 SDValue Imm = CurDAG->getSignedTargetConstant(

165 Res = CurDAG->getMachineNode(Op, DL, ResTy, Imm);

166 ReplaceNode(Node, Res);

167 return;

168 }

169 break;

170 }

171 }

172

173

174 SelectCode(Node);

175}

176

179 std::vector &OutOps) {

182 CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getGRLenVT());

183 switch (ConstraintID) {

184 default:

186

188 Base = Op.getOperand(0);

190 break;

191

193 if (CurDAG->isBaseWithConstantOffset(Op)) {

196 Base = Op.getOperand(0);

198 Op.getValueType());

199 }

200 }

201 break;

202

204 break;

205

207 if (CurDAG->isBaseWithConstantOffset(Op)) {

211 Base = Op.getOperand(0);

213 Op.getValueType());

214 }

215 }

216 break;

217 }

218 OutOps.push_back(Base);

219 OutOps.push_back(Offset);

220 return false;

221}

222

224

225

228 CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT());

229 else

231 return true;

232}

233

234

239

241 return false;

242

243

244

247 return false;

248 Base = CurDAG->getRegister(LoongArch::R0, VT);

250 return true;

251}

252

254

256 return false;

258 return true;

259}

260

265

266

267 if (CurDAG->isBaseWithConstantOffset(Addr)) {

272 return true;

273 }

274 }

275

276

277

280 return true;

281}

282

285

286

287

289 const APInt &AndMask = N->getConstantOperandAPInt(1);

290

291

292

295

297 ShAmt = N.getOperand(0);

298 return true;

299 }

300

301

302

303 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0));

305 ShAmt = N.getOperand(0);

306 return true;

307 }

308 } else if (N.getOpcode() == LoongArchISD::BSTRPICK) {

309

310

314 uint64_t msb = N.getConstantOperandVal(1), lsb = N.getConstantOperandVal(2);

315 if (lsb == 0 && Log2_32(ShiftWidth) <= msb + 1) {

316 ShAmt = N.getOperand(0);

317 return true;

318 }

319 } else if (N.getOpcode() == ISD::SUB &&

321 uint64_t Imm = N.getConstantOperandVal(0);

322

323

324 if (Imm != 0 && Imm % ShiftWidth == 0) {

326 EVT VT = N.getValueType();

328 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT);

329 unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W;

331 CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1));

333 return true;

334 }

335 }

336

337 ShAmt = N;

338 return true;

339}

340

344 Val = N.getOperand(0);

345 return true;

346 }

347 if (N.getOpcode() == LoongArchISD::BSTRPICK &&

348 N.getConstantOperandVal(1) < UINT64_C(0X1F) &&

349 N.getConstantOperandVal(2) == UINT64_C(0)) {

350 Val = N;

351 return true;

352 }

353 MVT VT = N.getSimpleValueType();

355 Val = N;

356 return true;

357 }

358

359 return false;

360}

361

365 if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) {

366 Val = N.getOperand(0);

367 return true;

368 }

369 }

370 MVT VT = N.getSimpleValueType();

372 if (CurDAG->MaskedValueIsZero(N, Mask)) {

373 Val = N;

374 return true;

375 }

376

377 return false;

378}

379

381 unsigned MinSizeInBits) const {

382 if (!Subtarget->hasExtLSX())

383 return false;

384

386

388 return false;

389

390 APInt SplatValue, SplatUndef;

391 unsigned SplatBitSize;

392 bool HasAnyUndefs;

393

394 if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,

395 MinSizeInBits, false))

396 return false;

397

398 Imm = SplatValue;

399

400 return true;

401}

402

403template <unsigned ImmBitSize, bool IsSigned>

406 EVT EltTy = N->getValueType(0).getVectorElementType();

407

408 if (N->getOpcode() == ISD::BITCAST)

409 N = N->getOperand(0);

410

413 if (IsSigned && ImmValue.isSignedIntN(ImmBitSize)) {

414 SplatVal = CurDAG->getSignedTargetConstant(

416 return true;

417 }

418 if (!IsSigned && ImmValue.isIntN(ImmBitSize)) {

420 Subtarget->getGRLenVT());

421 return true;

422 }

423 }

424

425 return false;

426}

427

429 SDValue &SplatImm) const {

431 EVT EltTy = N->getValueType(0).getVectorElementType();

432

433 if (N->getOpcode() == ISD::BITCAST)

434 N = N->getOperand(0);

435

438 int32_t Log2 = (~ImmValue).exactLogBase2();

439

440 if (Log2 != -1) {

441 SplatImm = CurDAG->getSignedTargetConstant(Log2, SDLoc(N), EltTy);

442 return true;

443 }

444 }

445

446 return false;

447}

448

450 SDValue &SplatImm) const {

452 EVT EltTy = N->getValueType(0).getVectorElementType();

453

454 if (N->getOpcode() == ISD::BITCAST)

455 N = N->getOperand(0);

456

460

461 if (Log2 != -1) {

462 SplatImm = CurDAG->getSignedTargetConstant(Log2, SDLoc(N), EltTy);

463 return true;

464 }

465 }

466

467 return false;

468}

469

470

471

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

AMDGPU Register Bank Select

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

Class for arbitrary precision integers.

uint64_t getZExtValue() const

Get zero extended value.

unsigned getBitWidth() const

Return the number of bits in the APInt.

int32_t exactLogBase2() const

bool isSignedIntN(unsigned N) const

Check if this APInt has an N-bits signed integer value.

LLVM_ABI APInt sextOrTrunc(unsigned width) const

Sign extend or truncate to width.

bool isSubsetOf(const APInt &RHS) const

This operation checks that all bits set in this APInt are also set in RHS.

static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)

Constructs an APInt value that has the top hiBitsSet bits set.

bool isIntN(unsigned N) const

Check if this APInt has an N-bits unsigned integer value.

int64_t getSExtValue() const

Get sign extended value.

A "pseudo-class" with methods for operating on BUILD_VECTORs.

LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const

Check if this is a constant splat, and if so, find the smallest element size that splats the vector.

uint64_t getZExtValue() const

int64_t getSExtValue() const

FunctionPass class - This class is used to implement most global optimizations.

LoongArchDAGToDAGISelLegacy(LoongArchTargetMachine &TM, CodeGenOptLevel OptLevel)

Definition LoongArchISelDAGToDAG.cpp:27

bool selectNonFIBaseAddr(SDValue Addr, SDValue &Base)

Definition LoongArchISelDAGToDAG.cpp:253

bool selectSExti32(SDValue N, SDValue &Val)

Definition LoongArchISelDAGToDAG.cpp:341

bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps) override

SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...

Definition LoongArchISelDAGToDAG.cpp:177

bool selectVSplatUimmPow2(SDValue N, SDValue &SplatImm) const

Definition LoongArchISelDAGToDAG.cpp:449

bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt)

Definition LoongArchISelDAGToDAG.cpp:283

bool selectZExti32(SDValue N, SDValue &Val)

Definition LoongArchISelDAGToDAG.cpp:362

bool SelectAddrRegImm12(SDValue Addr, SDValue &Base, SDValue &Offset)

Definition LoongArchISelDAGToDAG.cpp:261

bool SelectAddrConstant(SDValue Addr, SDValue &Base, SDValue &Offset)

Definition LoongArchISelDAGToDAG.cpp:235

bool selectVSplat(SDNode *N, APInt &Imm, unsigned MinSizeInBits) const

Definition LoongArchISelDAGToDAG.cpp:380

bool selectVSplatImm(SDValue N, SDValue &SplatVal)

Definition LoongArchISelDAGToDAG.cpp:404

bool selectVSplatUimmInvPow2(SDValue N, SDValue &SplatImm) const

Definition LoongArchISelDAGToDAG.cpp:428

bool SelectBaseAddr(SDValue Addr, SDValue &Base)

Definition LoongArchISelDAGToDAG.cpp:223

std::pair< bool, uint64_t > isImmVLDILegalForMode1(const APInt &SplatValue, const unsigned SplatBitSize) const

Check if a constant splat can be generated using [x]vldi, where imm[12] is 1.

bool is128BitVector() const

Return true if this is a 128-bit vector type.

TypeSize getSizeInBits() const

Returns the size of the specified MVT in bits.

bool is256BitVector() const

Return true if this is a 256-bit vector type.

An SDNode that represents everything that will be needed to construct a MachineInstr.

Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...

Represents one node in the SelectionDAG.

EVT getValueType(unsigned ResNo) const

Return the type of a specified result.

Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.

const SDValue & getOperand(unsigned i) const

MVT getSimpleValueType() const

Return the simple ValueType of the referenced return value.

SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)

#define llvm_unreachable(msg)

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

@ C

The default llvm calling convention, compatible with C.

@ SIGN_EXTEND_INREG

SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...

@ AND

Bitwise operators - logical and, logical or, logical xor.

@ BUILD_VECTOR

BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...

InstSeq generateInstSeq(int64_t Val)

This is an optimization pass for GlobalISel generic memory operations.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

bool isAligned(Align Lhs, uint64_t SizeInBytes)

Checks that SizeInBytes is a multiple of the alignment.

unsigned Log2_32(uint32_t Value)

Return the floor log base 2 of the specified value, -1 if the value is zero.

constexpr bool isPowerOf2_32(uint32_t Value)

Return true if the argument is a power of two > 0.

CodeGenOptLevel

Code generation optimization level.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

FunctionPass * createLoongArchISelDag(LoongArchTargetMachine &TM, CodeGenOptLevel OptLevel)

Definition LoongArchISelDAGToDAG.cpp:472

DWARFExpression::Operation Op

constexpr int32_t SignExtend32(uint32_t X)

Sign-extend the number in the bottom B bits of X to a 32-bit integer.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

constexpr bool isIntN(unsigned N, int64_t x)

Checks if an signed integer fits into the given (dynamic) bit width.

constexpr int64_t SignExtend64(uint64_t x)

Sign-extend the number in the bottom B bits of X to a 64-bit integer.

unsigned Log2(Align A)

Returns the log2 of the alignment.

Implement std::hash so that hash_code can be used in STL containers.

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

TypeSize getSizeInBits() const

Return the size of the specified value type in bits.

bool is128BitVector() const

Return true if this is a 128-bit vector type.

bool is256BitVector() const

Return true if this is a 256-bit vector type.

EVT getVectorElementType() const

Given a vector type, return the type of each element.