Skip to content

Commit

Permalink
[CUDA] Add utility functions for dealing with CUDA versions / archite…
Browse files Browse the repository at this point in the history
…ctures.

Summary:
Currently our handling of CUDA architectures is scattered all around
clang.  This patch centralizes it.

A key advantage of this centralization is that you can now write a C++
switch on e.g. CudaArch and get a compile error if you don't handle one
of the enum values.

Reviewers: tra

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D21867

llvm-svn: 274681
  • Loading branch information
Justin Lebar committed Jul 6, 2016
1 parent ef1aaac commit 6290761
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 110 deletions.
77 changes: 77 additions & 0 deletions clang/include/clang/Basic/Cuda.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//===--- Cuda.h - Utilities for compiling CUDA code ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_CUDA_H
#define LLVM_CLANG_BASIC_CUDA_H

namespace llvm {
class StringRef;
} // namespace llvm

namespace clang {

enum class CudaVersion {
UNKNOWN,
CUDA_70,
CUDA_75,
CUDA_80,
};
const char *CudaVersionToString(CudaVersion V);

// No string -> CudaVersion conversion function because there's no canonical
// spelling of the various CUDA versions.

enum class CudaArch {
UNKNOWN,
SM_20,
SM_21,
SM_30,
SM_32,
SM_35,
SM_37,
SM_50,
SM_52,
SM_53,
SM_60,
SM_61,
SM_62,
};
const char *CudaArchToString(CudaArch A);

// The input should have the form "sm_20".
CudaArch StringToCudaArch(llvm::StringRef S);

enum class CudaVirtualArch {
UNKNOWN,
COMPUTE_20,
COMPUTE_30,
COMPUTE_32,
COMPUTE_35,
COMPUTE_37,
COMPUTE_50,
COMPUTE_52,
COMPUTE_53,
COMPUTE_60,
COMPUTE_61,
COMPUTE_62,
};
const char *CudaVirtualArchToString(CudaVirtualArch A);

// The input should have the form "compute_20".
CudaVirtualArch StringToCudaVirtualArch(llvm::StringRef S);

/// Get the compute_xx corresponding to an sm_yy.
CudaVirtualArch VirtualArchForCudaArch(CudaArch A);

/// Get the earliest CudaVersion that supports the given CudaArch.
CudaVersion MinVersionForCudaArch(CudaArch A);

} // namespace clang

#endif
19 changes: 8 additions & 11 deletions clang/include/clang/Driver/Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_DRIVER_ACTION_H
#define LLVM_CLANG_DRIVER_ACTION_H

#include "clang/Basic/Cuda.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -157,26 +158,22 @@ class BindArchAction : public Action {

