110e730a2SDan Gohman //===-- WebAssemblyTargetTransformInfo.cpp - WebAssembly-specific TTI -----===//
210e730a2SDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
610e730a2SDan Gohman //
710e730a2SDan Gohman //===----------------------------------------------------------------------===//
810e730a2SDan Gohman ///
910e730a2SDan Gohman /// \file
105f8f34e4SAdrian Prantl /// This file defines the WebAssembly-specific TargetTransformInfo
1110e730a2SDan Gohman /// implementation.
1210e730a2SDan Gohman ///
1310e730a2SDan Gohman //===----------------------------------------------------------------------===//
1410e730a2SDan Gohman
1510e730a2SDan Gohman #include "WebAssemblyTargetTransformInfo.h"
16b3bde2eaSDavid Blaikie #include "llvm/CodeGen/CostTable.h"
1710e730a2SDan Gohman #include "llvm/Support/Debug.h"
1810e730a2SDan Gohman using namespace llvm;
1910e730a2SDan Gohman
2010e730a2SDan Gohman #define DEBUG_TYPE "wasmtti"
2110e730a2SDan Gohman
2210e730a2SDan Gohman TargetTransformInfo::PopcntSupportKind
getPopcntSupport(unsigned TyWidth) const2301612f62SDan Gohman WebAssemblyTTIImpl::getPopcntSupport(unsigned TyWidth) const {
2410e730a2SDan Gohman assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
2501612f62SDan Gohman return TargetTransformInfo::PSK_FastHardware;
2601612f62SDan Gohman }
2773d7a555SDan Gohman
getNumberOfRegisters(unsigned ClassID) const289802268aSZi Xuan Wu unsigned WebAssemblyTTIImpl::getNumberOfRegisters(unsigned ClassID) const {
299802268aSZi Xuan Wu unsigned Result = BaseT::getNumberOfRegisters(ClassID);
3073d7a555SDan Gohman
3173d7a555SDan Gohman // For SIMD, use at least 16 registers, as a rough guess.
329802268aSZi Xuan Wu bool Vector = (ClassID == 1);
3373d7a555SDan Gohman if (Vector)
3473d7a555SDan Gohman Result = std::max(Result, 16u);
3573d7a555SDan Gohman
3673d7a555SDan Gohman return Result;
3773d7a555SDan Gohman }
3873d7a555SDan Gohman
getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const3955d18b3cSSander de Smalen TypeSize WebAssemblyTTIImpl::getRegisterBitWidth(
4055d18b3cSSander de Smalen TargetTransformInfo::RegisterKind K) const {
4155d18b3cSSander de Smalen switch (K) {
4255d18b3cSSander de Smalen case TargetTransformInfo::RGK_Scalar:
4355d18b3cSSander de Smalen return TypeSize::getFixed(64);
4455d18b3cSSander de Smalen case TargetTransformInfo::RGK_FixedWidthVector:
4555d18b3cSSander de Smalen return TypeSize::getFixed(getST()->hasSIMD128() ? 128 : 64);
4655d18b3cSSander de Smalen case TargetTransformInfo::RGK_ScalableVector:
4755d18b3cSSander de Smalen return TypeSize::getScalable(0);
4855d18b3cSSander de Smalen }
4973d7a555SDan Gohman
5055d18b3cSSander de Smalen llvm_unreachable("Unsupported register kind");
5173d7a555SDan Gohman }
5273d7a555SDan Gohman
getArithmeticInstrCost(unsigned Opcode,Type * Ty,TTI::TargetCostKind CostKind,TTI::OperandValueKind Opd1Info,TTI::OperandValueKind Opd2Info,TTI::OperandValueProperties Opd1PropInfo,TTI::OperandValueProperties Opd2PropInfo,ArrayRef<const Value * > Args,const Instruction * CxtI)534f42d873SSander de Smalen InstructionCost WebAssemblyTTIImpl::getArithmeticInstrCost(
5440574fefSSam Parker unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
554f42d873SSander de Smalen TTI::OperandValueKind Opd1Info, TTI::OperandValueKind Opd2Info,
564f42d873SSander de Smalen TTI::OperandValueProperties Opd1PropInfo,
57be7a1070SDavid Green TTI::OperandValueProperties Opd2PropInfo, ArrayRef<const Value *> Args,
58be7a1070SDavid Green const Instruction *CxtI) {
5973d7a555SDan Gohman
604f42d873SSander de Smalen InstructionCost Cost =
614f42d873SSander de Smalen BasicTTIImplBase<WebAssemblyTTIImpl>::getArithmeticInstrCost(
6240574fefSSam Parker Opcode, Ty, CostKind, Opd1Info, Opd2Info, Opd1PropInfo, Opd2PropInfo);
6373d7a555SDan Gohman
6418c56a07SHeejin Ahn if (auto *VTy = dyn_cast<VectorType>(Ty)) {
6573d7a555SDan Gohman switch (Opcode) {
6673d7a555SDan Gohman case Instruction::LShr:
6773d7a555SDan Gohman case Instruction::AShr:
6873d7a555SDan Gohman case Instruction::Shl:
6973d7a555SDan Gohman // SIMD128's shifts currently only accept a scalar shift count. For each
7073d7a555SDan Gohman // element, we'll need to extract, op, insert. The following is a rough
7173d7a555SDan Gohman // approxmation.
7273d7a555SDan Gohman if (Opd2Info != TTI::OK_UniformValue &&
7373d7a555SDan Gohman Opd2Info != TTI::OK_UniformConstantValue)
745e2c7363SChristopher Tetreault Cost =
755e2c7363SChristopher Tetreault cast<FixedVectorType>(VTy)->getNumElements() *
7673d7a555SDan Gohman (TargetTransformInfo::TCC_Basic +
7740574fefSSam Parker getArithmeticInstrCost(Opcode, VTy->getElementType(), CostKind) +
7873d7a555SDan Gohman TargetTransformInfo::TCC_Basic);
7973d7a555SDan Gohman break;
8073d7a555SDan Gohman }
8173d7a555SDan Gohman }
8273d7a555SDan Gohman return Cost;
8373d7a555SDan Gohman }
8473d7a555SDan Gohman
getVectorInstrCost(unsigned Opcode,Type * Val,unsigned Index)851af35e77SSander de Smalen InstructionCost WebAssemblyTTIImpl::getVectorInstrCost(unsigned Opcode,
861af35e77SSander de Smalen Type *Val,
8773d7a555SDan Gohman unsigned Index) {
881af35e77SSander de Smalen InstructionCost Cost =
891af35e77SSander de Smalen BasicTTIImplBase::getVectorInstrCost(Opcode, Val, Index);
9073d7a555SDan Gohman
9173d7a555SDan Gohman // SIMD128's insert/extract currently only take constant indices.
9273d7a555SDan Gohman if (Index == -1u)
9373d7a555SDan Gohman return Cost + 25 * TargetTransformInfo::TCC_Expensive;
9473d7a555SDan Gohman
9573d7a555SDan Gohman return Cost;
9673d7a555SDan Gohman }
97d53d9528SThomas Lively
areInlineCompatible(const Function * Caller,const Function * Callee) const98d53d9528SThomas Lively bool WebAssemblyTTIImpl::areInlineCompatible(const Function *Caller,
99d53d9528SThomas Lively const Function *Callee) const {
100d53d9528SThomas Lively // Allow inlining only when the Callee has a subset of the Caller's
101d53d9528SThomas Lively // features. In principle, we should be able to inline regardless of any
102d53d9528SThomas Lively // features because WebAssembly supports features at module granularity, not
103d53d9528SThomas Lively // function granularity, but without this restriction it would be possible for
104d53d9528SThomas Lively // a module to "forget" about features if all the functions that used them
105d53d9528SThomas Lively // were inlined.
106d53d9528SThomas Lively const TargetMachine &TM = getTLI()->getTargetMachine();
107d53d9528SThomas Lively
108d53d9528SThomas Lively const FeatureBitset &CallerBits =
109d53d9528SThomas Lively TM.getSubtargetImpl(*Caller)->getFeatureBits();
110d53d9528SThomas Lively const FeatureBitset &CalleeBits =
111d53d9528SThomas Lively TM.getSubtargetImpl(*Callee)->getFeatureBits();
112d53d9528SThomas Lively
113d53d9528SThomas Lively return (CallerBits & CalleeBits) == CalleeBits;
114d53d9528SThomas Lively }
1159d81ccc0SSam Parker
getUnrollingPreferences(Loop * L,ScalarEvolution & SE,TTI::UnrollingPreferences & UP,OptimizationRemarkEmitter * ORE) const1169d81ccc0SSam Parker void WebAssemblyTTIImpl::getUnrollingPreferences(
1176f6e9a86SRoman Lebedev Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP,
1186f6e9a86SRoman Lebedev OptimizationRemarkEmitter *ORE) const {
1199d81ccc0SSam Parker // Scan the loop: don't unroll loops with calls. This is a standard approach
1209d81ccc0SSam Parker // for most (all?) targets.
1219d81ccc0SSam Parker for (BasicBlock *BB : L->blocks())
1229d81ccc0SSam Parker for (Instruction &I : *BB)
1239d81ccc0SSam Parker if (isa<CallInst>(I) || isa<InvokeInst>(I))
1249d81ccc0SSam Parker if (const Function *F = cast<CallBase>(I).getCalledFunction())
1259d81ccc0SSam Parker if (isLoweredToCall(F))
1269d81ccc0SSam Parker return;
1279d81ccc0SSam Parker
1289d81ccc0SSam Parker // The chosen threshold is within the range of 'LoopMicroOpBufferSize' of
1299d81ccc0SSam Parker // the various microarchitectures that use the BasicTTI implementation and
1309d81ccc0SSam Parker // has been selected through heuristics across multiple cores and runtimes.
1319d81ccc0SSam Parker UP.Partial = UP.Runtime = UP.UpperBound = true;
1329d81ccc0SSam Parker UP.PartialThreshold = 30;
1339d81ccc0SSam Parker
1349d81ccc0SSam Parker // Avoid unrolling when optimizing for size.
1359d81ccc0SSam Parker UP.OptSizeThreshold = 0;
1369d81ccc0SSam Parker UP.PartialOptSizeThreshold = 0;
1379d81ccc0SSam Parker
1389d81ccc0SSam Parker // Set number of instructions optimized when "back edge"
1399d81ccc0SSam Parker // becomes "fall through" to default value of 2.
1409d81ccc0SSam Parker UP.BEInsns = 2;
1419d81ccc0SSam Parker }
142*0b5ead65SChuanqi Xu
supportsTailCalls() const143*0b5ead65SChuanqi Xu bool WebAssemblyTTIImpl::supportsTailCalls() const {
144*0b5ead65SChuanqi Xu return getST()->hasTailCall();
145*0b5ead65SChuanqi Xu }
146