LLVM: lib/IR/VFABIDemangler.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

17#include

18

19using namespace llvm;

20

21#define DEBUG_TYPE "vfabi-demangler"

22

23namespace {

24

25

26

27enum class ParseRet {

28 OK,

29 None,

30 Error

31};

32

33

34

35

37 if (MangledName.empty())

38 return ParseRet::Error;

39

41 ISA = VFISAKind::LLVM;

42 } else {

44 .Case("n", VFISAKind::AdvancedSIMD)

45 .Case("s", VFISAKind::SVE)

46 .Case("r", VFISAKind::RVV)

47 .Case("b", VFISAKind::SSE)

48 .Case("c", VFISAKind::AVX)

49 .Case("d", VFISAKind::AVX2)

50 .Case("e", VFISAKind::AVX512)

51 .Default(VFISAKind::Unknown);

52 MangledName = MangledName.drop_front(1);

53 }

54

55 return ParseRet::OK;

56}

57

58

59

60

61static ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) {

63 IsMasked = true;

64 return ParseRet::OK;

65 }

66

68 IsMasked = false;

69 return ParseRet::OK;

70 }

71

72 return ParseRet::Error;

73}

74

75

76

77

78

79

81 std::pair<unsigned, bool> &ParsedVF) {

83

84 if (ISA != VFISAKind::SVE && ISA != VFISAKind::RVV) {

85 LLVM_DEBUG(dbgs() << "Vector function variant declared with scalable VF "

86 << "but ISA supported for SVE and RVV only\n");

87 return ParseRet::Error;

88 }

89

90

91

92

93 ParsedVF = {0, true};

94 return ParseRet::OK;

95 }

96

97 unsigned VF = 0;

99 return ParseRet::Error;

100

101

102 if (VF == 0)

103 return ParseRet::Error;

104

105 ParsedVF = {VF, false};

106 return ParseRet::OK;

107}

108

109

110

111

112

113

114

115

116

117

118

119

120

121static ParseRet tryParseLinearTokenWithRuntimeStep(StringRef &ParseString,

127 return ParseRet::Error;

128 return ParseRet::OK;

129 }

130

131 return ParseRet::None;

132}

133

134

135

136

137

138

139

140

141

142

143

144

145static ParseRet tryParseLinearWithRuntimeStep(StringRef &ParseString,

147 int &StepOrPos) {

148 ParseRet Ret;

149

150

151 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "ls");

152 if (Ret != ParseRet::None)

153 return Ret;

154

155

156 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Rs");

157 if (Ret != ParseRet::None)

158 return Ret;

159

160

161 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Ls");

162 if (Ret != ParseRet::None)

163 return Ret;

164

165

166 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Us");

167 if (Ret != ParseRet::None)

168 return Ret;

169

170 return ParseRet::None;

171}

172

173

174

175

176

177

178

179

180

181

182

183

184

185static ParseRet tryParseCompileTimeLinearToken(StringRef &ParseString,

187 int &LinearStep,

191 const bool Negate = ParseString.consume_front("n");

193 LinearStep = 1;

194 if (Negate)

195 LinearStep *= -1;

196 return ParseRet::OK;

197 }

198

199 return ParseRet::None;

200}

201

202

203

204

205

206

207

208

209

210

211static ParseRet tryParseLinearWithCompileTimeStep(StringRef &ParseString,

213 int &StepOrPos) {

214

215 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "l") ==

216 ParseRet::OK)

217 return ParseRet::OK;

218

219

220 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "R") ==

221 ParseRet::OK)

222 return ParseRet::OK;

223

224

225 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "L") ==

226 ParseRet::OK)

227 return ParseRet::OK;

228

229

230 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "U") ==

231 ParseRet::OK)

232 return ParseRet::OK;

233

234 return ParseRet::None;

235}

236

237

238

239

240

241

242

243

244

246 int &StepOrPos) {

248 PKind = VFParamKind::Vector;

249 StepOrPos = 0;

250 return ParseRet::OK;

251 }

252

254 PKind = VFParamKind::OMP_Uniform;

255 StepOrPos = 0;

256 return ParseRet::OK;

257 }

258

259 const ParseRet HasLinearRuntime =

260 tryParseLinearWithRuntimeStep(ParseString, PKind, StepOrPos);

261 if (HasLinearRuntime != ParseRet::None)

262 return HasLinearRuntime;

263

264 const ParseRet HasLinearCompileTime =

265 tryParseLinearWithCompileTimeStep(ParseString, PKind, StepOrPos);

