// 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;
}
}
// 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));
+}
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<unsigned, const TargetRegisterClass *>
RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
StringRef Constraint,
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;
}
// 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<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
StringRef Constraint, MVT VT) const override;
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
+}
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
+}