[RISCV] Add support for the various RISC-V FMA instruction variants

Adds support for the various RISC-V FMA instructions (fmadd, fmsub, fnmsub, fnmadd).

The criteria for choosing whether a fused add or subtract is used, as well as
whether the product is negated or not, is whether some of the arguments to the
llvm.fma.* intrinsic are negated or not. In the tests, extraneous fadd
instructions were added to avoid the negation being performed using a xor
trick, which prevented the proper FMA forms from being selected and thus
tested.

The FMA instruction patterns might seem incorrect (e.g., fnmadd: -rs1 * rs2 -
rs3), but they should be correct. The misleading names were inherited from
MIPS, where the negation happens after computing the sum.

The llvm.fmuladd.* intrinsics still do not generate RISC-V FMA instructions,
as that depends on TargetLowering::isFMAFasterthanFMulAndFAdd.

Some comments in the test files about what type of instructions are there
tested were updated, to better reflect the current content of those test
files.

Differential Revision: https://reviews.llvm.org/D54205
Patch by Luís Marques.

llvm-svn: 349023
diff --git a/llvm/test/CodeGen/RISCV/float-intrinsics.ll b/llvm/test/CodeGen/RISCV/float-intrinsics.ll
index 1da644f..57f3a28 100644
--- a/llvm/test/CodeGen/RISCV/float-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/float-intrinsics.ll
@@ -6,7 +6,7 @@
 
 declare float @llvm.sqrt.f32(float)
 