266 if (HasLinearCompileTime != ParseRet::None)

267 return HasLinearCompileTime;

268

269 return ParseRet::None;

270}

271

272

273

274

275

276

277

278

279

280static ParseRet tryParseAlign(StringRef &ParseString, Align &Alignment) {

282

285 return ParseRet::Error;

286

288 return ParseRet::Error;

289

290 Alignment = Align(Val);

291

292 return ParseRet::OK;

293 }

294

295 return ParseRet::None;

296}

297

298

299

300

301

302

303

304static std::optional getElementCountForTy(const VFISAKind ISA,

305 const Type *Ty) {

306 assert((ISA == VFISAKind::SVE || ISA == VFISAKind::RVV) &&

307 "Scalable VF decoding only implemented for SVE and RVV\n");

308

317

318 return std::nullopt;

319}

320

321

322

323static std::optional

326

329 for (auto &Param : Params) {

330

331

332 if (Param.ParamKind == VFParamKind::Vector) {

333 Type *PTy = Signature->getParamType(Param.ParamPos);

334

335 std::optional EC = getElementCountForTy(ISA, PTy);

336

337

338 if (!EC)

339 return std::nullopt;

340

341

342 if (ElementCount::isKnownLT(*EC, MinEC))

343 MinEC = *EC;

344 }

345 }

346

347

348 Type *RetTy = Signature->getReturnType();

349 if (RetTy->isVoidTy()) {

350

353 return std::nullopt;

354

356 std::optional ReturnEC = getElementCountForTy(ISA, RetTy);

357

358

359 if (!ReturnEC)

360 return std::nullopt;

361 if (ElementCount::isKnownLT(*ReturnEC, MinEC))

362 MinEC = *ReturnEC;

363 }

364 }

365

366

367

368

369

370 if (MinEC.getKnownMinValue() < std::numeric_limits::max())

371 return MinEC;

372

373 return std::nullopt;

374}

375}

376

377

378

381 const StringRef OriginalName = MangledName;

382

383

384

385 StringRef VectorName = MangledName;

386

387

389 return std::nullopt;

390

391

392

394 if (tryParseISA(MangledName, ISA) != ParseRet::OK)

395 return std::nullopt;

396

397

398 bool IsMasked;

399 if (tryParseMask(MangledName, IsMasked) != ParseRet::OK)

400 return std::nullopt;

401

402

403 std::pair<unsigned, bool> ParsedVF;

404 if (tryParseVLEN(MangledName, ISA, ParsedVF) != ParseRet::OK)

405 return std::nullopt;

406

407

408 ParseRet ParamFound;

410 do {

411 const unsigned ParameterPos = Parameters.size();

413 int StepOrPos;

414 ParamFound = tryParseParameter(MangledName, PKind, StepOrPos);

415

416

417 if (ParamFound == ParseRet::Error)

418 return std::nullopt;

419

420 if (ParamFound == ParseRet::OK) {

422

423 const ParseRet AlignFound = tryParseAlign(MangledName, Alignment);

424

425 if (AlignFound == ParseRet::Error)

426 return std::nullopt;

427

428

429 Parameters.push_back({ParameterPos, PKind, StepOrPos, Alignment});

430 }

431 } while (ParamFound == ParseRet::OK);

432

433

434

435 if (Parameters.empty())

436 return std::nullopt;

437

438

439

440 if (Parameters.size() != FTy->getNumParams())

441 return std::nullopt;

442

443

444

445

446

447

448 std::optional EC;

449 if (ParsedVF.second) {

450 EC = getScalableECFromSignature(FTy, ISA, Parameters);

451 if (!EC)

452 return std::nullopt;

453 } else

455

456

457

459 return std::nullopt;

460

461

462

464 MangledName.take_while([](char In) { return In != '('; });

465

466 if (ScalarName.empty())

467 return std::nullopt;

468

469

470 MangledName = MangledName.ltrim(ScalarName);

471

474 return std::nullopt;

475

476 VectorName = MangledName;

477

478 if (VectorName.empty())

479 return std::nullopt;

480 }

481

482

483

484 if (ISA == VFISAKind::LLVM && VectorName == OriginalName)

485 return std::nullopt;

486

487

488

489 if (IsMasked) {

490 const unsigned Pos = Parameters.size();

491 Parameters.push_back({Pos, VFParamKind::GlobalPredicate});

492 }

493

494

495

496

497

498

499 const auto NGlobalPreds =

501 return PK.ParamKind == VFParamKind::GlobalPredicate;

502 });

