summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/NVPTX/NVPTXSubtarget.cpp
blob: 989be50d45554ec97c1deb26a41fe1ddee25773f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//===- NVPTXSubtarget.cpp - NVPTX Subtarget Information -------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the NVPTX specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "NVPTXSubtarget.h"
#include "NVPTXSelectionDAGInfo.h"
#include "NVPTXTargetMachine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"

using namespace llvm;

#define DEBUG_TYPE "nvptx-subtarget"

#define GET_SUBTARGETINFO_ENUM
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "NVPTXGenSubtargetInfo.inc"

static cl::opt<bool>
    NoF16Math("nvptx-no-f16-math", cl::Hidden,
              cl::desc("NVPTX Specific: Disable generation of f16 math ops."),
              cl::init(false));

static cl::opt<bool> NoF32x2("nvptx-no-f32x2", cl::Hidden,
                             cl::desc("NVPTX Specific: Disable generation of "
                                      "f32x2 instructions and registers."),
                             cl::init(false));

// Pin the vtable to this file.
void NVPTXSubtarget::anchor() {}

NVPTXSubtarget &NVPTXSubtarget::initializeSubtargetDependencies(StringRef CPU,
                                                                StringRef FS) {
  TargetName = std::string(CPU);

  ParseSubtargetFeatures(getTargetName(), /*TuneCPU=*/getTargetName(), FS);

  // Re-map SM version numbers, SmVersion carries the regular SMs which do
  // have relative order, while FullSmVersion allows distinguishing sm_90 from
  // sm_90a, which would *not* be a subset of sm_91.
  SmVersion = getSmVersion();

  // Set default to PTX 6.0 (CUDA 9.0)
  if (PTXVersion == 0) {
    PTXVersion = 60;
  }

  return *this;
}

NVPTXSubtarget::NVPTXSubtarget(const Triple &TT, const std::string &CPU,
                               const std::string &FS,
                               const NVPTXTargetMachine &TM)
    : NVPTXGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), PTXVersion(0),
      FullSmVersion(200), SmVersion(getSmVersion()),
      InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this) {
  TSInfo = std::make_unique<NVPTXSelectionDAGInfo>();
}

NVPTXSubtarget::~NVPTXSubtarget() = default;

const SelectionDAGTargetInfo *NVPTXSubtarget::getSelectionDAGInfo() const {
  return TSInfo.get();
}

bool NVPTXSubtarget::hasPTXWithFamilySMs(unsigned PTXVersion,
                                         ArrayRef<unsigned> SMVersions) const {
  unsigned PTXVer = getPTXVersion();
  if (!hasFamilySpecificFeatures() || PTXVer < PTXVersion)
    return false;

  unsigned SMVer = getSmVersion();
  return llvm::any_of(SMVersions, [&](unsigned SM) {
    // sm_101 is a different family, never group it with sm_10x.
    if (SMVer == 101 || SM == 101)
      return SMVer == SM &&
             // PTX 9.0 and later renamed sm_101 to sm_110, so sm_101 is not
             // supported.
             !(PTXVer >= 90 && SMVer == 101);

    return getSmFamilyVersion() == SM / 10 && SMVer >= SM;
  });
}

bool NVPTXSubtarget::hasPTXWithAccelSMs(unsigned PTXVersion,
                                        ArrayRef<unsigned> SMVersions) const {
  unsigned PTXVer = getPTXVersion();
  if (!hasArchAccelFeatures() || PTXVer < PTXVersion)
    return false;

  unsigned SMVer = getSmVersion();
  return llvm::any_of(SMVersions, [&](unsigned SM) {
    return SMVer == SM &&
           // PTX 9.0 and later renamed sm_101 to sm_110, so sm_101 is not
           // supported.
           !(PTXVer >= 90 && SMVer == 101);
  });
}

bool NVPTXSubtarget::allowFP16Math() const {
  return hasFP16Math() && NoF16Math == false;
}

bool NVPTXSubtarget::hasF32x2Instructions() const {
  return SmVersion >= 100 && PTXVersion >= 86 && !NoF32x2;
}

bool NVPTXSubtarget::hasNativeBF16Support(int Opcode) const {
  if (!hasBF16Math())
    return false;

  switch (Opcode) {
  // Several BF16 instructions are available on sm_90 only.
  case ISD::FADD:
  case ISD::FMUL:
  case ISD::FSUB:
  case ISD::SELECT:
  case ISD::SELECT_CC:
  case ISD::SETCC:
  case ISD::FEXP2:
  case ISD::FCEIL:
  case ISD::FFLOOR:
  case ISD::FNEARBYINT:
  case ISD::FRINT:
  case ISD::FROUNDEVEN:
  case ISD::FTRUNC:
    return getSmVersion() >= 90 && getPTXVersion() >= 78;
  // Several BF16 instructions are available on sm_80 only.
  case ISD::FMINNUM:
  case ISD::FMAXNUM:
  case ISD::FMAXNUM_IEEE:
  case ISD::FMINNUM_IEEE:
  case ISD::FMAXIMUM:
  case ISD::FMINIMUM:
    return getSmVersion() >= 80 && getPTXVersion() >= 70;
  }
  return true;
}

void NVPTXSubtarget::failIfClustersUnsupported(
    std::string const &FailureMessage) const {
  if (hasClusters())
    return;

  report_fatal_error(formatv(
      "NVPTX SM architecture \"{}\" and PTX version \"{}\" do not support {}. "
      "Requires SM >= 90 and PTX >= 78.",
      getFullSmVersion(), PTXVersion, FailureMessage));
}