diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -58,9 +58,9 @@ // extension that the compiler currently supports. static Optional isExperimentalExtension(StringRef Ext) { - if (Ext == "b" || Ext == "zbb" || Ext == "zbc" || Ext == "zbe" || - Ext == "zbf" || Ext == "zbm" || Ext == "zbp" || Ext == "zbr" || - Ext == "zbs" || Ext == "zbt" || Ext == "zbproposedc") + if (Ext == "b" || Ext == "zba" || Ext == "zbb" || Ext == "zbc" || + Ext == "zbe" || Ext == "zbf" || Ext == "zbm" || Ext == "zbp" || + Ext == "zbr" || Ext == "zbs" || Ext == "zbt" || Ext == "zbproposedc") return RISCVExtensionVersion{"0", "92"}; if (Ext == "v") return RISCVExtensionVersion{"0", "9"}; diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c --- a/clang/test/Driver/riscv-arch.c +++ b/clang/test/Driver/riscv-arch.c @@ -365,6 +365,10 @@ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBB-ZBP-UNDERSCORE %s // RV32-EXPERIMENTAL-ZBB-ZBP-UNDERSCORE: error: invalid arch name 'rv32izbb0p92zbp0p92', multi-character extensions must be separated by underscores +// RUN: %clang -target riscv32-unknown-elf -march=rv32izba0p92 -menable-experimental-extensions -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBA %s +// RV32-EXPERIMENTAL-ZBA: "-target-feature" "+experimental-zba" + // RUN: %clang -target riscv32-unknown-elf -march=rv32iv -### %s -c 2>&1 | \ // RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-V-NOFLAG %s // RV32-EXPERIMENTAL-V-NOFLAG: error: invalid arch name 'rv32iv' 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 @@ -56,6 +56,13 @@ AssemblerPredicate<(all_of FeatureStdExtC), "'C' (Compressed Instructions)">; +def FeatureExtZba + : SubtargetFeature<"experimental-zba", "HasStdExtZba", "true", + "'Zba' (Base 'B' Instructions)">; +def HasStdExtZba : Predicate<"Subtarget->hasStdExtZba()">, + AssemblerPredicate<(all_of FeatureExtZba), + "'Zba' (Address calculation 'B' Instructions)">; + def FeatureExtZbb : SubtargetFeature<"experimental-zbb", "HasStdExtZbb", "true", "'Zbb' (Base 'B' Instructions)">; @@ -137,7 +144,8 @@ def FeatureStdExtB : SubtargetFeature<"experimental-b", "HasStdExtB", "true", "'B' (Bit Manipulation Instructions)", - [FeatureExtZbb, + [FeatureExtZba, + FeatureExtZbb, FeatureExtZbc, FeatureExtZbe, FeatureExtZbf, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td @@ -369,7 +369,7 @@ def UNSHFLI : RVBShfl_ri<0b000010, 0b101, OPC_OP_IMM, "unshfli">, Sched<[]>; } // Predicates = [HasStdExtZbp] -let Predicates = [HasStdExtZbb, IsRV64] in { +let Predicates = [HasStdExtZba, IsRV64] in { def SLLIUW : RVBShift_ri<0b00001, 0b001, OPC_OP_IMM_32, "slli.uw">, Sched<[]>; def ADDUW : ALUW_rr<0b0000100, 0b000, "add.uw">, Sched<[]>; } // Predicates = [HasStdExtZbb, IsRV64] @@ -838,13 +838,16 @@ (SHFLI GPR:$rs1, (i64 1))>; } // Predicates = [HasStdExtZbp, IsRV64] -let Predicates = [HasStdExtZbb, IsRV64] in { +let Predicates = [HasStdExtZba, IsRV64] in { def : Pat<(SLLIUWPat GPR:$rs1, uimm5:$shamt), (SLLIUW GPR:$rs1, uimm5:$shamt)>; def : Pat<(shl (and GPR:$rs1, 0xFFFFFFFF), uimm5:$shamt), (SLLIUW GPR:$rs1, uimm5:$shamt)>; def : Pat<(add GPR:$rs1, (and GPR:$rs2, (i64 0xFFFFFFFF))), (ADDUW GPR:$rs1, GPR:$rs2)>; +} + +let Predicates = [HasStdExtZbb, IsRV64] in { def : Pat<(not (riscv_sllw (not GPR:$rs1), GPR:$rs2)), (SLOW GPR:$rs1, GPR:$rs2)>; def : Pat<(not (riscv_srlw (not GPR:$rs1), GPR:$rs2)), 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 @@ -40,6 +40,7 @@ bool HasStdExtD = false; bool HasStdExtC = false; bool HasStdExtB = false; + bool HasStdExtZba = false; bool HasStdExtZbb = false; bool HasStdExtZbc = false; bool HasStdExtZbe = false; @@ -106,6 +107,7 @@ bool hasStdExtD() const { return HasStdExtD; } bool hasStdExtC() const { return HasStdExtC; } bool hasStdExtB() const { return HasStdExtB; } + bool hasStdExtZba() const { return HasStdExtZba; } bool hasStdExtZbb() const { return HasStdExtZbb; } bool hasStdExtZbc() const { return HasStdExtZbc; } bool hasStdExtZbe() const { return HasStdExtZbe; } diff --git a/llvm/test/CodeGen/RISCV/rv64Zba.ll b/llvm/test/CodeGen/RISCV/rv64Zba.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rv64Zba.ll @@ -0,0 +1,111 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=RV64I +; RUN: llc -mtriple=riscv64 -mattr=+experimental-b -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=RV64IB +; RUN: llc -mtriple=riscv64 -mattr=+experimental-zba -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=RV64IBA + +define i64 @slliuw(i64 %a) nounwind { +; RV64I-LABEL: slliuw: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 1 +; RV64I-NEXT: addi a1, zero, 1 +; RV64I-NEXT: slli a1, a1, 33 +; RV64I-NEXT: addi a1, a1, -2 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64IB-LABEL: slliuw: +; RV64IB: # %bb.0: +; RV64IB-NEXT: slli.uw a0, a0, 1 +; RV64IB-NEXT: ret +; +; RV64IBA-LABEL: slliuw: +; RV64IBA: # %bb.0: +; RV64IBA-NEXT: slli.uw a0, a0, 1 +; RV64IBA-NEXT: ret + %conv1 = shl i64 %a, 1 + %shl = and i64 %conv1, 8589934590 + ret i64 %shl +} + +define i128 @slliuw_2(i32 signext %0, i128* %1) { +; RV64I-LABEL: slliuw_2: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 32 +; RV64I-NEXT: slli a0, a0, 4 +; RV64I-NEXT: add a1, a1, a0 +; RV64I-NEXT: ld a0, 0(a1) +; RV64I-NEXT: ld a1, 8(a1) +; RV64I-NEXT: ret +; +; RV64IB-LABEL: slliuw_2: +; RV64IB: # %bb.0: +; RV64IB-NEXT: slli.uw a0, a0, 4 +; RV64IB-NEXT: add a1, a1, a0 +; RV64IB-NEXT: ld a0, 0(a1) +; RV64IB-NEXT: ld a1, 8(a1) +; RV64IB-NEXT: ret +; +; RV64IBA-LABEL: slliuw_2: +; RV64IBA: # %bb.0: +; RV64IBA-NEXT: slli.uw a0, a0, 4 +; RV64IBA-NEXT: add a1, a1, a0 +; RV64IBA-NEXT: ld a0, 0(a1) +; RV64IBA-NEXT: ld a1, 8(a1) +; RV64IBA-NEXT: ret + %3 = zext i32 %0 to i64 + %4 = getelementptr inbounds i128, i128* %1, i64 %3 + %5 = load i128, i128* %4 + ret i128 %5 +} + +define i64 @adduw(i64 %a, i64 %b) nounwind { +; RV64I-LABEL: adduw: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: srli a1, a1, 32 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: ret +; +; RV64IB-LABEL: adduw: +; RV64IB: # %bb.0: +; RV64IB-NEXT: add.uw a0, a0, a1 +; RV64IB-NEXT: ret +; +; RV64IBA-LABEL: adduw: +; RV64IBA: # %bb.0: +; RV64IBA-NEXT: add.uw a0, a0, a1 +; RV64IBA-NEXT: ret + %and = and i64 %b, 4294967295 + %add = add i64 %and, %a + ret i64 %add +} + +define signext i8 @adduw_2(i32 signext %0, i8* %1) { +; RV64I-LABEL: adduw_2: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 32 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: lb a0, 0(a0) +; RV64I-NEXT: ret +; +; RV64IB-LABEL: adduw_2: +; RV64IB: # %bb.0: +; RV64IB-NEXT: add.uw a0, a1, a0 +; RV64IB-NEXT: lb a0, 0(a0) +; RV64IB-NEXT: ret +; +; RV64IBA-LABEL: adduw_2: +; RV64IBA: # %bb.0: +; RV64IBA-NEXT: add.uw a0, a1, a0 +; RV64IBA-NEXT: lb a0, 0(a0) +; RV64IBA-NEXT: ret + %3 = zext i32 %0 to i64 + %4 = getelementptr inbounds i8, i8* %1, i64 %3 + %5 = load i8, i8* %4 + ret i8 %5 +} diff --git a/llvm/test/CodeGen/RISCV/rv64Zbb.ll b/llvm/test/CodeGen/RISCV/rv64Zbb.ll --- a/llvm/test/CodeGen/RISCV/rv64Zbb.ll +++ b/llvm/test/CodeGen/RISCV/rv64Zbb.ll @@ -987,107 +987,3 @@ %abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true) ret i64 %abs } - -define i64 @slliuw(i64 %a) nounwind { -; RV64I-LABEL: slliuw: -; RV64I: # %bb.0: -; RV64I-NEXT: slli a0, a0, 1 -; RV64I-NEXT: addi a1, zero, 1 -; RV64I-NEXT: slli a1, a1, 33 -; RV64I-NEXT: addi a1, a1, -2 -; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: ret -; -; RV64IB-LABEL: slliuw: -; RV64IB: # %bb.0: -; RV64IB-NEXT: slli.uw a0, a0, 1 -; RV64IB-NEXT: ret -; -; RV64IBB-LABEL: slliuw: -; RV64IBB: # %bb.0: -; RV64IBB-NEXT: slli.uw a0, a0, 1 -; RV64IBB-NEXT: ret - %conv1 = shl i64 %a, 1 - %shl = and i64 %conv1, 8589934590 - ret i64 %shl -} - -define i128 @slliuw_2(i32 signext %0, i128* %1) { -; RV64I-LABEL: slliuw_2: -; RV64I: # %bb.0: -; RV64I-NEXT: slli a0, a0, 32 -; RV64I-NEXT: srli a0, a0, 32 -; RV64I-NEXT: slli a0, a0, 4 -; RV64I-NEXT: add a1, a1, a0 -; RV64I-NEXT: ld a0, 0(a1) -; RV64I-NEXT: ld a1, 8(a1) -; RV64I-NEXT: ret -; -; RV64IB-LABEL: slliuw_2: -; RV64IB: # %bb.0: -; RV64IB-NEXT: slli.uw a0, a0, 4 -; RV64IB-NEXT: add a1, a1, a0 -; RV64IB-NEXT: ld a0, 0(a1) -; RV64IB-NEXT: ld a1, 8(a1) -; RV64IB-NEXT: ret -; -; RV64IBB-LABEL: slliuw_2: -; RV64IBB: # %bb.0: -; RV64IBB-NEXT: slli.uw a0, a0, 4 -; RV64IBB-NEXT: add a1, a1, a0 -; RV64IBB-NEXT: ld a0, 0(a1) -; RV64IBB-NEXT: ld a1, 8(a1) -; RV64IBB-NEXT: ret - %3 = zext i32 %0 to i64 - %4 = getelementptr inbounds i128, i128* %1, i64 %3 - %5 = load i128, i128* %4 - ret i128 %5 -} - -define i64 @adduw(i64 %a, i64 %b) nounwind { -; RV64I-LABEL: adduw: -; RV64I: # %bb.0: -; RV64I-NEXT: slli a1, a1, 32 -; RV64I-NEXT: srli a1, a1, 32 -; RV64I-NEXT: add a0, a1, a0 -; RV64I-NEXT: ret -; -; RV64IB-LABEL: adduw: -; RV64IB: # %bb.0: -; RV64IB-NEXT: add.uw a0, a0, a1 -; RV64IB-NEXT: ret -; -; RV64IBB-LABEL: adduw: -; RV64IBB: # %bb.0: -; RV64IBB-NEXT: add.uw a0, a0, a1 -; RV64IBB-NEXT: ret - %and = and i64 %b, 4294967295 - %add = add i64 %and, %a - ret i64 %add -} - -define signext i8 @adduw_2(i32 signext %0, i8* %1) { -; RV64I-LABEL: adduw_2: -; RV64I: # %bb.0: -; RV64I-NEXT: slli a0, a0, 32 -; RV64I-NEXT: srli a0, a0, 32 -; RV64I-NEXT: add a0, a1, a0 -; RV64I-NEXT: lb a0, 0(a0) -; RV64I-NEXT: ret -; -; RV64IB-LABEL: adduw_2: -; RV64IB: # %bb.0: -; RV64IB-NEXT: add.uw a0, a1, a0 -; RV64IB-NEXT: lb a0, 0(a0) -; RV64IB-NEXT: ret -; -; RV64IBB-LABEL: adduw_2: -; RV64IBB: # %bb.0: -; RV64IBB-NEXT: add.uw a0, a1, a0 -; RV64IBB-NEXT: lb a0, 0(a0) -; RV64IBB-NEXT: ret - %3 = zext i32 %0 to i64 - %4 = getelementptr inbounds i8, i8* %1, i64 %3 - %5 = load i8, i8* %4 - ret i8 %5 -} diff --git a/llvm/test/MC/RISCV/rv64zba-invalid.s b/llvm/test/MC/RISCV/rv64zba-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zba-invalid.s @@ -0,0 +1,9 @@ +# RUN: not llvm-mc -triple riscv64 -mattr=+experimental-b,experimental-zba < %s 2>&1 | FileCheck %s + +# Too few operands +slli.uw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction +# Immediate operand out of range +slli.uw t0, t1, 64 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 63] +slli.uw t0, t1, -1 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 63] +# Too few operands +add.uw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction diff --git a/llvm/test/MC/RISCV/rv64zba-valid.s b/llvm/test/MC/RISCV/rv64zba-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zba-valid.s @@ -0,0 +1,20 @@ +# With B extension: +# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-b -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-b < %s \ +# RUN: | llvm-objdump --mattr=+experimental-b -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# With Bitmanip base extension: +# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zba -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zba < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zba -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: slli.uw t0, t1, 0 +# CHECK-ASM: encoding: [0x9b,0x12,0x03,0x08] +slli.uw t0, t1, 0 +# CHECK-ASM-AND-OBJ: add.uw t0, t1, t2 +# CHECK-ASM: encoding: [0xbb,0x02,0x73,0x08] +add.uw t0, t1, t2 diff --git a/llvm/test/MC/RISCV/rv64zbb-invalid.s b/llvm/test/MC/RISCV/rv64zbb-invalid.s --- a/llvm/test/MC/RISCV/rv64zbb-invalid.s +++ b/llvm/test/MC/RISCV/rv64zbb-invalid.s @@ -1,12 +1,5 @@ # RUN: not llvm-mc -triple riscv64 -mattr=+experimental-b,experimental-zbb < %s 2>&1 | FileCheck %s -# Too few operands -slli.uw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction -# Immediate operand out of range -slli.uw t0, t1, 64 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 63] -slli.uw t0, t1, -1 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 63] -# Too few operands -add.uw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction # Too few operands slow t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction # Too few operands diff --git a/llvm/test/MC/RISCV/rv64zbb-valid.s b/llvm/test/MC/RISCV/rv64zbb-valid.s --- a/llvm/test/MC/RISCV/rv64zbb-valid.s +++ b/llvm/test/MC/RISCV/rv64zbb-valid.s @@ -12,12 +12,6 @@ # RUN: | llvm-objdump --mattr=+experimental-zbb -d -r - \ # RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s -# CHECK-ASM-AND-OBJ: slli.uw t0, t1, 0 -# CHECK-ASM: encoding: [0x9b,0x12,0x03,0x08] -slli.uw t0, t1, 0 -# CHECK-ASM-AND-OBJ: add.uw t0, t1, t2 -# CHECK-ASM: encoding: [0xbb,0x02,0x73,0x08] -add.uw t0, t1, t2 # CHECK-ASM-AND-OBJ: slow t0, t1, t2 # CHECK-ASM: encoding: [0xbb,0x12,0x73,0x20] slow t0, t1, t2