From: Alex Bradbury Date: Fri, 25 Jan 2019 21:06:47 +0000 (+0000) Subject: [RISCV] Add another potential combine to {double,float}-bitmanip-dagcombines.ll X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=22d8eff14e23406a66d04e2636284f79ef533b81;p=llvm [RISCV] Add another potential combine to {double,float}-bitmanip-dagcombines.ll (fcopysign a, (fneg b)) will be expanded to bitwise operations by DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN if the floating point type isn't legal. Arguably it might be worth doing a combine even if it is legal. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@352240 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll b/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll index 7ad72cca60c..4e0fbbd35d6 100644 --- a/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll +++ b/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll @@ -78,3 +78,51 @@ define double @fabs(double %a) nounwind { %1 = call double @llvm.fabs.f64(double %a) ret double %1 } + +declare double @llvm.copysign.f64(double, double) + +; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise +; operations if floating point isn't supported. A combine could be written to +; do the same even when f64 is legal. + +define double @fcopysign_fneg(double %a, double %b) nounwind { +; RV32I-LABEL: fcopysign_fneg: +; RV32I: # %bb.0: +; RV32I-NEXT: not a2, a3 +; RV32I-NEXT: lui a3, 524288 +; RV32I-NEXT: and a2, a2, a3 +; RV32I-NEXT: addi a3, a3, -1 +; RV32I-NEXT: and a1, a1, a3 +; RV32I-NEXT: or a1, a1, a2 +; RV32I-NEXT: ret +; +; RV32IFD-LABEL: fcopysign_fneg: +; 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 +; +; RV64I-LABEL: fcopysign_fneg: +; RV64I: # %bb.0: +; RV64I-NEXT: addi a2, zero, -1 +; RV64I-NEXT: slli a2, a2, 63 +; RV64I-NEXT: not a1, a1 +; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: addi a2, a2, -1 +; RV64I-NEXT: and a0, a0, a2 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: ret + %1 = fneg double %b + %2 = call double @llvm.copysign.f64(double %a, double %1) + ret double %2 +} diff --git a/test/CodeGen/RISCV/float-bitmanip-dagcombines.ll b/test/CodeGen/RISCV/float-bitmanip-dagcombines.ll index 0911481e5c8..01f3152c497 100644 --- a/test/CodeGen/RISCV/float-bitmanip-dagcombines.ll +++ b/test/CodeGen/RISCV/float-bitmanip-dagcombines.ll @@ -2,7 +2,7 @@ ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefix=RV32I %s ; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV32I %s +; RUN: | FileCheck -check-prefix=RV32IF %s ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefix=RV64I %s @@ -19,6 +19,12 @@ define float @fneg(float %a) nounwind { ; RV32I-NEXT: xor a0, a0, a1 ; RV32I-NEXT: ret ; +; RV32IF-LABEL: fneg: +; RV32IF: # %bb.0: +; RV32IF-NEXT: lui a1, 524288 +; RV32IF-NEXT: xor a0, a0, a1 +; RV32IF-NEXT: ret +; ; RV64I-LABEL: fneg: ; RV64I: # %bb.0: ; RV64I-NEXT: lui a1, 524288 @@ -38,6 +44,13 @@ define float @fabs(float %a) nounwind { ; RV32I-NEXT: and a0, a0, a1 ; RV32I-NEXT: ret ; +; RV32IF-LABEL: fabs: +; RV32IF: # %bb.0: +; RV32IF-NEXT: lui a1, 524288 +; RV32IF-NEXT: addi a1, a1, -1 +; RV32IF-NEXT: and a0, a0, a1 +; RV32IF-NEXT: ret +; ; RV64I-LABEL: fabs: ; RV64I: # %bb.0: ; RV64I-NEXT: lui a1, 524288 @@ -47,3 +60,44 @@ define float @fabs(float %a) nounwind { %1 = call float @llvm.fabs.f32(float %a) ret float %1 } + +declare float @llvm.copysign.f32(float, float) + +; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise +; operations if floating point isn't supported. A combine could be written to +; do the same even when f32 is legal. + +define float @fcopysign_fneg(float %a, float %b) nounwind { +; RV32I-LABEL: fcopysign_fneg: +; RV32I: # %bb.0: +; RV32I-NEXT: not a1, a1 +; RV32I-NEXT: lui a2, 524288 +; RV32I-NEXT: and a1, a1, a2 +; RV32I-NEXT: addi a2, a2, -1 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: or a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32IF-LABEL: fcopysign_fneg: +; RV32IF: # %bb.0: +; RV32IF-NEXT: lui a2, 524288 +; RV32IF-NEXT: xor a1, a1, a2 +; RV32IF-NEXT: fmv.w.x ft0, a1 +; RV32IF-NEXT: fmv.w.x ft1, a0 +; RV32IF-NEXT: fsgnj.s ft0, ft1, ft0 +; RV32IF-NEXT: fmv.x.w a0, ft0 +; RV32IF-NEXT: ret +; +; RV64I-LABEL: fcopysign_fneg: +; RV64I: # %bb.0: +; RV64I-NEXT: not a1, a1 +; RV64I-NEXT: lui a2, 524288 +; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: addiw a2, a2, -1 +; RV64I-NEXT: and a0, a0, a2 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: ret + %1 = fneg float %b + %2 = call float @llvm.copysign.f32(float %a, float %1) + ret float %2 +}