[PATCH] D79187: [DAGCombiner] fold (fp_round (int_to_fp X)) -> (int_to_fp X)
Sam Elliott via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri May 1 04:26:03 PDT 2020
lenary updated this revision to Diff 261453.
lenary added a comment.
Address @efriedma's feedback and guidance:
- Use `hasOperation` to ensure legality. This causes the optimisation not to happen for the testcase on on RV64*F, in this example, I think because `i32` is not a legal type on that architecture. I'll follow-up this patch if I can get that working.
I have also refactored the check, and added an even greater commentary of why I
believe the transform to be correct, which I think means it applies in more
cases. This is based off the observation/assumption that `fp_round` always
removes precision of the final float, so that precision loss can always be
"moved" into the int_to_fp operation.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D79187/new/
https://reviews.llvm.org/D79187
Files:
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/lib/Target/RISCV/RISCVInstrInfoF.td
llvm/test/CodeGen/RISCV/fp-convert-indirect.ll
Index: llvm/test/CodeGen/RISCV/fp-convert-indirect.ll
===================================================================
--- llvm/test/CodeGen/RISCV/fp-convert-indirect.ll
+++ llvm/test/CodeGen/RISCV/fp-convert-indirect.ll
@@ -11,19 +11,15 @@
;; These testcases check that we merge sequences of `fcvt.d.wu; fcvt.s.d` into
;; `fcvt.s.wu`.
;;
-;; TODO: Unfortunately, though this only uses 32-bit FP instructions, we cannot
-;; do this optimisation without the D extension as we need 64-bit FP values to
-;; be legal to get the right operands to match.
+;; These folds are actually implemented in the DAGCombiner, because otherwise
+;; without the D extension the intermediate `double` will be legalised away and
+;; the conversions will be turned into libcalls.
define float @fcvt_s_w_via_d(i32 %a) nounwind {
; RV32IF-LABEL: fcvt_s_w_via_d:
; RV32IF: # %bb.0:
-; RV32IF-NEXT: addi sp, sp, -16
-; RV32IF-NEXT: sw ra, 12(sp)
-; RV32IF-NEXT: call __floatsidf
-; RV32IF-NEXT: call __truncdfsf2
-; RV32IF-NEXT: lw ra, 12(sp)
-; RV32IF-NEXT: addi sp, sp, 16
+; RV32IF-NEXT: fcvt.s.w ft0, a0
+; RV32IF-NEXT: fmv.x.w a0, ft0
; RV32IF-NEXT: ret
;
; RV32IFD-LABEL: fcvt_s_w_via_d:
@@ -56,12 +52,8 @@
define float @fcvt_s_wu_via_d(i32 %a) nounwind {
; RV32IF-LABEL: fcvt_s_wu_via_d:
; RV32IF: # %bb.0:
-; RV32IF-NEXT: addi sp, sp, -16
-; RV32IF-NEXT: sw ra, 12(sp)
-; RV32IF-NEXT: call __floatunsidf
-; RV32IF-NEXT: call __truncdfsf2
-; RV32IF-NEXT: lw ra, 12(sp)
-; RV32IF-NEXT: addi sp, sp, 16
+; RV32IF-NEXT: fcvt.s.wu ft0, a0
+; RV32IF-NEXT: fmv.x.w a0, ft0
; RV32IF-NEXT: ret
;
; RV32IFD-LABEL: fcvt_s_wu_via_d:
Index: llvm/lib/Target/RISCV/RISCVInstrInfoF.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVInstrInfoF.td
+++ llvm/lib/Target/RISCV/RISCVInstrInfoF.td
@@ -392,12 +392,6 @@
// [u]int->float. Match GCC and default to using dynamic rounding mode.
def : Pat<(sint_to_fp GPR:$rs1), (FCVT_S_W $rs1, 0b111)>;
def : Pat<(uint_to_fp GPR:$rs1), (FCVT_S_WU $rs1, 0b111)>;
-
-// [u]int->double->float
-def : Pat<(fpround (f64 (sint_to_fp GPR:$rs1))),
- (FCVT_S_W GPR:$rs1, 0b111)>;
-def : Pat<(fpround (f64 (uint_to_fp GPR:$rs1))),
- (FCVT_S_WU GPR:$rs1, 0b111)>;
} // Predicates = [HasStdExtF, IsRV32]
let Predicates = [HasStdExtF, IsRV64] in {
Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -13462,6 +13462,31 @@
if (N0.getOpcode() == ISD::FP_EXTEND && VT == N0.getOperand(0).getValueType())
return N0.getOperand(0);
+ // fold (fp_round ({u,s}int_to_fp x)) -> ({u,s}int_to_fp x)
+ // but only when the ({u,s}int_to_fp x) remains precise
+ if (N0.getOpcode() == ISD::SINT_TO_FP || N0.getOpcode() == ISD::UINT_TO_FP) {
+ SDValue IntNode = N0->getOperand(0);
+ EVT IntTy = IntNode.getValueType();
+
+ // The intuition behind this check is that the original DAG took an integer,
+ // and converted it to the resulting float, but via a more precise float.
+ // After the transform, the integer is converted directly to the resulting
+ // float, without the intermediate precise float.
+ //
+ // Because the intermediate float is rounded to the resulting float, we know
+ // the resulting float is less precise than the intermediate float.
+ // Therefore, the relative precision of the int to either float does not
+ // matter, as in all cases, the `fp_round` will be removing precision,
+ // regardless of whether the original `int_to_fp` loses precision or not.
+ //
+ // The only thing we do need to check is that we can perform the int_to_fp
+ // with this integer operand.
+ if (hasOperation(N0.getOpcode(), IntTy)) {
+ SDLoc DL(N);
+ return DAG.getNode(N0.getOpcode(), DL, VT, IntNode);
+ }
+ }
+
// fold (fp_round (fp_round x)) -> (fp_round x)
if (N0.getOpcode() == ISD::FP_ROUND) {
const bool NIsTrunc = N->getConstantOperandVal(1) == 1;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D79187.261453.patch
Type: text/x-patch
Size: 4163 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200501/6aa5fa08/attachment.bin>
More information about the llvm-commits
mailing list