Author: Jerry Zhang Jian Date: 2025-12-20T01:15:03+08:00 New Revision: fc69c804db3ef12b65ed0900d84f4e26ce06d5cb
URL: https://github.com/llvm/llvm-project/commit/fc69c804db3ef12b65ed0900d84f4e26ce06d5cb DIFF: https://github.com/llvm/llvm-project/commit/fc69c804db3ef12b65ed0900d84f4e26ce06d5cb.diff LOG: [RISCV] Implement conditional Zca implies C extension rule (#172860) This change implements the conditional "Zca implies C" rule to match GCC's behavior (PR119122) and the RISC-V specification for MISA.C. The rule is: - For RV32: - No F and no D: Zca alone implies C - F but no D: Zca + Zcf implies C - F and D: Zca + Zcf + Zcd implies C - For RV64: - No D: Zca alone implies C - D: Zca + Zcd implies C This fixes multilib matching issues where LLVM-generated march strings didn't include the C extension when GCC's multilib configurations expected it. Reference: - GCC PR119122: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119122 - RISC-V Zc spec: https://github.com/riscv/riscv-isa-manual/blob/main/src/zc.adoc Signed-off-by: Jerry Zhang Jian <[email protected]> Added: Modified: clang/test/Preprocessor/riscv-target-features.c llvm/lib/Target/RISCV/RISCVFeatures.td llvm/lib/TargetParser/RISCVISAInfo.cpp llvm/test/CodeGen/RISCV/attributes-qc.ll llvm/test/CodeGen/RISCV/attributes.ll llvm/test/MC/RISCV/attribute-arch.s llvm/unittests/TargetParser/RISCVISAInfoTest.cpp Removed: ################################################################################ diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 56c738bc007fb..2563d83179795 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -702,6 +702,7 @@ // RUN: %clang --target=riscv64-unknown-linux-gnu \ // RUN: -march=rv64izca1p0 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZCA-EXT %s +// CHECK-ZCA-EXT: __riscv_c 2000000{{$}} // CHECK-ZCA-EXT: __riscv_zca 1000000{{$}} // RUN: %clang --target=riscv32-unknown-linux-gnu \ @@ -710,16 +711,19 @@ // RUN: %clang --target=riscv64-unknown-linux-gnu \ // RUN: -march=rv64izcb1p0 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZCB-EXT %s +// CHECK-ZCB-EXT: __riscv_c 2000000{{$}} // CHECK-ZCB-EXT: __riscv_zca 1000000{{$}} // CHECK-ZCB-EXT: __riscv_zcb 1000000{{$}} // RUN: %clang --target=riscv32-unknown-linux-gnu \ // RUN: -march=rv32izcd1p0 -E -dM %s \ -// RUN: -o - | FileCheck --check-prefix=CHECK-ZCD-EXT %s +// RUN: -o - | FileCheck --check-prefix=CHECK-ZCD-EXT-RV32 %s // RUN: %clang --target=riscv64-unknown-linux-gnu \ // RUN: -march=rv64izcd1p0 -E -dM %s \ -// RUN: -o - | FileCheck --check-prefix=CHECK-ZCD-EXT %s -// CHECK-ZCD-EXT: __riscv_zcd 1000000{{$}} +// RUN: -o - | FileCheck --check-prefix=CHECK-ZCD-EXT-RV64 %s +// CHECK-ZCD-EXT-RV32: __riscv_zcd 1000000{{$}} +// CHECK-ZCD-EXT-RV64: __riscv_c 2000000{{$}} +// CHECK-ZCD-EXT-RV64: __riscv_zcd 1000000{{$}} // RUN: %clang --target=riscv32-unknown-linux-gnu \ // RUN: -march=rv32izce1p0 -E -dM %s \ @@ -727,6 +731,7 @@ // RUN: %clang --target=riscv64-unknown-linux-gnu \ // RUN: -march=rv64izce1p0 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZCE-EXT %s +// CHECK-ZCE-EXT: __riscv_c 2000000{{$}} // CHECK-ZCE-EXT: __riscv_zce 1000000{{$}} // RUN: %clang --target=riscv32-unknown-linux-gnu \ @@ -753,6 +758,7 @@ // RUN: %clang --target=riscv64-unknown-linux-gnu \ // RUN: -march=rv64izcmp1p0 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZCMP-EXT %s +// CHECK-ZCMP-EXT: __riscv_c 2000000{{$}} // CHECK-ZCMP-EXT: __riscv_zca 1000000{{$}} // CHECK-ZCMP-EXT: __riscv_zcmp 1000000{{$}} @@ -762,6 +768,7 @@ // RUN: %clang --target=riscv64-unknown-linux-gnu \ // RUN: -march=rv64izcmt1p0 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZCMT-EXT %s +// CHECK-ZCMT-EXT: __riscv_c 2000000{{$}} // CHECK-ZCMT-EXT: __riscv_zca 1000000{{$}} // CHECK-ZCMT-EXT: __riscv_zcmt 1000000{{$}} diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 305e1f21a92c2..3a76ac6351fdf 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -387,7 +387,7 @@ def FeatureStdExtZca "part of the C extension, excluding compressed " "floating point loads/stores">, RISCVExtensionBitmask<1, 2>; -// FIXME: Update this message - Zca always implies C. +// Note: Zca conditionally implies C (see RISCVISAInfo::updateImplication). def HasStdExtZca : Predicate<"Subtarget->hasStdExtZca()">, AssemblerPredicate<(any_of FeatureStdExtZca), diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index 235bd71278a1b..aaca51d8a9cda 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -875,6 +875,37 @@ void RISCVISAInfo::updateImplication() { Exts["zcf"] = *Version; } + // Add C if Zca is enabled and the conditions are met. + // This follows the RISC-V spec rules for MISA.C and matches GCC behavior + // (PR119122). The rule is: + // For RV32: + // - No F and no D: Zca alone implies C + // - F but no D: Zca + Zcf implies C + // - F and D: Zca + Zcf + Zcd implies C + // For RV64: + // - No D: Zca alone implies C + // - D: Zca + Zcd implies C + if (Exts.count("zca") && !Exts.count("c")) { + bool ShouldAddC = false; + if (XLen == 32) { + if (Exts.count("d")) + ShouldAddC = Exts.count("zcf") && Exts.count("zcd"); + else if (Exts.count("f")) + ShouldAddC = Exts.count("zcf"); + else + ShouldAddC = true; + } else if (XLen == 64) { + if (Exts.count("d")) + ShouldAddC = Exts.count("zcd"); + else + ShouldAddC = true; + } + if (ShouldAddC) { + auto Version = findDefaultVersion("c"); + Exts["c"] = *Version; + } + } + // Handle I/E after implications have been resolved, in case either // of them was implied by another extension. bool HasE = Exts.count("e") != 0; diff --git a/llvm/test/CodeGen/RISCV/attributes-qc.ll b/llvm/test/CodeGen/RISCV/attributes-qc.ll index 5eed466346a5c..1c62378dea9ca 100644 --- a/llvm/test/CodeGen/RISCV/attributes-qc.ll +++ b/llvm/test/CodeGen/RISCV/attributes-qc.ll @@ -22,27 +22,27 @@ ; RUN: llc -mtriple=riscv64 -mattr=+experimental-xqccmp %s -o - | FileCheck --check-prefix=RV64XQCCMP %s -; RV32XQCCMP: .attribute 5, "rv32i2p1_zca1p0_xqccmp0p3" +; RV32XQCCMP: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqccmp0p3" ; RV32XQCIA: .attribute 5, "rv32i2p1_xqcia0p7" -; RV32XQCIAC: .attribute 5, "rv32i2p1_zca1p0_xqciac0p3" -; RV32XQCIBI: .attribute 5, "rv32i2p1_zca1p0_xqcibi0p2" -; RV32XQCIBM: .attribute 5, "rv32i2p1_zca1p0_xqcibm0p8" +; RV32XQCIAC: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqciac0p3" +; RV32XQCIBI: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqcibi0p2" +; RV32XQCIBM: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqcibm0p8" ; RV32XQCICLI: .attribute 5, "rv32i2p1_xqcicli0p3" -; RV32XQCICM: .attribute 5, "rv32i2p1_zca1p0_xqcicm0p2" +; RV32XQCICM: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqcicm0p2" ; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2" ; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p4" -; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p10" +; RV32XQCIINT: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqciint0p10" ; RV32XQCIIO: .attribute 5, "rv32i2p1_xqciio0p1" -; RV32XQCILB: .attribute 5, "rv32i2p1_zca1p0_xqcilb0p2" -; RV32XQCILI: .attribute 5, "rv32i2p1_zca1p0_xqcili0p2" -; RV32XQCILIA: .attribute 5, "rv32i2p1_zca1p0_xqcilia0p2" -; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p3" +; RV32XQCILB: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqcilb0p2" +; RV32XQCILI: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqcili0p2" +; RV32XQCILIA: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqcilia0p2" +; RV32XQCILO: .attribute 5, "rv32i2p1_c2p0_zca1p0_xqcilo0p3" ; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p6" -; RV32XQCISIM: attribute 5, "rv32i2p1_zca1p0_xqcisim0p2" +; RV32XQCISIM: attribute 5, "rv32i2p1_c2p0_zca1p0_xqcisim0p2" ; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2" -; RV32XQCISYNC: attribute 5, "rv32i2p1_zca1p0_xqcisync0p3" +; RV32XQCISYNC: attribute 5, "rv32i2p1_c2p0_zca1p0_xqcisync0p3" -; RV64XQCCMP: .attribute 5, "rv64i2p1_zca1p0_xqccmp0p3" +; RV64XQCCMP: .attribute 5, "rv64i2p1_c2p0_zca1p0_xqccmp0p3" define i32 @addi(i32 %a) { %1 = add i32 %a, 1 diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll index 2fb063af8f8c8..e24230926e270 100644 --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -393,16 +393,16 @@ ; RV32XCVMEM: .attribute 5, "rv32i2p1_xcvmem1p0" ; RV32XCVSIMD: .attribute 5, "rv32i2p1_xcvsimd1p0" ; RV32XCVBI: .attribute 5, "rv32i2p1_xcvbi1p0" -; RV32XWCHC: .attribute 5, "rv32i2p1_zca1p0_xwchc2p2" +; RV32XWCHC: .attribute 5, "rv32i2p1_c2p0_zca1p0_xwchc2p2" ; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0" ; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc1p0" ; RV32COMBINEINTOA: .attribute 5, "rv32i2p1_a2p1_zaamo1p0_zalrsc1p0" -; RV32ZCA: .attribute 5, "rv32i2p1_zca1p0" -; RV32ZCB: .attribute 5, "rv32i2p1_zca1p0_zcb1p0" +; RV32ZCA: .attribute 5, "rv32i2p1_c2p0_zca1p0" +; RV32ZCB: .attribute 5, "rv32i2p1_c2p0_zca1p0_zcb1p0" ; RV32ZCD: .attribute 5, "rv32i2p1_f2p2_d2p2_zicsr2p0_zca1p0_zcd1p0" -; RV32ZCF: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zca1p0_zcf1p0" -; RV32ZCMP: .attribute 5, "rv32i2p1_zca1p0_zcmp1p0" -; RV32ZCMT: .attribute 5, "rv32i2p1_zicsr2p0_zca1p0_zcmt1p0" +; RV32ZCF: .attribute 5, "rv32i2p1_f2p2_c2p0_zicsr2p0_zca1p0_zcf1p0" +; RV32ZCMP: .attribute 5, "rv32i2p1_c2p0_zca1p0_zcmp1p0" +; RV32ZCMT: .attribute 5, "rv32i2p1_c2p0_zicsr2p0_zca1p0_zcmt1p0" ; RV32ZICSR: .attribute 5, "rv32i2p1_zicsr2p0" ; RV32ZIFENCEI: .attribute 5, "rv32i2p1_zifencei2p0" ; RV32ZICNTR: .attribute 5, "rv32i2p1_zicntr2p0_zicsr2p0" @@ -429,8 +429,8 @@ ; RV32ZICOND: .attribute 5, "rv32i2p1_zicond1p0" ; RV32ZILSD: .attribute 5, "rv32i2p1_zilsd1p0" ; RV32ZIMOP: .attribute 5, "rv32i2p1_zimop1p0" -; RV32ZCLSD: .attribute 5, "rv32i2p1_zilsd1p0_zca1p0_zclsd1p0" -; RV32ZCMOP: .attribute 5, "rv32i2p1_zca1p0_zcmop1p0" +; RV32ZCLSD: .attribute 5, "rv32i2p1_c2p0_zilsd1p0_zca1p0_zclsd1p0" +; RV32ZCMOP: .attribute 5, "rv32i2p1_c2p0_zca1p0_zcmop1p0" ; RV32SMAIA: .attribute 5, "rv32i2p1_smaia1p0" ; RV32SSAIA: .attribute 5, "rv32i2p1_ssaia1p0" ; RV32SMCSRIND: .attribute 5, "rv32i2p1_smcsrind1p0" @@ -544,11 +544,11 @@ ; RV64ZAAMO: .attribute 5, "rv64i2p1_zaamo1p0" ; RV64ZALRSC: .attribute 5, "rv64i2p1_zalrsc1p0" ; RV64COMBINEINTOA: .attribute 5, "rv64i2p1_a2p1_zaamo1p0_zalrsc1p0" -; RV64ZCA: .attribute 5, "rv64i2p1_zca1p0" -; RV64ZCB: .attribute 5, "rv64i2p1_zca1p0_zcb1p0" -; RV64ZCD: .attribute 5, "rv64i2p1_f2p2_d2p2_zicsr2p0_zca1p0_zcd1p0" -; RV64ZCMP: .attribute 5, "rv64i2p1_zca1p0_zcmp1p0" -; RV64ZCMT: .attribute 5, "rv64i2p1_zicsr2p0_zca1p0_zcmt1p0" +; RV64ZCA: .attribute 5, "rv64i2p1_c2p0_zca1p0" +; RV64ZCB: .attribute 5, "rv64i2p1_c2p0_zca1p0_zcb1p0" +; RV64ZCD: .attribute 5, "rv64i2p1_f2p2_d2p2_c2p0_zicsr2p0_zca1p0_zcd1p0" +; RV64ZCMP: .attribute 5, "rv64i2p1_c2p0_zca1p0_zcmp1p0" +; RV64ZCMT: .attribute 5, "rv64i2p1_c2p0_zicsr2p0_zca1p0_zcmt1p0" ; RV64ZICCAMOA: .attribute 5, "rv64i2p1_ziccamoa1p0" ; RV64ZICCAMOC: .attribute 5, "rv64i2p1_ziccamoc1p0" ; RV64ZICCIF: .attribute 5, "rv64i2p1_ziccif1p0" @@ -579,7 +579,7 @@ ; RV64ZVFH: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zfhmin1p0_zve32f1p0_zve32x1p0_zvfh1p0_zvfhmin1p0_zvl32b1p0" ; RV64ZICOND: .attribute 5, "rv64i2p1_zicond1p0" ; RV64ZIMOP: .attribute 5, "rv64i2p1_zimop1p0" -; RV64ZCMOP: .attribute 5, "rv64i2p1_zca1p0_zcmop1p0" +; RV64ZCMOP: .attribute 5, "rv64i2p1_c2p0_zca1p0_zcmop1p0" ; RV64SMAIA: .attribute 5, "rv64i2p1_smaia1p0" ; RV64SSAIA: .attribute 5, "rv64i2p1_ssaia1p0" ; RV64SMCSRIND: .attribute 5, "rv64i2p1_smcsrind1p0" @@ -626,7 +626,7 @@ ; RVA23S64: .attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_b1p0_v1p0_h1p0_zic64b1p0_zicbom1p0_zicbop1p0_zicboz1p0_ziccamoa1p0_ziccif1p0_zicclsm1p0_ziccrse1p0_zicntr2p0_zicond1p0_zicsr2p0_zifencei2p0_zihintntl1p0_zihintpause2p0_zihpm2p0_zimop1p0_zmmul1p0_za64rs1p0_zaamo1p0_zalrsc1p0_zawrs1p0_zfa1p0_zfhmin1p0_zca1p0_zcb1p0_zcd1p0_zcmop1p0_zba1p0_zbb1p0_zbs1p0_zkt1p0_zvbb1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvfhmin1p0_zvkb1p0_zvkt1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0_sha1p0_shcounterenw1p0_shgatpa1p0_shtvala1p0_shvsatpa1p0_shvstvala1p0_shvstvecd1p0_ssccptr1p0_sscofpmf1p0_sscounterenw1p0_ssnpm1p0_ssstateen1p0_sstc1p0_sstvala1p0_sstvecd1p0_ssu64xl1p0_supm1p0_svade1p0_svbare1p0_svinval1p0_svnapot1p0_svpbmt1p0" ; RVB23U64: .attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_b1p0_zic64b1p0_zicbom1p0_zicbop1p0_zicboz1p0_ziccamoa1p0_ziccif1p0_zicclsm1p0_ziccrse1p0_zicntr2p0_zicond1p0_zicsr2p0_zihintntl1p0_zihintpause2p0_zihpm2p0_zimop1p0_zmmul1p0_za64rs1p0_zaamo1p0_zalrsc1p0_zawrs1p0_zfa1p0_zca1p0_zcb1p0_zcd1p0_zcmop1p0_zba1p0_zbb1p0_zbs1p0_zkt1p0" ; RVB23S64: .attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_b1p0_zic64b1p0_zicbom1p0_zicbop1p0_zicboz1p0_ziccamoa1p0_ziccif1p0_zicclsm1p0_ziccrse1p0_zicntr2p0_zicond1p0_zicsr2p0_zifencei2p0_zihintntl1p0_zihintpause2p0_zihpm2p0_zimop1p0_zmmul1p0_za64rs1p0_zaamo1p0_zalrsc1p0_zawrs1p0_zfa1p0_zca1p0_zcb1p0_zcd1p0_zcmop1p0_zba1p0_zbb1p0_zbs1p0_zkt1p0_ssccptr1p0_sscofpmf1p0_sscounterenw1p0_sstc1p0_sstvala1p0_sstvecd1p0_ssu64xl1p0_svade1p0_svbare1p0_svinval1p0_svnapot1p0_svpbmt1p0" -; RVM23U32: .attribute 5, "rv32i2p1_m2p0_b1p0_zicbop1p0_zicond1p0_zicsr2p0_zihintntl1p0_zihintpause2p0_zimop1p0_zmmul1p0_zca1p0_zcb1p0_zce1p0_zcmop1p0_zcmp1p0_zcmt1p0_zba1p0_zbb1p0_zbs1p0" +; RVM23U32: .attribute 5, "rv32i2p1_m2p0_c2p0_b1p0_zicbop1p0_zicond1p0_zicsr2p0_zihintntl1p0_zihintpause2p0_zimop1p0_zmmul1p0_zca1p0_zcb1p0_zce1p0_zcmop1p0_zcmp1p0_zcmt1p0_zba1p0_zbb1p0_zbs1p0" define i32 @addi(i32 %a) { %1 = add i32 %a, 1 diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s index fb5f033262b57..98c2a09d9d7fa 100644 --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -250,25 +250,25 @@ # CHECK: attribute 5, "rv32i2p1_f2p2_zicsr2p0_zkt1p0_zve32f1p0_zve32x1p0_zvl32b1p0" .attribute arch, "rv32izca1p0" -# CHECK: attribute 5, "rv32i2p1_zca1p0" +# CHECK: attribute 5, "rv32i2p1_c2p0_zca1p0" .attribute arch, "rv32izcd1p0" # CHECK: attribute 5, "rv32i2p1_f2p2_d2p2_zicsr2p0_zca1p0_zcd1p0" .attribute arch, "rv32izcf1p0" -# CHECK: attribute 5, "rv32i2p1_f2p2_zicsr2p0_zca1p0_zcf1p0" +# CHECK: attribute 5, "rv32i2p1_f2p2_c2p0_zicsr2p0_zca1p0_zcf1p0" .attribute arch, "rv32izcb1p0" -# CHECK: attribute 5, "rv32i2p1_zca1p0_zcb1p0" +# CHECK: attribute 5, "rv32i2p1_c2p0_zca1p0_zcb1p0" .attribute arch, "rv32izclsd1p0" -# CHECK: attribute 5, "rv32i2p1_zilsd1p0_zca1p0_zclsd1p0" +# CHECK: attribute 5, "rv32i2p1_c2p0_zilsd1p0_zca1p0_zclsd1p0" .attribute arch, "rv32izcmp1p0" -# CHECK: attribute 5, "rv32i2p1_zca1p0_zcmp1p0" +# CHECK: attribute 5, "rv32i2p1_c2p0_zca1p0_zcmp1p0" .attribute arch, "rv32izcmt1p0" -# CHECK: attribute 5, "rv32i2p1_zicsr2p0_zca1p0_zcmt1p0" +# CHECK: attribute 5, "rv32i2p1_c2p0_zicsr2p0_zca1p0_zcmt1p0" .attribute arch, "rv64i_xsfvcp" # CHECK: attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_xsfvcp1p0" diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp index 2de4352dcac64..a2ac67724152b 100644 --- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp +++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp @@ -628,24 +628,40 @@ TEST(ParseArchString, RejectsConflictingExtensions) { "extension is enabled"); } - for (StringRef Input : {"rv32id_zcd1p0_zcmp1p0", "rv64id_zcd1p0_zcmp1p0"}) { + // RV32 + D + Zcd doesn't synthesize C (needs Zcf), so error mentions 'zcd' + for (StringRef Input : {"rv32id_zcd1p0_zcmp1p0"}) { EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), "'zcmp' extension is incompatible with 'zcd' extension when 'd' " "extension is enabled"); } + // RV64 + D + Zcd synthesizes C, so error mentions 'c' + for (StringRef Input : {"rv64id_zcd1p0_zcmp1p0"}) { + EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), + "'zcmp' extension is incompatible with 'c' extension when 'd' " + "extension is enabled"); + } + for (StringRef Input : {"rv32idc_zcmt1p0", "rv64idc_zcmt1p0"}) { EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), "'zcmt' extension is incompatible with 'c' extension when 'd' " "extension is enabled"); } - for (StringRef Input : {"rv32id_zcd1p0_zcmt1p0", "rv64id_zcd1p0_zcmt1p0"}) { + // RV32 + D + Zcd doesn't synthesize C (needs Zcf), so error mentions 'zcd' + for (StringRef Input : {"rv32id_zcd1p0_zcmt1p0"}) { EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), "'zcmt' extension is incompatible with 'zcd' extension when 'd' " "extension is enabled"); } + // RV64 + D + Zcd synthesizes C, so error mentions 'c' + for (StringRef Input : {"rv64id_zcd1p0_zcmt1p0"}) { + EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), + "'zcmt' extension is incompatible with 'c' extension when 'd' " + "extension is enabled"); + } + for (StringRef Input : {"rv64if_zcf"}) { EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), "'zcf' is only supported for 'rv32'"); @@ -870,11 +886,13 @@ TEST(OrderedExtensionMap, ExtensionsAreCorrectlyOrdered) { } TEST(ParseArchString, ZceImplication) { + // RV32 Zce without F/D: Zca implies C auto MaybeRV32IZce = RISCVISAInfo::parseArchString("rv32izce", true); ASSERT_THAT_EXPECTED(MaybeRV32IZce, Succeeded()); const auto &ExtsRV32IZce = (*MaybeRV32IZce)->getExtensions(); - EXPECT_EQ(ExtsRV32IZce.size(), 7UL); + EXPECT_EQ(ExtsRV32IZce.size(), 8UL); EXPECT_EQ(ExtsRV32IZce.count("i"), 1U); + EXPECT_EQ(ExtsRV32IZce.count("c"), 1U); EXPECT_EQ(ExtsRV32IZce.count("zicsr"), 1U); EXPECT_EQ(ExtsRV32IZce.count("zca"), 1U); EXPECT_EQ(ExtsRV32IZce.count("zcb"), 1U); @@ -882,11 +900,13 @@ TEST(ParseArchString, ZceImplication) { EXPECT_EQ(ExtsRV32IZce.count("zcmp"), 1U); EXPECT_EQ(ExtsRV32IZce.count("zcmt"), 1U); + // RV32 Zce with F (no D): Zca + Zcf implies C auto MaybeRV32IFZce = RISCVISAInfo::parseArchString("rv32ifzce", true); ASSERT_THAT_EXPECTED(MaybeRV32IFZce, Succeeded()); const auto &ExtsRV32IFZce = (*MaybeRV32IFZce)->getExtensions(); - EXPECT_EQ(ExtsRV32IFZce.size(), 9UL); + EXPECT_EQ(ExtsRV32IFZce.size(), 10UL); EXPECT_EQ(ExtsRV32IFZce.count("i"), 1U); + EXPECT_EQ(ExtsRV32IFZce.count("c"), 1U); EXPECT_EQ(ExtsRV32IFZce.count("zicsr"), 1U); EXPECT_EQ(ExtsRV32IFZce.count("f"), 1U); EXPECT_EQ(ExtsRV32IFZce.count("zca"), 1U); @@ -896,11 +916,13 @@ TEST(ParseArchString, ZceImplication) { EXPECT_EQ(ExtsRV32IFZce.count("zcmp"), 1U); EXPECT_EQ(ExtsRV32IFZce.count("zcmt"), 1U); + // RV32 Zce with D: has Zcf but not Zcd, so no C auto MaybeRV32IDZce = RISCVISAInfo::parseArchString("rv32idzce", true); ASSERT_THAT_EXPECTED(MaybeRV32IDZce, Succeeded()); const auto &ExtsRV32IDZce = (*MaybeRV32IDZce)->getExtensions(); EXPECT_EQ(ExtsRV32IDZce.size(), 10UL); EXPECT_EQ(ExtsRV32IDZce.count("i"), 1U); + EXPECT_EQ(ExtsRV32IDZce.count("c"), 0U); EXPECT_EQ(ExtsRV32IDZce.count("zicsr"), 1U); EXPECT_EQ(ExtsRV32IDZce.count("f"), 1U); EXPECT_EQ(ExtsRV32IDZce.count("d"), 1U); @@ -911,11 +933,13 @@ TEST(ParseArchString, ZceImplication) { EXPECT_EQ(ExtsRV32IDZce.count("zcmp"), 1U); EXPECT_EQ(ExtsRV32IDZce.count("zcmt"), 1U); + // RV64 Zce without F/D: Zca implies C auto MaybeRV64IZce = RISCVISAInfo::parseArchString("rv64izce", true); ASSERT_THAT_EXPECTED(MaybeRV64IZce, Succeeded()); const auto &ExtsRV64IZce = (*MaybeRV64IZce)->getExtensions(); - EXPECT_EQ(ExtsRV64IZce.size(), 7UL); + EXPECT_EQ(ExtsRV64IZce.size(), 8UL); EXPECT_EQ(ExtsRV64IZce.count("i"), 1U); + EXPECT_EQ(ExtsRV64IZce.count("c"), 1U); EXPECT_EQ(ExtsRV64IZce.count("zicsr"), 1U); EXPECT_EQ(ExtsRV64IZce.count("zca"), 1U); EXPECT_EQ(ExtsRV64IZce.count("zcb"), 1U); @@ -923,11 +947,13 @@ TEST(ParseArchString, ZceImplication) { EXPECT_EQ(ExtsRV64IZce.count("zcmp"), 1U); EXPECT_EQ(ExtsRV64IZce.count("zcmt"), 1U); + // RV64 Zce with F (no D): Zca implies C (Zcf not relevant on RV64) auto MaybeRV64IFZce = RISCVISAInfo::parseArchString("rv64ifzce", true); ASSERT_THAT_EXPECTED(MaybeRV64IFZce, Succeeded()); const auto &ExtsRV64IFZce = (*MaybeRV64IFZce)->getExtensions(); - EXPECT_EQ(ExtsRV64IFZce.size(), 8UL); + EXPECT_EQ(ExtsRV64IFZce.size(), 9UL); EXPECT_EQ(ExtsRV64IFZce.count("i"), 1U); + EXPECT_EQ(ExtsRV64IFZce.count("c"), 1U); EXPECT_EQ(ExtsRV64IFZce.count("zicsr"), 1U); EXPECT_EQ(ExtsRV64IFZce.count("f"), 1U); EXPECT_EQ(ExtsRV64IFZce.count("zca"), 1U); @@ -936,17 +962,13 @@ TEST(ParseArchString, ZceImplication) { EXPECT_EQ(ExtsRV64IFZce.count("zcmp"), 1U); EXPECT_EQ(ExtsRV64IFZce.count("zcmt"), 1U); - EXPECT_EQ(ExtsRV64IFZce.count("zca"), 1U); - EXPECT_EQ(ExtsRV64IFZce.count("zcb"), 1U); - EXPECT_EQ(ExtsRV64IFZce.count("zce"), 1U); - EXPECT_EQ(ExtsRV64IFZce.count("zcmp"), 1U); - EXPECT_EQ(ExtsRV64IFZce.count("zcmt"), 1U); - + // RV64 Zce with D: has no Zcd, so no C auto MaybeRV64IDZce = RISCVISAInfo::parseArchString("rv64idzce", true); ASSERT_THAT_EXPECTED(MaybeRV64IDZce, Succeeded()); const auto &ExtsRV64IDZce = (*MaybeRV64IDZce)->getExtensions(); EXPECT_EQ(ExtsRV64IDZce.size(), 9UL); EXPECT_EQ(ExtsRV64IDZce.count("i"), 1U); + EXPECT_EQ(ExtsRV64IDZce.count("c"), 0U); EXPECT_EQ(ExtsRV64IDZce.count("zicsr"), 1U); EXPECT_EQ(ExtsRV64IDZce.count("f"), 1U); EXPECT_EQ(ExtsRV64IDZce.count("d"), 1U); @@ -957,6 +979,72 @@ TEST(ParseArchString, ZceImplication) { EXPECT_EQ(ExtsRV64IDZce.count("zcmt"), 1U); } +TEST(ParseArchString, ZcaImpliesC) { + // Test Zca implies C behavior matching GCC PR119122 + + // RV32 Zca alone implies C + auto MaybeRV32IZca = RISCVISAInfo::parseArchString("rv32i_zca", true); + ASSERT_THAT_EXPECTED(MaybeRV32IZca, Succeeded()); + const auto &ExtsRV32IZca = (*MaybeRV32IZca)->getExtensions(); + EXPECT_EQ(ExtsRV32IZca.count("c"), 1U); + EXPECT_EQ(ExtsRV32IZca.count("zca"), 1U); + + // RV32 with F: Zca + Zcf implies C + auto MaybeRV32IFZcaZcf = + RISCVISAInfo::parseArchString("rv32if_zca_zcf", true); + ASSERT_THAT_EXPECTED(MaybeRV32IFZcaZcf, Succeeded()); + const auto &ExtsRV32IFZcaZcf = (*MaybeRV32IFZcaZcf)->getExtensions(); + EXPECT_EQ(ExtsRV32IFZcaZcf.count("c"), 1U); + EXPECT_EQ(ExtsRV32IFZcaZcf.count("zca"), 1U); + EXPECT_EQ(ExtsRV32IFZcaZcf.count("zcf"), 1U); + + // RV32 with F but no Zcf: no C + auto MaybeRV32IFZca = RISCVISAInfo::parseArchString("rv32if_zca", true); + ASSERT_THAT_EXPECTED(MaybeRV32IFZca, Succeeded()); + const auto &ExtsRV32IFZca = (*MaybeRV32IFZca)->getExtensions(); + EXPECT_EQ(ExtsRV32IFZca.count("c"), 0U); + EXPECT_EQ(ExtsRV32IFZca.count("zca"), 1U); + + // RV32 with D: Zca + Zcf + Zcd implies C + auto MaybeRV32IDZcaZcfZcd = + RISCVISAInfo::parseArchString("rv32ifd_zca_zcf_zcd", true); + ASSERT_THAT_EXPECTED(MaybeRV32IDZcaZcfZcd, Succeeded()); + const auto &ExtsRV32IDZcaZcfZcd = (*MaybeRV32IDZcaZcfZcd)->getExtensions(); + EXPECT_EQ(ExtsRV32IDZcaZcfZcd.count("c"), 1U); + EXPECT_EQ(ExtsRV32IDZcaZcfZcd.count("zca"), 1U); + EXPECT_EQ(ExtsRV32IDZcaZcfZcd.count("zcf"), 1U); + EXPECT_EQ(ExtsRV32IDZcaZcfZcd.count("zcd"), 1U); + + // RV32 with D but no Zcd: no C + auto MaybeRV32IDZcaZcf = + RISCVISAInfo::parseArchString("rv32ifd_zca_zcf", true); + ASSERT_THAT_EXPECTED(MaybeRV32IDZcaZcf, Succeeded()); + const auto &ExtsRV32IDZcaZcf = (*MaybeRV32IDZcaZcf)->getExtensions(); + EXPECT_EQ(ExtsRV32IDZcaZcf.count("c"), 0U); + + // RV64 Zca alone implies C + auto MaybeRV64IZca = RISCVISAInfo::parseArchString("rv64i_zca", true); + ASSERT_THAT_EXPECTED(MaybeRV64IZca, Succeeded()); + const auto &ExtsRV64IZca = (*MaybeRV64IZca)->getExtensions(); + EXPECT_EQ(ExtsRV64IZca.count("c"), 1U); + EXPECT_EQ(ExtsRV64IZca.count("zca"), 1U); + + // RV64 with D: Zca + Zcd implies C + auto MaybeRV64IDZcaZcd = + RISCVISAInfo::parseArchString("rv64ifd_zca_zcd", true); + ASSERT_THAT_EXPECTED(MaybeRV64IDZcaZcd, Succeeded()); + const auto &ExtsRV64IDZcaZcd = (*MaybeRV64IDZcaZcd)->getExtensions(); + EXPECT_EQ(ExtsRV64IDZcaZcd.count("c"), 1U); + EXPECT_EQ(ExtsRV64IDZcaZcd.count("zca"), 1U); + EXPECT_EQ(ExtsRV64IDZcaZcd.count("zcd"), 1U); + + // RV64 with D but no Zcd: no C + auto MaybeRV64IDZca = RISCVISAInfo::parseArchString("rv64ifd_zca", true); + ASSERT_THAT_EXPECTED(MaybeRV64IDZca, Succeeded()); + const auto &ExtsRV64IDZca = (*MaybeRV64IDZca)->getExtensions(); + EXPECT_EQ(ExtsRV64IDZca.count("c"), 0U); +} + TEST(isSupportedExtensionWithVersion, AcceptsSingleExtensionWithVersion) { EXPECT_TRUE(RISCVISAInfo::isSupportedExtensionWithVersion("zbb1p0")); EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion("zbb")); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
