[llvm] [Hexagon] Add an option to use fast FP to int convert for some HVX cases (PR #169562)
Fateme Hosseini via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 26 07:44:13 PST 2025
https://github.com/fhossein-quic updated https://github.com/llvm/llvm-project/pull/169562
>From c85bb90115ca0f4c67721b2536375f1b7302ec42 Mon Sep 17 00:00:00 2001
From: Sergei Larin <slarin at codeaurora.org>
Date: Thu, 10 Jul 2025 15:34:18 -0700
Subject: [PATCH] [Hexagon] Add an option to use fast FP to int convert for
some HVX cases
Lowering several flavors of fptosi for HVX can be done faster, but violates
c/c++ convention on some arch tags. Nevertheless customers are using direct
intrinsics with "incorrect" rounding mode and want compiler to do the same.
Default behavior is not changed.
Patch By: Fateme Hosseini
Co-authored-by: Sergei Larin <slarin at qti.qualcomm.com>
---
.../Target/Hexagon/HexagonISelLoweringHVX.cpp | 30 +++++++++++++++++++
.../CodeGen/Hexagon/autohvx/fp-to-int_2.ll | 28 +++++++++++++++++
2 files changed, 58 insertions(+)
create mode 100644 llvm/test/CodeGen/Hexagon/autohvx/fp-to-int_2.ll
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
index 212a57bc7cde5..0b782d79237da 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
@@ -31,6 +31,10 @@ static cl::opt<unsigned> HvxWidenThreshold("hexagon-hvx-widen",
cl::Hidden, cl::init(16),
cl::desc("Lower threshold (in bytes) for widening to HVX vectors"));
+static cl::opt<bool>
+ EnableFpFastConvert("hexagon-fp-fast-convert", cl::Hidden, cl::init(false),
+ cl::desc("Enable FP fast conversion routine."));
+
static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
@@ -2970,6 +2974,32 @@ HexagonTargetLowering::ExpandHvxFpToInt(SDValue Op, SelectionDAG &DAG) const {
MVT ResTy = ty(Op);
assert(InpTy.changeTypeToInteger() == ResTy);
+ // At this point this is an experiment under a flag.
+ // In arch before V81 the rounding mode is towards nearest value.
+ // The C/C++ standard requires rounding towards zero:
+ // C (C99 and later): ISO/IEC 9899:2018 (C18), section 6.3.1.4 — "When a
+ // finite value of real floating type is converted to an integer type, the
+ // fractional part is discarded (i.e., the value is truncated toward zero)."
+ // C++: ISO/IEC 14882:2020 (C++20), section 7.3.7 — "A prvalue of a
+ // floating-point type can be converted to a prvalue of an integer type. The
+ // conversion truncates; that is, the fractional part is discarded."
+ if (InpTy == MVT::v64f16) {
+ if (Subtarget.useHVXV81Ops()) {
+ // This is c/c++ compliant
+ SDValue ConvVec =
+ getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
+ return ConvVec;
+ } else if (EnableFpFastConvert) {
+ // Vd32.h=Vu32.hf same as Q6_Vh_equals_Vhf
+ SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
+ return ConvVec;
+ }
+ } else if (EnableFpFastConvert && InpTy == MVT::v32f32) {
+ // Vd32.w=Vu32.sf same as Q6_Vw_equals_Vsf
+ SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
+ return ConvVec;
+ }
+
// int32_t conv_f32_to_i32(uint32_t inp) {
// // s | exp8 | frac23
//
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/fp-to-int_2.ll b/llvm/test/CodeGen/Hexagon/autohvx/fp-to-int_2.ll
new file mode 100644
index 0000000000000..a05964e9afde7
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/autohvx/fp-to-int_2.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=hexagon -hexagon-hvx-widen=32 -hexagon-fp-fast-convert=true -mattr=+hvxv68,+hvx-length128b,+hvx-qfloat < %s | FileCheck %s
+
+; f16 -> s16
+; No widening
+define void @f16s16_0(ptr %a0, ptr %a1) #0 {
+; CHECK-LABEL: f16s16_0:
+; CHECK: {
+; CHECK: [[DST:v[0-9]+]].h = [[SRC:v[0-9]+]].hf
+; CHECK-NEXT: jumpr r31
+; CHECK: vmem(r1+#0) = [[DST]].new
+; CHECK-NEXT: }
+
+ %v0 = load <64 x half>, ptr %a0, align 128
+ %v1 = fptosi <64 x half> %v0 to <64 x i16>
+ store <64 x i16> %v1, ptr %a1, align 128
+ ret void
+}
+
+; Widen result #2
+define void @f32s8_2(ptr %a0, ptr %a1) {
+; CHECK-LABEL: f32s8_2:
+; CHECK: v{{.*}}.w = v{{.*}}.sf
+ %v0 = load <32 x float>, ptr %a0, align 128
+ %v1 = fptosi <32 x float> %v0 to <32 x i8>
+ store <32 x i8> %v1, ptr %a1, align 128
+ ret void
+}
More information about the llvm-commits
mailing list