Skip to content

Commit

Permalink
[RISCV] Add -m[no-]scalar-strict-align and -m[no-]vector-strict-align…
Browse files Browse the repository at this point in the history
…. (#95024)
  • Loading branch information
topperc authored Jul 14, 2024
1 parent 7c15fba commit 73acf8d
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 39 deletions.
4 changes: 4 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,10 @@ RISC-V Support
- ``__attribute__((rvv_vector_bits(N)))`` is now supported for RVV vbool*_t types.
- Profile names in ``-march`` option are now supported.
- Passing empty structs/unions as arguments in C++ is now handled correctly. The behavior is similar to GCC's.
- ``-m[no-]scalar-strict-align`` and ``-m[no-]vector-strict-align`` options have
been added to give separate control of whether scalar or vector misaligned
accesses may be created. ``-m[no-]strict-align`` applies to both scalar and
vector.

CUDA/HIP Language Changes
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4854,6 +4854,14 @@ def mstrict_align : Flag<["-"], "mstrict-align">, Group<m_Group>,
HelpText<"Force all memory accesses to be aligned (AArch64/LoongArch/RISC-V only)">;
def mno_strict_align : Flag<["-"], "mno-strict-align">, Group<m_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch64/LoongArch/RISC-V only)">;
def mscalar_strict_align : Flag<["-"], "mscalar-strict-align">, Group<m_Group>,
HelpText<"Force all scalar memory accesses to be aligned (RISC-V only)">;
def mno_scalar_strict_align : Flag<["-"], "mno-scalar-strict-align">, Group<m_Group>,
HelpText<"Allow scalar memory accesses to be unaligned (RISC-V only)">;
def mvector_strict_align : Flag<["-"], "mvector-strict-align">, Group<m_Group>,
HelpText<"Force all vector memory accesses to be aligned (RISC-V only)">;
def mno_vector_strict_align : Flag<["-"], "mno-vector-strict-align">, Group<m_Group>,
HelpText<"Allow vector memory accesses to be unaligned (RISC-V only)">;
def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_arm_Features_Group>;
def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>,
HelpText<"Disallow generation of complex IT blocks. It is off by default.">;
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Basic/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__riscv_v_fixed_vlen",
Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));

if (FastUnalignedAccess)
if (FastScalarUnalignedAccess)
Builder.defineMacro("__riscv_misaligned_fast");
else
Builder.defineMacro("__riscv_misaligned_avoid");
Expand Down Expand Up @@ -353,8 +353,8 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx"))
HasLegalHalfType = true;

FastUnalignedAccess = llvm::is_contained(Features, "+unaligned-scalar-mem") &&
llvm::is_contained(Features, "+unaligned-vector-mem");
FastScalarUnalignedAccess =
llvm::is_contained(Features, "+unaligned-scalar-mem");

if (llvm::is_contained(Features, "+experimental"))
HasExperimental = true;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class RISCVTargetInfo : public TargetInfo {
std::unique_ptr<llvm::RISCVISAInfo> ISAInfo;

private:
bool FastUnalignedAccess;
bool FastScalarUnalignedAccess;
bool HasExperimental = false;

public:
Expand Down
42 changes: 31 additions & 11 deletions clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (!getArchFeatures(D, MArch, Features, Args))
return;

bool CPUFastUnaligned = false;
bool CPUFastScalarUnaligned = false;
bool CPUFastVectorUnaligned = false;

// If users give march and mcpu, get std extension feature from MArch
// and other features (ex. mirco architecture feature) from mcpu
Expand All @@ -88,8 +89,10 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,

getRISCFeaturesFromMcpu(D, A, Triple, CPU, Features);

if (llvm::RISCV::hasFastUnalignedAccess(CPU))
CPUFastUnaligned = true;
if (llvm::RISCV::hasFastScalarUnalignedAccess(CPU))
CPUFastScalarUnaligned = true;
if (llvm::RISCV::hasFastVectorUnalignedAccess(CPU))
CPUFastVectorUnaligned = true;
}

// Handle features corresponding to "-ffixed-X" options
Expand Down Expand Up @@ -169,20 +172,37 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("-relax");
}

