1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 3; RUN: | FileCheck -check-prefix=RV32I %s 4; RUN: llc -mtriple=riscv32 -target-abi ilp32 -mattr=+f -verify-machineinstrs < %s \ 5; RUN: | FileCheck -check-prefix=RV32IF %s 6; RUN: llc -mtriple=riscv32 -target-abi ilp32 -mattr=+zfinx -verify-machineinstrs < %s \ 7; RUN: | FileCheck -check-prefix=RV32IZFINX %s 8; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ 9; RUN: | FileCheck -check-prefix=RV64I %s 10; RUN: llc -mtriple=riscv64 -target-abi lp64 -mattr=+f -verify-machineinstrs < %s \ 11; RUN: | FileCheck -check-prefix=RV64IF %s 12; RUN: llc -mtriple=riscv64 -target-abi lp64 -mattr=+zfinx -verify-machineinstrs < %s \ 13; RUN: | FileCheck -check-prefix=RV64IZFINX %s 14 15; This file tests cases where simple floating point operations can be 16; profitably handled though bit manipulation if a soft-float ABI is being used 17; (e.g. fneg implemented by XORing the sign bit). This is typically handled in 18; DAGCombiner::visitBITCAST, but this target-independent code may not trigger 19; in cases where we perform custom legalisation (e.g. RV64F). 20 21define float @fneg(float %a) nounwind { 22; RV32I-LABEL: fneg: 23; RV32I: # %bb.0: 24; RV32I-NEXT: lui a1, 524288 25; RV32I-NEXT: xor a0, a0, a1 26; RV32I-NEXT: ret 27; 28; RV32IF-LABEL: fneg: 29; RV32IF: # %bb.0: 30; RV32IF-NEXT: lui a1, 524288 31; RV32IF-NEXT: xor a0, a0, a1 32; RV32IF-NEXT: ret 33; 34; RV32IZFINX-LABEL: fneg: 35; RV32IZFINX: # %bb.0: 36; RV32IZFINX-NEXT: fneg.s a0, a0 37; RV32IZFINX-NEXT: ret 38; 39; RV64I-LABEL: fneg: 40; RV64I: # %bb.0: 41; RV64I-NEXT: lui a1, 524288 42; RV64I-NEXT: xor a0, a0, a1 43; RV64I-NEXT: ret 44; 45; RV64IF-LABEL: fneg: 46; RV64IF: # %bb.0: 47; RV64IF-NEXT: lui a1, 524288 48; RV64IF-NEXT: xor a0, a0, a1 49; RV64IF-NEXT: ret 50; 51; RV64IZFINX-LABEL: fneg: 52; RV64IZFINX: # %bb.0: 53; RV64IZFINX-NEXT: fneg.s a0, a0 54; RV64IZFINX-NEXT: ret 55 %1 = fneg float %a 56 ret float %1 57} 58 59declare float @llvm.fabs.f32(float) 60 61define float @fabs(float %a) nounwind { 62; RV32I-LABEL: fabs: 63; RV32I: # %bb.0: 64; RV32I-NEXT: slli a0, a0, 1 65; RV32I-NEXT: srli a0, a0, 1 66; RV32I-NEXT: ret 67; 68; RV32IF-LABEL: fabs: 69; RV32IF: # %bb.0: 70; RV32IF-NEXT: slli a0, a0, 1 71; RV32IF-NEXT: srli a0, a0, 1 72; RV32IF-NEXT: ret 73; 74; RV32IZFINX-LABEL: fabs: 75; RV32IZFINX: # %bb.0: 76; RV32IZFINX-NEXT: fabs.s a0, a0 77; RV32IZFINX-NEXT: ret 78; 79; RV64I-LABEL: fabs: 80; RV64I: # %bb.0: 81; RV64I-NEXT: slli a0, a0, 33 82; RV64I-NEXT: srli a0, a0, 33 83; RV64I-NEXT: ret 84; 85; RV64IF-LABEL: fabs: 86; RV64IF: # %bb.0: 87; RV64IF-NEXT: slli a0, a0, 33 88; RV64IF-NEXT: srli a0, a0, 33 89; RV64IF-NEXT: ret 90; 91; RV64IZFINX-LABEL: fabs: 92; RV64IZFINX: # %bb.0: 93; RV64IZFINX-NEXT: fabs.s a0, a0 94; RV64IZFINX-NEXT: ret 95 %1 = call float @llvm.fabs.f32(float %a) 96 ret float %1 97} 98 99declare float @llvm.copysign.f32(float, float) 100 101; DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN will convert to bitwise 102; operations if floating point isn't supported. A combine could be written to 103; do the same even when f32 is legal. 104 105define float @fcopysign_fneg(float %a, float %b) nounwind { 106; RV32I-LABEL: fcopysign_fneg: 107; RV32I: # %bb.0: 108; RV32I-NEXT: not a1, a1 109; RV32I-NEXT: lui a2, 524288 110; RV32I-NEXT: slli a0, a0, 1 111; RV32I-NEXT: and a1, a1, a2 112; RV32I-NEXT: srli a0, a0, 1 113; RV32I-NEXT: or a0, a0, a1 114; RV32I-NEXT: ret 115; 116; RV32IF-LABEL: fcopysign_fneg: 117; RV32IF: # %bb.0: 118; RV32IF-NEXT: fmv.w.x fa5, a0 119; RV32IF-NEXT: not a0, a1 120; RV32IF-NEXT: fmv.w.x fa4, a0 121; RV32IF-NEXT: fsgnj.s fa5, fa5, fa4 122; RV32IF-NEXT: fmv.x.w a0, fa5 123; RV32IF-NEXT: ret 124; 125; RV32IZFINX-LABEL: fcopysign_fneg: 126; RV32IZFINX: # %bb.0: 127; RV32IZFINX-NEXT: fsgnjn.s a0, a0, a1 128; RV32IZFINX-NEXT: ret 129; 130; RV64I-LABEL: fcopysign_fneg: 131; RV64I: # %bb.0: 132; RV64I-NEXT: not a1, a1 133; RV64I-NEXT: lui a2, 524288 134; RV64I-NEXT: slli a0, a0, 33 135; RV64I-NEXT: and a1, a1, a2 136; RV64I-NEXT: srli a0, a0, 33 137; RV64I-NEXT: or a0, a0, a1 138; RV64I-NEXT: ret 139; 140; RV64IF-LABEL: fcopysign_fneg: 141; RV64IF: # %bb.0: 142; RV64IF-NEXT: fmv.w.x fa5, a1 143; RV64IF-NEXT: fmv.w.x fa4, a0 144; RV64IF-NEXT: fsgnjn.s fa5, fa4, fa5 145; RV64IF-NEXT: fmv.x.w a0, fa5 146; RV64IF-NEXT: ret 147; 148; RV64IZFINX-LABEL: fcopysign_fneg: 149; RV64IZFINX: # %bb.0: 150; RV64IZFINX-NEXT: fsgnjn.s a0, a0, a1 151; RV64IZFINX-NEXT: ret 152 %1 = fneg float %b 153 %2 = call float @llvm.copysign.f32(float %a, float %1) 154 ret float %2 155} 156