Index: cfe/trunk/lib/Basic/Targets/RISCV.cpp =================================================================== --- cfe/trunk/lib/Basic/Targets/RISCV.cpp +++ cfe/trunk/lib/Basic/Targets/RISCV.cpp @@ -71,6 +71,10 @@ // A 5-bit unsigned immediate for CSR access instructions. Info.setRequiresImmediate(0, 31); return true; + case 'f': + // A floating-point register. + Info.setAllowsRegister(); + return true; } } Index: cfe/trunk/test/CodeGen/riscv-inline-asm.c =================================================================== --- cfe/trunk/test/CodeGen/riscv-inline-asm.c +++ cfe/trunk/test/CodeGen/riscv-inline-asm.c @@ -26,3 +26,15 @@ // CHECK: call void asm sideeffect "", "K"(i32 0) asm volatile ("" :: "K"(0)); } + +float f; +double d; +void test_f() { +// CHECK-LABEL: define void @test_f() +// CHECK: [[FLT_ARG:%[a-zA-Z_0-9]+]] = load float, float* @f +// CHECK: call void asm sideeffect "", "f"(float [[FLT_ARG]]) + asm volatile ("" :: "f"(f)); +// CHECK: [[FLT_ARG:%[a-zA-Z_0-9]+]] = load double, double* @d +// CHECK: call void asm sideeffect "", "f"(double [[FLT_ARG]]) + asm volatile ("" :: "f"(d)); +} Index: llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h =================================================================== --- llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h +++ llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h @@ -92,6 +92,7 @@ // This method returns the name of a target specific DAG node. const char *getTargetNodeName(unsigned Opcode) const override; + ConstraintType getConstraintType(StringRef Constraint) const override; std::pair getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; Index: llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2397,6 +2397,21 @@ return nullptr; } +/// getConstraintType - Given a constraint letter, return the type of +/// constraint it is for this target. +RISCVTargetLowering::ConstraintType +RISCVTargetLowering::getConstraintType(StringRef Constraint) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: + break; + case 'f': + return C_RegisterClass; + } + } + return TargetLowering::getConstraintType(Constraint); +} + std::pair RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, @@ -2407,6 +2422,12 @@ switch (Constraint[0]) { case 'r': return std::make_pair(0U, &RISCV::GPRRegClass); + case 'f': + if (Subtarget.hasStdExtF() && VT == MVT::f32) + return std::make_pair(0U, &RISCV::FPR32RegClass); + if (Subtarget.hasStdExtD() && VT == MVT::f64) + return std::make_pair(0U, &RISCV::FPR64RegClass); + break; default: break; } Index: llvm/trunk/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll =================================================================== --- llvm/trunk/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll +++ llvm/trunk/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32F %s +; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64F %s + +@gd = external global double + +define double @constraint_f_double(double %a) nounwind { +; RV32F-LABEL: constraint_f_double: +; RV32F: # %bb.0: +; RV32F-NEXT: addi sp, sp, -16 +; RV32F-NEXT: sw a0, 8(sp) +; RV32F-NEXT: sw a1, 12(sp) +; RV32F-NEXT: fld ft0, 8(sp) +; RV32F-NEXT: lui a0, %hi(gd) +; RV32F-NEXT: fld ft1, %lo(gd)(a0) +; RV32F-NEXT: #APP +; RV32F-NEXT: fadd.d ft0, ft0, ft1 +; RV32F-NEXT: #NO_APP +; RV32F-NEXT: fsd ft0, 8(sp) +; RV32F-NEXT: lw a0, 8(sp) +; RV32F-NEXT: lw a1, 12(sp) +; RV32F-NEXT: addi sp, sp, 16 +; RV32F-NEXT: ret +; +; RV64F-LABEL: constraint_f_double: +; RV64F: # %bb.0: +; RV64F-NEXT: fmv.d.x ft0, a0 +; RV64F-NEXT: lui a0, %hi(gd) +; RV64F-NEXT: fld ft1, %lo(gd)(a0) +; RV64F-NEXT: #APP +; RV64F-NEXT: fadd.d ft0, ft0, ft1 +; RV64F-NEXT: #NO_APP +; RV64F-NEXT: fmv.x.d a0, ft0 +; RV64F-NEXT: ret + %1 = load double, double* @gd + %2 = tail call double asm "fadd.d $0, $1, $2", "=f,f,f"(double %a, double %1) + ret double %2 +} Index: llvm/trunk/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll =================================================================== --- llvm/trunk/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll +++ llvm/trunk/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32F %s +; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64F %s + +@gf = external global float + +define float @constraint_f_float(float %a) nounwind { +; RV32F-LABEL: constraint_f_float: +; RV32F: # %bb.0: +; RV32F-NEXT: fmv.w.x ft0, a0 +; RV32F-NEXT: lui a0, %hi(gf) +; RV32F-NEXT: flw ft1, %lo(gf)(a0) +; RV32F-NEXT: #APP +; RV32F-NEXT: fadd.s ft0, ft0, ft1 +; RV32F-NEXT: #NO_APP +; RV32F-NEXT: fmv.x.w a0, ft0 +; RV32F-NEXT: ret +; +; RV64F-LABEL: constraint_f_float: +; RV64F: # %bb.0: +; RV64F-NEXT: fmv.w.x ft0, a0 +; RV64F-NEXT: lui a0, %hi(gf) +; RV64F-NEXT: flw ft1, %lo(gf)(a0) +; RV64F-NEXT: #APP +; RV64F-NEXT: fadd.s ft0, ft0, ft1 +; RV64F-NEXT: #NO_APP +; RV64F-NEXT: fmv.x.w a0, ft0 +; RV64F-NEXT: ret + %1 = load float, float* @gf + %2 = tail call float asm "fadd.s $0, $1, $2", "=f,f,f"(float %a, float %1) + ret float %2 +} Index: llvm/trunk/test/CodeGen/RISCV/inline-asm-invalid.ll =================================================================== --- llvm/trunk/test/CodeGen/RISCV/inline-asm-invalid.ll +++ llvm/trunk/test/CodeGen/RISCV/inline-asm-invalid.ll @@ -22,3 +22,11 @@ tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 -1) ret void } + +define void @constraint_f() nounwind { +; CHECK: error: couldn't allocate input reg for constraint 'f' + tail call void asm "fadd.s fa0, fa0, $0", "f"(float 0.0) +; CHECK: error: couldn't allocate input reg for constraint 'f' + tail call void asm "fadd.d fa0, fa0, $0", "f"(double 0.0) + ret void +}