165 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=riscv32 -target-abi=ilp32 -verify-machineinstrs < %s \3; RUN: | FileCheck -check-prefix=RV32I %s4; RUN: llc -mtriple=riscv32 -target-abi=ilp32 -mattr=+d -verify-machineinstrs < %s \5; RUN: | FileCheck -check-prefix=RV32IFD %s6; RUN: llc -mtriple=riscv32 -target-abi=ilp32 -mattr=+zdinx -verify-machineinstrs < %s \7; RUN: | FileCheck -check-prefix=RV32IZFINXZDINX %s8; RUN: llc -mtriple=riscv64 -target-abi=lp64 -verify-machineinstrs < %s \9; RUN: | FileCheck -check-prefix=RV64I %s10; RUN: llc -mtriple=riscv64 -target-abi=lp64 -mattr=+d -verify-machineinstrs < %s \11; RUN: | FileCheck -check-prefix=RV64IFD %s12; RUN: llc -mtriple=riscv64 -target-abi=lp64 -mattr=+zdinx -verify-machineinstrs < %s \13; RUN: | FileCheck -check-prefix=RV64IZFINXZDINX %s14;15; This file tests cases where simple floating point operations can be16; profitably handled though bit manipulation if a soft-float ABI is being used17; (e.g. fneg implemented by XORing the sign bit). This is typically handled in18; DAGCombiner::visitBITCAST, but this target-independent code may not trigger19; in cases where we perform custom legalisation (e.g. RV32IFD).20 21; TODO: Add an appropriate target-specific DAG combine that can handle22; RISCVISD::SplitF64/BuildPairF64 used for RV32IFD.23 24define double @fneg(double %a) nounwind {25; RV32I-LABEL: fneg:26; RV32I: # %bb.0:27; RV32I-NEXT: lui a2, 52428828; RV32I-NEXT: xor a1, a1, a229; RV32I-NEXT: ret30;31; RV32IFD-LABEL: fneg:32; RV32IFD: # %bb.0:33; RV32IFD-NEXT: lui a2, 52428834; RV32IFD-NEXT: xor a1, a1, a235; RV32IFD-NEXT: ret36;37; RV32IZFINXZDINX-LABEL: fneg:38; RV32IZFINXZDINX: # %bb.0:39; RV32IZFINXZDINX-NEXT: fneg.d a0, a040; RV32IZFINXZDINX-NEXT: ret41;42; RV64I-LABEL: fneg:43; RV64I: # %bb.0:44; RV64I-NEXT: li a1, -145; RV64I-NEXT: slli a1, a1, 6346; RV64I-NEXT: xor a0, a0, a147; RV64I-NEXT: ret48;49; RV64IFD-LABEL: fneg:50; RV64IFD: # %bb.0:51; RV64IFD-NEXT: li a1, -152; RV64IFD-NEXT: slli a1, a1, 6353; RV64IFD-NEXT: xor a0, a0, a154; RV64IFD-NEXT: ret55;56; RV64IZFINXZDINX-LABEL: fneg:57; RV64IZFINXZDINX: # %bb.0:58; RV64IZFINXZDINX-NEXT: fneg.d a0, a059; RV64IZFINXZDINX-NEXT: ret60 %1 = fneg double %a61 ret double %162}63 64define double @fabs(double %a) nounwind {65; RV32I-LABEL: fabs:66; RV32I: # %bb.0:67; RV32I-NEXT: slli a1, a1, 168; RV32I-NEXT: srli a1, a1, 169; RV32I-NEXT: ret70;71; RV32IFD-LABEL: fabs:72; RV32IFD: # %bb.0:73; RV32IFD-NEXT: slli a1, a1, 174; RV32IFD-NEXT: srli a1, a1, 175; RV32IFD-NEXT: ret76;77; RV32IZFINXZDINX-LABEL: fabs:78; RV32IZFINXZDINX: # %bb.0:79; RV32IZFINXZDINX-NEXT: fabs.d a0, a080; RV32IZFINXZDINX-NEXT: ret81;82; RV64I-LABEL: fabs:83; RV64I: # %bb.0:84; RV64I-NEXT: slli a0, a0, 185; RV64I-NEXT: srli a0, a0, 186; RV64I-NEXT: ret87;88; RV64IFD-LABEL: fabs:89; RV64IFD: # %bb.0:90; RV64IFD-NEXT: slli a0, a0, 191; RV64IFD-NEXT: srli a0, a0, 192; RV64IFD-NEXT: ret93;94; RV64IZFINXZDINX-LABEL: fabs:95; RV64IZFINXZDINX: # %bb.0:96; RV64IZFINXZDINX-NEXT: fabs.d a0, a097; RV64IZFINXZDINX-NEXT: ret98 %1 = call double @llvm.fabs.f64(double %a)99 ret double %1100}101 102; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise103; operations if floating point isn't supported. A combine could be written to104; do the same even when f64 is legal.105 106define double @fcopysign_fneg(double %a, double %b) nounwind {107; RV32I-LABEL: fcopysign_fneg:108; RV32I: # %bb.0:109; RV32I-NEXT: not a2, a3110; RV32I-NEXT: lui a3, 524288111; RV32I-NEXT: slli a1, a1, 1112; RV32I-NEXT: and a2, a2, a3113; RV32I-NEXT: srli a1, a1, 1114; RV32I-NEXT: or a1, a1, a2115; RV32I-NEXT: ret116;117; RV32IFD-LABEL: fcopysign_fneg:118; RV32IFD: # %bb.0:119; RV32IFD-NEXT: addi sp, sp, -16120; RV32IFD-NEXT: sw a2, 8(sp)121; RV32IFD-NEXT: sw a3, 12(sp)122; RV32IFD-NEXT: fld fa5, 8(sp)123; RV32IFD-NEXT: sw a0, 8(sp)124; RV32IFD-NEXT: sw a1, 12(sp)125; RV32IFD-NEXT: fld fa4, 8(sp)126; RV32IFD-NEXT: fsgnjn.d fa5, fa4, fa5127; RV32IFD-NEXT: fsd fa5, 8(sp)128; RV32IFD-NEXT: lw a0, 8(sp)129; RV32IFD-NEXT: lw a1, 12(sp)130; RV32IFD-NEXT: addi sp, sp, 16131; RV32IFD-NEXT: ret132;133; RV32IZFINXZDINX-LABEL: fcopysign_fneg:134; RV32IZFINXZDINX: # %bb.0:135; RV32IZFINXZDINX-NEXT: fsgnjn.d a0, a0, a2136; RV32IZFINXZDINX-NEXT: ret137;138; RV64I-LABEL: fcopysign_fneg:139; RV64I: # %bb.0:140; RV64I-NEXT: not a1, a1141; RV64I-NEXT: slli a0, a0, 1142; RV64I-NEXT: srli a0, a0, 1143; RV64I-NEXT: srli a1, a1, 63144; RV64I-NEXT: slli a1, a1, 63145; RV64I-NEXT: or a0, a0, a1146; RV64I-NEXT: ret147;148; RV64IFD-LABEL: fcopysign_fneg:149; RV64IFD: # %bb.0:150; RV64IFD-NEXT: fmv.d.x fa5, a0151; RV64IFD-NEXT: not a0, a1152; RV64IFD-NEXT: fmv.d.x fa4, a0153; RV64IFD-NEXT: fsgnj.d fa5, fa5, fa4154; RV64IFD-NEXT: fmv.x.d a0, fa5155; RV64IFD-NEXT: ret156;157; RV64IZFINXZDINX-LABEL: fcopysign_fneg:158; RV64IZFINXZDINX: # %bb.0:159; RV64IZFINXZDINX-NEXT: fsgnjn.d a0, a0, a1160; RV64IZFINXZDINX-NEXT: ret161 %1 = fneg double %b162 %2 = call double @llvm.copysign.f64(double %a, double %1)163 ret double %2164}165