503 assert(NGlobalPreds < 2 && "Cannot have more than one global predicate.");

504 if (NGlobalPreds)

505 assert(Parameters.back().ParamKind == VFParamKind::GlobalPredicate &&

506 "The global predicate must be the last parameter");

507

508 const VFShape Shape({*EC, Parameters});

509 return VFInfo({Shape, std::string(ScalarName), std::string(VectorName), ISA});

510}

511

514 .Case("v", VFParamKind::Vector)

515 .Case("l", VFParamKind::OMP_Linear)

516 .Case("R", VFParamKind::OMP_LinearRef)

517 .Case("L", VFParamKind::OMP_LinearVal)

518 .Case("U", VFParamKind::OMP_LinearUVal)

519 .Case("ls", VFParamKind::OMP_LinearPos)

520 .Case("Ls", VFParamKind::OMP_LinearValPos)

521 .Case("Rs", VFParamKind::OMP_LinearRefPos)

522 .Case("Us", VFParamKind::OMP_LinearUValPos)

523 .Case("u", VFParamKind::OMP_Uniform)

524 .Default(VFParamKind::Unknown);

525

526 if (ParamKind != VFParamKind::Unknown)

527 return ParamKind;

528

529

530 llvm_unreachable("This fuction should be invoken only on parameters"

531 " that have a textual representation in the mangled name"

532 " of the Vector Function ABI");

533}

534

539 return;

540

542 S.split(ListAttr, ",");

543

545 std::optional Info =

548 LLVM_DEBUG(dbgs() << "VFABI: Adding mapping '" << S << "' for " << CI

549 << "\n");

550 VariantMappings.push_back(std::string(S));

551 } else

552 LLVM_DEBUG(dbgs() << "VFABI: Invalid mapping '" << S << "'\n");

553 }

554}

555

558

561 int ScalarParamIndex = 0;

562 for (auto VFParam : Info.Shape.Parameters) {

563 if (VFParam.ParamKind == VFParamKind::GlobalPredicate) {

567 continue;

568 }

569

570 Type *OperandTy = ScalarFTy->getParamType(ScalarParamIndex++);

571 if (VFParam.ParamKind == VFParamKind::Vector)

572 OperandTy = VectorType::get(OperandTy, VF);

574 }

575

577 if (RetTy->isVoidTy())

579 return FunctionType::get(RetTy, VecTypes, false);

580}

581

584 if (VariantMappings.empty())

585 return;

586

589 for (const std::string &VariantMapping : VariantMappings)

590 Out << VariantMapping << ",";

591

592 assert(!Buffer.str().empty() && "Must have at least one char.");

594

596#ifndef NDEBUG

597 for (const std::string &VariantMapping : VariantMappings) {

598 LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << VariantMapping << "'\n");

599 std::optional VI =

601 assert(VI && "Cannot add an invalid VFABI name.");

602 assert(M->getNamedValue(VI->VectorName) &&

603 "Cannot add variant to attribute: "

604 "vector function declaration is missing.");

605 }

606#endif

608 Attribute::get(M->getContext(), MappingsAttrName, Buffer.str()));

609}

610

612 for (unsigned Pos = 0, NumParams = Parameters.size(); Pos < NumParams;

613 ++Pos) {

614 assert(Parameters[Pos].ParamPos == Pos && "Broken parameter list.");

615

617 default:

618 break;

623

624 if (Parameters[Pos].LinearStepOrPos == 0)

625 return false;

626 break;

631

632

633 if (Parameters[Pos].LinearStepOrPos >= int(NumParams))

634 return false;

635

638 return false;

639

640 if (Parameters[Pos].LinearStepOrPos == int(Pos))

641 return false;

642 break;

644

645

646 for (unsigned NextPos = Pos + 1; NextPos < NumParams; ++NextPos)

648 return false;

649 break;

650 }

651 }

652 return true;

653}

Analysis containing CSE Info

Module.h This file contains the declarations for the Module class.

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

This file implements a set that has insertion order iteration characteristics.

This file defines the SmallString class.

This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...

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

bool empty() const

empty - Check if the array is empty.

static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)

Return a uniquified Attribute object.

StringRef getValueAsString() const

Return the attribute's value as a string.

void addFnAttr(Attribute::AttrKind Kind)

Adds the attribute to the function.

Attribute getFnAttr(StringRef Kind) const

Get the attribute of a given kind for the function.

FunctionType * getFunctionType() const

This class represents a function call, abstracting a target machine's calling convention.

static constexpr ElementCount getScalable(ScalarTy MinVal)

