Previous version was reviewed here https://github.com/llvm/llvm-project/pull/123360 It is mostly the same, adjusted after graph-to-tree transformation Patch tries to remove wide alternate operations. Currently SLP vectorizer emits something like this: ``` %0 = add i32 %1 = sub i32 %2 = add i32 %3 = sub i32 %4 = add i32 %5 = sub i32 %6 = add i32 %7 = sub i32 transformes to %v1 = add <8 x i32> %v2 = sub <8 x i32> %res = shuffle %v1, %v2, <0, 9, 2, 11, 4, 13, 6, 15> ``` i.e. half of the results are just unused. This leads to increased register pressure and potentially doubles number of operations. Patch introduces SplitVectorize mode, where it splits the operations by opcodes and produces instead something like this: ``` %v1 = add <4 x i32> %v2 = sub <4 x i32> %res = shuffle %v1, %v2, <0, 4, 1, 5, 2, 6, 3, 7> ``` It allows to improve the performance by reducing number of ops. Also, it turns on some other improvements, like improved graph reordering. -O3+LTO, AVX512 Metric: size..text Program size..text results results0 diff test-suite :: MultiSource/Benchmarks/Olden/tsp/tsp.test 2788.00 2820.00 1.1% test-suite :: MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/timberwolfmc.test 278168.00 280904.00 1.0% test-suite :: MultiSource/Benchmarks/FreeBench/pifft/pifft.test 82682.00 83258.00 0.7% test-suite :: External/SPEC/CFP2006/433.milc/433.milc.test 139344.00 139712.00 0.3% test-suite :: MultiSource/Benchmarks/FreeBench/fourinarow/fourinarow.test 27149.00 27197.00 0.2% test-suite :: MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4.test 1008188.00 1009948.00 0.2% test-suite :: MultiSource/Benchmarks/mediabench/gsm/toast/toast.test 39226.00 39290.00 0.2% test-suite :: MultiSource/Benchmarks/MiBench/telecomm-gsm/telecomm-gsm.test 39229.00 39293.00 0.2% test-suite :: External/SPEC/CINT2017rate/500.perlbench_r/500.perlbench_r.test 2074533.00 2076549.00 0.1% test-suite :: External/SPEC/CINT2017speed/600.perlbench_s/600.perlbench_s.test 2074533.00 2076549.00 0.1% test-suite :: External/SPEC/CINT2006/464.h264ref/464.h264ref.test 798440.00 798952.00 0.1% test-suite :: MultiSource/Benchmarks/DOE-ProxyApps-C/miniGMG/miniGMG.test 44123.00 44139.00 0.0% test-suite :: MultiSource/Benchmarks/Bullet/bullet.test 318942.00 319038.00 0.0% test-suite :: External/SPEC/CFP2017rate/511.povray_r/511.povray_r.test 1159880.00 1160152.00 0.0% test-suite :: MultiSource/Benchmarks/DOE-ProxyApps-C/miniAMR/miniAMR.test 73595.00 73611.00 0.0% test-suite :: External/SPEC/CFP2006/453.povray/453.povray.test 1146124.00 1146348.00 0.0% test-suite :: MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/CLAMR.test 203831.00 203847.00 0.0% test-suite :: MultiSource/Benchmarks/MiBench/consumer-lame/consumer-lame.test 207662.00 207678.00 0.0% test-suite :: External/SPEC/CFP2006/447.dealII/447.dealII.test 589851.00 589883.00 0.0% test-suite :: External/SPEC/CFP2017rate/538.imagick_r/538.imagick_r.test 1398543.00 1398559.00 0.0% test-suite :: External/SPEC/CFP2017speed/638.imagick_s/638.imagick_s.test 1398543.00 1398559.00 0.0% test-suite :: External/SPEC/CFP2017rate/510.parest_r/510.parest_r.test 2050990.00 2051006.00 0.0% test-suite :: External/SPEC/CFP2017rate/526.blender_r/526.blender_r.test 12559687.00 12559591.00 -0.0% test-suite :: External/SPEC/CINT2006/403.gcc/403.gcc.test 3074157.00 3074125.00 -0.0% test-suite :: External/SPEC/CINT2006/400.perlbench/400.perlbench.test 1092252.00 1092188.00 -0.0% test-suite :: External/SPEC/CFP2017rate/508.namd_r/508.namd_r.test 779763.00 779715.00 -0.0% test-suite :: MultiSource/Benchmarks/ASCI_Purple/SMG2000/smg2000.test 253517.00 253485.00 -0.0% test-suite :: MultiSource/Applications/JM/lencod/lencod.test 848259.00 848035.00 -0.0% test-suite :: MultiSource/Benchmarks/DOE-ProxyApps-C++/miniFE/miniFE.test 93064.00 93016.00 -0.1% test-suite :: MultiSource/Applications/JM/ldecod/ldecod.test 383747.00 383475.00 -0.1% test-suite :: External/SPEC/CINT2017speed/625.x264_s/625.x264_s.test 673051.00 662907.00 -1.5% test-suite :: External/SPEC/CINT2017rate/525.x264_r/525.x264_r.test 673051.00 662907.00 -1.5% Olden/tsp - small variations Prolangs-C/TimberWolfMC - small variations, some code not inlined FreeBench/pifft - extra store <8 x double> vectorized, some other extra vectorizations CFP2006/433.milc - better vector code FreeBench/fourinarow - better vector code Benchmarks/tramp3d-v4 - extra vector code, small variations mediabench/gsm/toast - small variations MiBench/telecomm-gsm - small variations CINT2017rate/500.perlbench_r CINT2017speed/600.perlbench_s - better vector code, small variations CINT2006/464.h264ref - some smaller code + changes similar to x264 DOE-ProxyApps-C/miniGMG - small variations Benchmarks/Bullet - small variations CFP2017rate/511.povray_r - small variations DOE-ProxyApps-C/miniAMR - small variations CFP2006/453.povray - small variations DOE-ProxyApps-C++/CLAMR - small variations MiBench/consumer-lame - small variations CFP2006/447.dealII - small variations CFP2017rate/538.imagick_r CFP2017speed/638.imagick_s - small variations CFP2017rate/510.parest_r - better vector code, small variations CFP2017rate/526.blender_r - small variations CINT2006/403.gcc - small variations CINT2006/400.perlbench - small variations CFP2017rate/508.namd_r - small variations ASCI_Purple/SMG2000 - small variations JM/lencod - extra store <16 x i32>, small variations DOE-ProxyApps-C++/miniFE - small variations JM/ldecod - extra vector code, small variations, less shuffles CINT2017speed/625.x264_s CINT2017rate/525.x264_r - the number of instructions increased, but looks like they are more performant. E.g., for function x264_pixel_satd_8x8, llvm-mca reports better throughput - 84 for the current version and 59 for the new version. -O3+LTO, mcpu=sifive-p470 Metric: size..text results results0 diff test-suite :: External/SPEC/CINT2006/464.h264ref/464.h264ref.test 580768.00 581118.00 0.1% test-suite :: MultiSource/Applications/d/make_dparser.test 78854.00 78894.00 0.1% test-suite :: MultiSource/Applications/JM/lencod/lencod.test 633448.00 633750.00 0.0% test-suite :: MultiSource/Benchmarks/Bullet/bullet.test 277002.00 277080.00 0.0% test-suite :: External/SPEC/CINT2006/400.perlbench/400.perlbench.test 931938.00 931960.00 0.0% test-suite :: External/SPEC/CINT2006/403.gcc/403.gcc.test 2512806.00 2512822.00 0.0% test-suite :: External/SPEC/CINT2017speed/602.gcc_s/602.gcc_s.test 7659880.00 7659876.00 -0.0% test-suite :: External/SPEC/CINT2017rate/502.gcc_r/502.gcc_r.test 7659880.00 7659876.00 -0.0% test-suite :: External/SPEC/CFP2017rate/510.parest_r/510.parest_r.test 1602448.00 1602434.00 -0.0% test-suite :: External/SPEC/CFP2017rate/526.blender_r/526.blender_r.test 9496664.00 9496542.00 -0.0% test-suite :: MultiSource/Benchmarks/MiBench/consumer-lame/consumer-lame.test 147424.00 147422.00 -0.0% test-suite :: External/SPEC/CINT2017speed/600.perlbench_s/600.perlbench_s.test 1764608.00 1764578.00 -0.0% test-suite :: External/SPEC/CINT2017rate/500.perlbench_r/500.perlbench_r.test 1764608.00 1764578.00 -0.0% test-suite :: MultiSource/Benchmarks/7zip/7zip-benchmark.test 841656.00 841632.00 -0.0% test-suite :: External/SPEC/CFP2006/453.povray/453.povray.test 949026.00 948962.00 -0.0% test-suite :: External/SPEC/CFP2017rate/511.povray_r/511.povray_r.test 946348.00 946284.00 -0.0% test-suite :: MultiSource/Applications/JM/ldecod/ldecod.test 279794.00 279764.00 -0.0% test-suite :: MultiSource/Benchmarks/mediabench/g721/g721encode/encode.test 4776.00 4772.00 -0.1% test-suite :: MultiSource/Benchmarks/mediabench/gsm/toast/toast.test 25074.00 25028.00 -0.2% test-suite :: MultiSource/Benchmarks/MiBench/telecomm-gsm/telecomm-gsm.test 25074.00 25028.00 -0.2% test-suite :: MultiSource/Benchmarks/DOE-ProxyApps-C/miniGMG/miniGMG.test 29336.00 29184.00 -0.5% test-suite :: External/SPEC/CINT2017rate/525.x264_r/525.x264_r.test 535390.00 510124.00 -4.7% test-suite :: External/SPEC/CINT2017speed/625.x264_s/625.x264_s.test 535390.00 510124.00 -4.7% test-suite :: SingleSource/Regression/C/gcc-c-torture/execute/ieee/GCC-C-execute-ieee-pr50310.test 886.00 608.00 -31.4% CINT2006/464.h264ref - extra v16i32 reduction d/make_dparser - better vector code JM/lencod - extra v16i32 reduction Benchmarks/Bullet - smaller vector code CINT2006/400.perlbench - better vector code CINT2006/403.gcc - small variations CINT2017speed/602.gcc_s CINT2017rate/502.gcc_r - small variations CFP2017rate/510.parest_r - small variations CFP2017rate/526.blender_r - small variations MiBench/consumer-lame - small variations CINT2017speed/600.perlbench_s CINT2017rate/500.perlbench_r - small variations Benchmarks/7zip - small variations CFP2017rate/511.povray_r - small variations JM/ldecod - extra vector code mediabench/g721/g721encode - extra vector code mediabench/gsm - extra vector code MiBench/telecomm-gsm - extra vector code DOE-ProxyApps-C/miniGMG - extra vector code CINT2017rate/525.x264_r CINT2017speed/625.x264_s - reduced number of wide operations and shuffles, saving the registers, similar to X86, extra code in pixel_hadamard_ac vectorized ieee/GCC-C-execute-ieee-pr50310 - extra code vectorized CINT2006/464.h264ref - extra vector code in find_sad_16x16 JM/lencod - extra vector code in find_sad_16x16 d/make_dparser - smaller vector code Benchmarks/Bullet - small variations CINT2006/400.perlbench - smaller vector code CFP2017rate/526.blender_r - small variations, extra store <8 x float> in the loop, extra store <8 x i8> in loop CINT2017rate/500.perlbench_r CINT2017speed/600.perlbench_s - small variations MiBench/consumer-lame - small variations JM/ldecod - extra vector code mediabench/g721/g721encode - small variations Reviewers: hiraditya Reviewed By: hiraditya Pull Request: https://github.com/llvm/llvm-project/pull/128907
1523 lines
56 KiB
C++
1523 lines
56 KiB
C++
//===- llvm/Analysis/TargetTransformInfo.cpp ------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
|
#include "llvm/Analysis/CFG.h"
|
|
#include "llvm/Analysis/LoopIterator.h"
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
#include "llvm/Analysis/TargetTransformInfoImpl.h"
|
|
#include "llvm/IR/CFG.h"
|
|
#include "llvm/IR/Dominators.h"
|
|
#include "llvm/IR/Instruction.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/Operator.h"
|
|
#include "llvm/InitializePasses.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include <optional>
|
|
#include <utility>
|
|
|
|
using namespace llvm;
|
|
using namespace PatternMatch;
|
|
|
|
#define DEBUG_TYPE "tti"
|
|
|
|
static cl::opt<bool> EnableReduxCost("costmodel-reduxcost", cl::init(false),
|
|
cl::Hidden,
|
|
cl::desc("Recognize reduction patterns."));
|
|
|
|
static cl::opt<unsigned> CacheLineSize(
|
|
"cache-line-size", cl::init(0), cl::Hidden,
|
|
cl::desc("Use this to override the target cache line size when "
|
|
"specified by the user."));
|
|
|
|
static cl::opt<unsigned> MinPageSize(
|
|
"min-page-size", cl::init(0), cl::Hidden,
|
|
cl::desc("Use this to override the target's minimum page size."));
|
|
|
|
static cl::opt<unsigned> PredictableBranchThreshold(
|
|
"predictable-branch-threshold", cl::init(99), cl::Hidden,
|
|
cl::desc(
|
|
"Use this to override the target's predictable branch threshold (%)."));
|
|
|
|
namespace {
|
|
/// No-op implementation of the TTI interface using the utility base
|
|
/// classes.
|
|
///
|
|
/// This is used when no target specific information is available.
|
|
struct NoTTIImpl : TargetTransformInfoImplCRTPBase<NoTTIImpl> {
|
|
explicit NoTTIImpl(const DataLayout &DL)
|
|
: TargetTransformInfoImplCRTPBase<NoTTIImpl>(DL) {}
|
|
};
|
|
} // namespace
|
|
|
|
bool HardwareLoopInfo::canAnalyze(LoopInfo &LI) {
|
|
// If the loop has irreducible control flow, it can not be converted to
|
|
// Hardware loop.
|
|
LoopBlocksRPO RPOT(L);
|
|
RPOT.perform(&LI);
|
|
if (containsIrreducibleCFG<const BasicBlock *>(RPOT, LI))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
IntrinsicCostAttributes::IntrinsicCostAttributes(
|
|
Intrinsic::ID Id, const CallBase &CI, InstructionCost ScalarizationCost,
|
|
bool TypeBasedOnly, const TargetLibraryInfo *LibInfo)
|
|
: II(dyn_cast<IntrinsicInst>(&CI)), RetTy(CI.getType()), IID(Id),
|
|
ScalarizationCost(ScalarizationCost), LibInfo(LibInfo) {
|
|
|
|
if (const auto *FPMO = dyn_cast<FPMathOperator>(&CI))
|
|
FMF = FPMO->getFastMathFlags();
|
|
|
|
if (!TypeBasedOnly)
|
|
Arguments.insert(Arguments.begin(), CI.arg_begin(), CI.arg_end());
|
|
FunctionType *FTy = CI.getCalledFunction()->getFunctionType();
|
|
ParamTys.insert(ParamTys.begin(), FTy->param_begin(), FTy->param_end());
|
|
}
|
|
|
|
IntrinsicCostAttributes::IntrinsicCostAttributes(Intrinsic::ID Id, Type *RTy,
|
|
ArrayRef<Type *> Tys,
|
|
FastMathFlags Flags,
|
|
const IntrinsicInst *I,
|
|
InstructionCost ScalarCost)
|
|
: II(I), RetTy(RTy), IID(Id), FMF(Flags), ScalarizationCost(ScalarCost) {
|
|
ParamTys.insert(ParamTys.begin(), Tys.begin(), Tys.end());
|
|
}
|
|
|
|
IntrinsicCostAttributes::IntrinsicCostAttributes(Intrinsic::ID Id, Type *Ty,
|
|
ArrayRef<const Value *> Args)
|
|
: RetTy(Ty), IID(Id) {
|
|
|
|
Arguments.insert(Arguments.begin(), Args.begin(), Args.end());
|
|
ParamTys.reserve(Arguments.size());
|
|
for (const Value *Argument : Arguments)
|
|
ParamTys.push_back(Argument->getType());
|
|
}
|
|
|
|
IntrinsicCostAttributes::IntrinsicCostAttributes(
|
|
Intrinsic::ID Id, Type *RTy, ArrayRef<const Value *> Args,
|
|
ArrayRef<Type *> Tys, FastMathFlags Flags, const IntrinsicInst *I,
|
|
InstructionCost ScalarCost, TargetLibraryInfo const *LibInfo)
|
|
: II(I), RetTy(RTy), IID(Id), FMF(Flags), ScalarizationCost(ScalarCost),
|
|
LibInfo(LibInfo) {
|
|
ParamTys.insert(ParamTys.begin(), Tys.begin(), Tys.end());
|
|
Arguments.insert(Arguments.begin(), Args.begin(), Args.end());
|
|
}
|
|
|
|
HardwareLoopInfo::HardwareLoopInfo(Loop *L) : L(L) {
|
|
// Match default options:
|
|
// - hardware-loop-counter-bitwidth = 32
|
|
// - hardware-loop-decrement = 1
|
|
CountType = Type::getInt32Ty(L->getHeader()->getContext());
|
|
LoopDecrement = ConstantInt::get(CountType, 1);
|
|
}
|
|
|
|
bool HardwareLoopInfo::isHardwareLoopCandidate(ScalarEvolution &SE,
|
|
LoopInfo &LI, DominatorTree &DT,
|
|
bool ForceNestedLoop,
|
|
bool ForceHardwareLoopPHI) {
|
|
SmallVector<BasicBlock *, 4> ExitingBlocks;
|
|
L->getExitingBlocks(ExitingBlocks);
|
|
|
|
for (BasicBlock *BB : ExitingBlocks) {
|
|
// If we pass the updated counter back through a phi, we need to know
|
|
// which latch the updated value will be coming from.
|
|
if (!L->isLoopLatch(BB)) {
|
|
if (ForceHardwareLoopPHI || CounterInReg)
|
|
continue;
|
|
}
|
|
|
|
const SCEV *EC = SE.getExitCount(L, BB);
|
|
if (isa<SCEVCouldNotCompute>(EC))
|
|
continue;
|
|
if (const SCEVConstant *ConstEC = dyn_cast<SCEVConstant>(EC)) {
|
|
if (ConstEC->getValue()->isZero())
|
|
continue;
|
|
} else if (!SE.isLoopInvariant(EC, L))
|
|
continue;
|
|
|
|
if (SE.getTypeSizeInBits(EC->getType()) > CountType->getBitWidth())
|
|
continue;
|
|
|
|
// If this exiting block is contained in a nested loop, it is not eligible
|
|
// for insertion of the branch-and-decrement since the inner loop would
|
|
// end up messing up the value in the CTR.
|
|
if (!IsNestingLegal && LI.getLoopFor(BB) != L && !ForceNestedLoop)
|
|
continue;
|
|
|
|
// We now have a loop-invariant count of loop iterations (which is not the
|
|
// constant zero) for which we know that this loop will not exit via this
|
|
// existing block.
|
|
|
|
// We need to make sure that this block will run on every loop iteration.
|
|
// For this to be true, we must dominate all blocks with backedges. Such
|
|
// blocks are in-loop predecessors to the header block.
|
|
bool NotAlways = false;
|
|
for (BasicBlock *Pred : predecessors(L->getHeader())) {
|
|
if (!L->contains(Pred))
|
|
continue;
|
|
|
|
if (!DT.dominates(BB, Pred)) {
|
|
NotAlways = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NotAlways)
|
|
continue;
|
|
|
|
// Make sure this blocks ends with a conditional branch.
|
|
Instruction *TI = BB->getTerminator();
|
|
if (!TI)
|
|
continue;
|
|
|
|
if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
|
|
if (!BI->isConditional())
|
|
continue;
|
|
|
|
ExitBranch = BI;
|
|
} else
|
|
continue;
|
|
|
|
// Note that this block may not be the loop latch block, even if the loop
|
|
// has a latch block.
|
|
ExitBlock = BB;
|
|
ExitCount = EC;
|
|
break;
|
|
}
|
|
|
|
if (!ExitBlock)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
TargetTransformInfo::TargetTransformInfo(const DataLayout &DL)
|
|
: TTIImpl(new Model<NoTTIImpl>(NoTTIImpl(DL))) {}
|
|
|
|
TargetTransformInfo::~TargetTransformInfo() = default;
|
|
|
|
TargetTransformInfo::TargetTransformInfo(TargetTransformInfo &&Arg)
|
|
: TTIImpl(std::move(Arg.TTIImpl)) {}
|
|
|
|
TargetTransformInfo &TargetTransformInfo::operator=(TargetTransformInfo &&RHS) {
|
|
TTIImpl = std::move(RHS.TTIImpl);
|
|
return *this;
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getInliningThresholdMultiplier() const {
|
|
return TTIImpl->getInliningThresholdMultiplier();
|
|
}
|
|
|
|
unsigned
|
|
TargetTransformInfo::getInliningCostBenefitAnalysisSavingsMultiplier() const {
|
|
return TTIImpl->getInliningCostBenefitAnalysisSavingsMultiplier();
|
|
}
|
|
|
|
unsigned
|
|
TargetTransformInfo::getInliningCostBenefitAnalysisProfitableMultiplier()
|
|
const {
|
|
return TTIImpl->getInliningCostBenefitAnalysisProfitableMultiplier();
|
|
}
|
|
|
|
int TargetTransformInfo::getInliningLastCallToStaticBonus() const {
|
|
return TTIImpl->getInliningLastCallToStaticBonus();
|
|
}
|
|
|
|
unsigned
|
|
TargetTransformInfo::adjustInliningThreshold(const CallBase *CB) const {
|
|
return TTIImpl->adjustInliningThreshold(CB);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getCallerAllocaCost(const CallBase *CB,
|
|
const AllocaInst *AI) const {
|
|
return TTIImpl->getCallerAllocaCost(CB, AI);
|
|
}
|
|
|
|
int TargetTransformInfo::getInlinerVectorBonusPercent() const {
|
|
return TTIImpl->getInlinerVectorBonusPercent();
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getGEPCost(
|
|
Type *PointeeType, const Value *Ptr, ArrayRef<const Value *> Operands,
|
|
Type *AccessType, TTI::TargetCostKind CostKind) const {
|
|
return TTIImpl->getGEPCost(PointeeType, Ptr, Operands, AccessType, CostKind);
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getPointersChainCost(
|
|
ArrayRef<const Value *> Ptrs, const Value *Base,
|
|
const TTI::PointersChainInfo &Info, Type *AccessTy,
|
|
TTI::TargetCostKind CostKind) const {
|
|
assert((Base || !Info.isSameBase()) &&
|
|
"If pointers have same base address it has to be provided.");
|
|
return TTIImpl->getPointersChainCost(Ptrs, Base, Info, AccessTy, CostKind);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getEstimatedNumberOfCaseClusters(
|
|
const SwitchInst &SI, unsigned &JTSize, ProfileSummaryInfo *PSI,
|
|
BlockFrequencyInfo *BFI) const {
|
|
return TTIImpl->getEstimatedNumberOfCaseClusters(SI, JTSize, PSI, BFI);
|
|
}
|
|
|
|
InstructionCost
|
|
TargetTransformInfo::getInstructionCost(const User *U,
|
|
ArrayRef<const Value *> Operands,
|
|
enum TargetCostKind CostKind) const {
|
|
InstructionCost Cost = TTIImpl->getInstructionCost(U, Operands, CostKind);
|
|
assert((CostKind == TTI::TCK_RecipThroughput || Cost >= 0) &&
|
|
"TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
BranchProbability TargetTransformInfo::getPredictableBranchThreshold() const {
|
|
return PredictableBranchThreshold.getNumOccurrences() > 0
|
|
? BranchProbability(PredictableBranchThreshold, 100)
|
|
: TTIImpl->getPredictableBranchThreshold();
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getBranchMispredictPenalty() const {
|
|
return TTIImpl->getBranchMispredictPenalty();
|
|
}
|
|
|
|
bool TargetTransformInfo::hasBranchDivergence(const Function *F) const {
|
|
return TTIImpl->hasBranchDivergence(F);
|
|
}
|
|
|
|
bool TargetTransformInfo::isSourceOfDivergence(const Value *V) const {
|
|
if (const auto *Call = dyn_cast<CallBase>(V)) {
|
|
if (Call->hasFnAttr(Attribute::NoDivergenceSource))
|
|
return false;
|
|
}
|
|
return TTIImpl->isSourceOfDivergence(V);
|
|
}
|
|
|
|
bool llvm::TargetTransformInfo::isAlwaysUniform(const Value *V) const {
|
|
return TTIImpl->isAlwaysUniform(V);
|
|
}
|
|
|
|
bool llvm::TargetTransformInfo::isValidAddrSpaceCast(unsigned FromAS,
|
|
unsigned ToAS) const {
|
|
return TTIImpl->isValidAddrSpaceCast(FromAS, ToAS);
|
|
}
|
|
|
|
bool llvm::TargetTransformInfo::addrspacesMayAlias(unsigned FromAS,
|
|
unsigned ToAS) const {
|
|
return TTIImpl->addrspacesMayAlias(FromAS, ToAS);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getFlatAddressSpace() const {
|
|
return TTIImpl->getFlatAddressSpace();
|
|
}
|
|
|
|
bool TargetTransformInfo::collectFlatAddressOperands(
|
|
SmallVectorImpl<int> &OpIndexes, Intrinsic::ID IID) const {
|
|
return TTIImpl->collectFlatAddressOperands(OpIndexes, IID);
|
|
}
|
|
|
|
bool TargetTransformInfo::isNoopAddrSpaceCast(unsigned FromAS,
|
|
unsigned ToAS) const {
|
|
return TTIImpl->isNoopAddrSpaceCast(FromAS, ToAS);
|
|
}
|
|
|
|
bool TargetTransformInfo::canHaveNonUndefGlobalInitializerInAddressSpace(
|
|
unsigned AS) const {
|
|
return TTIImpl->canHaveNonUndefGlobalInitializerInAddressSpace(AS);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getAssumedAddrSpace(const Value *V) const {
|
|
return TTIImpl->getAssumedAddrSpace(V);
|
|
}
|
|
|
|
bool TargetTransformInfo::isSingleThreaded() const {
|
|
return TTIImpl->isSingleThreaded();
|
|
}
|
|
|
|
std::pair<const Value *, unsigned>
|
|
TargetTransformInfo::getPredicatedAddrSpace(const Value *V) const {
|
|
return TTIImpl->getPredicatedAddrSpace(V);
|
|
}
|
|
|
|
Value *TargetTransformInfo::rewriteIntrinsicWithAddressSpace(
|
|
IntrinsicInst *II, Value *OldV, Value *NewV) const {
|
|
return TTIImpl->rewriteIntrinsicWithAddressSpace(II, OldV, NewV);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLoweredToCall(const Function *F) const {
|
|
return TTIImpl->isLoweredToCall(F);
|
|
}
|
|
|
|
bool TargetTransformInfo::isHardwareLoopProfitable(
|
|
Loop *L, ScalarEvolution &SE, AssumptionCache &AC,
|
|
TargetLibraryInfo *LibInfo, HardwareLoopInfo &HWLoopInfo) const {
|
|
return TTIImpl->isHardwareLoopProfitable(L, SE, AC, LibInfo, HWLoopInfo);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getEpilogueVectorizationMinVF() const {
|
|
return TTIImpl->getEpilogueVectorizationMinVF();
|
|
}
|
|
|
|
bool TargetTransformInfo::preferPredicateOverEpilogue(
|
|
TailFoldingInfo *TFI) const {
|
|
return TTIImpl->preferPredicateOverEpilogue(TFI);
|
|
}
|
|
|
|
TailFoldingStyle TargetTransformInfo::getPreferredTailFoldingStyle(
|
|
bool IVUpdateMayOverflow) const {
|
|
return TTIImpl->getPreferredTailFoldingStyle(IVUpdateMayOverflow);
|
|
}
|
|
|
|
std::optional<Instruction *>
|
|
TargetTransformInfo::instCombineIntrinsic(InstCombiner &IC,
|
|
IntrinsicInst &II) const {
|
|
return TTIImpl->instCombineIntrinsic(IC, II);
|
|
}
|
|
|
|
std::optional<Value *> TargetTransformInfo::simplifyDemandedUseBitsIntrinsic(
|
|
InstCombiner &IC, IntrinsicInst &II, APInt DemandedMask, KnownBits &Known,
|
|
bool &KnownBitsComputed) const {
|
|
return TTIImpl->simplifyDemandedUseBitsIntrinsic(IC, II, DemandedMask, Known,
|
|
KnownBitsComputed);
|
|
}
|
|
|
|
std::optional<Value *> TargetTransformInfo::simplifyDemandedVectorEltsIntrinsic(
|
|
InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts,
|
|
APInt &UndefElts2, APInt &UndefElts3,
|
|
std::function<void(Instruction *, unsigned, APInt, APInt &)>
|
|
SimplifyAndSetOp) const {
|
|
return TTIImpl->simplifyDemandedVectorEltsIntrinsic(
|
|
IC, II, DemandedElts, UndefElts, UndefElts2, UndefElts3,
|
|
SimplifyAndSetOp);
|
|
}
|
|
|
|
void TargetTransformInfo::getUnrollingPreferences(
|
|
Loop *L, ScalarEvolution &SE, UnrollingPreferences &UP,
|
|
OptimizationRemarkEmitter *ORE) const {
|
|
return TTIImpl->getUnrollingPreferences(L, SE, UP, ORE);
|
|
}
|
|
|
|
void TargetTransformInfo::getPeelingPreferences(Loop *L, ScalarEvolution &SE,
|
|
PeelingPreferences &PP) const {
|
|
return TTIImpl->getPeelingPreferences(L, SE, PP);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm) const {
|
|
return TTIImpl->isLegalAddImmediate(Imm);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalAddScalableImmediate(int64_t Imm) const {
|
|
return TTIImpl->isLegalAddScalableImmediate(Imm);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalICmpImmediate(int64_t Imm) const {
|
|
return TTIImpl->isLegalICmpImmediate(Imm);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
|
|
int64_t BaseOffset,
|
|
bool HasBaseReg, int64_t Scale,
|
|
unsigned AddrSpace,
|
|
Instruction *I,
|
|
int64_t ScalableOffset) const {
|
|
return TTIImpl->isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
|
|
Scale, AddrSpace, I, ScalableOffset);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLSRCostLess(const LSRCost &C1,
|
|
const LSRCost &C2) const {
|
|
return TTIImpl->isLSRCostLess(C1, C2);
|
|
}
|
|
|
|
bool TargetTransformInfo::isNumRegsMajorCostOfLSR() const {
|
|
return TTIImpl->isNumRegsMajorCostOfLSR();
|
|
}
|
|
|
|
bool TargetTransformInfo::shouldDropLSRSolutionIfLessProfitable() const {
|
|
return TTIImpl->shouldDropLSRSolutionIfLessProfitable();
|
|
}
|
|
|
|
bool TargetTransformInfo::isProfitableLSRChainElement(Instruction *I) const {
|
|
return TTIImpl->isProfitableLSRChainElement(I);
|
|
}
|
|
|
|
bool TargetTransformInfo::canMacroFuseCmp() const {
|
|
return TTIImpl->canMacroFuseCmp();
|
|
}
|
|
|
|
bool TargetTransformInfo::canSaveCmp(Loop *L, BranchInst **BI,
|
|
ScalarEvolution *SE, LoopInfo *LI,
|
|
DominatorTree *DT, AssumptionCache *AC,
|
|
TargetLibraryInfo *LibInfo) const {
|
|
return TTIImpl->canSaveCmp(L, BI, SE, LI, DT, AC, LibInfo);
|
|
}
|
|
|
|
TTI::AddressingModeKind
|
|
TargetTransformInfo::getPreferredAddressingMode(const Loop *L,
|
|
ScalarEvolution *SE) const {
|
|
return TTIImpl->getPreferredAddressingMode(L, SE);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalMaskedStore(Type *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->isLegalMaskedStore(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalMaskedLoad(Type *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->isLegalMaskedLoad(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalNTStore(Type *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->isLegalNTStore(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalNTLoad(Type *DataType, Align Alignment) const {
|
|
return TTIImpl->isLegalNTLoad(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalBroadcastLoad(Type *ElementTy,
|
|
ElementCount NumElements) const {
|
|
return TTIImpl->isLegalBroadcastLoad(ElementTy, NumElements);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalMaskedGather(Type *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->isLegalMaskedGather(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalAltInstr(
|
|
VectorType *VecTy, unsigned Opcode0, unsigned Opcode1,
|
|
const SmallBitVector &OpcodeMask) const {
|
|
return TTIImpl->isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalMaskedScatter(Type *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->isLegalMaskedScatter(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::forceScalarizeMaskedGather(VectorType *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->forceScalarizeMaskedGather(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::forceScalarizeMaskedScatter(VectorType *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->forceScalarizeMaskedScatter(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalMaskedCompressStore(Type *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->isLegalMaskedCompressStore(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalMaskedExpandLoad(Type *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->isLegalMaskedExpandLoad(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalStridedLoadStore(Type *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->isLegalStridedLoadStore(DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalInterleavedAccessType(
|
|
VectorType *VTy, unsigned Factor, Align Alignment,
|
|
unsigned AddrSpace) const {
|
|
return TTIImpl->isLegalInterleavedAccessType(VTy, Factor, Alignment,
|
|
AddrSpace);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalMaskedVectorHistogram(Type *AddrType,
|
|
Type *DataType) const {
|
|
return TTIImpl->isLegalMaskedVectorHistogram(AddrType, DataType);
|
|
}
|
|
|
|
bool TargetTransformInfo::enableOrderedReductions() const {
|
|
return TTIImpl->enableOrderedReductions();
|
|
}
|
|
|
|
bool TargetTransformInfo::hasDivRemOp(Type *DataType, bool IsSigned) const {
|
|
return TTIImpl->hasDivRemOp(DataType, IsSigned);
|
|
}
|
|
|
|
bool TargetTransformInfo::hasVolatileVariant(Instruction *I,
|
|
unsigned AddrSpace) const {
|
|
return TTIImpl->hasVolatileVariant(I, AddrSpace);
|
|
}
|
|
|
|
bool TargetTransformInfo::prefersVectorizedAddressing() const {
|
|
return TTIImpl->prefersVectorizedAddressing();
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getScalingFactorCost(
|
|
Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg,
|
|
int64_t Scale, unsigned AddrSpace) const {
|
|
InstructionCost Cost = TTIImpl->getScalingFactorCost(
|
|
Ty, BaseGV, BaseOffset, HasBaseReg, Scale, AddrSpace);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
bool TargetTransformInfo::LSRWithInstrQueries() const {
|
|
return TTIImpl->LSRWithInstrQueries();
|
|
}
|
|
|
|
bool TargetTransformInfo::isTruncateFree(Type *Ty1, Type *Ty2) const {
|
|
return TTIImpl->isTruncateFree(Ty1, Ty2);
|
|
}
|
|
|
|
bool TargetTransformInfo::isProfitableToHoist(Instruction *I) const {
|
|
return TTIImpl->isProfitableToHoist(I);
|
|
}
|
|
|
|
bool TargetTransformInfo::useAA() const { return TTIImpl->useAA(); }
|
|
|
|
bool TargetTransformInfo::isTypeLegal(Type *Ty) const {
|
|
return TTIImpl->isTypeLegal(Ty);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getRegUsageForType(Type *Ty) const {
|
|
return TTIImpl->getRegUsageForType(Ty);
|
|
}
|
|
|
|
bool TargetTransformInfo::shouldBuildLookupTables() const {
|
|
return TTIImpl->shouldBuildLookupTables();
|
|
}
|
|
|
|
bool TargetTransformInfo::shouldBuildLookupTablesForConstant(
|
|
Constant *C) const {
|
|
return TTIImpl->shouldBuildLookupTablesForConstant(C);
|
|
}
|
|
|
|
bool TargetTransformInfo::shouldBuildRelLookupTables() const {
|
|
return TTIImpl->shouldBuildRelLookupTables();
|
|
}
|
|
|
|
bool TargetTransformInfo::useColdCCForColdCall(Function &F) const {
|
|
return TTIImpl->useColdCCForColdCall(F);
|
|
}
|
|
|
|
bool TargetTransformInfo::isTargetIntrinsicTriviallyScalarizable(
|
|
Intrinsic::ID ID) const {
|
|
return TTIImpl->isTargetIntrinsicTriviallyScalarizable(ID);
|
|
}
|
|
|
|
bool TargetTransformInfo::isTargetIntrinsicWithScalarOpAtArg(
|
|
Intrinsic::ID ID, unsigned ScalarOpdIdx) const {
|
|
return TTIImpl->isTargetIntrinsicWithScalarOpAtArg(ID, ScalarOpdIdx);
|
|
}
|
|
|
|
bool TargetTransformInfo::isTargetIntrinsicWithOverloadTypeAtArg(
|
|
Intrinsic::ID ID, int OpdIdx) const {
|
|
return TTIImpl->isTargetIntrinsicWithOverloadTypeAtArg(ID, OpdIdx);
|
|
}
|
|
|
|
bool TargetTransformInfo::isTargetIntrinsicWithStructReturnOverloadAtField(
|
|
Intrinsic::ID ID, int RetIdx) const {
|
|
return TTIImpl->isTargetIntrinsicWithStructReturnOverloadAtField(ID, RetIdx);
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getScalarizationOverhead(
|
|
VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,
|
|
TTI::TargetCostKind CostKind, ArrayRef<Value *> VL) const {
|
|
return TTIImpl->getScalarizationOverhead(Ty, DemandedElts, Insert, Extract,
|
|
CostKind, VL);
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getOperandsScalarizationOverhead(
|
|
ArrayRef<const Value *> Args, ArrayRef<Type *> Tys,
|
|
TTI::TargetCostKind CostKind) const {
|
|
return TTIImpl->getOperandsScalarizationOverhead(Args, Tys, CostKind);
|
|
}
|
|
|
|
bool TargetTransformInfo::supportsEfficientVectorElementLoadStore() const {
|
|
return TTIImpl->supportsEfficientVectorElementLoadStore();
|
|
}
|
|
|
|
bool TargetTransformInfo::supportsTailCalls() const {
|
|
return TTIImpl->supportsTailCalls();
|
|
}
|
|
|
|
bool TargetTransformInfo::supportsTailCallFor(const CallBase *CB) const {
|
|
return TTIImpl->supportsTailCallFor(CB);
|
|
}
|
|
|
|
bool TargetTransformInfo::enableAggressiveInterleaving(
|
|
bool LoopHasReductions) const {
|
|
return TTIImpl->enableAggressiveInterleaving(LoopHasReductions);
|
|
}
|
|
|
|
TargetTransformInfo::MemCmpExpansionOptions
|
|
TargetTransformInfo::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
|
|
return TTIImpl->enableMemCmpExpansion(OptSize, IsZeroCmp);
|
|
}
|
|
|
|
bool TargetTransformInfo::enableSelectOptimize() const {
|
|
return TTIImpl->enableSelectOptimize();
|
|
}
|
|
|
|
bool TargetTransformInfo::shouldTreatInstructionLikeSelect(
|
|
const Instruction *I) const {
|
|
return TTIImpl->shouldTreatInstructionLikeSelect(I);
|
|
}
|
|
|
|
bool TargetTransformInfo::enableInterleavedAccessVectorization() const {
|
|
return TTIImpl->enableInterleavedAccessVectorization();
|
|
}
|
|
|
|
bool TargetTransformInfo::enableMaskedInterleavedAccessVectorization() const {
|
|
return TTIImpl->enableMaskedInterleavedAccessVectorization();
|
|
}
|
|
|
|
bool TargetTransformInfo::isFPVectorizationPotentiallyUnsafe() const {
|
|
return TTIImpl->isFPVectorizationPotentiallyUnsafe();
|
|
}
|
|
|
|
bool
|
|
TargetTransformInfo::allowsMisalignedMemoryAccesses(LLVMContext &Context,
|
|
unsigned BitWidth,
|
|
unsigned AddressSpace,
|
|
Align Alignment,
|
|
unsigned *Fast) const {
|
|
return TTIImpl->allowsMisalignedMemoryAccesses(Context, BitWidth,
|
|
AddressSpace, Alignment, Fast);
|
|
}
|
|
|
|
TargetTransformInfo::PopcntSupportKind
|
|
TargetTransformInfo::getPopcntSupport(unsigned IntTyWidthInBit) const {
|
|
return TTIImpl->getPopcntSupport(IntTyWidthInBit);
|
|
}
|
|
|
|
bool TargetTransformInfo::haveFastSqrt(Type *Ty) const {
|
|
return TTIImpl->haveFastSqrt(Ty);
|
|
}
|
|
|
|
bool TargetTransformInfo::isExpensiveToSpeculativelyExecute(
|
|
const Instruction *I) const {
|
|
return TTIImpl->isExpensiveToSpeculativelyExecute(I);
|
|
}
|
|
|
|
bool TargetTransformInfo::isFCmpOrdCheaperThanFCmpZero(Type *Ty) const {
|
|
return TTIImpl->isFCmpOrdCheaperThanFCmpZero(Ty);
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getFPOpCost(Type *Ty) const {
|
|
InstructionCost Cost = TTIImpl->getFPOpCost(Ty);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getIntImmCodeSizeCost(unsigned Opcode,
|
|
unsigned Idx,
|
|
const APInt &Imm,
|
|
Type *Ty) const {
|
|
InstructionCost Cost = TTIImpl->getIntImmCodeSizeCost(Opcode, Idx, Imm, Ty);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost
|
|
TargetTransformInfo::getIntImmCost(const APInt &Imm, Type *Ty,
|
|
TTI::TargetCostKind CostKind) const {
|
|
InstructionCost Cost = TTIImpl->getIntImmCost(Imm, Ty, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getIntImmCostInst(
|
|
unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty,
|
|
TTI::TargetCostKind CostKind, Instruction *Inst) const {
|
|
InstructionCost Cost =
|
|
TTIImpl->getIntImmCostInst(Opcode, Idx, Imm, Ty, CostKind, Inst);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost
|
|
TargetTransformInfo::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
|
|
const APInt &Imm, Type *Ty,
|
|
TTI::TargetCostKind CostKind) const {
|
|
InstructionCost Cost =
|
|
TTIImpl->getIntImmCostIntrin(IID, Idx, Imm, Ty, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
bool TargetTransformInfo::preferToKeepConstantsAttached(
|
|
const Instruction &Inst, const Function &Fn) const {
|
|
return TTIImpl->preferToKeepConstantsAttached(Inst, Fn);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getNumberOfRegisters(unsigned ClassID) const {
|
|
return TTIImpl->getNumberOfRegisters(ClassID);
|
|
}
|
|
|
|
bool TargetTransformInfo::hasConditionalLoadStoreForType(Type *Ty) const {
|
|
return TTIImpl->hasConditionalLoadStoreForType(Ty);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getRegisterClassForType(bool Vector,
|
|
Type *Ty) const {
|
|
return TTIImpl->getRegisterClassForType(Vector, Ty);
|
|
}
|
|
|
|
const char *TargetTransformInfo::getRegisterClassName(unsigned ClassID) const {
|
|
return TTIImpl->getRegisterClassName(ClassID);
|
|
}
|
|
|
|
TypeSize TargetTransformInfo::getRegisterBitWidth(
|
|
TargetTransformInfo::RegisterKind K) const {
|
|
return TTIImpl->getRegisterBitWidth(K);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getMinVectorRegisterBitWidth() const {
|
|
return TTIImpl->getMinVectorRegisterBitWidth();
|
|
}
|
|
|
|
std::optional<unsigned> TargetTransformInfo::getMaxVScale() const {
|
|
return TTIImpl->getMaxVScale();
|
|
}
|
|
|
|
std::optional<unsigned> TargetTransformInfo::getVScaleForTuning() const {
|
|
return TTIImpl->getVScaleForTuning();
|
|
}
|
|
|
|
bool TargetTransformInfo::isVScaleKnownToBeAPowerOfTwo() const {
|
|
return TTIImpl->isVScaleKnownToBeAPowerOfTwo();
|
|
}
|
|
|
|
bool TargetTransformInfo::shouldMaximizeVectorBandwidth(
|
|
TargetTransformInfo::RegisterKind K) const {
|
|
return TTIImpl->shouldMaximizeVectorBandwidth(K);
|
|
}
|
|
|
|
ElementCount TargetTransformInfo::getMinimumVF(unsigned ElemWidth,
|
|
bool IsScalable) const {
|
|
return TTIImpl->getMinimumVF(ElemWidth, IsScalable);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getMaximumVF(unsigned ElemWidth,
|
|
unsigned Opcode) const {
|
|
return TTIImpl->getMaximumVF(ElemWidth, Opcode);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getStoreMinimumVF(unsigned VF, Type *ScalarMemTy,
|
|
Type *ScalarValTy) const {
|
|
return TTIImpl->getStoreMinimumVF(VF, ScalarMemTy, ScalarValTy);
|
|
}
|
|
|
|
bool TargetTransformInfo::shouldConsiderAddressTypePromotion(
|
|
const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const {
|
|
return TTIImpl->shouldConsiderAddressTypePromotion(
|
|
I, AllowPromotionWithoutCommonHeader);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getCacheLineSize() const {
|
|
return CacheLineSize.getNumOccurrences() > 0 ? CacheLineSize
|
|
: TTIImpl->getCacheLineSize();
|
|
}
|
|
|
|
std::optional<unsigned>
|
|
TargetTransformInfo::getCacheSize(CacheLevel Level) const {
|
|
return TTIImpl->getCacheSize(Level);
|
|
}
|
|
|
|
std::optional<unsigned>
|
|
TargetTransformInfo::getCacheAssociativity(CacheLevel Level) const {
|
|
return TTIImpl->getCacheAssociativity(Level);
|
|
}
|
|
|
|
std::optional<unsigned> TargetTransformInfo::getMinPageSize() const {
|
|
return MinPageSize.getNumOccurrences() > 0 ? MinPageSize
|
|
: TTIImpl->getMinPageSize();
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getPrefetchDistance() const {
|
|
return TTIImpl->getPrefetchDistance();
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getMinPrefetchStride(
|
|
unsigned NumMemAccesses, unsigned NumStridedMemAccesses,
|
|
unsigned NumPrefetches, bool HasCall) const {
|
|
return TTIImpl->getMinPrefetchStride(NumMemAccesses, NumStridedMemAccesses,
|
|
NumPrefetches, HasCall);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getMaxPrefetchIterationsAhead() const {
|
|
return TTIImpl->getMaxPrefetchIterationsAhead();
|
|
}
|
|
|
|
bool TargetTransformInfo::enableWritePrefetching() const {
|
|
return TTIImpl->enableWritePrefetching();
|
|
}
|
|
|
|
bool TargetTransformInfo::shouldPrefetchAddressSpace(unsigned AS) const {
|
|
return TTIImpl->shouldPrefetchAddressSpace(AS);
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getPartialReductionCost(
|
|
unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,
|
|
ElementCount VF, PartialReductionExtendKind OpAExtend,
|
|
PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp) const {
|
|
return TTIImpl->getPartialReductionCost(Opcode, InputTypeA, InputTypeB,
|
|
AccumType, VF, OpAExtend, OpBExtend,
|
|
BinOp);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getMaxInterleaveFactor(ElementCount VF) const {
|
|
return TTIImpl->getMaxInterleaveFactor(VF);
|
|
}
|
|
|
|
TargetTransformInfo::OperandValueInfo
|
|
TargetTransformInfo::getOperandInfo(const Value *V) {
|
|
OperandValueKind OpInfo = OK_AnyValue;
|
|
OperandValueProperties OpProps = OP_None;
|
|
|
|
if (isa<ConstantInt>(V) || isa<ConstantFP>(V)) {
|
|
if (const auto *CI = dyn_cast<ConstantInt>(V)) {
|
|
if (CI->getValue().isPowerOf2())
|
|
OpProps = OP_PowerOf2;
|
|
else if (CI->getValue().isNegatedPowerOf2())
|
|
OpProps = OP_NegatedPowerOf2;
|
|
}
|
|
return {OK_UniformConstantValue, OpProps};
|
|
}
|
|
|
|
// A broadcast shuffle creates a uniform value.
|
|
// TODO: Add support for non-zero index broadcasts.
|
|
// TODO: Add support for different source vector width.
|
|
if (const auto *ShuffleInst = dyn_cast<ShuffleVectorInst>(V))
|
|
if (ShuffleInst->isZeroEltSplat())
|
|
OpInfo = OK_UniformValue;
|
|
|
|
const Value *Splat = getSplatValue(V);
|
|
|
|
// Check for a splat of a constant or for a non uniform vector of constants
|
|
// and check if the constant(s) are all powers of two.
|
|
if (Splat) {
|
|
// Check for a splat of a uniform value. This is not loop aware, so return
|
|
// true only for the obviously uniform cases (argument, globalvalue)
|
|
if (isa<Argument>(Splat) || isa<GlobalValue>(Splat)) {
|
|
OpInfo = OK_UniformValue;
|
|
} else if (isa<Constant>(Splat)) {
|
|
OpInfo = OK_UniformConstantValue;
|
|
if (auto *CI = dyn_cast<ConstantInt>(Splat)) {
|
|
if (CI->getValue().isPowerOf2())
|
|
OpProps = OP_PowerOf2;
|
|
else if (CI->getValue().isNegatedPowerOf2())
|
|
OpProps = OP_NegatedPowerOf2;
|
|
}
|
|
}
|
|
} else if (const auto *CDS = dyn_cast<ConstantDataSequential>(V)) {
|
|
OpInfo = OK_NonUniformConstantValue;
|
|
bool AllPow2 = true, AllNegPow2 = true;
|
|
for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I) {
|
|
if (auto *CI = dyn_cast<ConstantInt>(CDS->getElementAsConstant(I))) {
|
|
AllPow2 &= CI->getValue().isPowerOf2();
|
|
AllNegPow2 &= CI->getValue().isNegatedPowerOf2();
|
|
if (AllPow2 || AllNegPow2)
|
|
continue;
|
|
}
|
|
AllPow2 = AllNegPow2 = false;
|
|
break;
|
|
}
|
|
OpProps = AllPow2 ? OP_PowerOf2 : OpProps;
|
|
OpProps = AllNegPow2 ? OP_NegatedPowerOf2 : OpProps;
|
|
} else if (isa<ConstantVector>(V) || isa<ConstantDataVector>(V)) {
|
|
OpInfo = OK_NonUniformConstantValue;
|
|
}
|
|
|
|
return {OpInfo, OpProps};
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getArithmeticInstrCost(
|
|
unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
|
|
OperandValueInfo Op1Info, OperandValueInfo Op2Info,
|
|
ArrayRef<const Value *> Args, const Instruction *CxtI,
|
|
const TargetLibraryInfo *TLibInfo) const {
|
|
|
|
// Use call cost for frem intructions that have platform specific vector math
|
|
// functions, as those will be replaced with calls later by SelectionDAG or
|
|
// ReplaceWithVecLib pass.
|
|
if (TLibInfo && Opcode == Instruction::FRem) {
|
|
VectorType *VecTy = dyn_cast<VectorType>(Ty);
|
|
LibFunc Func;
|
|
if (VecTy &&
|
|
TLibInfo->getLibFunc(Instruction::FRem, Ty->getScalarType(), Func) &&
|
|
TLibInfo->isFunctionVectorizable(TLibInfo->getName(Func),
|
|
VecTy->getElementCount()))
|
|
return getCallInstrCost(nullptr, VecTy, {VecTy, VecTy}, CostKind);
|
|
}
|
|
|
|
InstructionCost Cost =
|
|
TTIImpl->getArithmeticInstrCost(Opcode, Ty, CostKind,
|
|
Op1Info, Op2Info,
|
|
Args, CxtI);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getAltInstrCost(
|
|
VectorType *VecTy, unsigned Opcode0, unsigned Opcode1,
|
|
const SmallBitVector &OpcodeMask, TTI::TargetCostKind CostKind) const {
|
|
InstructionCost Cost =
|
|
TTIImpl->getAltInstrCost(VecTy, Opcode0, Opcode1, OpcodeMask, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getShuffleCost(
|
|
ShuffleKind Kind, VectorType *Ty, ArrayRef<int> Mask,
|
|
TTI::TargetCostKind CostKind, int Index, VectorType *SubTp,
|
|
ArrayRef<const Value *> Args, const Instruction *CxtI) const {
|
|
InstructionCost Cost = TTIImpl->getShuffleCost(Kind, Ty, Mask, CostKind,
|
|
Index, SubTp, Args, CxtI);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
TargetTransformInfo::PartialReductionExtendKind
|
|
TargetTransformInfo::getPartialReductionExtendKind(Instruction *I) {
|
|
if (isa<SExtInst>(I))
|
|
return PR_SignExtend;
|
|
if (isa<ZExtInst>(I))
|
|
return PR_ZeroExtend;
|
|
return PR_None;
|
|
}
|
|
|
|
TTI::CastContextHint
|
|
TargetTransformInfo::getCastContextHint(const Instruction *I) {
|
|
if (!I)
|
|
return CastContextHint::None;
|
|
|
|
auto getLoadStoreKind = [](const Value *V, unsigned LdStOp, unsigned MaskedOp,
|
|
unsigned GatScatOp) {
|
|
const Instruction *I = dyn_cast<Instruction>(V);
|
|
if (!I)
|
|
return CastContextHint::None;
|
|
|
|
if (I->getOpcode() == LdStOp)
|
|
return CastContextHint::Normal;
|
|
|
|
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
|
|
if (II->getIntrinsicID() == MaskedOp)
|
|
return TTI::CastContextHint::Masked;
|
|
if (II->getIntrinsicID() == GatScatOp)
|
|
return TTI::CastContextHint::GatherScatter;
|
|
}
|
|
|
|
return TTI::CastContextHint::None;
|
|
};
|
|
|
|
switch (I->getOpcode()) {
|
|
case Instruction::ZExt:
|
|
case Instruction::SExt:
|
|
case Instruction::FPExt:
|
|
return getLoadStoreKind(I->getOperand(0), Instruction::Load,
|
|
Intrinsic::masked_load, Intrinsic::masked_gather);
|
|
case Instruction::Trunc:
|
|
case Instruction::FPTrunc:
|
|
if (I->hasOneUse())
|
|
return getLoadStoreKind(*I->user_begin(), Instruction::Store,
|
|
Intrinsic::masked_store,
|
|
Intrinsic::masked_scatter);
|
|
break;
|
|
default:
|
|
return CastContextHint::None;
|
|
}
|
|
|
|
return TTI::CastContextHint::None;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getCastInstrCost(
|
|
unsigned Opcode, Type *Dst, Type *Src, CastContextHint CCH,
|
|
TTI::TargetCostKind CostKind, const Instruction *I) const {
|
|
assert((I == nullptr || I->getOpcode() == Opcode) &&
|
|
"Opcode should reflect passed instruction.");
|
|
InstructionCost Cost =
|
|
TTIImpl->getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getExtractWithExtendCost(
|
|
unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index) const {
|
|
InstructionCost Cost =
|
|
TTIImpl->getExtractWithExtendCost(Opcode, Dst, VecTy, Index);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getCFInstrCost(
|
|
unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I) const {
|
|
assert((I == nullptr || I->getOpcode() == Opcode) &&
|
|
"Opcode should reflect passed instruction.");
|
|
InstructionCost Cost = TTIImpl->getCFInstrCost(Opcode, CostKind, I);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getCmpSelInstrCost(
|
|
unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,
|
|
TTI::TargetCostKind CostKind, OperandValueInfo Op1Info,
|
|
OperandValueInfo Op2Info, const Instruction *I) const {
|
|
assert((I == nullptr || I->getOpcode() == Opcode) &&
|
|
"Opcode should reflect passed instruction.");
|
|
InstructionCost Cost = TTIImpl->getCmpSelInstrCost(
|
|
Opcode, ValTy, CondTy, VecPred, CostKind, Op1Info, Op2Info, I);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getVectorInstrCost(
|
|
unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
|
|
Value *Op0, Value *Op1) const {
|
|
assert((Opcode == Instruction::InsertElement ||
|
|
Opcode == Instruction::ExtractElement) &&
|
|
"Expecting Opcode to be insertelement/extractelement.");
|
|
InstructionCost Cost =
|
|
TTIImpl->getVectorInstrCost(Opcode, Val, CostKind, Index, Op0, Op1);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getVectorInstrCost(
|
|
unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
|
|
Value *Scalar,
|
|
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx) const {
|
|
assert((Opcode == Instruction::InsertElement ||
|
|
Opcode == Instruction::ExtractElement) &&
|
|
"Expecting Opcode to be insertelement/extractelement.");
|
|
InstructionCost Cost = TTIImpl->getVectorInstrCost(
|
|
Opcode, Val, CostKind, Index, Scalar, ScalarUserAndIdx);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost
|
|
TargetTransformInfo::getVectorInstrCost(const Instruction &I, Type *Val,
|
|
TTI::TargetCostKind CostKind,
|
|
unsigned Index) const {
|
|
// FIXME: Assert that Opcode is either InsertElement or ExtractElement.
|
|
// This is mentioned in the interface description and respected by all
|
|
// callers, but never asserted upon.
|
|
InstructionCost Cost = TTIImpl->getVectorInstrCost(I, Val, CostKind, Index);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getInsertExtractValueCost(
|
|
unsigned Opcode, TTI::TargetCostKind CostKind) const {
|
|
assert((Opcode == Instruction::InsertValue ||
|
|
Opcode == Instruction::ExtractValue) &&
|
|
"Expecting Opcode to be insertvalue/extractvalue.");
|
|
InstructionCost Cost = TTIImpl->getInsertExtractValueCost(Opcode, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getReplicationShuffleCost(
|
|
Type *EltTy, int ReplicationFactor, int VF, const APInt &DemandedDstElts,
|
|
TTI::TargetCostKind CostKind) const {
|
|
InstructionCost Cost = TTIImpl->getReplicationShuffleCost(
|
|
EltTy, ReplicationFactor, VF, DemandedDstElts, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getMemoryOpCost(
|
|
unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace,
|
|
TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo,
|
|
const Instruction *I) const {
|
|
assert((I == nullptr || I->getOpcode() == Opcode) &&
|
|
"Opcode should reflect passed instruction.");
|
|
InstructionCost Cost = TTIImpl->getMemoryOpCost(
|
|
Opcode, Src, Alignment, AddressSpace, CostKind, OpInfo, I);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getMaskedMemoryOpCost(
|
|
unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace,
|
|
TTI::TargetCostKind CostKind) const {
|
|
InstructionCost Cost = TTIImpl->getMaskedMemoryOpCost(Opcode, Src, Alignment,
|
|
AddressSpace, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getGatherScatterOpCost(
|
|
unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask,
|
|
Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) const {
|
|
InstructionCost Cost = TTIImpl->getGatherScatterOpCost(
|
|
Opcode, DataTy, Ptr, VariableMask, Alignment, CostKind, I);
|
|
assert((!Cost.isValid() || Cost >= 0) &&
|
|
"TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getExpandCompressMemoryOpCost(
|
|
unsigned Opcode, Type *DataTy, bool VariableMask, Align Alignment,
|
|
TTI::TargetCostKind CostKind, const Instruction *I) const {
|
|
InstructionCost Cost = TTIImpl->getExpandCompressMemoryOpCost(
|
|
Opcode, DataTy, VariableMask, Alignment, CostKind, I);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getStridedMemoryOpCost(
|
|
unsigned Opcode, Type *DataTy, const Value *Ptr, bool VariableMask,
|
|
Align Alignment, TTI::TargetCostKind CostKind, const Instruction *I) const {
|
|
InstructionCost Cost = TTIImpl->getStridedMemoryOpCost(
|
|
Opcode, DataTy, Ptr, VariableMask, Alignment, CostKind, I);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getInterleavedMemoryOpCost(
|
|
unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
|
|
Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
|
|
bool UseMaskForCond, bool UseMaskForGaps) const {
|
|
InstructionCost Cost = TTIImpl->getInterleavedMemoryOpCost(
|
|
Opcode, VecTy, Factor, Indices, Alignment, AddressSpace, CostKind,
|
|
UseMaskForCond, UseMaskForGaps);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost
|
|
TargetTransformInfo::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
|
|
TTI::TargetCostKind CostKind) const {
|
|
InstructionCost Cost = TTIImpl->getIntrinsicInstrCost(ICA, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost
|
|
TargetTransformInfo::getCallInstrCost(Function *F, Type *RetTy,
|
|
ArrayRef<Type *> Tys,
|
|
TTI::TargetCostKind CostKind) const {
|
|
InstructionCost Cost = TTIImpl->getCallInstrCost(F, RetTy, Tys, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getNumberOfParts(Type *Tp) const {
|
|
return TTIImpl->getNumberOfParts(Tp);
|
|
}
|
|
|
|
InstructionCost
|
|
TargetTransformInfo::getAddressComputationCost(Type *Tp, ScalarEvolution *SE,
|
|
const SCEV *Ptr) const {
|
|
InstructionCost Cost = TTIImpl->getAddressComputationCost(Tp, SE, Ptr);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getMemcpyCost(const Instruction *I) const {
|
|
InstructionCost Cost = TTIImpl->getMemcpyCost(I);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
uint64_t TargetTransformInfo::getMaxMemIntrinsicInlineSizeThreshold() const {
|
|
return TTIImpl->getMaxMemIntrinsicInlineSizeThreshold();
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getArithmeticReductionCost(
|
|
unsigned Opcode, VectorType *Ty, std::optional<FastMathFlags> FMF,
|
|
TTI::TargetCostKind CostKind) const {
|
|
InstructionCost Cost =
|
|
TTIImpl->getArithmeticReductionCost(Opcode, Ty, FMF, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getMinMaxReductionCost(
|
|
Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF,
|
|
TTI::TargetCostKind CostKind) const {
|
|
InstructionCost Cost =
|
|
TTIImpl->getMinMaxReductionCost(IID, Ty, FMF, CostKind);
|
|
assert(Cost >= 0 && "TTI should not produce negative costs!");
|
|
return Cost;
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getExtendedReductionCost(
|
|
unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *Ty,
|
|
FastMathFlags FMF, TTI::TargetCostKind CostKind) const {
|
|
return TTIImpl->getExtendedReductionCost(Opcode, IsUnsigned, ResTy, Ty, FMF,
|
|
CostKind);
|
|
}
|
|
|
|
InstructionCost TargetTransformInfo::getMulAccReductionCost(
|
|
bool IsUnsigned, Type *ResTy, VectorType *Ty,
|
|
TTI::TargetCostKind CostKind) const {
|
|
return TTIImpl->getMulAccReductionCost(IsUnsigned, ResTy, Ty, CostKind);
|
|
}
|
|
|
|
InstructionCost
|
|
TargetTransformInfo::getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const {
|
|
return TTIImpl->getCostOfKeepingLiveOverCall(Tys);
|
|
}
|
|
|
|
bool TargetTransformInfo::getTgtMemIntrinsic(IntrinsicInst *Inst,
|
|
MemIntrinsicInfo &Info) const {
|
|
return TTIImpl->getTgtMemIntrinsic(Inst, Info);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getAtomicMemIntrinsicMaxElementSize() const {
|
|
return TTIImpl->getAtomicMemIntrinsicMaxElementSize();
|
|
}
|
|
|
|
Value *TargetTransformInfo::getOrCreateResultFromMemIntrinsic(
|
|
IntrinsicInst *Inst, Type *ExpectedType) const {
|
|
return TTIImpl->getOrCreateResultFromMemIntrinsic(Inst, ExpectedType);
|
|
}
|
|
|
|
Type *TargetTransformInfo::getMemcpyLoopLoweringType(
|
|
LLVMContext &Context, Value *Length, unsigned SrcAddrSpace,
|
|
unsigned DestAddrSpace, Align SrcAlign, Align DestAlign,
|
|
std::optional<uint32_t> AtomicElementSize) const {
|
|
return TTIImpl->getMemcpyLoopLoweringType(Context, Length, SrcAddrSpace,
|
|
DestAddrSpace, SrcAlign, DestAlign,
|
|
AtomicElementSize);
|
|
}
|
|
|
|
void TargetTransformInfo::getMemcpyLoopResidualLoweringType(
|
|
SmallVectorImpl<Type *> &OpsOut, LLVMContext &Context,
|
|
unsigned RemainingBytes, unsigned SrcAddrSpace, unsigned DestAddrSpace,
|
|
Align SrcAlign, Align DestAlign,
|
|
std::optional<uint32_t> AtomicCpySize) const {
|
|
TTIImpl->getMemcpyLoopResidualLoweringType(
|
|
OpsOut, Context, RemainingBytes, SrcAddrSpace, DestAddrSpace, SrcAlign,
|
|
DestAlign, AtomicCpySize);
|
|
}
|
|
|
|
bool TargetTransformInfo::areInlineCompatible(const Function *Caller,
|
|
const Function *Callee) const {
|
|
return TTIImpl->areInlineCompatible(Caller, Callee);
|
|
}
|
|
|
|
unsigned
|
|
TargetTransformInfo::getInlineCallPenalty(const Function *F,
|
|
const CallBase &Call,
|
|
unsigned DefaultCallPenalty) const {
|
|
return TTIImpl->getInlineCallPenalty(F, Call, DefaultCallPenalty);
|
|
}
|
|
|
|
bool TargetTransformInfo::areTypesABICompatible(
|
|
const Function *Caller, const Function *Callee,
|
|
const ArrayRef<Type *> &Types) const {
|
|
return TTIImpl->areTypesABICompatible(Caller, Callee, Types);
|
|
}
|
|
|
|
bool TargetTransformInfo::isIndexedLoadLegal(MemIndexedMode Mode,
|
|
Type *Ty) const {
|
|
return TTIImpl->isIndexedLoadLegal(Mode, Ty);
|
|
}
|
|
|
|
bool TargetTransformInfo::isIndexedStoreLegal(MemIndexedMode Mode,
|
|
Type *Ty) const {
|
|
return TTIImpl->isIndexedStoreLegal(Mode, Ty);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getLoadStoreVecRegBitWidth(unsigned AS) const {
|
|
return TTIImpl->getLoadStoreVecRegBitWidth(AS);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalToVectorizeLoad(LoadInst *LI) const {
|
|
return TTIImpl->isLegalToVectorizeLoad(LI);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalToVectorizeStore(StoreInst *SI) const {
|
|
return TTIImpl->isLegalToVectorizeStore(SI);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalToVectorizeLoadChain(
|
|
unsigned ChainSizeInBytes, Align Alignment, unsigned AddrSpace) const {
|
|
return TTIImpl->isLegalToVectorizeLoadChain(ChainSizeInBytes, Alignment,
|
|
AddrSpace);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalToVectorizeStoreChain(
|
|
unsigned ChainSizeInBytes, Align Alignment, unsigned AddrSpace) const {
|
|
return TTIImpl->isLegalToVectorizeStoreChain(ChainSizeInBytes, Alignment,
|
|
AddrSpace);
|
|
}
|
|
|
|
bool TargetTransformInfo::isLegalToVectorizeReduction(
|
|
const RecurrenceDescriptor &RdxDesc, ElementCount VF) const {
|
|
return TTIImpl->isLegalToVectorizeReduction(RdxDesc, VF);
|
|
}
|
|
|
|
bool TargetTransformInfo::isElementTypeLegalForScalableVector(Type *Ty) const {
|
|
return TTIImpl->isElementTypeLegalForScalableVector(Ty);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getLoadVectorFactor(unsigned VF,
|
|
unsigned LoadSize,
|
|
unsigned ChainSizeInBytes,
|
|
VectorType *VecTy) const {
|
|
return TTIImpl->getLoadVectorFactor(VF, LoadSize, ChainSizeInBytes, VecTy);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getStoreVectorFactor(unsigned VF,
|
|
unsigned StoreSize,
|
|
unsigned ChainSizeInBytes,
|
|
VectorType *VecTy) const {
|
|
return TTIImpl->getStoreVectorFactor(VF, StoreSize, ChainSizeInBytes, VecTy);
|
|
}
|
|
|
|
bool TargetTransformInfo::preferFixedOverScalableIfEqualCost() const {
|
|
return TTIImpl->preferFixedOverScalableIfEqualCost();
|
|
}
|
|
|
|
bool TargetTransformInfo::preferInLoopReduction(unsigned Opcode,
|
|
Type *Ty) const {
|
|
return TTIImpl->preferInLoopReduction(Opcode, Ty);
|
|
}
|
|
|
|
bool TargetTransformInfo::preferAlternateOpcodeVectorization() const {
|
|
return TTIImpl->preferAlternateOpcodeVectorization();
|
|
}
|
|
|
|
bool TargetTransformInfo::preferPredicatedReductionSelect(unsigned Opcode,
|
|
Type *Ty) const {
|
|
return TTIImpl->preferPredicatedReductionSelect(Opcode, Ty);
|
|
}
|
|
|
|
bool TargetTransformInfo::preferEpilogueVectorization() const {
|
|
return TTIImpl->preferEpilogueVectorization();
|
|
}
|
|
|
|
TargetTransformInfo::VPLegalization
|
|
TargetTransformInfo::getVPLegalizationStrategy(const VPIntrinsic &VPI) const {
|
|
return TTIImpl->getVPLegalizationStrategy(VPI);
|
|
}
|
|
|
|
bool TargetTransformInfo::hasArmWideBranch(bool Thumb) const {
|
|
return TTIImpl->hasArmWideBranch(Thumb);
|
|
}
|
|
|
|
uint64_t TargetTransformInfo::getFeatureMask(const Function &F) const {
|
|
return TTIImpl->getFeatureMask(F);
|
|
}
|
|
|
|
bool TargetTransformInfo::isMultiversionedFunction(const Function &F) const {
|
|
return TTIImpl->isMultiversionedFunction(F);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getMaxNumArgs() const {
|
|
return TTIImpl->getMaxNumArgs();
|
|
}
|
|
|
|
bool TargetTransformInfo::shouldExpandReduction(const IntrinsicInst *II) const {
|
|
return TTIImpl->shouldExpandReduction(II);
|
|
}
|
|
|
|
TargetTransformInfo::ReductionShuffle
|
|
TargetTransformInfo::getPreferredExpandedReductionShuffle(
|
|
const IntrinsicInst *II) const {
|
|
return TTIImpl->getPreferredExpandedReductionShuffle(II);
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getGISelRematGlobalCost() const {
|
|
return TTIImpl->getGISelRematGlobalCost();
|
|
}
|
|
|
|
unsigned TargetTransformInfo::getMinTripCountTailFoldingThreshold() const {
|
|
return TTIImpl->getMinTripCountTailFoldingThreshold();
|
|
}
|
|
|
|
bool TargetTransformInfo::supportsScalableVectors() const {
|
|
return TTIImpl->supportsScalableVectors();
|
|
}
|
|
|
|
bool TargetTransformInfo::enableScalableVectorization() const {
|
|
return TTIImpl->enableScalableVectorization();
|
|
}
|
|
|
|
bool TargetTransformInfo::hasActiveVectorLength(unsigned Opcode, Type *DataType,
|
|
Align Alignment) const {
|
|
return TTIImpl->hasActiveVectorLength(Opcode, DataType, Alignment);
|
|
}
|
|
|
|
bool TargetTransformInfo::isProfitableToSinkOperands(
|
|
Instruction *I, SmallVectorImpl<Use *> &OpsToSink) const {
|
|
return TTIImpl->isProfitableToSinkOperands(I, OpsToSink);
|
|
}
|
|
|
|
bool TargetTransformInfo::isVectorShiftByScalarCheap(Type *Ty) const {
|
|
return TTIImpl->isVectorShiftByScalarCheap(Ty);
|
|
}
|
|
|
|
unsigned
|
|
TargetTransformInfo::getNumBytesToPadGlobalArray(unsigned Size,
|
|
Type *ArrayType) const {
|
|
return TTIImpl->getNumBytesToPadGlobalArray(Size, ArrayType);
|
|
}
|
|
|
|
void TargetTransformInfo::collectKernelLaunchBounds(
|
|
const Function &F,
|
|
SmallVectorImpl<std::pair<StringRef, int64_t>> &LB) const {
|
|
return TTIImpl->collectKernelLaunchBounds(F, LB);
|
|
}
|
|
|
|
TargetTransformInfo::Concept::~Concept() = default;
|
|
|
|
TargetIRAnalysis::TargetIRAnalysis() : TTICallback(&getDefaultTTI) {}
|
|
|
|
TargetIRAnalysis::TargetIRAnalysis(
|
|
std::function<Result(const Function &)> TTICallback)
|
|
: TTICallback(std::move(TTICallback)) {}
|
|
|
|
TargetIRAnalysis::Result TargetIRAnalysis::run(const Function &F,
|
|
FunctionAnalysisManager &) {
|
|
assert(!F.isIntrinsic() && "Should not request TTI for intrinsics");
|
|
return TTICallback(F);
|
|
}
|
|
|
|
AnalysisKey TargetIRAnalysis::Key;
|
|
|
|
TargetIRAnalysis::Result TargetIRAnalysis::getDefaultTTI(const Function &F) {
|
|
return Result(F.getDataLayout());
|
|
}
|
|
|
|
// Register the basic pass.
|
|
INITIALIZE_PASS(TargetTransformInfoWrapperPass, "tti",
|
|
"Target Transform Information", false, true)
|
|
char TargetTransformInfoWrapperPass::ID = 0;
|
|
|
|
void TargetTransformInfoWrapperPass::anchor() {}
|
|
|
|
TargetTransformInfoWrapperPass::TargetTransformInfoWrapperPass()
|
|
: ImmutablePass(ID) {
|
|
initializeTargetTransformInfoWrapperPassPass(
|
|
*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
TargetTransformInfoWrapperPass::TargetTransformInfoWrapperPass(
|
|
TargetIRAnalysis TIRA)
|
|
: ImmutablePass(ID), TIRA(std::move(TIRA)) {
|
|
initializeTargetTransformInfoWrapperPassPass(
|
|
*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
TargetTransformInfo &TargetTransformInfoWrapperPass::getTTI(const Function &F) {
|
|
FunctionAnalysisManager DummyFAM;
|
|
TTI = TIRA.run(F, DummyFAM);
|
|
return *TTI;
|
|
}
|
|
|
|
ImmutablePass *
|
|
llvm::createTargetTransformInfoWrapperPass(TargetIRAnalysis TIRA) {
|
|
return new TargetTransformInfoWrapperPass(std::move(TIRA));
|
|
}
|