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) {
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) {
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;
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.