LLVM: lib/Target/Hexagon/HexagonGenWideningVecFloatInstr.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

99#include "llvm/IR/IntrinsicsHexagon.h"

105#include

106#include

107

108using namespace llvm;

109

110namespace llvm {

114}

115

116namespace {

117

118class HexagonGenWideningVecFloatInstr : public FunctionPass {

119public:

120 static char ID;

121

122 HexagonGenWideningVecFloatInstr() : FunctionPass(ID) {

125 }

126

127 HexagonGenWideningVecFloatInstr(const HexagonTargetMachine *TM)

128 : FunctionPass(ID), TM(TM) {

131 }

132

133 StringRef getPassName() const override {

134 return "Hexagon generate widening vector float instructions";

135 }

136

138

139 void getAnalysisUsage(AnalysisUsage &AU) const override {

140 FunctionPass::getAnalysisUsage(AU);

141 }

142

143private:

145 const HexagonTargetMachine *TM = nullptr;

146 const HexagonSubtarget *HST = nullptr;

147 unsigned HwVLen;

148 unsigned NumHalfEltsInFullVec;

149

150 struct OPInfo {

153 unsigned ExtInSize;

154 };

155

156 bool visitBlock(BasicBlock *B);

157 bool processInstruction(Instruction *Inst);

158 bool replaceWithIntrinsic(Instruction *Inst, OPInfo &OP1Info,

159 OPInfo &OP2Info);

160

162 bool isExtendedConstant(Constant *C);

163 unsigned getElementSizeInBits(Value *V);

165

167 unsigned NewEltsize, unsigned NumElts);

168

169 std::pair<Value *, Value *> opSplit(Value *OP, Instruction *Inst);

170

172 Value *NewOP2, FixedVectorType *ResType,

173 unsigned NumElts, bool BitCastOp);

174};

175

176}

177

178char HexagonGenWideningVecFloatInstr::ID = 0;

179

181 "Hexagon generate "

182 "widening vector float instructions",

183 false, false)

186 "Hexagon generate "

187 "widening vector float instructions",

189

190bool HexagonGenWideningVecFloatInstr::isExtendedConstant(Constant *C) {

191 if (Value *SplatV = C->getSplatValue()) {

192 if (auto *CFP = dyn_cast(SplatV)) {

193 bool Ignored;

194 APFloat APF = CFP->getValueAPF();

195 APFloat::opStatus sts = APF.convert(

196 APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);

197 if (sts == APFloat::opStatus::opOK || sts == APFloat::opStatus::opInexact)

198 return true;

199 }

200 return false;

201 }

203 for (unsigned i = 0, e = NumElts; i != e; ++i) {

205 bool Ignored;

206 APFloat APF = CFP->getValueAPF();

210 return false;

211 continue;

212 }

213 return false;

214 }

215 return true;

216}

217

218unsigned HexagonGenWideningVecFloatInstr::getElementSizeInBits(Value *V) {

219 Type *ValTy = V->getType();

220 Type *EltTy = ValTy;

222 unsigned EltSize =

223 cast(EltTy)->getElementType()->getPrimitiveSizeInBits();

224 unsigned ReducedSize = EltSize / 2;

225

226 return ReducedSize;

227 }

228

232}

233

234bool HexagonGenWideningVecFloatInstr::getOperandInfo(Value *V, OPInfo &OPI) {

235 using namespace PatternMatch;

236 OPI.OP = V;

237 Value *ExtV = nullptr;

239

243 m_Poison(), m_ZeroMask()))) {

244

246

247 if (ExtVType->getElementType()->isBFloatTy())

248

249 return false;

250 } else {

251

253 return false;

254 }

255

256 OPI.ExtInOP = ExtV;

257 OPI.ExtInSize = getElementSizeInBits(OPI.ExtInOP);

258 return true;

259 }

260

262 if (!isExtendedConstant(C))

263 return false;

264 OPI.ExtInOP = C;

265 OPI.ExtInSize = getElementSizeInBits(OPI.ExtInOP);

266 return true;

267 }

268

269 return false;

270}

271

272Type *HexagonGenWideningVecFloatInstr::getElementTy(unsigned size,

274 switch (size) {

275 case 16:

277 case 32:

279 default:

281 }

282}

283

284Value *HexagonGenWideningVecFloatInstr::adjustExtensionForOp(

285 OPInfo &OPI, IRBuilder<> &IRB, unsigned NewExtSize, unsigned NumElts) {

286 Value *V = OPI.ExtInOP;

287 unsigned EltSize = getElementSizeInBits(OPI.ExtInOP);

288 assert(NewExtSize >= EltSize);

289 Type *EltType = getElementTy(NewExtSize, IRB);

291

294

295 if (V->getType()->isVectorTy())

296 if (NewExtSize == EltSize)

297 return V;

298

299 return nullptr;

300}

