Skip to content

Commit

Permalink
[Clang][LoongArch] Handle -march/-m{single,double,soft}-float/-mfpu o…
Browse files Browse the repository at this point in the history
…ptions

This patch adds options -march, -msingle-float, -mdouble-float,
-msoft-float and -mfpu for LoongArch.

Clang options `msingle_float` and `mdouble_float` are moved from
`m_mips_Features_Group` to `m_Group` because now more than targets use
them.

Reference:
https://github.com/loongson/LoongArch-Documentation/blob/main/docs/LoongArch-toolchain-conventions-EN.adoc

TODO: add -mtune.

Differential Revision: https://reviews.llvm.org/D136146
  • Loading branch information
SixWeining authored and gonglingqin committed Nov 10, 2022
1 parent 098e201 commit 135a927
Show file tree
Hide file tree
Showing 18 changed files with 403 additions and 21 deletions.
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Expand Up @@ -691,4 +691,7 @@ def warn_drv_sarif_format_unstable : Warning<

def err_drv_riscv_unsupported_with_linker_relaxation : Error<
"%0 is unsupported with RISC-V linker relaxation (-mrelax)">;

def err_drv_loongarch_invalid_mfpu_EQ : Error<
"invalid argument '%0' to -mfpu=; must be one of: 64, 32, 0, none">;
}
4 changes: 2 additions & 2 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -3910,8 +3910,8 @@ def mdsp : Flag<["-"], "mdsp">, Group<m_mips_Features_Group>;
def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_mips_Features_Group>;
def mdspr2 : Flag<["-"], "mdspr2">, Group<m_mips_Features_Group>;
def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group<m_mips_Features_Group>;
def msingle_float : Flag<["-"], "msingle-float">, Group<m_mips_Features_Group>;
def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_mips_Features_Group>;
def msingle_float : Flag<["-"], "msingle-float">, Group<m_Group>;
def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_Group>;
def mmadd4 : Flag<["-"], "mmadd4">, Group<m_mips_Features_Group>,
HelpText<"Enable the generation of 4-operand madd.s, madd.d and related instructions.">;
def mno_madd4 : Flag<["-"], "mno-madd4">, Group<m_mips_Features_Group>,
Expand Down
92 changes: 84 additions & 8 deletions clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
Expand Up @@ -7,33 +7,109 @@
//===----------------------------------------------------------------------===//

#include "LoongArch.h"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Support/LoongArchTargetParser.h"

using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;

StringRef loongarch::getLoongArchABI(const ArgList &Args,
StringRef loongarch::getLoongArchABI(const Driver &D, const ArgList &Args,
const llvm::Triple &Triple) {
assert((Triple.getArch() == llvm::Triple::loongarch32 ||
Triple.getArch() == llvm::Triple::loongarch64) &&
"Unexpected triple");
bool IsLA32 = Triple.getArch() == llvm::Triple::loongarch32;

// Check -m*-float firstly since they have highest priority.
if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
options::OPT_msingle_float,
options::OPT_msoft_float)) {
if (A->getOption().matches(options::OPT_mdouble_float))
return IsLA32 ? "ilp32d" : "lp64d";
if (A->getOption().matches(options::OPT_msingle_float))
return IsLA32 ? "ilp32f" : "lp64f";
if (A->getOption().matches(options::OPT_msoft_float))
return IsLA32 ? "ilp32s" : "lp64s";
}

// If `-mabi=` is specified, use it.
if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
return A->getValue();

// Select abi based on -mfpu=xx.
if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
StringRef FPU = A->getValue();
if (FPU == "64")
return IsLA32 ? "ilp32d" : "lp64d";
if (FPU == "32")
return IsLA32 ? "ilp32f" : "lp64f";
if (FPU == "0" || FPU == "none")
return IsLA32 ? "ilp32s" : "lp64s";
D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;
}

// Choose a default based on the triple.
// TODO: select appropiate ABI.
return Triple.getArch() == llvm::Triple::loongarch32 ? "ilp32d" : "lp64d";
return IsLA32 ? "ilp32d" : "lp64d";
}