-define float @sqrt_f32(float %a) {
+define float @sqrt_f32(float %a) nounwind {
 ; RV32IF-LABEL: sqrt_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    fmv.w.x ft0, a0
@@ -14,12 +14,12 @@
 ; RV32IF-NEXT:    fmv.x.w a0, ft0
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.sqrt.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.powi.f32(float, i32)
 
-define float @powi_f32(float %a, i32 %b) {
+define float @powi_f32(float %a, i32 %b) nounwind {
 ; RV32IF-LABEL: powi_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -29,12 +29,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.powi.f32(float %a, i32 %b)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.sin.f32(float)
 
-define float @sin_f32(float %a) {
+define float @sin_f32(float %a) nounwind {
 ; RV32IF-LABEL: sin_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -44,12 +44,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.sin.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.cos.f32(float)
 
-define float @cos_f32(float %a) {
+define float @cos_f32(float %a) nounwind {
 ; RV32IF-LABEL: cos_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -59,11 +59,11 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.cos.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 ; The sin+cos combination results in an FSINCOS SelectionDAG node.
-define float @sincos_f32(float %a) {
+define float @sincos_f32(float %a) nounwind {
 ; RV32IF-LABEL: sincos_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -87,12 +87,12 @@
   %1 = call float @llvm.sin.f32(float %a)
   %2 = call float @llvm.cos.f32(float %a)
   %3 = fadd float %1, %2
-	ret float %3
+  ret float %3
 }
 
 declare float @llvm.pow.f32(float, float)
 
-define float @pow_f32(float %a, float %b) {
+define float @pow_f32(float %a, float %b) nounwind {
 ; RV32IF-LABEL: pow_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -102,12 +102,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.pow.f32(float %a, float %b)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.exp.f32(float)
 
-define float @exp_f32(float %a) {
+define float @exp_f32(float %a) nounwind {
 ; RV32IF-LABEL: exp_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -117,12 +117,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.exp.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.exp2.f32(float)
 
-define float @exp2_f32(float %a) {
+define float @exp2_f32(float %a) nounwind {
 ; RV32IF-LABEL: exp2_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -132,12 +132,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.exp2.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.log.f32(float)
 
-define float @log_f32(float %a) {
+define float @log_f32(float %a) nounwind {
 ; RV32IF-LABEL: log_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -147,12 +147,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.log.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.log10.f32(float)
 
-define float @log10_f32(float %a) {
+define float @log10_f32(float %a) nounwind {
 ; RV32IF-LABEL: log10_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -162,12 +162,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.log10.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.log2.f32(float)
 
-define float @log2_f32(float %a) {
+define float @log2_f32(float %a) nounwind {
 ; RV32IF-LABEL: log2_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -177,28 +177,44 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.log2.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.fma.f32(float, float, float)
 
-; TODO: Select RISC-V FMA instruction.
-define float @fma_f32(float %a, float %b, float %c) {
+define float @fma_f32(float %a, float %b, float %c) nounwind {
 ; RV32IF-LABEL: fma_f32:
 ; RV32IF:       # %bb.0:
-; RV32IF-NEXT:    addi sp, sp, -16
-; RV32IF-NEXT:    sw ra, 12(sp)
-; RV32IF-NEXT:    call fmaf
-; RV32IF-NEXT:    lw ra, 12(sp)
-; RV32IF-NEXT:    addi sp, sp, 16
+; RV32IF-NEXT:    fmv.w.x ft0, a2
+; RV32IF-NEXT:    fmv.w.x ft1, a1
+; RV32IF-NEXT:    fmv.w.x ft2, a0
+; RV32IF-NEXT:    fmadd.s ft0, ft2, ft1, ft0
+; RV32IF-NEXT:    fmv.x.w a0, ft0
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.fma.f32(float %a, float %b, float %c)
-	ret float %1
+  ret float %1
+}
+
+declare float @llvm.fmuladd.f32(float, float, float)
+
+define float @fmuladd_f32(float %a, float %b, float %c) nounwind {
+; Use of fmadd depends on TargetLowering::isFMAFasterthanFMulAndFAdd
+; RV32IF-LABEL: fmuladd_f32:
+; RV32IF:       # %bb.0:
+; RV32IF-NEXT:    fmv.w.x ft0, a1
+; RV32IF-NEXT:    fmv.w.x ft1, a0
+; RV32IF-NEXT:    fmul.s ft0, ft1, ft0
+; RV32IF-NEXT:    fmv.w.x ft1, a2
+; RV32IF-NEXT:    fadd.s ft0, ft0, ft1
+; RV32IF-NEXT:    fmv.x.w a0, ft0
+; RV32IF-NEXT:    ret
+  %1 = call float @llvm.fmuladd.f32(float %a, float %b, float %c)
+  ret float %1
 }
 
 declare float @llvm.fabs.f32(float)
 
-define float @fabs_f32(float %a) {
+define float @fabs_f32(float %a) nounwind {
 ; RV32IF-LABEL: fabs_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    lui a1, 524288
@@ -206,7 +222,7 @@
 ; RV32IF-NEXT:    and a0, a0, a1
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.fabs.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.minnum.f32(float, float)
@@ -270,7 +286,7 @@
 
 declare float @llvm.floor.f32(float)
 
-define float @floor_f32(float %a) {
+define float @floor_f32(float %a) nounwind {
 ; RV32IF-LABEL: floor_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -280,12 +296,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.floor.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.ceil.f32(float)
 
-define float @ceil_f32(float %a) {
+define float @ceil_f32(float %a) nounwind {
 ; RV32IF-LABEL: ceil_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -295,12 +311,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.ceil.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.trunc.f32(float)
 
-define float @trunc_f32(float %a) {
+define float @trunc_f32(float %a) nounwind {
 ; RV32IF-LABEL: trunc_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -310,12 +326,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.trunc.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.rint.f32(float)
 
-define float @rint_f32(float %a) {
+define float @rint_f32(float %a) nounwind {
 ; RV32IF-LABEL: rint_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -325,12 +341,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.rint.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.nearbyint.f32(float)
 
-define float @nearbyint_f32(float %a) {
+define float @nearbyint_f32(float %a) nounwind {
 ; RV32IF-LABEL: nearbyint_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -340,12 +356,12 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.nearbyint.f32(float %a)
-	ret float %1
+  ret float %1
 }
 
 declare float @llvm.round.f32(float)
 
-define float @round_f32(float %a) {
+define float @round_f32(float %a) nounwind {
 ; RV32IF-LABEL: round_f32:
 ; RV32IF:       # %bb.0:
 ; RV32IF-NEXT:    addi sp, sp, -16
@@ -355,5 +371,5 @@
 ; RV32IF-NEXT:    addi sp, sp, 16
 ; RV32IF-NEXT:    ret
   %1 = call float @llvm.round.f32(float %a)
-	ret float %1
+  ret float %1
 }