301

302std::pair<Value *, Value *>

303HexagonGenWideningVecFloatInstr::opSplit(Value *OP, Instruction *Inst) {

307 Intrinsic::ID IntHi = Intrinsic::hexagon_V6_hi_128B;

308 Intrinsic::ID IntLo = Intrinsic::hexagon_V6_lo_128B;

311 if (NumElts == 128) {

314 }

317 return std::pair<Value *, Value *>(OP1Hi, OP1Lo);

318}

319

320Value *HexagonGenWideningVecFloatInstr::createIntrinsic(

322 FixedVectorType *ResType, unsigned NumElts, bool BitCastOp) {

323

327 M, Intrinsic::hexagon_V6_vconv_sf_qf32_128B);

330

331

332 if (NumElts == NumHalfEltsInFullVec / 2) {

334 for (unsigned i = 0; i < NumHalfEltsInFullVec; ++i)

336 NewOP1 =

339 NewOP2 =

342 }

343

344 if (BitCastOp) {

347 }

348

350

351

352

354 unsigned HalfVecPoint = NumHalfEltsInFullVec / 2;

355 for (unsigned i = 0; i < HalfVecPoint; ++i) {

357 Mask.push_back(IRB.getInt32(HalfVecPoint + i));

358 }

361

362 std::pair<Value *, Value *> SplitOP = opSplit(NewIn, Inst);

365

366 if (ResType->getNumElements() == NumHalfEltsInFullVec / 2) {

367 return ConvHi;

368 }

369

372

374 for (unsigned i = 0; i < NumElts; ++i)

376

377 NewIn =

379 return NewIn;

380}

381

382bool HexagonGenWideningVecFloatInstr::replaceWithIntrinsic(Instruction *Inst,

383 OPInfo &OP1Info,

384 OPInfo &OP2Info) {

389

390 unsigned MaxEltSize = OP1Info.ExtInSize;

391 unsigned NewOpEltSize = MaxEltSize;

392 unsigned NewResEltSize = 2 * MaxEltSize;

393

394 unsigned ResVLen = NewResEltSize * NumElts;

395 if (NewOpEltSize > 16 || ((ResVLen > HwVLen) && (ResVLen % HwVLen) != 0))

396 return false;

397

398 Intrinsic::ID IntId = Intrinsic::hexagon_V6_vmpy_qf32_hf_128B;

400 Value *NewOP1 = adjustExtensionForOp(OP1Info, IRB, NewOpEltSize, NumElts);

401 Value *NewOP2 = adjustExtensionForOp(OP2Info, IRB, NewOpEltSize, NumElts);

402

403 if (NewOP1 == nullptr || NewOP2 == nullptr)

404 return false;

405

406 if (ResVLen > 2 * HwVLen) {

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435 assert(ResVLen == 4 * HwVLen);

436

437 unsigned HalfElts = NumElts / 2;

438 std::pair<Value *, Value *> SplitOP1 = opSplit(NewOP1, Inst);

439 std::pair<Value *, Value *> SplitOP2 = opSplit(NewOP2, Inst);

442 createIntrinsic(IntId, Inst, SplitOP1.first, SplitOP2.first,

443 castResType, HalfElts, false);

445 createIntrinsic(IntId, Inst, SplitOP1.second, SplitOP2.second,

446 castResType, HalfElts, false);

447 assert(InstEltSize == NewResEltSize);

449 for (unsigned i = 0; i < NumElts; ++i)

451

454

456 return true;

457 }

458

459 auto *ResType =

461

462

463

464

465 if (!(NumElts == NumHalfEltsInFullVec &&

466 ResType->getNumElements() == NumHalfEltsInFullVec) &&

467 !(NumElts == NumHalfEltsInFullVec / 2 &&

468 ResType->getNumElements() == NumHalfEltsInFullVec / 2))

469 return false;

471 createIntrinsic(IntId, Inst, NewOP1, NewOP2, ResType, NumElts, true);

472

474 return true;

475}

476

477

478

479bool HexagonGenWideningVecFloatInstr::processInstruction(Instruction *Inst) {

483 return false;

486 return false;

487 if (InstLen < HwVLen)

488 return false;

489

490 using namespace PatternMatch;

491

493 OPInfo OP1Info, OP2Info;

494

495

496

498 OP1Info.ExtInOP = OP1;

499 OP1Info.ExtInSize = getElementSizeInBits(OP1);

500 OP2Info.ExtInOP = OP2;

501 OP2Info.ExtInSize = getElementSizeInBits(OP2);

502

504 if (!Op1Vtype->getElementType()->isHalfTy()) {

505 return false;

506 }

507 } else {

508 return false;

509 }

