mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-08 03:37:46 +00:00
VectorUtils.h needs to be included in LoopAccessAnalysis.cpp for getIntrinsicIDForCall but hasVectorInstrinsicScalarOpd is not used by this module. NFC. This is part of the patchset that splits out the memory dependence logic from LoopVectorizationLegality into a new class LoopAccessAnalysis. LoopAccessAnalysis will be used by the new Loop Distribution pass. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227753 91177308-0d34-0410-b5e6-96231b3b80d8
206 lines
6.2 KiB
C++
206 lines
6.2 KiB
C++
//===- llvm/Transforms/Utils/VectorUtils.h - Vector utilities -*- C++ -*-=====//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines some vectorizer utilities.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
|
|
#define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
|
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
#include "llvm/IR/Intrinsics.h"
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
|
|
namespace llvm {
|
|
|
|
/// \brief Identify if the intrinsic is trivially vectorizable.
|
|
///
|
|
/// This method returns true if the intrinsic's argument types are all
|
|
/// scalars for the scalar form of the intrinsic and all vectors for
|
|
/// the vector form of the intrinsic.
|
|
static inline bool isTriviallyVectorizable(Intrinsic::ID ID) {
|
|
switch (ID) {
|
|
case Intrinsic::sqrt:
|
|
case Intrinsic::sin:
|
|
case Intrinsic::cos:
|
|
case Intrinsic::exp:
|
|
case Intrinsic::exp2:
|
|
case Intrinsic::log:
|
|
case Intrinsic::log10:
|
|
case Intrinsic::log2:
|
|
case Intrinsic::fabs:
|
|
case Intrinsic::minnum:
|
|
case Intrinsic::maxnum:
|
|
case Intrinsic::copysign:
|
|
case Intrinsic::floor:
|
|
case Intrinsic::ceil:
|
|
case Intrinsic::trunc:
|
|
case Intrinsic::rint:
|
|
case Intrinsic::nearbyint:
|
|
case Intrinsic::round:
|
|
case Intrinsic::bswap:
|
|
case Intrinsic::ctpop:
|
|
case Intrinsic::pow:
|
|
case Intrinsic::fma:
|
|
case Intrinsic::fmuladd:
|
|
case Intrinsic::ctlz:
|
|
case Intrinsic::cttz:
|
|
case Intrinsic::powi:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static inline bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID,
|
|
unsigned ScalarOpdIdx) {
|
|
switch (ID) {
|
|
case Intrinsic::ctlz:
|
|
case Intrinsic::cttz:
|
|
case Intrinsic::powi:
|
|
return (ScalarOpdIdx == 1);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static Intrinsic::ID checkUnaryFloatSignature(const CallInst &I,
|
|
Intrinsic::ID ValidIntrinsicID) {
|
|
if (I.getNumArgOperands() != 1 ||
|
|
!I.getArgOperand(0)->getType()->isFloatingPointTy() ||
|
|
I.getType() != I.getArgOperand(0)->getType() ||
|
|
!I.onlyReadsMemory())
|
|
return Intrinsic::not_intrinsic;
|
|
|
|
return ValidIntrinsicID;
|
|
}
|
|
|
|
static Intrinsic::ID checkBinaryFloatSignature(const CallInst &I,
|
|
Intrinsic::ID ValidIntrinsicID) {
|
|
if (I.getNumArgOperands() != 2 ||
|
|
!I.getArgOperand(0)->getType()->isFloatingPointTy() ||
|
|
!I.getArgOperand(1)->getType()->isFloatingPointTy() ||
|
|
I.getType() != I.getArgOperand(0)->getType() ||
|
|
I.getType() != I.getArgOperand(1)->getType() ||
|
|
!I.onlyReadsMemory())
|
|
return Intrinsic::not_intrinsic;
|
|
|
|
return ValidIntrinsicID;
|
|
}
|
|
|
|
static Intrinsic::ID
|
|
getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI) {
|
|
// If we have an intrinsic call, check if it is trivially vectorizable.
|
|
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
|
|
Intrinsic::ID ID = II->getIntrinsicID();
|
|
if (isTriviallyVectorizable(ID) || ID == Intrinsic::lifetime_start ||
|
|
ID == Intrinsic::lifetime_end || ID == Intrinsic::assume)
|
|
return ID;
|
|
else
|
|
return Intrinsic::not_intrinsic;
|
|
}
|
|
|
|
if (!TLI)
|
|
return Intrinsic::not_intrinsic;
|
|
|
|
LibFunc::Func Func;
|
|
Function *F = CI->getCalledFunction();
|
|
// We're going to make assumptions on the semantics of the functions, check
|
|
// that the target knows that it's available in this environment and it does
|
|
// not have local linkage.
|
|
if (!F || F->hasLocalLinkage() || !TLI->getLibFunc(F->getName(), Func))
|
|
return Intrinsic::not_intrinsic;
|
|
|
|
// Otherwise check if we have a call to a function that can be turned into a
|
|
// vector intrinsic.
|
|
switch (Func) {
|
|
default:
|
|
break;
|
|
case LibFunc::sin:
|
|
case LibFunc::sinf:
|
|
case LibFunc::sinl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::sin);
|
|
case LibFunc::cos:
|
|
case LibFunc::cosf:
|
|
case LibFunc::cosl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::cos);
|
|
case LibFunc::exp:
|
|
case LibFunc::expf:
|
|
case LibFunc::expl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::exp);
|
|
case LibFunc::exp2:
|
|
case LibFunc::exp2f:
|
|
case LibFunc::exp2l:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::exp2);
|
|
case LibFunc::log:
|
|
case LibFunc::logf:
|
|
case LibFunc::logl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::log);
|
|
case LibFunc::log10:
|
|
case LibFunc::log10f:
|
|
case LibFunc::log10l:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::log10);
|
|
case LibFunc::log2:
|
|
case LibFunc::log2f:
|
|
case LibFunc::log2l:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::log2);
|
|
case LibFunc::fabs:
|
|
case LibFunc::fabsf:
|
|
case LibFunc::fabsl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::fabs);
|
|
case LibFunc::fmin:
|
|
case LibFunc::fminf:
|
|
case LibFunc::fminl:
|
|
return checkBinaryFloatSignature(*CI, Intrinsic::minnum);
|
|
case LibFunc::fmax:
|
|
case LibFunc::fmaxf:
|
|
case LibFunc::fmaxl:
|
|
return checkBinaryFloatSignature(*CI, Intrinsic::maxnum);
|
|
case LibFunc::copysign:
|
|
case LibFunc::copysignf:
|
|
case LibFunc::copysignl:
|
|
return checkBinaryFloatSignature(*CI, Intrinsic::copysign);
|
|
case LibFunc::floor:
|
|
case LibFunc::floorf:
|
|
case LibFunc::floorl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::floor);
|
|
case LibFunc::ceil:
|
|
case LibFunc::ceilf:
|
|
case LibFunc::ceill:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::ceil);
|
|
case LibFunc::trunc:
|
|
case LibFunc::truncf:
|
|
case LibFunc::truncl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::trunc);
|
|
case LibFunc::rint:
|
|
case LibFunc::rintf:
|
|
case LibFunc::rintl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::rint);
|
|
case LibFunc::nearbyint:
|
|
case LibFunc::nearbyintf:
|
|
case LibFunc::nearbyintl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::nearbyint);
|
|
case LibFunc::round:
|
|
case LibFunc::roundf:
|
|
case LibFunc::roundl:
|
|
return checkUnaryFloatSignature(*CI, Intrinsic::round);
|
|
case LibFunc::pow:
|
|
case LibFunc::powf:
|
|
case LibFunc::powl:
|
|
return checkBinaryFloatSignature(*CI, Intrinsic::pow);
|
|
}
|
|
|
|
return Intrinsic::not_intrinsic;
|
|
}
|
|
|
|
} // llvm namespace
|
|
|
|
#endif
|