WebAssemblyTargetTransformInfo.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //===-- WebAssemblyTargetTransformInfo.cpp - WebAssembly-specific TTI -----===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file
  10. /// This file defines the WebAssembly-specific TargetTransformInfo
  11. /// implementation.
  12. ///
  13. //===----------------------------------------------------------------------===//
  14. #include "WebAssemblyTargetTransformInfo.h"
  15. #include "llvm/CodeGen/CostTable.h"
  16. #include "llvm/Support/Debug.h"
  17. using namespace llvm;
  18. #define DEBUG_TYPE "wasmtti"
  19. TargetTransformInfo::PopcntSupportKind
  20. WebAssemblyTTIImpl::getPopcntSupport(unsigned TyWidth) const {
  21. assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
  22. return TargetTransformInfo::PSK_FastHardware;
  23. }
  24. unsigned WebAssemblyTTIImpl::getNumberOfRegisters(unsigned ClassID) const {
  25. unsigned Result = BaseT::getNumberOfRegisters(ClassID);
  26. // For SIMD, use at least 16 registers, as a rough guess.
  27. bool Vector = (ClassID == 1);
  28. if (Vector)
  29. Result = std::max(Result, 16u);
  30. return Result;
  31. }
  32. TypeSize WebAssemblyTTIImpl::getRegisterBitWidth(
  33. TargetTransformInfo::RegisterKind K) const {
  34. switch (K) {
  35. case TargetTransformInfo::RGK_Scalar:
  36. return TypeSize::getFixed(64);
  37. case TargetTransformInfo::RGK_FixedWidthVector:
  38. return TypeSize::getFixed(getST()->hasSIMD128() ? 128 : 64);
  39. case TargetTransformInfo::RGK_ScalableVector:
  40. return TypeSize::getScalable(0);
  41. }
  42. llvm_unreachable("Unsupported register kind");
  43. }
  44. InstructionCost WebAssemblyTTIImpl::getArithmeticInstrCost(
  45. unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
  46. TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info,
  47. ArrayRef<const Value *> Args,
  48. const Instruction *CxtI) {
  49. InstructionCost Cost =
  50. BasicTTIImplBase<WebAssemblyTTIImpl>::getArithmeticInstrCost(
  51. Opcode, Ty, CostKind, Op1Info, Op2Info);
  52. if (auto *VTy = dyn_cast<VectorType>(Ty)) {
  53. switch (Opcode) {
  54. case Instruction::LShr:
  55. case Instruction::AShr:
  56. case Instruction::Shl:
  57. // SIMD128's shifts currently only accept a scalar shift count. For each
  58. // element, we'll need to extract, op, insert. The following is a rough
  59. // approximation.
  60. if (!Op2Info.isUniform())
  61. Cost =
  62. cast<FixedVectorType>(VTy)->getNumElements() *
  63. (TargetTransformInfo::TCC_Basic +
  64. getArithmeticInstrCost(Opcode, VTy->getElementType(), CostKind) +
  65. TargetTransformInfo::TCC_Basic);
  66. break;
  67. }
  68. }
  69. return Cost;
  70. }
  71. InstructionCost
  72. WebAssemblyTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val,
  73. TTI::TargetCostKind CostKind,
  74. unsigned Index, Value *Op0, Value *Op1) {
  75. InstructionCost Cost = BasicTTIImplBase::getVectorInstrCost(
  76. Opcode, Val, CostKind, Index, Op0, Op1);
  77. // SIMD128's insert/extract currently only take constant indices.
  78. if (Index == -1u)
  79. return Cost + 25 * TargetTransformInfo::TCC_Expensive;
  80. return Cost;
  81. }
  82. bool WebAssemblyTTIImpl::areInlineCompatible(const Function *Caller,
  83. const Function *Callee) const {
  84. // Allow inlining only when the Callee has a subset of the Caller's
  85. // features. In principle, we should be able to inline regardless of any
  86. // features because WebAssembly supports features at module granularity, not
  87. // function granularity, but without this restriction it would be possible for
  88. // a module to "forget" about features if all the functions that used them
  89. // were inlined.
  90. const TargetMachine &TM = getTLI()->getTargetMachine();
  91. const FeatureBitset &CallerBits =
  92. TM.getSubtargetImpl(*Caller)->getFeatureBits();
  93. const FeatureBitset &CalleeBits =
  94. TM.getSubtargetImpl(*Callee)->getFeatureBits();
  95. return (CallerBits & CalleeBits) == CalleeBits;
  96. }
  97. void WebAssemblyTTIImpl::getUnrollingPreferences(
  98. Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP,
  99. OptimizationRemarkEmitter *ORE) const {
  100. // Scan the loop: don't unroll loops with calls. This is a standard approach
  101. // for most (all?) targets.
  102. for (BasicBlock *BB : L->blocks())
  103. for (Instruction &I : *BB)
  104. if (isa<CallInst>(I) || isa<InvokeInst>(I))
  105. if (const Function *F = cast<CallBase>(I).getCalledFunction())
  106. if (isLoweredToCall(F))
  107. return;
  108. // The chosen threshold is within the range of 'LoopMicroOpBufferSize' of
  109. // the various microarchitectures that use the BasicTTI implementation and
  110. // has been selected through heuristics across multiple cores and runtimes.
  111. UP.Partial = UP.Runtime = UP.UpperBound = true;
  112. UP.PartialThreshold = 30;
  113. // Avoid unrolling when optimizing for size.
  114. UP.OptSizeThreshold = 0;
  115. UP.PartialOptSizeThreshold = 0;
  116. // Set number of instructions optimized when "back edge"
  117. // becomes "fall through" to default value of 2.
  118. UP.BEInsns = 2;
  119. }
  120. bool WebAssemblyTTIImpl::supportsTailCalls() const {
  121. return getST()->hasTailCall();
  122. }