Skip to content

Commit

Permalink
[LLVM/RISCV] Add +nofdiv target attribute to RISCV
Browse files Browse the repository at this point in the history
  • Loading branch information
nazavode authored and mbertuletti committed Jan 16, 2024
1 parent 28ce07c commit 01c5980
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 1 deletion.
2 changes: 2 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3314,6 +3314,8 @@ def mcmodel_EQ_medany : Flag<["-"], "mcmodel=medany">, Group<m_riscv_Features_Gr
HelpText<"Equivalent to -mcmodel=medium, compatible with RISC-V gcc.">;
def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group<m_Group>,
HelpText<"Enable use of experimental RISC-V extensions.">;
def mno_fdiv : Flag<["-"], "mno-fdiv">, Group<m_riscv_Features_Group>,
HelpText<"Don't use hardware floating-point divide and square root instructions (RISC-V only)">;

def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Basic/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,

if (FLen) {
Builder.defineMacro("__riscv_flen", Twine(FLen));
}

if (FLen && !HasNoFdiv) {
Builder.defineMacro("__riscv_fdiv");
Builder.defineMacro("__riscv_fsqrt");
}
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ namespace targets {

// RISC-V Target
class RISCVTargetInfo : public TargetInfo {
// Initialized via features.
unsigned HasNoFdiv : 1;

protected:
std::string ABI, CPU;
std::unique_ptr<llvm::RISCVISAInfo> ISAInfo;
static const Builtin::Info BuiltinInfo[];

public:
RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions & Opts)
: TargetInfo(Triple) {
LongDoubleWidth = 128;
LongDoubleAlign = 128;
Expand All @@ -42,6 +45,7 @@ class RISCVTargetInfo : public TargetInfo {
MCountName = "_mcount";
HasFloat16 = true;
HasBuiltinHeroDevVaList = true;
HasNoFdiv = llvm::is_contained(Opts.FeaturesAsWritten, "+nofdiv");
}

bool setCPU(const std::string &Name) override {
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,21 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);

// GCC Compatibility: -mno-fdiv
if (Args.hasArg(options::OPT_mno_fdiv)) {
// Args is const, and we can't prevent handleTargetFeaturesGroup to
// mess up with our own awkwardly spelled "-mno-fdiv" that gets
// interpreted as "negate fdiv feature", with a "-fdiv" being passed
// down.
Features.erase(std::remove_if(Features.begin(), Features.end(),
[](StringRef feat) {
return feat.equals("+fdiv") ||
feat.equals("-fdiv");
}),
Features.end());
Features.push_back("+nofdiv");
}
}

StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
Expand Down
48 changes: 48 additions & 0 deletions clang/test/Driver/riscv-arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,51 @@
// RUN: %clang -target riscv32-unknown-elf -march=rv32iv1p0_zvl32b1p0 -### %s -c 2>&1 | \
// RUN: FileCheck -check-prefix=RV32-ZVL-GOODVERS %s
// RV32-ZVL-GOODVERS: "-target-feature" "+zvl32b"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izbkc1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZBKC %s
// RV32-ZBKC: "-target-feature" "+zbkc"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izbkx1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZBKX %s
// RV32-ZBKX: "-target-feature" "+zbkx"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izbkb1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZBKB %s
// RV32-ZBKB: "-target-feature" "+zbkb"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izknd1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZKND %s
// RV32-ZKND: "-target-feature" "+zknd"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izkne1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZKNE %s
// RV32-ZKNE: "-target-feature" "+zkne"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izknh1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZKNH %s
// RV32-ZKNH: "-target-feature" "+zknh"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izksed1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZKSED %s
// RV32-ZKSED: "-target-feature" "+zksed"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izksh1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZKSH %s
// RV32-ZKSH: "-target-feature" "+zksh"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izkr1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZKR %s
// RV32-ZKR: "-target-feature" "+zkr"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izkt1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZKT %s
// RV32-ZKT: "-target-feature" "+zkt"

// RUN: %clang -target riscv32-unknown-elf -march=rv32izk1p0 -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZK %s
// RV32-ZK: "-target-feature" "+zk"

// RUN: %clang -target riscv32-unknown-elf -march=rv32imaf -mno-fdiv -### %s \
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-NOFDIV %s
// RV32-NOFDIV: "-target-feature" "+nofdiv"
11 changes: 11 additions & 0 deletions clang/test/Preprocessor/riscv-nofdiv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32if -mno-fdiv -x c -E -dM %s \
// RUN: -o - | FileCheck %s
// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64if -mno-fdiv -x c -E -dM %s \
// RUN: -o - | FileCheck %s
// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ifd -mno-fdiv -x c -E -dM %s \
// RUN: -o - | FileCheck %s
// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ifd -mno-fdiv -x c -E -dM %s \
// RUN: -o - | FileCheck %s

// CHECK-NOT: __riscv_fdiv
// CHECK-NOT: __riscv_fsqrt
8 changes: 8 additions & 0 deletions llvm/lib/Target/RISCV/RISCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,14 @@ def HasExtXmempool : Predicate<"Subtarget->hasExtXmempool()">,
AssemblerPredicate<(all_of FeatureExtXmempool),
"'Xmempool' (MemPool System)">;

def FeatureHasNoFdiv
: SubtargetFeature<"nofdiv", "HasNoFdiv", "true",
"Disable fdiv.* and fsqrt.* instructions, delegate to libcalls",
[FeatureStdExtF]>;
def HasNoFdiv : Predicate<"Subtarget->hasNoFdiv()">,
AssemblerPredicate<(all_of FeatureHasNoFdiv),
"Disable fdiv.* and fsqrt.* instructions, delegate to libcalls">;


//===----------------------------------------------------------------------===//
// Named operands for CSR instructions.
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,21 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom);
}