510

511 if (OP1Info.ExtInSize == OP2Info.ExtInSize && OP1Info.ExtInSize == 16 &&

512 getElementSizeInBits(Inst) == 32) {

513 return replaceWithIntrinsic(Inst, OP1Info, OP2Info);

514 }

515 }

516

518 return false;

519

521 return false;

522

523 if (!OP1Info.ExtInOP || !OP2Info.ExtInOP)

524 return false;

525

526 if (OP1Info.ExtInSize == OP2Info.ExtInSize && OP1Info.ExtInSize == 16) {

527 return replaceWithIntrinsic(Inst, OP1Info, OP2Info);

528 }

529

530 return false;

531}

532

533bool HexagonGenWideningVecFloatInstr::visitBlock(BasicBlock *B) {

535 for (auto &I : *B)

536 Changed |= processInstruction(&I);

538}

539

540bool HexagonGenWideningVecFloatInstr::runOnFunction(Function &F) {

541 M = F.getParent();

543

544

545

546

548 return false;

549

550 unsigned VecLength = HST->getVectorLength();

551 HwVLen = HST->getVectorLength() * 8;

552 NumHalfEltsInFullVec =

553 VecLength /

554 2;

556 for (auto &B : F)

558

560}

561

562FunctionPass *

564 return new HexagonGenWideningVecFloatInstr(&TM);

565}

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

This file implements a class to represent arbitrary precision integral constant values and operations...

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

This file contains the declarations for the subclasses of Constant, which represent the different fla...

static bool runOnFunction(Function &F, bool PostInlining)

Machine Check Debug Module

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

static std::optional< OperandInfo > getOperandInfo(const MachineOperand &MO)

static constexpr roundingMode rmNearestTiesToEven

static const fltSemantics & IEEEhalf()

opStatus

IEEE-754R 7: Default exception handling.

LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)

static LLVM_ABI Constant * get(ArrayRef< Constant * > V)

This is an important base class in LLVM.

Legacy analysis pass which computes a DominatorTree.

unsigned getNumElements() const

static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)

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

unsigned getVectorLength() const

bool useHVX128BOps() const

bool isTypeForHVX(Type *VecTy, bool IncludeBool=false) const

const HexagonSubtarget * getSubtargetImpl(const Function &F) const override

Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...

Value * CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)

IntegerType * getInt32Ty()

Fetch the type representing a 32-bit integer.

Type * getHalfTy()

Fetch the type representing a 16-bit floating point value.

ConstantInt * getInt32(uint32_t C)

Get a constant 32-bit value.

Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")

Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")

Type * getFloatTy()

Fetch the type representing a 32-bit floating point value.

CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)

PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...

static LLVM_ABI PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

static LLVM_ABI PoisonValue * get(Type *T)

Static factory methods - Return an 'poison' object of the specified type.

void push_back(const T &Elt)

bool isVectorTy() const

True if this is an instance of VectorType.

bool isBFloatTy() const

Return true if this is 'bfloat', a 16-bit bfloat type.

LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY

Return the basic size of this type if it is a primitive type.

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

LLVM_ABI void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

#define llvm_unreachable(msg)

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

constexpr std::underlying_type_t< E > Mask()

Get a bitmask with 1s in all places up to the high-order bit of E's largest value.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})

Look up the Function declaration of the intrinsic id in the Module M.

class_match< PoisonValue > m_Poison()

Match an arbitrary poison constant.

class_match< Constant > m_Constant()

Match an arbitrary Constant and ignore it.

BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)

bool match(Val *V, const Pattern &P)

TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)

Matches ShuffleVectorInst independently of mask value.

CastInst_match< OpTy, FPExtInst > m_FPExt(const OpTy &Op)

class_match< Value > m_Value()

Match an arbitrary value and ignore it.

is_zero m_Zero()

Match any null constant or a vector with all elements equal to 0.

ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)

Matches InsertElementInst.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

decltype(auto) dyn_cast(const From &Val)

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

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

void initializeHexagonGenWideningVecFloatInstrPass(PassRegistry &)

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

FunctionPass * createHexagonGenWideningVecFloatInstr(const HexagonTargetMachine &)

Definition HexagonGenWideningVecFloatInstr.cpp:563

decltype(auto) cast(const From &Val)

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