diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -97,6 +97,8 @@ bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override; + std::string convertConstraint(const char *&Constraint) const override; + bool hasFeature(StringRef Feature) const override; bool handleTargetFeatures(std::vector &Features, diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -31,7 +31,13 @@ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", - "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}; + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", + + // Vector registers + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"}; return llvm::makeArrayRef(GCCRegNames); } @@ -81,7 +87,29 @@ // An address that is held in a general-purpose register. Info.setAllowsMemory(); return true; + case 'v': + // A vector register. + if (Name[1] == 'r' || Name[1] == 'm') { + Info.setAllowsRegister(); + Name += 1; + return true; + } + return false; + } +} + +std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const { + std::string R; + switch (*Constraint) { + case 'v': + R = std::string("v"); + Constraint += 1; + break; + default: + R = TargetInfo::convertConstraint(Constraint); + break; } + return R; } void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm-rvv.c b/clang/test/CodeGen/RISCV/riscv-inline-asm-rvv.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm-rvv.c @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +experimental-v \ +// RUN: -O2 -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-v \ +// RUN: -O2 -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +// Test RISC-V V-extension specific inline assembly constraints. +#include + +void test_v_reg() { + asm volatile( + "vsetvli x1, x0, e32,m2,tu,mu\n" + "vadd.vv v1, v2, v3, v0.t" + : + : + : "v1", "x1"); +// CHECK-LABEL: define{{.*}} @test_v_reg +// CHECK: "~{v1},~{x1}" +} + +vint32m1_t test_vr(vint32m1_t a, vint32m1_t b) { +// CHECK-LABEL: define{{.*}} @test_vr +// CHECK: %0 = tail call asm sideeffect "vadd.vv $0, $1, $2", "=v,v,v"( %a, %b) + vint32m1_t ret; + asm volatile ("vadd.vv %0, %1, %2" : "=vr"(ret) : "vr"(a), "vr"(b)); + return ret; +} + +vbool1_t test_vm(vbool1_t a, vbool1_t b) { +// CHECK-LABEL: define{{.*}} @test_vm +// CHECK: %0 = tail call asm sideeffect "vmand.mm $0, $1, $2", "=v,v,v"( %a, %b) + vbool1_t ret; + asm volatile ("vmand.mm %0, %1, %2" : "=vm"(ret) : "vm"(a), "vm"(b)); + return ret; +}