if (Subtarget.hasNoFdiv()) {
assert(Subtarget.hasStdExtF() && "+nofdiv implies +f");
setOperationAction(ISD::FDIV, MVT::f32, LibCall);
setOperationAction(ISD::STRICT_FDIV, MVT::f32, LibCall);
setOperationAction(ISD::FSQRT, MVT::f32, LibCall);
setOperationAction(ISD::STRICT_FSQRT, MVT::f32, LibCall);
}

if (Subtarget.hasNoFdiv() && Subtarget.hasStdExtD()) {
setOperationAction(ISD::FDIV, MVT::f64, LibCall);
setOperationAction(ISD::STRICT_FDIV, MVT::f64, LibCall);
setOperationAction(ISD::FSQRT, MVT::f64, LibCall);
setOperationAction(ISD::STRICT_FSQRT, MVT::f64, LibCall);
}

// Function alignments.
const Align FunctionAlignment(Subtarget.hasStdExtC() ? 2 : 4);
setMinFunctionAlignment(FunctionAlignment);
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/RISCVSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
bool HasExtXfexpauxvecquarter = false;
bool HasExtXfexpauxvecaltquarter = false;
// -->
bool HasNoFdiv = false;
bool HasRV64 = false;
bool IsRV32E = false;
bool EnableLinkerRelax = false;
Expand Down Expand Up @@ -307,6 +308,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
bool hasExtXfexpauxvecquarter() const { return HasExtXfexpauxvecquarter; }
bool hasExtXfexpauxvecaltquarter() const { return HasExtXfexpauxvecaltquarter; }
// -->
bool hasNoFdiv() const { return HasNoFdiv; }
bool is64Bit() const { return HasRV64; }
bool isRV32E() const { return IsRV32E; }
bool enableLinkerRelax() const { return EnableLinkerRelax; }
Expand Down
35 changes: 35 additions & 0 deletions llvm/test/CodeGen/RISCV/nofdiv.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
; RUN: llc -mtriple=riscv32 -mattr=+f -mattr=+nofdiv -verify-machineinstrs < %s | FileCheck %s
; RUN: llc -mtriple=riscv32 -mattr=+d -mattr=+nofdiv -verify-machineinstrs < %s | FileCheck %s
; RUN: llc -mtriple=riscv64 -mattr=+f -mattr=+nofdiv -verify-machineinstrs < %s | FileCheck %s
; RUN: llc -mtriple=riscv64 -mattr=+d -mattr=+nofdiv -verify-machineinstrs < %s | FileCheck %s

define float @fdiv_s(float %a, float %b) {
; CHECK-LABEL: fdiv_s:
; CHECK: call __divsf3@plt
%ret = fdiv float %a, %b
ret float %ret
}

define double @fdiv_d(double %a, double %b) {
; CHECK-LABEL: fdiv_d:
; CHECK: call __divdf3@plt
%ret = fdiv double %a, %b
ret double %ret
}

define float @sqrt_s(float %a) {
; CHECK-LABEL: sqrt_s:
; CHECK: call sqrtf@plt
%ret = call float @llvm.sqrt.f32(float %a)
ret float %ret
}

define double @sqrt_d(double %a) {
; CHECK-LABEL: sqrt_d:
; CHECK: call sqrt@plt
%ret = call double @llvm.sqrt.f64(double %a)
ret double %ret
}

declare float @llvm.sqrt.f32(float %a)
declare double @llvm.sqrt.f64(double %a)

0 comments on commit 01c5980

Please sign in to comment.