static constexpr ElementCount getFixed(ScalarTy MinVal)

Lightweight error class with error context and mandatory checking.

Class to represent function types.

unsigned getNumParams() const

Return the number of fixed parameters this function type requires.

Type * getParamType(unsigned i) const

Parameter type accessors.

Type * getReturnType() const

const Module * getModule() const

Return the module owning the function this instruction belongs to or nullptr it the function does not...

A Module instance is used to store all the information related to an LLVM module.

Function * getFunction(StringRef Name) const

Look up the specified function in the module symbol table.

A vector that has set insertion semantics.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

StringRef str() const

Explicit conversion to StringRef.

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

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

std::pair< StringRef, StringRef > split(char Separator) const

Split into two substrings around the first occurrence of a separator character.

bool consume_back(StringRef Suffix)

Returns true if this StringRef has the given suffix and removes that suffix.

bool consumeInteger(unsigned Radix, T &Result)

Parse the current string as an integer of the specified radix.

constexpr bool empty() const

empty - Check if the string is empty.

StringRef take_while(function_ref< bool(char)> F) const

Return the longest prefix of 'this' such that every character in the prefix satisfies the given predi...

StringRef drop_front(size_t N=1) const

Return a StringRef equal to 'this' but with the first N elements dropped.

StringRef ltrim(char Char) const

Return string with consecutive Char characters starting from the the left removed.

bool consume_front(StringRef Prefix)

Returns true if this StringRef has the given prefix and removes that prefix.

StringRef take_front(size_t N=1) const

Return a StringRef equal to 'this' but with only the first N elements remaining.

A switch()-like statement whose cases are string literals.

StringSwitch & Case(StringLiteral S, T Value)

Class to represent struct types.

The instances of the Type class are immutable: once they are created, they are never changed.

bool isPointerTy() const

True if this is an instance of PointerType.

static IntegerType * getInt1Ty(LLVMContext &C)

bool isFloatTy() const

Return true if this is 'float', a 32-bit IEEE fp type.

bool is16bitFPTy() const

Return true if this is a 16-bit float type.

LLVMContext & getContext() const

Return the LLVMContext in which this type was uniqued.

bool isDoubleTy() const

Return true if this is 'double', a 64-bit IEEE fp type.

bool isIntegerTy() const

True if this is an instance of IntegerType.

Base class of all SIMD vector types.

constexpr ScalarTy getKnownMinValue() const

Returns the minimum value this quantity can represent.

A raw_ostream that writes to an SmallVector or SmallString.

#define llvm_unreachable(msg)

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

static constexpr char const * MappingsAttrName

std::optional< VFInfo > tryDemangleForVFABI(StringRef MangledName, const FunctionType *FTy)

Function to construct a VFInfo out of a mangled names in the following format:

FunctionType * createFunctionType(const VFInfo &Info, const FunctionType *ScalarFTy)

Constructs a FunctionType by applying vector function information to the type of a matching scalar fu...

void getVectorVariantNames(const CallInst &CI, SmallVectorImpl< std::string > &VariantMappings)

Populates a set of strings representing the Vector Function ABI variants associated to the CallInst C...

void setVectorVariantNames(CallInst *CI, ArrayRef< std::string > VariantMappings)

Overwrite the Vector Function ABI variants attribute with the names provide in VariantMappings.

VFParamKind getVFParamKindFromString(const StringRef Token)

Retrieve the VFParamKind from a string token.

static constexpr char const * _LLVM_

LLVM Internal VFABI ISA token for vector functions.

This is an optimization pass for GlobalISel generic memory operations.

bool isUnpackedStructLiteral(StructType *StructTy)

constexpr bool isPowerOf2_64(uint64_t Value)

Return true if the argument is a power of two > 0 (64 bit edition.)

raw_ostream & dbgs()

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

Type * toVectorizedTy(Type *Ty, ElementCount EC)

A helper for converting to vectorized types.

VFISAKind

Describes the type of Instruction Set Architecture.

auto count_if(R &&Range, UnaryPredicate P)

Wrapper function around std::count_if to count the number of times an element satisfying a given pred...

ArrayRef< Type * > getContainedTypes(Type *const &Ty)

Returns the types contained in Ty.

VFParamKind

Describes the type of Parameters.

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

Holds the VFShape for a specific scalar to vector function mapping.

Encapsulates information needed to describe a parameter.

Contains the information about the kind of vectorization available.

bool hasValidParameterList() const

Validation check on the Parameters in the VFShape.

SmallVector< VFParameter, 8 > Parameters