// If -mstrict-align or -mno-strict-align is passed, use it. Otherwise, the
// unaligned-*-mem is enabled if the CPU supports it or the target is
// If -mstrict-align, -mno-strict-align, -mscalar-strict-align, or
// -mno-scalar-strict-align is passed, use it. Otherwise, the
// unaligned-scalar-mem is enabled if the CPU supports it or the target is
// Android.
if (const Arg *A = Args.getLastArg(options::OPT_mno_strict_align,
options::OPT_mstrict_align)) {
if (A->getOption().matches(options::OPT_mno_strict_align)) {
if (const Arg *A = Args.getLastArg(
options::OPT_mno_strict_align, options::OPT_mscalar_strict_align,
options::OPT_mstrict_align, options::OPT_mno_scalar_strict_align)) {
if (A->getOption().matches(options::OPT_mno_strict_align) ||
A->getOption().matches(options::OPT_mno_scalar_strict_align)) {
Features.push_back("+unaligned-scalar-mem");
Features.push_back("+unaligned-vector-mem");
} else {
Features.push_back("-unaligned-scalar-mem");
Features.push_back("-unaligned-vector-mem");
}
} else if (CPUFastUnaligned || Triple.isAndroid()) {
} else if (CPUFastScalarUnaligned || Triple.isAndroid()) {
Features.push_back("+unaligned-scalar-mem");
}

// If -mstrict-align, -mno-strict-align, -mvector-strict-align, or
// -mno-vector-strict-align is passed, use it. Otherwise, the
// unaligned-vector-mem is enabled if the CPU supports it or the target is
// Android.
if (const Arg *A = Args.getLastArg(
options::OPT_mno_strict_align, options::OPT_mvector_strict_align,
options::OPT_mstrict_align, options::OPT_mno_vector_strict_align)) {
if (A->getOption().matches(options::OPT_mno_strict_align) ||
A->getOption().matches(options::OPT_mno_vector_strict_align)) {
Features.push_back("+unaligned-vector-mem");
} else {
Features.push_back("-unaligned-vector-mem");
}
} else if (CPUFastVectorUnaligned || Triple.isAndroid()) {
Features.push_back("+unaligned-vector-mem");
}

Expand Down
24 changes: 17 additions & 7 deletions clang/test/Driver/riscv-features.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// RUN: %clang --target=riscv32-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s
// RUN: %clang --target=riscv64-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s
// RUN: %clang --target=riscv64-linux-android -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ANDROID,DEFAULT,FAST-UNALIGNED-ACCESS
// RUN: %clang -mabi=lp64d --target=riscv64-linux-android -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ANDROID,DEFAULT,FAST-UNALIGNED-ACCESS
// RUN: %clang -mabi=lp64d --target=riscv64-linux-android -mstrict-align -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=NO-FAST-UNALIGNED-ACCESS
// RUN: %clang --target=riscv64-linux-android -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ANDROID,DEFAULT,FAST-SCALAR-UNALIGNED-ACCESS,FAST-VECTOR-UNALIGNED-ACCESS
// RUN: %clang -mabi=lp64d --target=riscv64-linux-android -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ANDROID,DEFAULT,FAST-SCALAR-UNALIGNED-ACCESS,FAST-VECTOR-UNALIGNED-ACCESS
// RUN: %clang -mabi=lp64d --target=riscv64-linux-android -mstrict-align -mvector-strict-align -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=NO-FAST-SCALAR-UNALIGNED-ACCESS,NO-FAST-VECTOR-UNALIGNED-ACCESS


// CHECK: fno-signed-char
Expand Down Expand Up @@ -35,13 +35,23 @@
// NO-FORCE-SW-SCS: "-target-feature" "-forced-sw-shadow-stack"
// DEFAULT-NOT: "-target-feature" "+forced-sw-shadow-stack"

// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-strict-align 2>&1 | FileCheck %s -check-prefix=FAST-UNALIGNED-ACCESS
// RUN: %clang --target=riscv32-unknown-elf -### %s -mstrict-align 2>&1 | FileCheck %s -check-prefix=NO-FAST-UNALIGNED-ACCESS
// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-strict-align 2>&1 | FileCheck %s -check-prefixes=FAST-SCALAR-UNALIGNED-ACCESS,FAST-VECTOR-UNALIGNED-ACCESS
// RUN: %clang --target=riscv32-unknown-elf -### %s -mstrict-align 2>&1 | FileCheck %s -check-prefixes=NO-FAST-SCALAR-UNALIGNED-ACCESS,NO-FAST-VECTOR-UNALIGNED-ACCESS
// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-scalar-strict-align 2>&1 | FileCheck %s -check-prefix=FAST-SCALAR-UNALIGNED-ACCESS
// RUN: %clang --target=riscv32-unknown-elf -### %s -mscalar-strict-align 2>&1 | FileCheck %s -check-prefix=NO-FAST-SCALAR-UNALIGNED-ACCESS
// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-scalar-strict-align -mstrict-align 2>&1 | FileCheck %s -check-prefixes=NO-FAST-SCALAR-UNALIGNED-ACCESS,NO-FAST-VECTOR-UNALIGNED-ACCESS
// RUN: touch %t.o
// RUN: %clang --target=riscv32-unknown-elf -### %t.o -mno-strict-align -mstrict-align

// FAST-UNALIGNED-ACCESS: "-target-feature" "+unaligned-scalar-mem" "-target-feature" "+unaligned-vector-mem"
// NO-FAST-UNALIGNED-ACCESS: "-target-feature" "-unaligned-scalar-mem" "-target-feature" "-unaligned-vector-mem"
// FAST-SCALAR-UNALIGNED-ACCESS: "-target-feature" "+unaligned-scalar-mem"
// NO-FAST-SCALAR-UNALIGNED-ACCESS: "-target-feature" "-unaligned-scalar-mem"

// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-vector-strict-align 2>&1 | FileCheck %s -check-prefix=FAST-VECTOR-UNALIGNED-ACCESS
// RUN: %clang --target=riscv32-unknown-elf -### %s -mvector-strict-align 2>&1 | FileCheck %s -check-prefix=NO-FAST-VECTOR-UNALIGNED-ACCESS
// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-vector-strict-align -mstrict-align 2>&1 | FileCheck %s -check-prefix=NO-FAST-VECTOR-UNALIGNED-ACCESS
// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-strict-align -mvector-strict-align 2>&1 | FileCheck %s -check-prefix=NO-FAST-VECTOR-UNALIGNED-ACCESS
// FAST-VECTOR-UNALIGNED-ACCESS: "-target-feature" "+unaligned-vector-mem"
// NO-FAST-VECTOR-UNALIGNED-ACCESS: "-target-feature" "-unaligned-vector-mem"

// RUN: %clang --target=riscv32-unknown-elf -### %s 2>&1 | FileCheck %s -check-prefix=NOUWTABLE
// RUN: %clang --target=riscv32-unknown-elf -fasynchronous-unwind-tables -### %s 2>&1 | FileCheck %s -check-prefix=UWTABLE
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/TargetParser/RISCVTargetParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ bool parseTuneCPU(StringRef CPU, bool IsRV64);
StringRef getMArchFromMcpu(StringRef CPU);
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
bool hasFastUnalignedAccess(StringRef CPU);
bool hasFastScalarUnalignedAccess(StringRef CPU);
bool hasFastVectorUnalignedAccess(StringRef CPU);

} // namespace RISCV

Expand Down
21 changes: 15 additions & 6 deletions llvm/lib/TargetParser/RISCVTargetParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,25 @@ namespace llvm {
namespace RISCV {

enum CPUKind : unsigned {
#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_UNALIGN) CK_##ENUM,
#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, \
FAST_VECTOR_UNALIGN) \
CK_##ENUM,
#define TUNE_PROC(ENUM, NAME) CK_##ENUM,
#include "llvm/TargetParser/RISCVTargetParserDef.inc"
};

struct CPUInfo {
StringLiteral Name;
StringLiteral DefaultMarch;
bool FastUnalignedAccess;
bool FastScalarUnalignedAccess;
bool FastVectorUnalignedAccess;
bool is64Bit() const { return DefaultMarch.starts_with("rv64"); }
};

constexpr CPUInfo RISCVCPUInfo[] = {
#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_UNALIGN) \
{NAME, DEFAULT_MARCH, FAST_UNALIGN},
#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, \
FAST_VECTOR_UNALIGN) \
{NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, FAST_VECTOR_UNALIGN},
#include "llvm/TargetParser/RISCVTargetParserDef.inc"
};

Expand All @@ -46,9 +50,14 @@ static const CPUInfo *getCPUInfoByName(StringRef CPU) {
return nullptr;
}

bool hasFastUnalignedAccess(StringRef CPU) {
bool hasFastScalarUnalignedAccess(StringRef CPU) {
const CPUInfo *Info = getCPUInfoByName(CPU);
return Info && Info->FastUnalignedAccess;
return Info && Info->FastScalarUnalignedAccess;
}

bool hasFastVectorUnalignedAccess(StringRef CPU) {
const CPUInfo *Info = getCPUInfoByName(CPU);
return Info && Info->FastVectorUnalignedAccess;
}

bool parseCPU(StringRef CPU, bool IsRV64) {
Expand Down
10 changes: 5 additions & 5 deletions llvm/test/TableGen/riscv-target-def.td
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,13 @@ def ROCKET : RISCVTuneProcessorModel<"rocket",
// CHECK: #endif // GET_SUPPORTED_PROFILES

// CHECK: #ifndef PROC
// CHECK-NEXT: #define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_UNALIGNED_ACCESS)
// CHECK-NEXT: #define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN, FAST_VECTOR_UNALIGN)
// CHECK-NEXT: #endif

// CHECK: PROC(GENERIC_RV32, {"generic-rv32"}, {"rv32i2p1"}, 0)
// CHECK-NEXT: PROC(GENERIC_RV64, {"generic-rv64"}, {"rv64i2p1"}, 0)
// CHECK-NEXT: PROC(ROCKET_RV32, {"rocket-rv32"}, {"rv32i2p1_zicsr2p0_zidummy0p1_zifencei2p0"}, 0)
// CHECK-NEXT: PROC(ROCKET_RV64, {"rocket-rv64"}, {"rv64i2p1_zicsr2p0_zidummy0p1_zifencei2p0"}, 0)
// CHECK: PROC(GENERIC_RV32, {"generic-rv32"}, {"rv32i2p1"}, 0, 0)
// CHECK-NEXT: PROC(GENERIC_RV64, {"generic-rv64"}, {"rv64i2p1"}, 0, 0)
// CHECK-NEXT: PROC(ROCKET_RV32, {"rocket-rv32"}, {"rv32i2p1_zicsr2p0_zidummy0p1_zifencei2p0"}, 0, 0)
// CHECK-NEXT: PROC(ROCKET_RV64, {"rocket-rv64"}, {"rv64i2p1_zicsr2p0_zidummy0p1_zifencei2p0"}, 0, 0)

// CHECK: #undef PROC

Expand Down
9 changes: 4 additions & 5 deletions llvm/utils/TableGen/RISCVTargetDefEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ static void emitRISCVProfiles(RecordKeeper &Records, raw_ostream &OS) {

static void emitRISCVProcs(RecordKeeper &RK, raw_ostream &OS) {
OS << "#ifndef PROC\n"
<< "#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_UNALIGNED_ACCESS)\n"
<< "#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN"
<< ", FAST_VECTOR_UNALIGN)\n"
<< "#endif\n\n";

// Iterate on all definition records.
Expand All @@ -180,9 +181,6 @@ static void emitRISCVProcs(RecordKeeper &RK, raw_ostream &OS) {
return Feature->getValueAsString("Name") == "unaligned-vector-mem";
});

bool FastUnalignedAccess =
FastScalarUnalignedAccess && FastVectorUnalignedAccess;

OS << "PROC(" << Rec->getName() << ", {\"" << Rec->getValueAsString("Name")
<< "\"}, {\"";

Expand All @@ -193,7 +191,8 @@ static void emitRISCVProcs(RecordKeeper &RK, raw_ostream &OS) {
printMArch(OS, Features);
else
OS << MArch;
OS << "\"}, " << FastUnalignedAccess << ")\n";
OS << "\"}, " << FastScalarUnalignedAccess << ", "
<< FastVectorUnalignedAccess << ")\n";
}
OS << "\n#undef PROC\n";
OS << "\n";
Expand Down

0 comments on commit 73acf8d

Please sign in to comment.