Index: llvm/lib/Support/RISCVISAInfo.cpp =================================================================== --- llvm/lib/Support/RISCVISAInfo.cpp +++ llvm/lib/Support/RISCVISAInfo.cpp @@ -58,6 +58,7 @@ {"zbkb", RISCVExtensionVersion{1, 0}}, {"zbkc", RISCVExtensionVersion{1, 0}}, + {"zbkx", RISCVExtensionVersion{1, 0}}, {"v", RISCVExtensionVersion{1, 0}}, {"zvl32b", RISCVExtensionVersion{1, 0}}, Index: llvm/lib/Target/RISCV/RISCV.td =================================================================== --- llvm/lib/Target/RISCV/RISCV.td +++ llvm/lib/Target/RISCV/RISCV.td @@ -150,6 +150,19 @@ AssemblerPredicate<(all_of FeatureStdExtZbkb), "'Zbkb' (Bitmanip instructions for Cryptography)">; +def FeatureStdExtZbkx + : SubtargetFeature<"zbkx", "HasStdExtZbkx", "true", + "'Zbkx' (Crossbar permutation instructions)">; +def HasStdExtZbkx : Predicate<"Subtarget->hasStdExtZbkx()">, + AssemblerPredicate<(all_of FeatureStdExtZbkx), + "'Zbkx' (Crossbar permutation instructions)">; + +def HasStdExtZbpOrZbkx + : Predicate<"Subtarget->hasStdExtZbp() || Subtarget->hasStdExtZbkx()">, + AssemblerPredicate<(any_of FeatureStdExtZbp, FeatureStdExtZbkx), + "'Zbp' (Permutation 'Zb' Instructions) or " + "'Zbkx' (Crossbar permutation instructions)">; + def HasStdExtZbpOrZbkb : Predicate<"Subtarget->hasStdExtZbp() || Subtarget->hasStdExtZbkb()">, AssemblerPredicate<(any_of FeatureStdExtZbp, FeatureStdExtZbkb), Index: llvm/lib/Target/RISCV/RISCVInstrInfoZb.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ llvm/lib/Target/RISCV/RISCVInstrInfoZb.td @@ -27,6 +27,7 @@ // versions: // Zbkb - 1.0 // Zbkc - 1.0 +// Zbkx - 1.0 // //===----------------------------------------------------------------------===// @@ -359,9 +360,12 @@ def GREV : ALU_rr<0b0110100, 0b101, "grev">, Sched<[]>; } // Predicates = [HasStdExtZbp] +let Predicates = [HasStdExtZbpOrZbkx] in { +def XPERMN : ALU_rr<0b0010100, 0b010, "xperm4">, Sched<[]>; +def XPERMB : ALU_rr<0b0010100, 0b100, "xperm8">, Sched<[]>; +} // Predicates = [HasStdExtZbpOrZbkx] + let Predicates = [HasStdExtZbp] in { -def XPERMN : ALU_rr<0b0010100, 0b010, "xperm.n">, Sched<[]>; -def XPERMB : ALU_rr<0b0010100, 0b100, "xperm.b">, Sched<[]>; def XPERMH : ALU_rr<0b0010100, 0b110, "xperm.h">, Sched<[]>; } // Predicates = [HasStdExtZbp] @@ -768,6 +772,13 @@ (GORCIW GPR:$rd, GPR:$rs1, uimm5:$shamt), 0>; } // Predicates = [HasStdExtZbp, IsRV64] +// Zbp is unratified and that it would likely adopt the already ratified Zbkx names. +// Thus current Zbp instructions are defined as aliases for Zbkx instructions. +let Predicates = [HasStdExtZbp] in { + def : InstAlias<"xperm.b $rd, $rs1, $rs2", (XPERMB GPR:$rd, GPR:$rs1, GPR:$rs2)>; + def : InstAlias<"xperm.n $rd, $rs1, $rs2", (XPERMN GPR:$rd, GPR:$rs1, GPR:$rs2)>; +} // Predicates = [HasStdExtZbp] + let Predicates = [HasStdExtZbs] in { def : InstAlias<"bset $rd, $rs1, $shamt", (BSETI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>; Index: llvm/lib/Target/RISCV/RISCVSchedRocket.td =================================================================== --- llvm/lib/Target/RISCV/RISCVSchedRocket.td +++ llvm/lib/Target/RISCV/RISCVSchedRocket.td @@ -17,7 +17,8 @@ let LoadLatency = 3; let MispredictPenalty = 3; let CompleteModel = false; - let UnsupportedFeatures = [HasStdExtZbkb, HasStdExtZbkc, HasVInstructions, HasVInstructionsI64]; + let UnsupportedFeatures = [HasStdExtZbkb, HasStdExtZbkc, HasStdExtZbkx, + HasVInstructions, HasVInstructionsI64]; } //===----------------------------------------------------------------------===// Index: llvm/lib/Target/RISCV/RISCVSchedSiFive7.td =================================================================== --- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -15,7 +15,8 @@ let LoadLatency = 3; let MispredictPenalty = 3; let CompleteModel = 0; - let UnsupportedFeatures = [HasStdExtZbkb, HasStdExtZbkc, HasVInstructions]; + let UnsupportedFeatures = [HasStdExtZbkb, HasStdExtZbkc, HasStdExtZbkx, + HasVInstructions]; } // The SiFive7 microarchitecture has two pipelines: A and B. Index: llvm/lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- llvm/lib/Target/RISCV/RISCVSubtarget.h +++ llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -85,6 +85,7 @@ bool HasStdExtZfh = false; bool HasStdExtZbkb = false; bool HasStdExtZbkc = false; + bool HasStdExtZbkx = false; bool HasRV64 = false; bool IsRV32E = false; bool EnableLinkerRelax = false; @@ -160,6 +161,7 @@ bool hasStdExtZfh() const { return HasStdExtZfh; } bool hasStdExtZbkb() const { return HasStdExtZbkb; } bool hasStdExtZbkc() const { return HasStdExtZbkc; } + bool hasStdExtZbkx() const { return HasStdExtZbkx; } bool is64Bit() const { return HasRV64; } bool isRV32E() const { return IsRV32E; } bool enableLinkerRelax() const { return EnableLinkerRelax; } Index: llvm/test/CodeGen/RISCV/attributes.ll =================================================================== --- llvm/test/CodeGen/RISCV/attributes.ll +++ llvm/test/CodeGen/RISCV/attributes.ll @@ -21,6 +21,7 @@ ; RUN: llc -mtriple=riscv32 -mattr=+zbb,+zfh,+v,+f %s -o - | FileCheck --check-prefix=RV32COMBINED %s ; RUN: llc -mtriple=riscv32 -mattr=+zbkb %s -o - | FileCheck --check-prefix=RV32ZBKB %s ; RUN: llc -mtriple=riscv32 -mattr=+zbkc %s -o - | FileCheck --check-prefix=RV32ZBKC %s +; RUN: llc -mtriple=riscv32 -mattr=+zbkx %s -o - | FileCheck --check-prefix=RV32ZBKX %s ; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefix=RV64M %s ; RUN: llc -mtriple=riscv64 -mattr=+a %s -o - | FileCheck --check-prefix=RV64A %s ; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefix=RV64F %s @@ -42,7 +43,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+zbb,+zfh,+v,+f %s -o - | FileCheck --check-prefix=RV64COMBINED %s ; RUN: llc -mtriple=riscv64 -mattr=+zbkb %s -o - | FileCheck --check-prefix=RV64ZBKB %s ; RUN: llc -mtriple=riscv64 -mattr=+zbkc %s -o - | FileCheck --check-prefix=RV64ZBKC %s - +; RUN: llc -mtriple=riscv64 -mattr=+zbkx %s -o - | FileCheck --check-prefix=RV64ZBKX %s ; RV32M: .attribute 5, "rv32i2p0_m2p0" ; RV32A: .attribute 5, "rv32i2p0_a2p0" @@ -65,6 +66,7 @@ ; RV32COMBINED: .attribute 5, "rv32i2p0_f2p0_d2p0_v1p0_zfh1p0_zfhmin1p0_zbb1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" ; RV32ZBKB: .attribute 5, "rv32i2p0_zbkb1p0" ; RV32ZBKC: .attribute 5, "rv32i2p0_zbkc1p0" +; RV32ZBKX: .attribute 5, "rv32i2p0_zbkx1p0" ; RV64M: .attribute 5, "rv64i2p0_m2p0" ; RV64A: .attribute 5, "rv64i2p0_a2p0" @@ -87,6 +89,7 @@ ; RV64COMBINED: .attribute 5, "rv64i2p0_f2p0_d2p0_v1p0_zfh1p0_zfhmin1p0_zbb1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" ; RV64ZBKB: .attribute 5, "rv64i2p0_zbkb1p0" ; RV64ZBKC: .attribute 5, "rv64i2p0_zbkc1p0" +; RV64ZBKX: .attribute 5, "rv64i2p0_zbkx1p0" define i32 @addi(i32 %a) { %1 = add i32 %a, 1 Index: llvm/test/MC/RISCV/attribute-arch.s =================================================================== --- llvm/test/MC/RISCV/attribute-arch.s +++ llvm/test/MC/RISCV/attribute-arch.s @@ -130,3 +130,6 @@ .attribute arch, "rv32i_zbkc1p0" # CHECK: attribute 5, "rv32i2p0_zbkc1p0" + +.attribute arch, "rv32i_zbkx1p0" +# CHECK: attribute 5, "rv32i2p0_zbkx1p0" Index: llvm/test/MC/RISCV/rv32zbkx-invalid.s =================================================================== --- /dev/null +++ llvm/test/MC/RISCV/rv32zbkx-invalid.s @@ -0,0 +1,9 @@ +# RUN: not llvm-mc -triple riscv32 -mattr=+zbkx < %s 2>&1 | FileCheck %s + +# Too few operands +xperm8 t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction +# Too few operands +xperm4 t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction + +# Undefined Zbp instruction in Zbkx +xperm.h t0, t1, t2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zbp' (Permutation 'B' Instructions) \ No newline at end of file Index: llvm/test/MC/RISCV/rv32zbkx-valid.s =================================================================== --- /dev/null +++ llvm/test/MC/RISCV/rv32zbkx-valid.s @@ -0,0 +1,17 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+zbkx -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+zbkx -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=zbkx < %s \ +# RUN: | llvm-objdump --mattr=+zbkx -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=zbkx < %s \ +# RUN: | llvm-objdump --mattr=+zbkx -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: xperm8 t0, t1, t2 +# CHECK-ASM: encoding: [0xb3,0x42,0x73,0x28] +xperm8 t0, t1, t2 +# CHECK-ASM-AND-OBJ: xperm4 t0, t1, t2 +# CHECK-ASM: encoding: [0xb3,0x22,0x73,0x28] +xperm4 t0, t1, t2