1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \ 3; RUN: | FileCheck -check-prefix=RV32IF %s 4 5define float @fadd_s(float %a, float %b) nounwind { 6; RV32IF-LABEL: fadd_s: 7; RV32IF: # %bb.0: 8; RV32IF-NEXT: fmv.w.x ft0, a1 9; RV32IF-NEXT: fmv.w.x ft1, a0 10; RV32IF-NEXT: fadd.s ft0, ft1, ft0 11; RV32IF-NEXT: fmv.x.w a0, ft0 12; RV32IF-NEXT: ret 13 %1 = fadd float %a, %b 14 ret float %1 15} 16 17define float @fsub_s(float %a, float %b) nounwind { 18; RV32IF-LABEL: fsub_s: 19; RV32IF: # %bb.0: 20; RV32IF-NEXT: fmv.w.x ft0, a1 21; RV32IF-NEXT: fmv.w.x ft1, a0 22; RV32IF-NEXT: fsub.s ft0, ft1, ft0 23; RV32IF-NEXT: fmv.x.w a0, ft0 24; RV32IF-NEXT: ret 25 %1 = fsub float %a, %b 26 ret float %1 27} 28 29define float @fmul_s(float %a, float %b) nounwind { 30; RV32IF-LABEL: fmul_s: 31; RV32IF: # %bb.0: 32; RV32IF-NEXT: fmv.w.x ft0, a1 33; RV32IF-NEXT: fmv.w.x ft1, a0 34; RV32IF-NEXT: fmul.s ft0, ft1, ft0 35; RV32IF-NEXT: fmv.x.w a0, ft0 36; RV32IF-NEXT: ret 37 %1 = fmul float %a, %b 38 ret float %1 39} 40 41define float @fdiv_s(float %a, float %b) nounwind { 42; RV32IF-LABEL: fdiv_s: 43; RV32IF: # %bb.0: 44; RV32IF-NEXT: fmv.w.x ft0, a1 45; RV32IF-NEXT: fmv.w.x ft1, a0 46; RV32IF-NEXT: fdiv.s ft0, ft1, ft0 47; RV32IF-NEXT: fmv.x.w a0, ft0 48; RV32IF-NEXT: ret 49 %1 = fdiv float %a, %b 50 ret float %1 51} 52 53declare float @llvm.sqrt.f32(float) 54 55define float @fsqrt_s(float %a) nounwind { 56; RV32IF-LABEL: fsqrt_s: 57; RV32IF: # %bb.0: 58; RV32IF-NEXT: fmv.w.x ft0, a0 59; RV32IF-NEXT: fsqrt.s ft0, ft0 60; RV32IF-NEXT: fmv.x.w a0, ft0 61; RV32IF-NEXT: ret 62 %1 = call float @llvm.sqrt.f32(float %a) 63 ret float %1 64} 65 66declare float @llvm.copysign.f32(float, float) 67 68define float @fsgnj_s(float %a, float %b) nounwind { 69; RV32IF-LABEL: fsgnj_s: 70; RV32IF: # %bb.0: 71; RV32IF-NEXT: fmv.w.x ft0, a1 72; RV32IF-NEXT: fmv.w.x ft1, a0 73; RV32IF-NEXT: fsgnj.s ft0, ft1, ft0 74; RV32IF-NEXT: fmv.x.w a0, ft0 75; RV32IF-NEXT: ret 76 %1 = call float @llvm.copysign.f32(float %a, float %b) 77 ret float %1 78} 79 80define float @fneg_s(float %a) nounwind { 81; TODO: doesn't test the fneg selection pattern because 82; DAGCombiner::visitBITCAST will generate a xor on the incoming integer 83; argument 84; RV32IF-LABEL: fneg_s: 85; RV32IF: # %bb.0: 86; RV32IF-NEXT: lui a1, 524288 87; RV32IF-NEXT: xor a0, a0, a1 88; RV32IF-NEXT: ret 89 %1 = fsub float -0.0, %a 90 ret float %1 91} 92 93define float @fsgnjn_s(float %a, float %b) nounwind { 94; TODO: fsgnjn.s isn't selected because DAGCombiner::visitBITCAST will convert 95; (bitconvert (fneg x)) to a xor 96; RV32IF-LABEL: fsgnjn_s: 97; RV32IF: # %bb.0: 98; RV32IF-NEXT: lui a2, 524288 99; RV32IF-NEXT: xor a1, a1, a2 100; RV32IF-NEXT: fmv.w.x ft0, a1 101; RV32IF-NEXT: fmv.w.x ft1, a0 102; RV32IF-NEXT: fsgnj.s ft0, ft1, ft0 103; RV32IF-NEXT: fmv.x.w a0, ft0 104; RV32IF-NEXT: ret 105 %1 = fsub float -0.0, %b 106 %2 = call float @llvm.copysign.f32(float %a, float %1) 107 ret float %2 108} 109 110declare float @llvm.fabs.f32(float) 111 112define float @fabs_s(float %a) nounwind { 113; TODO: doesn't test the fabs selection pattern because 114; DAGCombiner::visitBITCAST will generate an and on the incoming integer 115; argument 116; RV32IF-LABEL: fabs_s: 117; RV32IF: # %bb.0: 118; RV32IF-NEXT: lui a1, 524288 119; RV32IF-NEXT: addi a1, a1, -1 120; RV32IF-NEXT: and a0, a0, a1 121; RV32IF-NEXT: ret 122 %1 = call float @llvm.fabs.f32(float %a) 123 ret float %1 124} 125 126declare float @llvm.minnum.f32(float, float) 127 128define float @fmin_s(float %a, float %b) nounwind { 129; RV32IF-LABEL: fmin_s: 130; RV32IF: # %bb.0: 131; RV32IF-NEXT: fmv.w.x ft0, a1 132; RV32IF-NEXT: fmv.w.x ft1, a0 133; RV32IF-NEXT: fmin.s ft0, ft1, ft0 134; RV32IF-NEXT: fmv.x.w a0, ft0 135; RV32IF-NEXT: ret 136 %1 = call float @llvm.minnum.f32(float %a, float %b) 137 ret float %1 138} 139 140declare float @llvm.maxnum.f32(float, float) 141 142define float @fmax_s(float %a, float %b) nounwind { 143; RV32IF-LABEL: fmax_s: 144; RV32IF: # %bb.0: 145; RV32IF-NEXT: fmv.w.x ft0, a1 146; RV32IF-NEXT: fmv.w.x ft1, a0 147; RV32IF-NEXT: fmax.s ft0, ft1, ft0 148; RV32IF-NEXT: fmv.x.w a0, ft0 149; RV32IF-NEXT: ret 150 %1 = call float @llvm.maxnum.f32(float %a, float %b) 151 ret float %1 152} 153 154define i32 @feq_s(float %a, float %b) nounwind { 155; RV32IF-LABEL: feq_s: 156; RV32IF: # %bb.0: 157; RV32IF-NEXT: fmv.w.x ft0, a1 158; RV32IF-NEXT: fmv.w.x ft1, a0 159; RV32IF-NEXT: feq.s a0, ft1, ft0 160; RV32IF-NEXT: ret 161 %1 = fcmp oeq float %a, %b 162 %2 = zext i1 %1 to i32 163 ret i32 %2 164} 165 166define i32 @flt_s(float %a, float %b) nounwind { 167; RV32IF-LABEL: flt_s: 168; RV32IF: # %bb.0: 169; RV32IF-NEXT: fmv.w.x ft0, a1 170; RV32IF-NEXT: fmv.w.x ft1, a0 171; RV32IF-NEXT: flt.s a0, ft1, ft0 172; RV32IF-NEXT: ret 173 %1 = fcmp olt float %a, %b 174 %2 = zext i1 %1 to i32 175 ret i32 %2 176} 177 178define i32 @fle_s(float %a, float %b) nounwind { 179; RV32IF-LABEL: fle_s: 180; RV32IF: # %bb.0: 181; RV32IF-NEXT: fmv.w.x ft0, a1 182; RV32IF-NEXT: fmv.w.x ft1, a0 183; RV32IF-NEXT: fle.s a0, ft1, ft0 184; RV32IF-NEXT: ret 185 %1 = fcmp ole float %a, %b 186 %2 = zext i1 %1 to i32 187 ret i32 %2 188} 189