Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
case ISD::EXTRACT_VECTOR_ELT:
R = SoftenFloatRes_EXTRACT_VECTOR_ELT(N, ResNo); break;
case ISD::FABS: R = SoftenFloatRes_FABS(N); break;
case ISD::FCANONICALIZE:
R = SoftenFloatRes_FCANONICALIZE(N); break;
case ISD::STRICT_FMINNUM:
case ISD::FMINNUM: R = SoftenFloatRes_FMINNUM(N); break;
case ISD::STRICT_FMAXNUM:
Expand Down Expand Up @@ -311,6 +313,12 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FABS(SDNode *N) {
return DAG.getNode(ISD::AND, SDLoc(N), NVT, Op, Mask);
}

SDValue DAGTypeLegalizer::SoftenFloatRes_FCANONICALIZE(SDNode *N) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code feels like a series of hacks to reuse existing Softening functions.

Can we do this instead. It's the code from LegalizeDAG with a BitConvertToInteger at the end.

SDValue DAGTypeLegalizer::SoftenFloatRes_FCANONICALIZE(SDNode *N) {                                           
  SDLoc dl(N);                                                                                                
                                                                                                              
  // This implements llvm.canonicalize.f* by multiplication with 1.0, as
  // suggested in
  // https://llvm.org/docs/LangRef.html#llvm-canonicalize-intrinsic.
  // It uses strict_fp operations even outside a strict_fp context in order
  // to guarantee that the canonicalization is not optimized away by later
  // passes. The result chain introduced by that is intentionally ignored
  // since no ordering requirement is intended here.

  // Create strict multiplication by 1.0.
  SDValue Operand = N->getOperand(0);
  EVT VT = Operand.getValueType();
  SDValue One = DAG.getConstantFP(1.0, dl, VT);
  SDValue Chain = DAG.getEntryNode();
  // Propagate existing flags on canonicalize, and additionally set
  // NoFPExcept.
  SDNodeFlags CanonicalizeFlags = N->getFlags();
  CanonicalizeFlags.setNoFPExcept(true);
  SDValue Mul = DAG.getNode(ISD::STRICT_FMUL, dl, {VT, MVT::Other},
                            {Chain, Operand, One}, CanonicalizeFlags);
  return BitConvertToInteger(Mul);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yes, thank you that's much better
you were right, I tried to bend the API to make it work like the other methods :)

return SoftenFloatRes_Unary(
N, GetFPLibCall(N->getValueType(0), RTLIB::FMIN_F32, RTLIB::FMIN_F64,
RTLIB::FMIN_F80, RTLIB::FMIN_F128, RTLIB::FMIN_PPCF128));
}

SDValue DAGTypeLegalizer::SoftenFloatRes_FMINNUM(SDNode *N) {
if (SDValue SelCC = TLI.createSelectForFMINNUM_FMAXNUM(N, DAG))
return SoftenFloatRes_SELECT_CC(SelCC.getNode());
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue SoftenFloatRes_FASIN(SDNode *N);
SDValue SoftenFloatRes_FATAN(SDNode *N);
SDValue SoftenFloatRes_FATAN2(SDNode *N);
SDValue SoftenFloatRes_FCANONICALIZE(SDNode *N);
SDValue SoftenFloatRes_FMINNUM(SDNode *N);
SDValue SoftenFloatRes_FMAXNUM(SDNode *N);
SDValue SoftenFloatRes_FMINIMUMNUM(SDNode *N);
Expand Down
64 changes: 64 additions & 0 deletions llvm/test/CodeGen/RISCV/fcanonicalize.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=riscv64 < %s | FileCheck -check-prefix=RV64I %s
; RUN: llc -mtriple=riscv64 -mattr=+d < %s | FileCheck -check-prefix=RV64D %s

define double @max(double, double) unnamed_addr #0 {
; RV64I-LABEL: max:
; RV64I: # %bb.0: # %start
; RV64I-NEXT: addi sp, sp, -32
; RV64I-NEXT: .cfi_def_cfa_offset 32
; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
; RV64I-NEXT: .cfi_offset ra, -8
; RV64I-NEXT: .cfi_offset s0, -16
; RV64I-NEXT: .cfi_offset s1, -24
; RV64I-NEXT: .cfi_offset s2, -32
; RV64I-NEXT: mv s0, a1
; RV64I-NEXT: mv s1, a0
; RV64I-NEXT: call __ltdf2
; RV64I-NEXT: srli s2, a0, 63
; RV64I-NEXT: mv a0, s1
; RV64I-NEXT: mv a1, s1
; RV64I-NEXT: call __unorddf2
; RV64I-NEXT: snez a0, a0
; RV64I-NEXT: or a0, a0, s2
; RV64I-NEXT: bnez a0, .LBB0_2
; RV64I-NEXT: # %bb.1: # %start
; RV64I-NEXT: mv s0, s1
; RV64I-NEXT: .LBB0_2: # %start
; RV64I-NEXT: mv a0, s0
; RV64I-NEXT: call fmin
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
; RV64I-NEXT: .cfi_restore ra
; RV64I-NEXT: .cfi_restore s0
; RV64I-NEXT: .cfi_restore s1
; RV64I-NEXT: .cfi_restore s2
; RV64I-NEXT: addi sp, sp, 32
; RV64I-NEXT: .cfi_def_cfa_offset 0
; RV64I-NEXT: ret
;
; RV64D-LABEL: max:
; RV64D: # %bb.0: # %start
; RV64D-NEXT: flt.d a0, fa0, fa1
; RV64D-NEXT: feq.d a1, fa0, fa0
; RV64D-NEXT: xori a1, a1, 1
; RV64D-NEXT: or a0, a1, a0
; RV64D-NEXT: bnez a0, .LBB0_2
; RV64D-NEXT: # %bb.1: # %start
; RV64D-NEXT: fmv.d fa1, fa0
; RV64D-NEXT: .LBB0_2: # %start
; RV64D-NEXT: fmin.d fa0, fa1, fa1
; RV64D-NEXT: ret
start:
%2 = fcmp olt double %0, %1
%3 = fcmp uno double %0, 0.000000e+00
%or.cond.i.i = or i1 %3, %2
%4 = select i1 %or.cond.i.i, double %1, double %0
%5 = tail call double @llvm.canonicalize.f64(double %4) #2
ret double %5
}