diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -374,25 +374,9 @@ ve::getVETargetFeatures(D, Args, Features); } - // Find the last of each feature. - llvm::StringMap LastOpt; - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - StringRef Name = Features[I]; - assert(Name[0] == '-' || Name[0] == '+'); - LastOpt[Name.drop_front(1)] = I; - } - - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - // If this feature was overridden, ignore it. - StringRef Name = Features[I]; - llvm::StringMap::iterator LastI = LastOpt.find(Name.drop_front(1)); - assert(LastI != LastOpt.end()); - unsigned Last = LastI->second; - if (Last != I) - continue; - + for (auto Feature : unifyTargetFeatures(Features)) { CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature"); - CmdArgs.push_back(Name.data()); + CmdArgs.push_back(Feature.data()); } } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -106,10 +106,20 @@ std::string getCPUName(const llvm::opt::ArgList &Args, const llvm::Triple &T, bool FromAs = false); +/// Iterate \p Args and convert -mxxx to +xxx and -mno-xxx to -xxx and +/// append it to \p Features. +/// +/// Note: Since \p Features may contain default values before calling +/// this function, or may be appended with entries to override arguments, +/// entries in \p Features are not unique. void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args, std::vector &Features, llvm::opt::OptSpecifier Group); +/// If there are multiple +xxx or -xxx features, keep the last one. +std::vector +unifyTargetFeatures(const std::vector &Features); + /// Handles the -save-stats option and returns the filename to save statistics /// to. SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -84,6 +84,31 @@ } } +std::vector +tools::unifyTargetFeatures(const std::vector &Features) { + std::vector UnifiedFeatures; + // Find the last of each feature. + llvm::StringMap LastOpt; + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + StringRef Name = Features[I]; + assert(Name[0] == '-' || Name[0] == '+'); + LastOpt[Name.drop_front(1)] = I; + } + + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + // If this feature was overridden, ignore it. + StringRef Name = Features[I]; + llvm::StringMap::iterator LastI = LastOpt.find(Name.drop_front(1)); + assert(LastI != LastOpt.end()); + unsigned Last = LastI->second; + if (Last != I) + continue; + + UnifiedFeatures.push_back(Name); + } + return UnifiedFeatures; +} + void tools::addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs, const char *ArgName, const char *EnvVar) { const char *DirList = ::getenv(EnvVar); diff --git a/clang/test/Driver/hip-toolchain-features.hip b/clang/test/Driver/hip-toolchain-features.hip --- a/clang/test/Driver/hip-toolchain-features.hip +++ b/clang/test/Driver/hip-toolchain-features.hip @@ -35,3 +35,13 @@ // ALL3: {{.*}}clang{{.*}}"-target-feature" "+xnack" "-target-feature" "+sram-ecc" // NOALL3: {{.*}}clang{{.*}}"-target-feature" "-xnack" "-target-feature" "-sram-ecc" + +// RUN: %clang -### -target x86_64-linux-gnu -fgpu-rdc -nogpulib \ +// RUN: --cuda-gpu-arch=gfx1010 %s \ +// RUN: -mcumode -mcumode -mno-cumode -mwavefrontsize64 -mcumode \ +// RUN: -mwavefrontsize64 -mno-wavefrontsize64 2>&1 \ +// RUN: | FileCheck %s -check-prefix=DUP +// DUP: {{.*}}clang{{.*}} "-target-feature" "-wavefrontsize16" +// DUP-SAME: "-target-feature" "+wavefrontsize32" +// DUP-SAME: "-target-feature" "-wavefrontsize64" +// DUP-SAME: "-target-feature" "+cumode"