void loongarch::getLoongArchTargetFeatures(const Driver &D,
const llvm::Triple &Triple,
const ArgList &Args,
std::vector<StringRef> &Features) {
// FIXME: hornor various clang options that may affect target features, e.g.
// -march/-mtune/-mdouble-float/-msingle-float/-msoft-float/-mfpu. See:
// https://loongson.github.io/LoongArch-Documentation/LoongArch-toolchain-conventions-EN.html
Features.push_back("+f");
Features.push_back("+d");
StringRef ArchName;
llvm::LoongArch::ArchKind ArchKind = llvm::LoongArch::ArchKind::AK_INVALID;
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
ArchKind = llvm::LoongArch::parseArch(A->getValue());
if (ArchKind == llvm::LoongArch::ArchKind::AK_INVALID) {
D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
return;
}
ArchName = A->getValue();
}

// TODO: handle -march=native and -mtune=xx.

// Select a default arch name.
if (ArchName.empty() && Triple.getArch() == llvm::Triple::loongarch64)
ArchName = "loongarch64";

if (!ArchName.empty())
llvm::LoongArch::getArchFeatures(ArchName, Features);

// Select floating-point features determined by -mdouble-float,
// -msingle-float, -msoft-float and -mfpu.
// Note: -m*-float wins any other options.
if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
options::OPT_msingle_float,
options::OPT_msoft_float)) {
if (A->getOption().matches(options::OPT_mdouble_float)) {
Features.push_back("+f");
Features.push_back("+d");
} else if (A->getOption().matches(options::OPT_msingle_float)) {
Features.push_back("+f");
Features.push_back("-d");
} else /*Soft-float*/ {
Features.push_back("-f");
Features.push_back("-d");
}
} else if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
StringRef FPU = A->getValue();
if (FPU == "64") {
Features.push_back("+f");
Features.push_back("+d");
} else if (FPU == "32") {
Features.push_back("+f");
Features.push_back("-d");
} else if (FPU == "0" || FPU == "none") {
Features.push_back("-f");
Features.push_back("-d");
} else {
D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;
}
}
}
5 changes: 4 additions & 1 deletion clang/lib/Driver/ToolChains/Arch/LoongArch.h
Expand Up @@ -17,7 +17,10 @@ namespace clang {
namespace driver {
namespace tools {
namespace loongarch {
StringRef getLoongArchABI(const llvm::opt::ArgList &Args,
void getLoongArchTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
StringRef getLoongArchABI(const Driver &D, const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);

void getLoongArchTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -1921,8 +1921,9 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
void Clang::AddLoongArchTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(
loongarch::getLoongArchABI(Args, getToolChain().getTriple()).data());
CmdArgs.push_back(loongarch::getLoongArchABI(getToolChain().getDriver(), Args,
getToolChain().getTriple())
.data());
}

void Clang::AddMIPSTargetArgs(const ArgList &Args,
Expand Down
14 changes: 8 additions & 6 deletions clang/lib/Driver/ToolChains/Linux.cpp
Expand Up @@ -469,16 +469,18 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
}
case llvm::Triple::loongarch32: {
LibDir = "lib32";
Loader = ("ld-linux-loongarch-" +
tools::loongarch::getLoongArchABI(Args, Triple) + ".so.1")
.str();
Loader =
("ld-linux-loongarch-" +
tools::loongarch::getLoongArchABI(getDriver(), Args, Triple) + ".so.1")
.str();
break;
}
case llvm::Triple::loongarch64: {
LibDir = "lib64";
Loader = ("ld-linux-loongarch-" +
tools::loongarch::getLoongArchABI(Args, Triple) + ".so.1")
.str();
Loader =
("ld-linux-loongarch-" +
tools::loongarch::getLoongArchABI(getDriver(), Args, Triple) + ".so.1")
.str();
break;
}
case llvm::Triple::m68k:
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Driver/loongarch-default-features.c
@@ -1,8 +1,8 @@
// RUN: %clang --target=loongarch32 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=LA32
// RUN: %clang --target=loongarch64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=LA64

// LA32: "target-features"="+d,+f"
// LA64: "target-features"="+d,+f"
// LA32-NOT: "target-features"=
// LA64: "target-features"="+64bit,+d,+f"

/// Dummy function
int foo(void) {
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Driver/loongarch-march-error.c
@@ -0,0 +1,7 @@
// RUN: not %clang --target=loongarch64 -march=loongarch -fsyntax-only %s 2>&1 \
// RUN: | FileCheck --check-prefix=LOONGARCH %s
// LOONGARCH: error: invalid arch name '-march=loongarch'

// RUN: not %clang --target=loongarch64 -march=LA464 -fsyntax-only %s 2>&1 \
// RUN: | FileCheck --check-prefix=LA464-UPPER %s
// LA464-UPPER: error: invalid arch name '-march=LA464'
32 changes: 32 additions & 0 deletions clang/test/Driver/loongarch-march.c
@@ -0,0 +1,32 @@
// RUN: %clang --target=loongarch64 -march=loongarch64 -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CC1-LOONGARCH64
// RUN: %clang --target=loongarch64 -march=la464 -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CC1-LA464
// RUN: %clang --target=loongarch64 -march=loongarch64 -S -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=IR-LOONGARCH64
// RUN: %clang --target=loongarch64 -march=la464 -S -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=IR-LA464

// CC1-LOONGARCH64-NOT: "-target-feature"
// CC1-LOONGARCH64: "-target-feature" "+64bit"
// CC1-LOONGARCH64-SAME: {{^}} "-target-feature" "+f"
// CC1-LOONGARCH64-SAME: {{^}} "-target-feature" "+d"
// CC1-LOONGARCH64-NOT: "-target-feature"
// CC1-LOONGARCH64: "-target-abi" "lp64d"

// CC1-LA464-NOT: "-target-feature"
// CC1-LA464: "-target-feature" "+64bit"
// CC1-LA464-SAME: {{^}} "-target-feature" "+f"
// CC1-LA464-SAME: {{^}} "-target-feature" "+d"
// CC1-LA464-SAME: {{^}} "-target-feature" "+lsx"
// CC1-LA464-SAME: {{^}} "-target-feature" "+lasx"
// CC1-LA464-NOT: "-target-feature"
// CC1-LA464: "-target-abi" "lp64d"

// IR-LOONGARCH64: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+d,+f"
// IR-LA464: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+d,+f,+lasx,+lsx"

/// Dummy function
int foo(void) {
return 3;
}
18 changes: 18 additions & 0 deletions clang/test/Driver/loongarch-mdouble-float.c
@@ -0,0 +1,18 @@
// RUN: %clang --target=loongarch64 -mdouble-float -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CC1
// RUN: %clang --target=loongarch64 -mdouble-float -S -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=IR

// CC1-NOT: "-target-feature"
// CC1: "-target-feature" "+64bit"
// CC1-SAME: {{^}} "-target-feature" "+f"
// CC1-SAME: {{^}} "-target-feature" "+d"
// CC1-NOT: "-target-feature"
// CC1: "-target-abi" "lp64d"

// IR: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+d,+f"

/// Dummy function
int foo(void) {
return 3;
}
4 changes: 4 additions & 0 deletions clang/test/Driver/loongarch-mfpu-error.c
@@ -0,0 +1,4 @@
// RUN: %clang --target=loongarch64 -mfpu=xxx -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s

// CHECK: invalid argument 'xxx' to -mfpu=; must be one of: 64, 32, 0, none
47 changes: 47 additions & 0 deletions clang/test/Driver/loongarch-mfpu.c
@@ -0,0 +1,47 @@
// RUN: %clang --target=loongarch64 -mfpu=64 -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CC1-FPU64
// RUN: %clang --target=loongarch64 -mfpu=32 -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CC1-FPU32
// RUN: %clang --target=loongarch64 -mfpu=0 -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CC1-FPU0
// RUN: %clang --target=loongarch64 -mfpu=none -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CC1-FPU0

// RUN: %clang --target=loongarch64 -mfpu=64 -S -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=IR-FPU64
// RUN: %clang --target=loongarch64 -mfpu=32 -S -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=IR-FPU32
// RUN: %clang --target=loongarch64 -mfpu=0 -S -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=IR-FPU0
// RUN: %clang --target=loongarch64 -mfpu=none -S -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=IR-FPU0

// CC1-FPU64-NOT: "-target-feature"
// CC1-FPU64: "-target-feature" "+64bit"
// CC1-FPU64-SAME: "-target-feature" "+f"
// CC1-FPU64-SAME: "-target-feature" "+d"
// CC1-FPU64-NOT: "-target-feature"
// CC1-FPU64: "-target-abi" "lp64d"

// CC1-FPU32-NOT: "-target-feature"
// CC1-FPU32: "-target-feature" "+64bit"
// CC1-FPU32-SAME: "-target-feature" "+f"
// CC1-FPU32-SAME: "-target-feature" "-d"
// CC1-FPU32-NOT: "-target-feature"
// CC1-FPU32: "-target-abi" "lp64f"

// CC1-FPU0-NOT: "-target-feature"
// CC1-FPU0: "-target-feature" "+64bit"
// CC1-FPU0-SAME: "-target-feature" "-f"
// CC1-FPU0-SAME: "-target-feature" "-d"
// CC1-FPU0-NOT: "-target-feature"
// CC1-FPU0: "-target-abi" "lp64s"

// IR-FPU64: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+d,+f"
// IR-FPU32: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+f,-d"
// IR-FPU0: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,-d,-f"

/// Dummy function
int foo(void) {
return 3;
}
18 changes: 18 additions & 0 deletions clang/test/Driver/loongarch-msingle-float.c
@@ -0,0 +1,18 @@
// RUN: %clang --target=loongarch64 -msingle-float -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CC1
// RUN: %clang --target=loongarch64 -msingle-float -S -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=IR

// CC1-NOT: "-target-feature"
// CC1: "-target-feature" "+64bit"
// CC1-SAME: {{^}} "-target-feature" "+f"
// CC1-SAME: {{^}} "-target-feature" "-d"
// CC1-NOT: "-target-feature"
// CC1: "-target-abi" "lp64f"

// IR: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+f,-d"

/// Dummy function
int foo(void) {
return 3;
}
18 changes: 18 additions & 0 deletions clang/test/Driver/loongarch-msoft-float.c
@@ -0,0 +1,18 @@
// RUN: %clang --target=loongarch64 -msoft-float -fsyntax-only %s -### 2>&1 \
// RUN: | FileCheck %s --check-prefix=CC1
// RUN: %clang --target=loongarch64 -msoft-float -S -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=IR

// CC1-NOT: "-target-feature"
// CC1: "-target-feature" "+64bit"
// CC1-SAME: {{^}} "-target-feature" "-f"
// CC1-SAME: {{^}} "-target-feature" "-d"
// CC1-NOT: "-target-feature"
// CC1: "-target-abi" "lp64s"

// IR: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,-d,-f"

/// Dummy function
int foo(void) {
return 3;
}
25 changes: 25 additions & 0 deletions llvm/include/llvm/Support/LoongArchTargetParser.def
@@ -0,0 +1,25 @@
#ifndef LOONGARCH_FEATURE
#define LOONGARCH_FEATURE(NAME, KIND)
#endif

LOONGARCH_FEATURE("invalid", FK_INVALID)
LOONGARCH_FEATURE("none", FK_NONE)
LOONGARCH_FEATURE("+64bit", FK_64BIT)
LOONGARCH_FEATURE("+f", FK_FP32)
LOONGARCH_FEATURE("+d", FK_FP64)
LOONGARCH_FEATURE("+lsx", FK_LSX)
LOONGARCH_FEATURE("+lasx", FK_LASX)
LOONGARCH_FEATURE("+lbt", FK_LBT)
LOONGARCH_FEATURE("+lvz", FK_LVZ)

#undef LOONGARCH_FEATURE

#ifndef LOONGARCH_ARCH
#define LOONGARCH_ARCH(NAME, KIND, FEATURES)
#endif

LOONGARCH_ARCH("invalid", AK_INVALID, FK_INVALID)
LOONGARCH_ARCH("loongarch64", AK_LOONGARCH64, FK_64BIT | FK_FP32 | FK_FP64)
LOONGARCH_ARCH("la464", AK_LA464, FK_64BIT | FK_FP32 | FK_FP64 | FK_LSX | FK_LASX)

#undef LOONGARCH_ARCH

0 comments on commit 135a927

Please sign in to comment.