diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -48,6 +48,7 @@ // CHECK-NOT: __riscv_zcb {{.*$}} // CHECK-NOT: __riscv_zcd {{.*$}} // CHECK-NOT: __riscv_zcf {{.*$}} +// CHECK-NOT: __riscv_zcmt {{.*$}} // CHECK-NOT: __riscv_h {{.*$}} // CHECK-NOT: __riscv_zvbb {{.*$}} // CHECK-NOT: __riscv_zvbc {{.*$}} @@ -511,6 +512,13 @@ // RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCF-EXT %s // CHECK-ZCF-EXT: __riscv_zcf 1000000{{$}} +// RUN: %clang -target riscv32 -march=rv32izcmt1p0 -menable-experimental-extensions \ +// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCMT-EXT %s +// RUN: %clang -target riscv64 -march=rv64izcmt1p0 -menable-experimental-extensions \ +// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCMT-EXT %s +// CHECK-ZCMT-EXT: __riscv_zca 1000000{{$}} +// CHECK-ZCMT-EXT: __riscv_zcmt 1000000{{$}} + // RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32izicsr2p0 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZICSR-EXT %s // RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64izicsr2p0 -x c -E -dM %s \ diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -195,6 +195,9 @@ ``experimental-zcf`` LLVM implements the `1.0.1 draft specification `__. +``experimental-zcmt`` + LLVM implements the `1.0.1 draft specification `_. + ``experimental-zfa`` LLVM implements the `0.2 draft specification `__. diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -144,6 +144,7 @@ {"zcb", RISCVExtensionVersion{1, 0}}, {"zcd", RISCVExtensionVersion{1, 0}}, {"zcf", RISCVExtensionVersion{1, 0}}, + {"zcmt", RISCVExtensionVersion{1, 0}}, {"zfa", RISCVExtensionVersion{0, 2}}, {"zicond", RISCVExtensionVersion{1, 0}}, {"zvfh", RISCVExtensionVersion{0, 1}}, @@ -851,6 +852,7 @@ } Error RISCVISAInfo::checkDependency() { + bool HasC = Exts.count("c") != 0; bool HasD = Exts.count("d") != 0; bool HasF = Exts.count("f") != 0; bool HasZfinx = Exts.count("zfinx") != 0; @@ -859,6 +861,8 @@ bool HasZve32f = Exts.count("zve32f") != 0; bool HasZve64d = Exts.count("zve64d") != 0; bool HasZvl = MinVLen != 0; + bool HasZcmt = Exts.count("zcmt") != 0; + bool HasZcd = Exts.count("zcd") != 0; if (HasF && HasZfinx) return createStringError(errc::invalid_argument, @@ -908,6 +912,16 @@ errc::invalid_argument, "'zvknhb' requires 'v' or 'zve64*' extension to also be specified"); + if (HasZcmt && HasD && HasC) + return createStringError( + errc::invalid_argument, + "'zcmt' is incompatible with 'c' extension when 'd' extension is set"); + + if (HasZcmt && HasD && HasZcd) + return createStringError(errc::invalid_argument, + "'zcmt' is incompatible with 'zcd' extension when " + "'d' extension is set"); + // Additional dependency checks. // TODO: The 'q' extension requires rv64. // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. @@ -921,6 +935,7 @@ static const char *ImpliedExtsXTHeadVdot[] = {"v"}; static const char *ImpliedExtsXsfvcp[] = {"zve32x"}; static const char *ImpliedExtsZcb[] = {"zca"}; +static const char *ImpliedExtsZcmt[] = {"zca"}; static const char *ImpliedExtsZdinx[] = {"zfinx"}; static const char *ImpliedExtsZfa[] = {"f"}; static const char *ImpliedExtsZfh[] = {"f"}; @@ -978,6 +993,7 @@ {{"xsfvcp"}, {ImpliedExtsXsfvcp}}, {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}}, {{"zcb"}, {ImpliedExtsZcb}}, + {{"zcmt"}, {ImpliedExtsZcmt}}, {{"zdinx"}, {ImpliedExtsZdinx}}, {{"zfa"}, {ImpliedExtsZfa}}, {{"zfh"}, {ImpliedExtsZfh}}, diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -361,6 +361,14 @@ "'C' (Compressed Instructions) or " "'Zcf' (Compressed Single-Precision Floating-Point Instructions)">; +def FeatureStdExtZcmt + : SubtargetFeature<"experimental-zcmt", "HasStdExtZcmt", "true", + "'Zcmt' (table jump instuctions for code-size reduction)", + [FeatureStdExtZca, FeatureStdExtZicsr]>; +def HasStdExtZcmt : Predicate<"Subtarget->hasStdExtZcmt()">, + AssemblerPredicate<(all_of FeatureStdExtZcmt), + "'Zcmt' (table jump instuctions for code-size reduction)">; + def FeatureNoRVCHints : SubtargetFeature<"no-rvc-hints", "EnableRVCHintInstrs", "false", "Disable RVC Hint Instructions.">; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td @@ -125,6 +125,26 @@ Sched<[WriteSTH, ReadStoreData, ReadMemBase]>; } +let Predicates = [HasStdExtZcmt], +hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { +def CM_JT : RVInst16CJ<0b101, 0b10, (outs), (ins uimm5:$index), + "cm.jt", "$index">{ + bits<5> index; + + let Inst{12-7} = 0b000000; + let Inst{6-2} = index; +} + +def CM_JALT : RVInst16CJ<0b101, 0b10, (outs), (ins uimm8:$index), + "cm.jalt", "$index">{ + bits<8> index; + + let Inst{12-10} = 0b000; + let Inst{9-2} = index; +} +} // Predicates = [HasStdExtZcmt] + + let Predicates = [HasStdExtZcb, HasStdExtMOrZmmul] in{ def : CompressPat<(MUL GPRC:$rs1, GPRC:$rs1, GPRC:$rs2), (C_MUL GPRC:$rs1, GPRC:$rs2)>; diff --git a/llvm/lib/Target/RISCV/RISCVSchedRocket.td b/llvm/lib/Target/RISCV/RISCVSchedRocket.td --- a/llvm/lib/Target/RISCV/RISCVSchedRocket.td +++ b/llvm/lib/Target/RISCV/RISCVSchedRocket.td @@ -18,9 +18,9 @@ let MispredictPenalty = 3; let CompleteModel = false; let UnsupportedFeatures = [HasStdExtZbkb, HasStdExtZbkc, HasStdExtZbkx, - HasStdExtZknd, HasStdExtZkne, HasStdExtZknh, - HasStdExtZksed, HasStdExtZksh, HasStdExtZkr, - HasVInstructions, HasVInstructionsI64]; + HasStdExtZcmt, HasStdExtZknd, HasStdExtZkne, + HasStdExtZknh, HasStdExtZksed, HasStdExtZksh, + HasStdExtZkr, HasVInstructions, HasVInstructionsI64]; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -16,9 +16,9 @@ let MispredictPenalty = 3; let CompleteModel = 0; let UnsupportedFeatures = [HasStdExtZbkb, HasStdExtZbkc, HasStdExtZbkx, - HasStdExtZknd, HasStdExtZkne, HasStdExtZknh, - HasStdExtZksed, HasStdExtZksh, HasStdExtZkr, - HasVInstructions]; + HasStdExtZcmt, HasStdExtZknd, HasStdExtZkne, + HasStdExtZknh, HasStdExtZksed, HasStdExtZksh, + HasStdExtZkr, HasVInstructions]; } // The SiFive7 microarchitecture has two pipelines: A and B. diff --git a/llvm/lib/Target/RISCV/RISCVSystemOperands.td b/llvm/lib/Target/RISCV/RISCVSystemOperands.td --- a/llvm/lib/Target/RISCV/RISCVSystemOperands.td +++ b/llvm/lib/Target/RISCV/RISCVSystemOperands.td @@ -407,3 +407,8 @@ def : SysReg<"vsieh", 0x214>; def : SysReg<"vsiph", 0x254>; } // isRV32Only + +// Jump Vector Table CSR +//===----------------------------------------------- + +def : SysReg<"jvt", 0x017>; diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -52,6 +52,7 @@ ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zcb %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCB %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zcd %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCD %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zcf %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCF %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zcmt %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCMT %s ; RUN: llc -mtriple=riscv32 -mattr=+zicsr %s -o - | FileCheck --check-prefixes=CHECK,RV32ZICSR %s ; RUN: llc -mtriple=riscv32 -mattr=+zifencei %s -o - | FileCheck --check-prefixes=CHECK,RV32ZIFENCEI %s ; RUN: llc -mtriple=riscv32 -mattr=+zicntr %s -o - | FileCheck --check-prefixes=CHECK,RV32ZICNTR %s @@ -132,6 +133,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zca %s -o - | FileCheck --check-prefixes=CHECK,RV64ZCA %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zcb %s -o - | FileCheck --check-prefixes=CHECK,RV64ZCB %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zcd %s -o - | FileCheck --check-prefixes=CHECK,RV64ZCD %s +; RUN: llc -mtriple=riscv64 -mattr=+experimental-zcmt %s -o - | FileCheck --check-prefixes=CHECK,RV64ZCMT %s ; RUN: llc -mtriple=riscv64 -mattr=+zicsr %s -o - | FileCheck --check-prefixes=CHECK,RV64ZICSR %s ; RUN: llc -mtriple=riscv64 -mattr=+zifencei %s -o - | FileCheck --check-prefixes=CHECK,RV64ZIFENCEI %s ; RUN: llc -mtriple=riscv64 -mattr=+zicntr %s -o - | FileCheck --check-prefixes=CHECK,RV64ZICNTR %s @@ -207,6 +209,7 @@ ; RV32ZCB: .attribute 5, "rv32i2p1_zca1p0_zcb1p0" ; RV32ZCD: .attribute 5, "rv32i2p1_zcd1p0" ; RV32ZCF: .attribute 5, "rv32i2p1_zcf1p0" +; RV32ZCMT: .attribute 5, "rv32i2p1_zicsr2p0_zca1p0_zcmt1p0" ; RV32ZICSR: .attribute 5, "rv32i2p1_zicsr2p0" ; RV32ZIFENCEI: .attribute 5, "rv32i2p1_zifencei2p0" ; RV32ZICNTR: .attribute 5, "rv32i2p1_zicntr1p0_zicsr2p0" @@ -286,6 +289,7 @@ ; RV64ZCA: .attribute 5, "rv64i2p1_zca1p0" ; RV64ZCB: .attribute 5, "rv64i2p1_zca1p0_zcb1p0" ; RV64ZCD: .attribute 5, "rv64i2p1_zcd1p0" +; RV64ZCMT: .attribute 5, "rv64i2p1_zicsr2p0_zca1p0_zcmt1p0" ; RV64ZICSR: .attribute 5, "rv64i2p1_zicsr2p0" ; RV64ZIFENCEI: .attribute 5, "rv64i2p1_zifencei2p0" ; RV64ZICNTR: .attribute 5, "rv64i2p1_zicntr1p0_zicsr2p0" diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -231,6 +231,9 @@ .attribute arch, "rv32izcb1p0" # CHECK: attribute 5, "rv32i2p1_zca1p0_zcb1p0" +.attribute arch, "rv32izcmt1p0" +# CHECK: attribute 5, "rv32i2p1_zca1p0_zcmt1p0" + .attribute arch, "rv64i_xsfvcp" # CHECK: attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_xsfvcp1p0" diff --git a/llvm/test/MC/RISCV/rv32zcmt-invalid.s b/llvm/test/MC/RISCV/rv32zcmt-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zcmt-invalid.s @@ -0,0 +1,10 @@ +# RUN: not llvm-mc -triple=riscv32 -mattr=+experimental-zcmt -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-ERROR %s +# RUN: not llvm-mc -triple=riscv64 -mattr=+experimental-zcmt -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-ERROR %s + +# CHECK-ERROR: error: immediate must be an integer in the range [0, 31] +cm.jt 64 + +# CHECK-ERROR: error: immediate must be an integer in the range [0, 255] +cm.jalt 256 diff --git a/llvm/test/MC/RISCV/rv32zcmt-valid.s b/llvm/test/MC/RISCV/rv32zcmt-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zcmt-valid.s @@ -0,0 +1,39 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zcmt\ +# RUN: -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zcmt\ +# RUN: -mattr=m < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zcmt\ +# RUN: -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefixes=CHECK-OBJ,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zcmt\ +# RUN: -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zcmt\ +# RUN: -mattr=m < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zcmt\ +# RUN: -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefixes=CHECK-OBJ,CHECK-ASM-AND-OBJ %s +# +# RUN: not llvm-mc -triple riscv32 \ +# RUN: -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s +# RUN: not llvm-mc -triple riscv64 \ +# RUN: -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s + +# CHECK-ASM-AND-OBJ: cm.jt 1 +# CHECK-ASM: encoding: [0x06,0xa0] +# CHECK-NO-EXT: error: instruction requires the following: 'Zcmt' (table jump instuctions for code-size reduction){{$}} +cm.jt 1 + +# CHECK-ASM: cm.jalt 1 +# CHECK-OBJ: cm.jt 1 +# CHECK-ASM: encoding: [0x06,0xa0] +# CHECK-NO-EXT: error: instruction requires the following: 'Zcmt' (table jump instuctions for code-size reduction){{$}} +cm.jalt 1 + +# CHECK-ASM-AND-OBJ: cm.jalt 32 +# CHECK-ASM: encoding: [0x82,0xa0] +# CHECK-NO-EXT: error: instruction requires the following: 'Zcmt' (table jump instuctions for code-size reduction){{$}} +cm.jalt 32 diff --git a/llvm/test/MC/RISCV/rvzcmt-user-csr-name.s b/llvm/test/MC/RISCV/rvzcmt-user-csr-name.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rvzcmt-user-csr-name.s @@ -0,0 +1,29 @@ +# RUN: llvm-mc %s -triple=riscv32 -riscv-no-aliases -mattr=+experimental-zcmt -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-INST,CHECK-ENC %s +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-zcmt < %s \ +# RUN: | llvm-objdump -d --mattr=+experimental-zcmt - \ +# RUN: | FileCheck -check-prefix=CHECK-INST-ALIAS %s +# +# RUN: llvm-mc %s -triple=riscv64 -riscv-no-aliases -mattr=+experimental-zcmt -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-INST,CHECK-ENC %s +# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zcmt < %s \ +# RUN: | llvm-objdump -d --mattr=+experimental-zcmt - \ +# RUN: | FileCheck -check-prefix=CHECK-INST-ALIAS %s + +################################## +# Jump Vector Table CSR +################################## + +# jvt +# name +# CHECK-INST: csrrs t1, jvt, zero +# CHECK-ENC: encoding: [0x73,0x23,0x70,0x01] +# CHECK-INST-ALIAS: csrr t1, jvt +# uimm12 +# CHECK-INST: csrrs t2, jvt, zero +# CHECK-ENC: encoding: [0xf3,0x23,0x70,0x01] +# CHECK-INST-ALIAS: csrr t2, jvt +# name +csrrs t1, jvt, zero +# uimm12 +csrrs t2, 0x017, zero