class CudaDeviceAction : public Action {
virtual void anchor();
/// GPU architecture to bind. Always of the form /sm_\d+/ or null (when the
/// action applies to multiple architectures).
const char *GpuArchName;

const CudaArch GpuArch;

/// True when action results are not consumed by the host action (e.g when
/// -fsyntax-only or --cuda-device-only options are used).
bool AtTopLevel;

public:
CudaDeviceAction(Action *Input, const char *ArchName, bool AtTopLevel);
CudaDeviceAction(Action *Input, CudaArch Arch, bool AtTopLevel);

const char *getGpuArchName() const { return GpuArchName; }

/// Gets the compute_XX that corresponds to getGpuArchName(). Returns null
/// when getGpuArchName() is null.
const char *getComputeArchName() const;
/// Get the CUDA GPU architecture to which this Action corresponds. Returns
/// UNKNOWN if this Action corresponds to multiple architectures.
CudaArch getGpuArch() const { return GpuArch; }

bool isAtTopLevel() const { return AtTopLevel; }

static bool IsValidGpuArchName(llvm::StringRef ArchName);

static bool classof(const Action *A) {
return A->getKind() == CudaDeviceClass;
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ add_clang_library(clangBasic
Attributes.cpp
Builtins.cpp
CharInfo.cpp
Cuda.cpp
Diagnostic.cpp
DiagnosticIDs.cpp
DiagnosticOptions.cpp
Expand Down
165 changes: 165 additions & 0 deletions clang/lib/Basic/Cuda.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include "clang/Basic/Cuda.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"

namespace clang {

const char *CudaVersionToString(CudaVersion V) {
switch (V) {
case CudaVersion::UNKNOWN:
return "unknown";
case CudaVersion::CUDA_70:
return "7.0";
case CudaVersion::CUDA_75:
return "7.5";
case CudaVersion::CUDA_80:
return "8.0";
}
}

const char *CudaArchToString(CudaArch A) {
switch (A) {
case CudaArch::UNKNOWN:
return "unknown";
case CudaArch::SM_20:
return "sm_20";
case CudaArch::SM_21:
return "sm_21";
case CudaArch::SM_30:
return "sm_30";
case CudaArch::SM_32:
return "sm_32";
case CudaArch::SM_35:
return "sm_35";
case CudaArch::SM_37:
return "sm_37";
case CudaArch::SM_50:
return "sm_50";
case CudaArch::SM_52:
return "sm_52";
case CudaArch::SM_53:
return "sm_53";
case CudaArch::SM_60:
return "sm_60";
case CudaArch::SM_61:
return "sm_61";
case CudaArch::SM_62:
return "sm_62";
}
}

CudaArch StringToCudaArch(llvm::StringRef S) {
return llvm::StringSwitch<CudaArch>(S)
.Case("sm_20", CudaArch::SM_20)
.Case("sm_21", CudaArch::SM_21)
.Case("sm_30", CudaArch::SM_30)
.Case("sm_32", CudaArch::SM_32)
.Case("sm_35", CudaArch::SM_35)
.Case("sm_37", CudaArch::SM_37)
.Case("sm_50", CudaArch::SM_50)
.Case("sm_52", CudaArch::SM_52)
.Case("sm_53", CudaArch::SM_53)
.Case("sm_60", CudaArch::SM_60)
.Case("sm_61", CudaArch::SM_61)
.Case("sm_62", CudaArch::SM_62)
.Default(CudaArch::UNKNOWN);
}

const char *CudaVirtualArchToString(CudaVirtualArch A) {
switch (A) {
case CudaVirtualArch::UNKNOWN:
return "unknown";
case CudaVirtualArch::COMPUTE_20:
return "compute_20";
case CudaVirtualArch::COMPUTE_30:
return "compute_30";
case CudaVirtualArch::COMPUTE_32:
return "compute_32";
case CudaVirtualArch::COMPUTE_35:
return "compute_35";
case CudaVirtualArch::COMPUTE_37:
return "compute_37";
case CudaVirtualArch::COMPUTE_50:
return "compute_50";
case CudaVirtualArch::COMPUTE_52:
return "compute_52";
case CudaVirtualArch::COMPUTE_53:
return "compute_53";
case CudaVirtualArch::COMPUTE_60:
return "compute_60";
case CudaVirtualArch::COMPUTE_61:
return "compute_61";
case CudaVirtualArch::COMPUTE_62:
return "compute_62";
}
}

CudaVirtualArch StringToCudaVirtualArch(llvm::StringRef S) {
return llvm::StringSwitch<CudaVirtualArch>(S)
.Case("compute_20", CudaVirtualArch::COMPUTE_20)
.Case("compute_30", CudaVirtualArch::COMPUTE_30)
.Case("compute_32", CudaVirtualArch::COMPUTE_32)
.Case("compute_35", CudaVirtualArch::COMPUTE_35)
.Case("compute_37", CudaVirtualArch::COMPUTE_37)
.Case("compute_50", CudaVirtualArch::COMPUTE_50)
.Case("compute_52", CudaVirtualArch::COMPUTE_52)
.Case("compute_53", CudaVirtualArch::COMPUTE_53)
.Case("compute_60", CudaVirtualArch::COMPUTE_60)
.Case("compute_61", CudaVirtualArch::COMPUTE_61)
.Case("compute_62", CudaVirtualArch::COMPUTE_62)
.Default(CudaVirtualArch::UNKNOWN);
}

CudaVirtualArch VirtualArchForCudaArch(CudaArch A) {
switch (A) {
case CudaArch::UNKNOWN:
return CudaVirtualArch::UNKNOWN;
case CudaArch::SM_20:
case CudaArch::SM_21:
return CudaVirtualArch::COMPUTE_20;
case CudaArch::SM_30:
return CudaVirtualArch::COMPUTE_30;
case CudaArch::SM_32:
return CudaVirtualArch::COMPUTE_32;
case CudaArch::SM_35:
return CudaVirtualArch::COMPUTE_35;
case CudaArch::SM_37:
return CudaVirtualArch::COMPUTE_37;
case CudaArch::SM_50:
return CudaVirtualArch::COMPUTE_50;
case CudaArch::SM_52:
return CudaVirtualArch::COMPUTE_52;
case CudaArch::SM_53:
return CudaVirtualArch::COMPUTE_53;
case CudaArch::SM_60:
return CudaVirtualArch::COMPUTE_60;
case CudaArch::SM_61:
return CudaVirtualArch::COMPUTE_61;
case CudaArch::SM_62:
return CudaVirtualArch::COMPUTE_62;
}
}

CudaVersion MinVersionForCudaArch(CudaArch A) {
switch (A) {
case CudaArch::UNKNOWN:
return CudaVersion::UNKNOWN;
case CudaArch::SM_20:
case CudaArch::SM_21:
case CudaArch::SM_30:
case CudaArch::SM_32:
case CudaArch::SM_35:
case CudaArch::SM_37:
case CudaArch::SM_50:
case CudaArch::SM_52:
case CudaArch::SM_53:
return CudaVersion::CUDA_70;
case CudaArch::SM_60:
case CudaArch::SM_61:
case CudaArch::SM_62:
return CudaVersion::CUDA_80;
}
}

} // namespace clang

0 comments on commit 6290761

Please sign in to comment.