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 @@ -447,3 +447,9 @@ // RUN: %clang -target riscv64 -march=rv64izicboz -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZICBOZ-EXT %s // CHECK-ZICBOZ-EXT: __riscv_zicboz 1000000{{$}} + +// RUN: %clang -target riscv32 -march=rv32izicbop -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZICBOP-EXT %s +// 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{{$}} 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 @@ -98,6 +98,7 @@ {"zicbom", RISCVExtensionVersion{1, 0}}, {"zicboz", RISCVExtensionVersion{1, 0}}, + {"zicbop", RISCVExtensionVersion{1, 0}}, }; static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { 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 @@ -689,6 +689,16 @@ bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); } + bool isSImm12Lsb00000() const { + if (!isImm()) + return false; + RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; + int64_t Imm; + bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); + return IsConstantImm && isShiftedInt<7, 5>(Imm) && + VK == RISCVMCExpr::VK_RISCV_None; + } + bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); } bool isSImm10Lsb0000NonZero() const { @@ -1198,6 +1208,10 @@ return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2, "immediate must be a multiple of 2 bytes in the range"); + case Match_InvalidSImm12Lsb00000: + return generateImmOutOfRangeError( + Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32, + "immediate must be a multiple of 32 bytes in the range"); case Match_InvalidSImm13Lsb0: return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -221,6 +221,7 @@ OPERAND_UIMM7, OPERAND_UIMM12, OPERAND_SIMM12, + OPERAND_SIMM12_LSB00000, OPERAND_UIMM20, OPERAND_UIMMLOG2XLEN, OPERAND_RVKRNUM, 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 @@ -414,6 +414,13 @@ AssemblerPredicate<(all_of FeatureStdExtZicboz), "'Zicboz' (Cache-Block Zero Instructions)">; +def FeatureStdExtZicbop + : SubtargetFeature<"zicbop", "HasStdExtZicbop", "true", + "'Zicbop' (Cache-Block Prefetch Instructions)">; +def HasStdExtZicbop : Predicate<"Subtarget->hasStdExtZicbop()">, + AssemblerPredicate<(all_of FeatureStdExtZicbop), + "'Zicbop' (Cache-Block Prefetch Instructions)">; + def Feature64Bit : SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">; def IsRV64 : Predicate<"Subtarget->is64Bit()">, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -1075,6 +1075,9 @@ case RISCVOp::OPERAND_SIMM12: Ok = isInt<12>(Imm); break; + case RISCVOp::OPERAND_SIMM12_LSB00000: + Ok = isShiftedInt<7, 5>(Imm); + break; case RISCVOp::OPERAND_UIMMLOG2XLEN: if (STI.getTargetTriple().isArch64Bit()) Ok = isUInt<6>(Imm); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicbo.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicbo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZicbo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicbo.td @@ -11,6 +11,26 @@ // //===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// Operand definitions. +//===----------------------------------------------------------------------===// + +// A 12-bit signed immediate where the least significant five bits are zero. +def simm12_lsb00000 : Operand, + ImmLeaf(Imm);}]> { + let ParserMatchClass = SImmAsmOperand<12, "Lsb00000">; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeSImmOperand<12>"; + let MCOperandPredicate = [{ + int64_t Imm; + if (MCOp.evaluateAsConstantImm(Imm)) + return isShiftedInt<7, 5>(Imm); + return MCOp.isBareSymbolRef(); + }]; + let OperandType = "OPERAND_SIMM12_LSB00000"; + let OperandNamespace = "RISCVOp"; +} + //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// @@ -22,6 +42,14 @@ let rd = 0b00000; } +let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in +class Prefetch_ri optype, string opcodestr> + : RVInstS<0b110, OPC_OP_IMM, (outs), (ins GPR:$rs1, simm12_lsb00000:$imm12), + opcodestr, "${imm12}(${rs1})"> { + let Inst{11-7} = 0b00000; + let rs2 = optype; +} + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -35,3 +63,9 @@ let Predicates = [HasStdExtZicboz] in { def CBO_ZERO : CBO_r<0b000000000100, "cbo.zero">, Sched<[]>; } // Predicates = [HasStdExtZicboz] + +let Predicates = [HasStdExtZicbop] in { +def PREFETCH_I : Prefetch_ri<0b00000, "prefetch.i">, Sched<[]>; +def PREFETCH_R : Prefetch_ri<0b00001, "prefetch.r">, Sched<[]>; +def PREFETCH_W : Prefetch_ri<0b00011, "prefetch.w">, Sched<[]>; +} // Predicates = [HasStdExtZicbop] 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 @@ -88,6 +88,7 @@ bool HasStdExtZk = false; bool HasStdExtZicbom = false; bool HasStdExtZicboz = false; + bool HasStdExtZicbop = false; bool HasRV64 = false; bool IsRV32E = false; bool EnableLinkerRelax = false; @@ -182,6 +183,7 @@ bool hasStdExtZkr() const { return HasStdExtZkr; } bool hasStdExtZicbom() const { return HasStdExtZicbom; } bool hasStdExtZicboz() const { return HasStdExtZicboz; } + bool hasStdExtZicbop() const { return HasStdExtZicbop; } bool is64Bit() const { return HasRV64; } bool isRV32E() const { return IsRV32E; } bool enableLinkerRelax() const { return EnableLinkerRelax; } 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 @@ -38,6 +38,7 @@ ; RUN: llc -mtriple=riscv32 -mattr=+zbkb,+zbkc,+zbkx,+zksed,+zksh %s -o - | FileCheck --check-prefix=RV32COMBINEINTOZKS %s ; 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=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 @@ -76,6 +77,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+zbkb,+zbkc,+zbkx,+zksed,+zksh %s -o - | FileCheck --check-prefix=RV64COMBINEINTOZKS %s ; 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 ; RV32M: .attribute 5, "rv32i2p0_m2p0" ; RV32A: .attribute 5, "rv32i2p0_a2p0" @@ -115,6 +117,7 @@ ; RV32COMBINEINTOZKS: .attribute 5, "rv32i2p0_zbkb1p0_zbkc1p0_zbkx1p0_zks1p0_zksed1p0_zksh1p0" ; RV32ZICBOM: .attribute 5, "rv32i2p0_zicbom1p0" ; RV32ZICBOZ: .attribute 5, "rv32i2p0_zicboz1p0" +; RV32ZICBOP: .attribute 5, "rv32i2p0_zicbop1p0" ; RV64M: .attribute 5, "rv64i2p0_m2p0" ; RV64A: .attribute 5, "rv64i2p0_a2p0" @@ -154,6 +157,7 @@ ; RV64COMBINEINTOZKS: .attribute 5, "rv64i2p0_zbkb1p0_zbkc1p0_zbkx1p0_zks1p0_zksed1p0_zksh1p0" ; RV64ZICBOM: .attribute 5, "rv64i2p0_zicbom1p0" ; RV64ZICBOZ: .attribute 5, "rv64i2p0_zicboz1p0" +; RV64ZICBOP: .attribute 5, "rv64i2p0_zicbop1p0" 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 @@ -93,6 +93,9 @@ .attribute arch, "rv32izicboz" # CHECK: attribute 5, "rv32i2p0_zicboz1p0" +.attribute arch, "rv32izicbop" +# CHECK: attribute 5, "rv32i2p0_zicbop1p0" + ## Experimental extensions require version string to be explicitly specified .attribute arch, "rv32izba1p0" diff --git a/llvm/test/MC/RISCV/rv32zicbom-invalid.s b/llvm/test/MC/RISCV/rv32zicbom-invalid.s --- a/llvm/test/MC/RISCV/rv32zicbom-invalid.s +++ b/llvm/test/MC/RISCV/rv32zicbom-invalid.s @@ -22,3 +22,6 @@ # Instructions from other zicbo* extensions aren't available without enabling # the appropriate -mattr flag. cbo.zero (t0) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicboz' (Cache-Block Zero Instructions) +prefetch.i 0(t3) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) +prefetch.r 0(t4) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) +prefetch.w 0(t5) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) diff --git a/llvm/test/MC/RISCV/rv32zicbop-invalid.s b/llvm/test/MC/RISCV/rv32zicbop-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicbop-invalid.s @@ -0,0 +1,29 @@ +# RUN: not llvm-mc -triple riscv32 -mattr=+zicbop < %s 2>&1 | FileCheck %s +# RUN: not llvm-mc -triple riscv64 -mattr=+zicbop < %s 2>&1 | FileCheck %s + +# Memory operand not formatted correctly. +prefetch.i a0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.r 32, a0 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction +prefetch.w a0(32) # CHECK: :[[@LINE]]:14: error: unexpected token + +# Out of range offset. +prefetch.i -2080(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.r 2048(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.w 2050(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] + +# Offsets that aren't multiples of 32. +prefetch.i 31(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.r -31(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.w 2047(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] + +# Symbols should not be accepted. +prefetch.i foo(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.r %lo(foo)(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.w %pcrel_lo(foo)(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] + +# Instructions from other zicbo* extensions aren't available without enabling +# the appropriate -mattr flag. +cbo.clean (t0) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) +cbo.flush (t1) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) +cbo.inval (t2) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) +cbo.zero (t0) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicboz' (Cache-Block Zero Instructions) diff --git a/llvm/test/MC/RISCV/rv32zicbop-valid.s b/llvm/test/MC/RISCV/rv32zicbop-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicbop-valid.s @@ -0,0 +1,40 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+zicbop -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+zicbop -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+zicbop < %s \ +# RUN: | llvm-objdump --mattr=+zicbop -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+zicbop < %s \ +# RUN: | llvm-objdump --mattr=+zicbop -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: prefetch.i -2048(t0) +# CHECK-ASM: encoding: [0x13,0xe0,0x02,0x80] +prefetch.i -2048(t0) +# CHECK-ASM-AND-OBJ: prefetch.i 2016(t0) +# CHECK-ASM: encoding: [0x13,0xe0,0x02,0x7e] +prefetch.i 2016(t0) + +# CHECK-ASM-AND-OBJ: prefetch.r -2048(t1) +# CHECK-ASM: encoding: [0x13,0x60,0x13,0x80] +prefetch.r -0x800(t1) +# CHECK-ASM-AND-OBJ: prefetch.r 2016(t1) +# CHECK-ASM: encoding: [0x13,0x60,0x13,0x7e] +prefetch.r 0x7e0(t1) + +# CHECK-ASM-AND-OBJ: prefetch.w -2048(t2) +# CHECK-ASM: encoding: [0x13,0xe0,0x33,0x80] +prefetch.w -2048(t2) +# CHECK-ASM-AND-OBJ: prefetch.w 2016(t2) +# CHECK-ASM: encoding: [0x13,0xe0,0x33,0x7e] +prefetch.w 2016(t2) + +# Ensure that enabling zicbop doesn't cause issues decoding ori instructions. + +# CHECK-ASM-AND-OBJ: ori a0, a1, -2048 +# CHECK-ASM: encoding: [0x13,0xe5,0x05,0x80] +ori a0, a1, -2048 +# CHECK-ASM-AND-OBJ: ori a0, a1, 0 +# CHECK-ASM: encoding: [0x13,0xe5,0x05,0x00] +ori a0, a1, 0 diff --git a/llvm/test/MC/RISCV/rv32zicboz-invalid.s b/llvm/test/MC/RISCV/rv32zicboz-invalid.s --- a/llvm/test/MC/RISCV/rv32zicboz-invalid.s +++ b/llvm/test/MC/RISCV/rv32zicboz-invalid.s @@ -14,3 +14,6 @@ cbo.clean (t0) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) cbo.flush (t1) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) cbo.inval (t2) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) +prefetch.i 0(t3) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) +prefetch.r 0(t4) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) +prefetch.w 0(t5) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions)