[RISCV] Add codegen support for RV32D floating point arithmetic operations

llvm-svn: 329874
This commit is contained in:
Alex Bradbury 2018-04-12 05:42:42 +00:00
parent dfaa021e99
commit 5d0dfa5e0e
3 changed files with 289 additions and 1 deletions

View File

@ -121,8 +121,11 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::BR_CC, MVT::f32, Expand);
}
if (Subtarget.hasStdExtD())
if (Subtarget.hasStdExtD()) {
setOperationAction(ISD::FMINNUM, MVT::f64, Legal);
setOperationAction(ISD::FMAXNUM, MVT::f64, Legal);
setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
}
setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
setOperationAction(ISD::BlockAddress, XLenVT, Custom);

View File

@ -191,6 +191,9 @@ def : InstAlias<"fneg.d $rd, $rs", (FSGNJN_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>;
// Pseudo-instructions and codegen patterns
//===----------------------------------------------------------------------===//
class PatFpr64Fpr64<SDPatternOperator OpNode, RVInstR Inst>
: Pat<(OpNode FPR64:$rs1, FPR64:$rs2), (Inst $rs1, $rs2)>;
class PatFpr64Fpr64DynFrm<SDPatternOperator OpNode, RVInstRFrm Inst>
: Pat<(OpNode FPR64:$rs1, FPR64:$rs2), (Inst $rs1, $rs2, 0b111)>;
@ -199,6 +202,32 @@ let Predicates = [HasStdExtD] in {
/// Float arithmetic operations
def : PatFpr64Fpr64DynFrm<fadd, FADD_D>;
def : PatFpr64Fpr64DynFrm<fsub, FSUB_D>;
def : PatFpr64Fpr64DynFrm<fmul, FMUL_D>;
def : PatFpr64Fpr64DynFrm<fdiv, FDIV_D>;
def : Pat<(fsqrt FPR64:$rs1), (FSQRT_D FPR64:$rs1, 0b111)>;
def : Pat<(fneg FPR64:$rs1), (FSGNJN_D $rs1, $rs1)>;
def : Pat<(fabs FPR64:$rs1), (FSGNJX_D $rs1, $rs1)>;
def : PatFpr64Fpr64<fcopysign, FSGNJ_D>;
def : Pat<(fcopysign FPR64:$rs1, (fneg FPR64:$rs2)), (FSGNJN_D $rs1, $rs2)>;
// The RISC-V 2.2 user-level ISA spec defines fmin and fmax as returning the
// canonical NaN when giving a signaling NaN. This doesn't match the LLVM
// behaviour (see https://bugs.llvm.org/show_bug.cgi?id=27363). However, the
// draft 2.3 ISA spec changes the definition of fmin and fmax in a way that
// matches LLVM's fminnum and fmaxnum
// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
def : PatFpr64Fpr64<fminnum, FMIN_D>;
def : PatFpr64Fpr64<fmaxnum, FMAX_D>;
/// Setcc
def : PatFpr64Fpr64<setoeq, FEQ_D>;
def : PatFpr64Fpr64<setolt, FLT_D>;
def : PatFpr64Fpr64<setole, FLE_D>;
/// Loads

View File

@ -21,3 +21,259 @@ define double @fadd_d(double %a, double %b) nounwind {
%1 = fadd double %a, %b
ret double %1
}
define double @fsub_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: fsub_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: fsub.d ft0, ft1, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = fsub double %a, %b
ret double %1
}
define double @fmul_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: fmul_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: fmul.d ft0, ft1, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = fmul double %a, %b
ret double %1
}
define double @fdiv_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: fdiv_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: fdiv.d ft0, ft1, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = fdiv double %a, %b
ret double %1
}
declare double @llvm.sqrt.f32(double)
define double @fsqrt_d(double %a) nounwind {
; RV32IFD-LABEL: fsqrt_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: fsqrt.d ft0, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = call double @llvm.sqrt.f32(double %a)
ret double %1
}
declare double @llvm.copysign.f32(double, double)
define double @fsgnj_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: fsgnj_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: fsgnj.d ft0, ft1, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = call double @llvm.copysign.f32(double %a, double %b)
ret double %1
}
define double @fneg_d(double %a) nounwind {
; RV32IFD-LABEL: fneg_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: fneg.d ft0, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = fsub double -0.0, %a
ret double %1
}
define double @fsgnjn_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: fsgnjn_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: fsgnjn.d ft0, ft1, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = fsub double -0.0, %b
%2 = call double @llvm.copysign.f32(double %a, double %1)
ret double %2
}
declare double @llvm.fabs.f32(double)
define double @fabs_d(double %a) nounwind {
; RV32IFD-LABEL: fabs_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: fabs.d ft0, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = call double @llvm.fabs.f32(double %a)
ret double %1
}
declare double @llvm.minnum.f32(double, double)
define double @fmin_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: fmin_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: fmin.d ft0, ft1, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = call double @llvm.minnum.f32(double %a, double %b)
ret double %1
}
declare double @llvm.maxnum.f32(double, double)
define double @fmax_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: fmax_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: fmax.d ft0, ft1, ft0
; RV32IFD-NEXT: fsd ft0, 8(sp)
; RV32IFD-NEXT: lw a0, 8(sp)
; RV32IFD-NEXT: lw a1, 12(sp)
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = call double @llvm.maxnum.f32(double %a, double %b)
ret double %1
}
define i32 @feq_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: feq_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: feq.d a0, ft1, ft0
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = fcmp oeq double %a, %b
%2 = zext i1 %1 to i32
ret i32 %2
}
define i32 @flt_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: flt_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: flt.d a0, ft1, ft0
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = fcmp olt double %a, %b
%2 = zext i1 %1 to i32
ret i32 %2
}
define i32 @fle_d(double %a, double %b) nounwind {
; RV32IFD-LABEL: fle_d:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: addi sp, sp, -16
; RV32IFD-NEXT: sw a2, 8(sp)
; RV32IFD-NEXT: sw a3, 12(sp)
; RV32IFD-NEXT: fld ft0, 8(sp)
; RV32IFD-NEXT: sw a0, 8(sp)
; RV32IFD-NEXT: sw a1, 12(sp)
; RV32IFD-NEXT: fld ft1, 8(sp)
; RV32IFD-NEXT: fle.d a0, ft1, ft0
; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
%1 = fcmp ole double %a, %b
%2 = zext i1 %1 to i32
ret i32 %2
}