Skip to content

Commit

Permalink
[NVPTX] Lower -1/x to neg.f64(rcp.rn.f64) instead of fdiv (#98343)
Browse files Browse the repository at this point in the history
The NVPTX backend lowers 1/x to rcp.rn.f64 instruction instead of slower
fdiv instruction. However, in the case of -1/x, it uses the slower fdiv
instruction. After this change, -1/x will be lowered into neg.f64
(rcp.rn.f64).
  • Loading branch information
rajatbajpai authored Jul 16, 2024
1 parent 331ba43 commit 3a0e015
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
17 changes: 17 additions & 0 deletions llvm/lib/Target/NVPTX/NVPTXInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,18 @@ def DoubleConst1 : PatLeaf<(fpimm), [{
return &N->getValueAPF().getSemantics() == &llvm::APFloat::IEEEdouble() &&
N->getValueAPF().convertToDouble() == 1.0;
}]>;
// Constant -1.0 (double)
def DoubleConstNeg1 : PatLeaf<(fpimm), [{
return &N->getValueAPF().getSemantics() == &llvm::APFloat::IEEEdouble() &&
N->getValueAPF().convertToDouble() == -1.0;
}]>;


// Constant -X -> X (double)
def NegDoubleConst : SDNodeXForm<fpimm, [{
return CurDAG->getTargetConstantFP(-(N->getValueAPF()),
SDLoc(N), MVT::f64);
}]>;

// Loads FP16 constant into a register.
//
Expand Down Expand Up @@ -1225,6 +1237,11 @@ def FDIV64ri :
"div.rn.f64 \t$dst, $a, $b;",
[(set Float64Regs:$dst, (fdiv Float64Regs:$a, fpimm:$b))]>;

// fdiv will be converted to rcp
// fneg (fdiv 1.0, X) => fneg (rcp.rn X)
def : Pat<(fdiv DoubleConstNeg1:$a, Float64Regs:$b),
(FNEGf64 (FDIV641r (NegDoubleConst node:$a), Float64Regs:$b))>;

//
// F32 Approximate reciprocal
//
Expand Down
58 changes: 58 additions & 0 deletions llvm/test/CodeGen/NVPTX/rcp-opt.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc < %s -march=nvptx64 | FileCheck %s
; RUN: %if ptxas %{ llc < %s -march=nvptx64 | %ptxas-verify %}

target triple = "nvptx64-nvidia-cuda"

;; Check if fneg (fdiv 1, X) lowers to fneg (rcp.rn X).

define double @test1(double %in) {
; CHECK-LABEL: test1(
; CHECK: {
; CHECK-NEXT: .reg .f64 %fd<4>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.f64 %fd1, [test1_param_0];
; CHECK-NEXT: rcp.rn.f64 %fd2, %fd1;
; CHECK-NEXT: neg.f64 %fd3, %fd2;
; CHECK-NEXT: st.param.f64 [func_retval0+0], %fd3;
; CHECK-NEXT: ret;
%div = fdiv double 1.000000e+00, %in
%neg = fsub double -0.000000e+00, %div
ret double %neg
}

;; Check if fdiv -1, X lowers to fneg (rcp.rn X).

define double @test2(double %in) {
; CHECK-LABEL: test2(
; CHECK: {
; CHECK-NEXT: .reg .f64 %fd<4>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.f64 %fd1, [test2_param_0];
; CHECK-NEXT: rcp.rn.f64 %fd2, %fd1;
; CHECK-NEXT: neg.f64 %fd3, %fd2;
; CHECK-NEXT: st.param.f64 [func_retval0+0], %fd3;
; CHECK-NEXT: ret;
%div = fdiv double -1.000000e+00, %in
ret double %div
}

;; Check if fdiv 1, (fneg X) lowers to fneg (rcp.rn X).

define double @test3(double %in) {
; CHECK-LABEL: test3(
; CHECK: {
; CHECK-NEXT: .reg .f64 %fd<4>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.f64 %fd1, [test3_param_0];
; CHECK-NEXT: rcp.rn.f64 %fd2, %fd1;
; CHECK-NEXT: neg.f64 %fd3, %fd2;
; CHECK-NEXT: st.param.f64 [func_retval0+0], %fd3;
; CHECK-NEXT: ret;
%neg = fsub double -0.000000e+00, %in
%div = fdiv double 1.000000e+00, %neg
ret double %div
}

0 comments on commit 3a0e015

Please sign in to comment.