99#include "llvm/IR/IntrinsicsHexagon.h"
118class HexagonGenWideningVecFloatInstr :
public FunctionPass {
127 HexagonGenWideningVecFloatInstr(
const HexagonTargetMachine *TM)
128 : FunctionPass(ID), TM(TM) {
133 StringRef getPassName()
const override {
134 return "Hexagon generate widening vector float instructions";
139 void getAnalysisUsage(AnalysisUsage &AU)
const override {
140 FunctionPass::getAnalysisUsage(AU);
145 const HexagonTargetMachine *TM =
nullptr;
146 const HexagonSubtarget *HST =
nullptr;
148 unsigned NumHalfEltsInFullVec;
156 bool visitBlock(BasicBlock *
B);
157 bool processInstruction(Instruction *Inst);
158 bool replaceWithIntrinsic(Instruction *Inst, OPInfo &OP1Info,
162 bool isExtendedConstant(Constant *
C);
163 unsigned getElementSizeInBits(
Value *V);
167 unsigned NewEltsize,
unsigned NumElts);
169 std::pair<Value *, Value *> opSplit(
Value *
OP, Instruction *Inst);
172 Value *NewOP2, FixedVectorType *ResType,
173 unsigned NumElts,
bool BitCastOp);
178char HexagonGenWideningVecFloatInstr::ID = 0;
182 "widening vector float instructions",
187 "widening vector float instructions",
190bool HexagonGenWideningVecFloatInstr::isExtendedConstant(
Constant *
C) {
191 if (
Value *SplatV =
C->getSplatValue()) {
192 if (auto *CFP = dyn_cast<ConstantFP>(SplatV)) {
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)
203 for (
unsigned i = 0, e = NumElts; i !=
e; ++i) {
206 APFloat APF = CFP->getValueAPF();
218unsigned HexagonGenWideningVecFloatInstr::getElementSizeInBits(
Value *V) {
219 Type *ValTy =
V->getType();
224 unsigned ReducedSize = EltSize / 2;
234bool HexagonGenWideningVecFloatInstr::getOperandInfo(
Value *V, OPInfo &OPI) {
235 using namespace PatternMatch;
237 Value *ExtV =
nullptr;
247 if (ExtVType->getElementType()->isBFloatTy())
257 OPI.ExtInSize = getElementSizeInBits(OPI.ExtInOP);
262 if (!isExtendedConstant(
C))
265 OPI.ExtInSize = getElementSizeInBits(OPI.ExtInOP);
272Type *HexagonGenWideningVecFloatInstr::getElementTy(
unsigned size,
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);
295 if (
V->getType()->isVectorTy())
296 if (NewExtSize == EltSize)
302std::pair<Value *, Value *>
303HexagonGenWideningVecFloatInstr::opSplit(
Value *
OP, Instruction *Inst) {
311 if (NumElts == 128) {
317 return std::pair<Value *, Value *>(OP1Hi, OP1Lo);
320Value *HexagonGenWideningVecFloatInstr::createIntrinsic(
322 FixedVectorType *ResType,
unsigned NumElts,
bool BitCastOp) {
327 M, Intrinsic::hexagon_V6_vconv_sf_qf32_128B);
332 if (NumElts == NumHalfEltsInFullVec / 2) {
334 for (
unsigned i = 0; i < NumHalfEltsInFullVec; ++i)
354 unsigned HalfVecPoint = NumHalfEltsInFullVec / 2;
355 for (
unsigned i = 0; i < HalfVecPoint; ++i) {
362 std::pair<Value *, Value *> SplitOP = opSplit(NewIn, Inst);
374 for (
unsigned i = 0; i < NumElts; ++i)
382bool HexagonGenWideningVecFloatInstr::replaceWithIntrinsic(Instruction *Inst,
390 unsigned MaxEltSize = OP1Info.ExtInSize;
391 unsigned NewOpEltSize = MaxEltSize;
392 unsigned NewResEltSize = 2 * MaxEltSize;
394 unsigned ResVLen = NewResEltSize * NumElts;
395 if (NewOpEltSize > 16 || ((ResVLen > HwVLen) && (ResVLen % HwVLen) != 0))
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);
403 if (NewOP1 ==
nullptr || NewOP2 ==
nullptr)
406 if (ResVLen > 2 * HwVLen) {
435 assert(ResVLen == 4 * HwVLen);
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)
465 if (!(NumElts == NumHalfEltsInFullVec &&
467 !(NumElts == NumHalfEltsInFullVec / 2 &&
471 createIntrinsic(IntId, Inst, NewOP1, NewOP2, ResType, NumElts,
true);
479bool HexagonGenWideningVecFloatInstr::processInstruction(Instruction *Inst) {
487 if (InstLen < HwVLen)
490 using namespace PatternMatch;
493 OPInfo OP1Info, OP2Info;
498 OP1Info.ExtInOP =
OP1;
499 OP1Info.ExtInSize = getElementSizeInBits(OP1);
500 OP2Info.ExtInOP =
OP2;
501 OP2Info.ExtInSize = getElementSizeInBits(OP2);
504 if (!Op1Vtype->getElementType()->isHalfTy()) {
511 if (OP1Info.ExtInSize == OP2Info.ExtInSize && OP1Info.ExtInSize == 16 &&
512 getElementSizeInBits(Inst) == 32) {
513 return replaceWithIntrinsic(Inst, OP1Info, OP2Info);
523 if (!OP1Info.ExtInOP || !OP2Info.ExtInOP)
526 if (OP1Info.ExtInSize == OP2Info.ExtInSize && OP1Info.ExtInSize == 16) {
527 return replaceWithIntrinsic(Inst, OP1Info, OP2Info);
533bool HexagonGenWideningVecFloatInstr::visitBlock(BasicBlock *
B) {
540bool HexagonGenWideningVecFloatInstr::runOnFunction(Function &
F) {
552 NumHalfEltsInFullVec =
564 return new HexagonGenWideningVecFloatInstr(&TM);
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<X> - 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 &)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.