diff options
-rw-r--r-- | llvm/lib/Target/NVPTX/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Target/NVPTX/NVPTX.h | 1 | ||||
-rw-r--r-- | llvm/lib/Target/NVPTX/NVPTXAssignValidGlobalNames.cpp | 84 | ||||
-rw-r--r-- | llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp | 3 | ||||
-rw-r--r-- | llvm/test/CodeGen/NVPTX/symbol-naming.ll | 27 |
5 files changed, 114 insertions, 2 deletions
diff --git a/llvm/lib/Target/NVPTX/CMakeLists.txt b/llvm/lib/Target/NVPTX/CMakeLists.txt index 20612b3ff5c..029118acf24 100644 --- a/llvm/lib/Target/NVPTX/CMakeLists.txt +++ b/llvm/lib/Target/NVPTX/CMakeLists.txt @@ -23,6 +23,7 @@ set(NVPTXCodeGen_sources NVPTXUtilities.cpp NVVMReflect.cpp NVPTXGenericToNVVM.cpp + NVPTXAssignValidGlobalNames.cpp NVPTXPrologEpilogPass.cpp NVPTXMCExpr.cpp ) diff --git a/llvm/lib/Target/NVPTX/NVPTX.h b/llvm/lib/Target/NVPTX/NVPTX.h index 490b49d9ead..8cbdd47b47e 100644 --- a/llvm/lib/Target/NVPTX/NVPTX.h +++ b/llvm/lib/Target/NVPTX/NVPTX.h @@ -61,6 +61,7 @@ inline static const char *NVPTXCondCodeToString(NVPTXCC::CondCodes CC) { FunctionPass * createNVPTXISelDag(NVPTXTargetMachine &TM, llvm::CodeGenOpt::Level OptLevel); +ModulePass *createNVPTXAssignValidGlobalNamesPass(); ModulePass *createGenericToNVVMPass(); ModulePass *createNVVMReflectPass(); ModulePass *createNVVMReflectPass(const StringMap<int>& Mapping); diff --git a/llvm/lib/Target/NVPTX/NVPTXAssignValidGlobalNames.cpp b/llvm/lib/Target/NVPTX/NVPTXAssignValidGlobalNames.cpp new file mode 100644 index 00000000000..158c4824682 --- /dev/null +++ b/llvm/lib/Target/NVPTX/NVPTXAssignValidGlobalNames.cpp @@ -0,0 +1,84 @@ +//===-- NVPTXAssignValidGlobalNames.cpp - Assign valid names to globals ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Clean up the names of global variables in the module to not contain symbols +// that are invalid in PTX. +// +// Currently NVPTX, like other backends, relies on generic symbol name +// sanitizing done by MC. However, the ptxas assembler is more stringent and +// disallows some additional characters in symbol names. This pass makes sure +// such names do not reach MC at all. +// +//===----------------------------------------------------------------------===// + +#include "NVPTX.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/raw_ostream.h" +#include <string> + +using namespace llvm; + +namespace { +/// \brief NVPTXAssignValidGlobalNames +class NVPTXAssignValidGlobalNames : public ModulePass { +public: + static char ID; + NVPTXAssignValidGlobalNames() : ModulePass(ID) {} + + virtual bool runOnModule(Module &M); + + /// \brief Clean up the name to remove symbols invalid in PTX. + std::string cleanUpName(StringRef Name); +}; +} + +char NVPTXAssignValidGlobalNames::ID = 0; + +namespace llvm { +void initializeNVPTXAssignValidGlobalNamesPass(PassRegistry &); +} + +INITIALIZE_PASS(NVPTXAssignValidGlobalNames, "nvptx-assign-valid-global-names", + "Assign valid PTX names to globals", false, false) + +bool NVPTXAssignValidGlobalNames::runOnModule(Module &M) { + for (GlobalVariable &GV : M.globals()) { + // We are only allowed to rename local symbols. + if (GV.hasLocalLinkage()) { + // setName doesn't do extra work if the name does not change. + // Note: this does not create collisions - if setName is asked to set the + // name to something that already exists, it adds a proper postfix to + // avoid collisions. + GV.setName(cleanUpName(GV.getName())); + } + } + + return true; +} + +std::string NVPTXAssignValidGlobalNames::cleanUpName(StringRef Name) { + std::string ValidName; + raw_string_ostream ValidNameStream(ValidName); + for (unsigned I = 0, E = Name.size(); I != E; ++I) { + char C = Name[I]; + if (C == '.' || C == '@') { + ValidNameStream << "_$_"; + } else { + ValidNameStream << C; + } + } + + return ValidNameStream.str(); +} + +ModulePass *llvm::createNVPTXAssignValidGlobalNamesPass() { + return new NVPTXAssignValidGlobalNames(); +} diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp index c0009fa9432..7d7d79314c6 100644 --- a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp @@ -49,6 +49,7 @@ using namespace llvm; namespace llvm { void initializeNVVMReflectPass(PassRegistry&); void initializeGenericToNVVMPass(PassRegistry&); +void initializeNVPTXAssignValidGlobalNamesPass(PassRegistry&); } extern "C" void LLVMInitializeNVPTXTarget() { @@ -60,6 +61,7 @@ extern "C" void LLVMInitializeNVPTXTarget() { // but it's very NVPTX-specific. initializeNVVMReflectPass(*PassRegistry::getPassRegistry()); initializeGenericToNVVMPass(*PassRegistry::getPassRegistry()); + initializeNVPTXAssignValidGlobalNamesPass(*PassRegistry::getPassRegistry()); } static std::string computeDataLayout(const NVPTXSubtarget &ST) { @@ -139,6 +141,7 @@ void NVPTXPassConfig::addIRPasses() { disablePass(&TailDuplicateID); TargetPassConfig::addIRPasses(); + addPass(createNVPTXAssignValidGlobalNamesPass()); addPass(createGenericToNVVMPass()); } diff --git a/llvm/test/CodeGen/NVPTX/symbol-naming.ll b/llvm/test/CodeGen/NVPTX/symbol-naming.ll index b7f1cfdc5b8..bd1333f1c4e 100644 --- a/llvm/test/CodeGen/NVPTX/symbol-naming.ll +++ b/llvm/test/CodeGen/NVPTX/symbol-naming.ll @@ -1,8 +1,31 @@ ; RUN: llc < %s -march=nvptx -mcpu=sm_20 | FileCheck %s --check-prefix=PTX32 ; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 | FileCheck %s --check-prefix=PTX64 -@.str = private unnamed_addr constant [6 x i8] c"%d %f\00", align 1 -@.str.again = private unnamed_addr constant [6 x i8] c"%d %f\00", align 1 +; Verify that the NVPTX target removes invalid symbol names prior to emitting +; PTX. ; PTX32-NOT: .str ; PTX64-NOT: .str + +; PTX32-DAG: _$_str1 +; PTX32-DAG: _$_str + +; PTX64-DAG: _$_str1 +; PTX64-DAG: _$_str + +target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64" +target triple = "nvptx64-unknown-unknown" + + +@.str = private unnamed_addr constant [13 x i8] c"%d %f %c %d\0A\00", align 1 +@_$_str = private unnamed_addr constant [13 x i8] c"%d %f %c %d\0A\00", align 1 + + +; Function Attrs: nounwind +define void @foo(i32 %a, float %b, i8 signext %c, i32 %e) { +entry: + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0)) + ret void +} + +declare i32 @printf(i8*, ...) |