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 @@ -45,6 +45,7 @@ // CHECK-NOT: __riscv_zk // CHECK-NOT: __riscv_zicbom // CHECK-NOT: __riscv_zicboz +// CHECK-NOT: __riscv_zcmt // RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32im -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-M-EXT %s @@ -462,3 +463,10 @@ // RUN: %clang -target riscv64 -march=rv64izicbop -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZICBOP-EXT %s // CHECK-ZICBOP-EXT: __riscv_zicbop 1000000{{$}} + +// RUN: %clang -target riscv32 -march=rv32izcmt0p70 -menable-experimental-extensions \ +// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCMT-EXT %s +// RUN: %clang -target riscv64 -march=rv64izcmt0p70 -menable-experimental-extensions \ +// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCMT-EXT %s +// CHECK-ZCMT-EXT: __riscv_zca 70000{{$}} +// CHECK-ZCMT-EXT: __riscv_zcmt 70000{{$}} 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 @@ -113,6 +113,7 @@ {"zbr", RISCVExtensionVersion{0, 93}}, {"zbt", RISCVExtensionVersion{0, 93}}, {"zca", RISCVExtensionVersion{0, 70}}, + {"zcmt", RISCVExtensionVersion{0, 70}}, {"zvfh", RISCVExtensionVersion{0, 1}}, }; @@ -778,6 +779,7 @@ static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"}; static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"}; static const char *ImpliedExtsZvfh[] = {"zve32f"}; +static const char *ImpliedExtsZcmt[] = {"zca"}; struct ImpliedExtsEntry { StringLiteral Name; @@ -793,6 +795,7 @@ // Note: The table needs to be sorted by name. static constexpr ImpliedExtsEntry ImpliedExts[] = { {{"v"}, {ImpliedExtsV}}, + {{"zcmt"}, {ImpliedExtsZcmt}}, {{"zdinx"}, {ImpliedExtsZdinx}}, {{"zfh"}, {ImpliedExtsZfh}}, {{"zfhmin"}, {ImpliedExtsZfhmin}}, diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -567,7 +567,9 @@ bool isUImm2() { return IsUImm<2>(); } bool isUImm3() { return IsUImm<3>(); } bool isUImm5() { return IsUImm<5>(); } + bool isUImm6() { return IsUImm<6>(); } bool isUImm7() { return IsUImm<7>(); } + bool isUImm8() { return IsUImm<8>(); } bool isRnumArg() const { int64_t Imm; @@ -1171,10 +1173,14 @@ return generateImmOutOfRangeError( Operands, ErrorInfo, 1, (1 << 5) - 1, "immediate must be in [0xfffe0, 0xfffff] or"); + case Match_InvalidUImm6: + return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1); case Match_InvalidUImm7Lsb00: return generateImmOutOfRangeError( Operands, ErrorInfo, 0, (1 << 7) - 4, "immediate must be a multiple of 4 bytes in the range"); + case Match_InvalidUImm8: + return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 9) - 1); case Match_InvalidUImm8Lsb00: return generateImmOutOfRangeError( Operands, ErrorInfo, 0, (1 << 8) - 4, diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -360,6 +360,14 @@ "'C' (Compressed Instructions) or " "'Zca' (part of the C extension, excluding compressed floating point loads/stores)">; +def FeatureExtZcmt + : SubtargetFeature<"experimental-zcmt", "HasStdExtZcmt", "true", + "'Zcmt' (table jump instuctions for code-size reduction)", + [FeatureExtZca]>; // TODO: add Zicsr as another dependence +def HasStdExtZcmt : Predicate<"Subtarget->hasStdExtZcmt() && !Subtarget->hasStdExtC()">, + AssemblerPredicate<(all_of FeatureExtZcmt, (not FeatureStdExtC)), + "'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/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1690,5 +1690,6 @@ include "RISCVInstrInfoZb.td" include "RISCVInstrInfoZk.td" include "RISCVInstrInfoV.td" +include "RISCVInstrInfoZc.td" include "RISCVInstrInfoZfh.td" include "RISCVInstrInfoZicbo.td" diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td @@ -0,0 +1,67 @@ +//===-- RISCVInstrInfoZc.td - RISC-V 'Zc' instructions -----*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// This file describes the RISC-V instructions from the 'Zc' Code-size +/// reduction extension, version 0.70.5. +/// This version is still experimental as the 'Zc' extension hasn't been +/// ratified yet. +/// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Operand and SDNode transformation definitions. +//===----------------------------------------------------------------------===// + +def uimm6 : Operand, + ImmLeaf(Imm);}]> { + let ParserMatchClass = UImmAsmOperand<6>; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeUImmOperand<6>"; + let MCOperandPredicate = [{ + int64_t Imm; + if (!MCOp.evaluateAsConstantImm(Imm)) + return false; + return MCOp.isBareSymbolRef(); + }]; +} + +def uimm8 : Operand, + ImmLeaf(Imm);}]> { + let ParserMatchClass = UImmAsmOperand<8>; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeUImmOperand<8>"; + let MCOperandPredicate = [{ + int64_t Imm; + if (!MCOp.evaluateAsConstantImm(Imm)) + return false; + return MCOp.isBareSymbolRef(); + }]; +} + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +let Predicates = [HasStdExtZcmt], +hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { +def CM_JT : RVInst16CJ<0b101, 0b10, (outs), (ins uimm6:$index), + "cm.jt", "$index">{ + bits<6> index; + + let Inst{12-8} = 0b00000; + let Inst{7-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; +} +} 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/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -62,6 +62,7 @@ bool HasStdExtZbs = false; bool HasStdExtZbt = false; bool HasStdExtZca = false; + bool HasStdExtZcmt = false; bool HasStdExtV = false; bool HasStdExtZve32x = false; bool HasStdExtZve32f = false; @@ -171,6 +172,7 @@ bool hasStdExtZbs() const { return HasStdExtZbs; } bool hasStdExtZbt() const { return HasStdExtZbt; } bool hasStdExtZca() const { return HasStdExtZca; } + bool hasStdExtZcmt() const { return HasStdExtZcmt; } bool hasStdExtZvl() const { return ZvlLen != 0; } bool hasStdExtZvfh() const { return HasStdExtZvfh; } bool hasStdExtZfhmin() const { return HasStdExtZfhmin; } 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 @@ -378,3 +378,9 @@ //===----------------------------------------------- def SEED : SysReg<"seed", 0x015>; + +//===----------------------------------------------- +// Table jump base 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 @@ -42,6 +42,7 @@ ; RUN: llc -mtriple=riscv32 -mattr=+zicbom %s -o - | FileCheck --check-prefix=RV32ZICBOM %s ; RUN: llc -mtriple=riscv32 -mattr=+zicboz %s -o - | FileCheck --check-prefix=RV32ZICBOZ %s ; RUN: llc -mtriple=riscv32 -mattr=+zicbop %s -o - | FileCheck --check-prefix=RV32ZICBOP %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zcmt %s -o - | FileCheck --check-prefix=RV32ZCMT %s ; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefix=RV64M %s ; RUN: llc -mtriple=riscv64 -mattr=+zmmul %s -o - | FileCheck --check-prefix=RV64ZMMUL %s ; RUN: llc -mtriple=riscv64 -mattr=+m,+zmmul %s -o - | FileCheck --check-prefix=RV64MZMMUL %s @@ -84,6 +85,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+zicbom %s -o - | FileCheck --check-prefix=RV64ZICBOM %s ; RUN: llc -mtriple=riscv64 -mattr=+zicboz %s -o - | FileCheck --check-prefix=RV64ZICBOZ %s ; RUN: llc -mtriple=riscv64 -mattr=+zicbop %s -o - | FileCheck --check-prefix=RV64ZICBOP %s +; RUN: llc -mtriple=riscv64 -mattr=+experimental-zcmt %s -o - | FileCheck --check-prefix=RV64ZCMT %s ; RV32M: .attribute 5, "rv32i2p0_m2p0" ; RV32ZMMUL: .attribute 5, "rv32i2p0_zmmul1p0" @@ -127,6 +129,7 @@ ; RV32ZICBOM: .attribute 5, "rv32i2p0_zicbom1p0" ; RV32ZICBOZ: .attribute 5, "rv32i2p0_zicboz1p0" ; RV32ZICBOP: .attribute 5, "rv32i2p0_zicbop1p0" +; RV32ZCMT: .attribute 5, "rv32i2p0_zcmt0p70" ; RV64M: .attribute 5, "rv64i2p0_m2p0" ; RV64ZMMUL: .attribute 5, "rv64i2p0_zmmul1p0" @@ -170,6 +173,7 @@ ; RV64ZICBOM: .attribute 5, "rv64i2p0_zicbom1p0" ; RV64ZICBOZ: .attribute 5, "rv64i2p0_zicboz1p0" ; RV64ZICBOP: .attribute 5, "rv64i2p0_zicbop1p0" +; RV64ZCMT: .attribute 5, "rv64i2p0_zcmt0p70" 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 --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -196,3 +196,6 @@ .attribute arch, "rv32izca0p70" # CHECK: attribute 5, "rv32i2p0_zca0p70" + +.attribute arch, "rv32izcmt0p70" +# CHECK: attribute 5, "rv32i2p0_zcmt0p70" 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,5 @@ +# RUN: not llvm-mc -triple=riscv32 -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, 63] +cm.jt 64 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,21 @@ +# 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 + +# CHECK-ASM-AND-OBJ: cm.jt 1 +# CHECK-ASM: encoding: [0x06,0xa0] +cm.jt 1 + +# CHECK-ASM: cm.jalt 1 +# CHECK-OBJ: cm.jt 1 +# CHECK-ASM: encoding: [0x06,0xa0] +cm.jalt 1 + +# CHECK-ASM-AND-OBJ: cm.jalt 64 +# CHECK-ASM: encoding: [0x02,0xa1] +cm.jalt 64 diff --git a/llvm/test/MC/RISCV/rv64zcmt-Invalid.s b/llvm/test/MC/RISCV/rv64zcmt-Invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zcmt-Invalid.s @@ -0,0 +1,5 @@ +# 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, 63] +cm.jt 64 diff --git a/llvm/test/MC/RISCV/rv64zcmt-valid.s b/llvm/test/MC/RISCV/rv64zcmt-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zcmt-valid.s @@ -0,0 +1,21 @@ +# 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 + +# CHECK-ASM-AND-OBJ: cm.jt 1 +# CHECK-ASM: encoding: [0x06,0xa0] +cm.jt 1 + +# CHECK-ASM: cm.jalt 1 +# CHECK-OBJ: cm.jt 1 +# CHECK-ASM: encoding: [0x06,0xa0] +cm.jalt 1 + +# CHECK-ASM-AND-OBJ: cm.jalt 64 +# CHECK-ASM: encoding: [0x02,0xa1] +cm.jalt 64