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