From 73acf8d755e04996f17b7694b4794459e492dede Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 14 Jul 2024 13:39:17 -0700 Subject: [PATCH] [RISCV] Add -m[no-]scalar-strict-align and -m[no-]vector-strict-align. (#95024) --- clang/docs/ReleaseNotes.rst | 4 ++ clang/include/clang/Driver/Options.td | 8 ++++ clang/lib/Basic/Targets/RISCV.cpp | 6 +-- clang/lib/Basic/Targets/RISCV.h | 2 +- clang/lib/Driver/ToolChains/Arch/RISCV.cpp | 42 ++++++++++++++----- clang/test/Driver/riscv-features.c | 24 +++++++---- .../llvm/TargetParser/RISCVTargetParser.h | 3 +- llvm/lib/TargetParser/RISCVTargetParser.cpp | 21 +++++++--- llvm/test/TableGen/riscv-target-def.td | 10 ++--- llvm/utils/TableGen/RISCVTargetDefEmitter.cpp | 9 ++-- 10 files changed, 90 insertions(+), 39 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5dc0f8b7e0bbb8..35cc15142089b2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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 ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index f1e8cb87e5321a..be177dc38bcf17 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4854,6 +4854,14 @@ def mstrict_align : Flag<["-"], "mstrict-align">, Group, HelpText<"Force all memory accesses to be aligned (AArch64/LoongArch/RISC-V only)">; def mno_strict_align : Flag<["-"], "mno-strict-align">, Group, HelpText<"Allow memory accesses to be unaligned (AArch64/LoongArch/RISC-V only)">; +def mscalar_strict_align : Flag<["-"], "mscalar-strict-align">, Group, + HelpText<"Force all scalar memory accesses to be aligned (RISC-V only)">; +def mno_scalar_strict_align : Flag<["-"], "mno-scalar-strict-align">, Group, + HelpText<"Allow scalar memory accesses to be unaligned (RISC-V only)">; +def mvector_strict_align : Flag<["-"], "mvector-strict-align">, Group, + HelpText<"Force all vector memory accesses to be aligned (RISC-V only)">; +def mno_vector_strict_align : Flag<["-"], "mno-vector-strict-align">, Group, + HelpText<"Allow vector memory accesses to be unaligned (RISC-V only)">; def mno_thumb : Flag<["-"], "mno-thumb">, Group; def mrestrict_it: Flag<["-"], "mrestrict-it">, Group, HelpText<"Disallow generation of complex IT blocks. It is off by default.">; diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 25ae7d64b577e4..9159162f01d1bd 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -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"); @@ -353,8 +353,8 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector &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; diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index d0e9cdc6da07b3..d5df6344bedc09 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -30,7 +30,7 @@ class RISCVTargetInfo : public TargetInfo { std::unique_ptr ISAInfo; private: - bool FastUnalignedAccess; + bool FastScalarUnalignedAccess; bool HasExperimental = false; public: diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index 1831a4113fcd08..c3f0251c80750b 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -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 @@ -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 @@ -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"); } diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index cfe293cd4667ff..b4fad5177c5f76 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -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 @@ -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 diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h index 5b1494efe7bdc0..7421dac2744b61 100644 --- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h +++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h @@ -35,7 +35,8 @@ bool parseTuneCPU(StringRef CPU, bool IsRV64); StringRef getMArchFromMcpu(StringRef CPU); void fillValidCPUArchList(SmallVectorImpl &Values, bool IsRV64); void fillValidTuneCPUArchList(SmallVectorImpl &Values, bool IsRV64); -bool hasFastUnalignedAccess(StringRef CPU); +bool hasFastScalarUnalignedAccess(StringRef CPU); +bool hasFastVectorUnalignedAccess(StringRef CPU); } // namespace RISCV diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp index 9003f9beffa7e7..db1b5f689d7daf 100644 --- a/llvm/lib/TargetParser/RISCVTargetParser.cpp +++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp @@ -21,7 +21,9 @@ 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" }; @@ -29,13 +31,15 @@ enum CPUKind : unsigned { 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" }; @@ -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) { diff --git a/llvm/test/TableGen/riscv-target-def.td b/llvm/test/TableGen/riscv-target-def.td index fb58448d7ce881..7137cf96fd3d44 100644 --- a/llvm/test/TableGen/riscv-target-def.td +++ b/llvm/test/TableGen/riscv-target-def.td @@ -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 diff --git a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp index b76ba05954aa51..04e9e0fa48db0a 100644 --- a/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp @@ -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. @@ -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") << "\"}, {\""; @@ -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";