[llvm] [SPARC] Use fzero/fzeros to materialize FP zeros when we have VIS (PR #135712)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 14 17:45:41 PDT 2025
https://github.com/koachan created https://github.com/llvm/llvm-project/pull/135712
None
>From 498699832e7fe3bba9e311fd666cbc86e287d0f9 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Tue, 15 Apr 2025 07:45:09 +0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
=?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5
---
llvm/lib/Target/Sparc/SparcISelLowering.cpp | 6 +
llvm/lib/Target/Sparc/SparcISelLowering.h | 3 +
llvm/lib/Target/Sparc/SparcInstrVIS.td | 17 ++-
llvm/test/CodeGen/SPARC/float-constants.ll | 115 ++++++++++++++++++++
4 files changed, 139 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 85b8750d40f46..bce8ddbd47586 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -3560,6 +3560,12 @@ bool SparcTargetLowering::useLoadStackGuardNode(const Module &M) const {
return true;
}
+bool SparcTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
+ bool ForCodeSize) const {
+ return Subtarget->isVIS() && (VT == MVT::f32 || VT == MVT::f64) &&
+ Imm.isZero();
+}
+
// Override to disable global variable loading on Linux.
void SparcTargetLowering::insertSSPDeclarations(Module &M) const {
if (!Subtarget->isTargetLinux())
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index 1bee5f4cfe84d..c09e465f5d05e 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -207,6 +207,9 @@ namespace llvm {
return VT != MVT::f128;
}
+ bool isFPImmLegal(const APFloat &Imm, EVT VT,
+ bool ForCodeSize) const override;
+
bool shouldInsertFencesForAtomic(const Instruction *I) const override {
// FIXME: We insert fences for each atomics and generate
// sub-optimal code for PSO/TSO. (Approximately nobody uses any
diff --git a/llvm/lib/Target/Sparc/SparcInstrVIS.td b/llvm/lib/Target/Sparc/SparcInstrVIS.td
index 8ce8f37f34040..5e0dce10b07ed 100644
--- a/llvm/lib/Target/Sparc/SparcInstrVIS.td
+++ b/llvm/lib/Target/Sparc/SparcInstrVIS.td
@@ -45,10 +45,10 @@ class VISInst2<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
!strconcat(OpcStr, " $rs2, $rd")>;
// For VIS Instructions with only rd operand.
-let Constraints = "$rd = $f", rs1 = 0, rs2 = 0 in
+let rs1 = 0, rs2 = 0 in
class VISInstD<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
: VISInstFormat<opfval,
- (outs RC:$rd), (ins RC:$f),
+ (outs RC:$rd), (ins),
!strconcat(OpcStr, " $rd")>;
// VIS 1 Instructions
@@ -277,3 +277,16 @@ def UMULXHI : VISInst<0b000010110, "umulxhi", I64Regs>;
def XMULX : VISInst<0b100010101, "xmulx", I64Regs>;
def XMULXHI : VISInst<0b100010110, "xmulxhi", I64Regs>;
} // Predicates = [IsVIS3]
+
+// FP immediate patterns.
+def fpimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>;
+def fpnegimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>;
+
+// VIS instruction patterns.
+let Predicates = [HasVIS] in {
+// Zero immediate.
+def : Pat<(f64 fpimm0), (FZERO)>;
+def : Pat<(f32 fpimm0), (FZEROS)>;
+def : Pat<(f64 fpnegimm0), (FNEGD (FZERO))>;
+def : Pat<(f32 fpnegimm0), (FNEGS (FZEROS))>;
+} // Predicates = [HasVIS]
diff --git a/llvm/test/CodeGen/SPARC/float-constants.ll b/llvm/test/CodeGen/SPARC/float-constants.ll
index b04ec68ed3d7e..440c75bfca9f9 100644
--- a/llvm/test/CodeGen/SPARC/float-constants.ll
+++ b/llvm/test/CodeGen/SPARC/float-constants.ll
@@ -1,6 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
; RUN: llc < %s -mtriple=sparc | FileCheck %s
; RUN: llc < %s -mtriple=sparcel | FileCheck %s --check-prefix=CHECK-LE
+; RUN: llc < %s -mtriple=sparcv9 -mattr=+vis | FileCheck %s --check-prefix=CHECK-VIS
;; Bitcast should not do a runtime conversion, but rather emit a
;; constant into integer registers directly.
@@ -17,6 +18,12 @@ define <2 x i32> @bitcast() nounwind {
; CHECK-LE-NEXT: sethi 1049856, %o1
; CHECK-LE-NEXT: retl
; CHECK-LE-NEXT: mov %g0, %o0
+;
+; CHECK-VIS-LABEL: bitcast:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: sethi 1049856, %o0
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: mov %g0, %o1
%1 = bitcast double 5.0 to <2 x i32>
ret <2 x i32> %1
}
@@ -43,6 +50,17 @@ define void @test_call() nounwind {
; CHECK-LE-NEXT: mov %g0, %o0
; CHECK-LE-NEXT: ret
; CHECK-LE-NEXT: restore
+;
+; CHECK-VIS-LABEL: test_call:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: save %sp, -176, %sp
+; CHECK-VIS-NEXT: sethi %h44(.LCPI1_0), %i0
+; CHECK-VIS-NEXT: add %i0, %m44(.LCPI1_0), %i0
+; CHECK-VIS-NEXT: sllx %i0, 12, %i0
+; CHECK-VIS-NEXT: call a
+; CHECK-VIS-NEXT: ldd [%i0+%l44(.LCPI1_0)], %f0
+; CHECK-VIS-NEXT: ret
+; CHECK-VIS-NEXT: restore
call void @a(double 5.0)
ret void
}
@@ -75,6 +93,103 @@ define double @test_intrins_call() nounwind {
; CHECK-LE-NEXT: mov %o1, %o3
; CHECK-LE-NEXT: ret
; CHECK-LE-NEXT: restore
+;
+; CHECK-VIS-LABEL: test_intrins_call:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: save %sp, -176, %sp
+; CHECK-VIS-NEXT: sethi %h44(.LCPI2_0), %i0
+; CHECK-VIS-NEXT: add %i0, %m44(.LCPI2_0), %i0
+; CHECK-VIS-NEXT: sllx %i0, 12, %i0
+; CHECK-VIS-NEXT: ldd [%i0+%l44(.LCPI2_0)], %f0
+; CHECK-VIS-NEXT: fmovd %f0, %f2
+; CHECK-VIS-NEXT: call pow
+; CHECK-VIS-NEXT: nop
+; CHECK-VIS-NEXT: ret
+; CHECK-VIS-NEXT: restore
%1 = call double @llvm.pow.f64(double 2.0, double 2.0)
ret double %1
}
+
+;; When we have VIS, f32/f64 zero constant should be materialized from fzero/fzeros.
+
+define double @pos_zero_double() nounwind {
+; CHECK-LABEL: pos_zero_double:
+; CHECK: ! %bb.0:
+; CHECK-NEXT: sethi %hi(.LCPI3_0), %o0
+; CHECK-NEXT: retl
+; CHECK-NEXT: ldd [%o0+%lo(.LCPI3_0)], %f0
+;
+; CHECK-LE-LABEL: pos_zero_double:
+; CHECK-LE: ! %bb.0:
+; CHECK-LE-NEXT: sethi %hi(.LCPI3_0), %o0
+; CHECK-LE-NEXT: retl
+; CHECK-LE-NEXT: ldd [%o0+%lo(.LCPI3_0)], %f0
+;
+; CHECK-VIS-LABEL: pos_zero_double:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: fzero %f0
+ ret double +0.0
+}
+
+define double @neg_zero_double() nounwind {
+; CHECK-LABEL: neg_zero_double:
+; CHECK: ! %bb.0:
+; CHECK-NEXT: sethi %hi(.LCPI4_0), %o0
+; CHECK-NEXT: retl
+; CHECK-NEXT: ldd [%o0+%lo(.LCPI4_0)], %f0
+;
+; CHECK-LE-LABEL: neg_zero_double:
+; CHECK-LE: ! %bb.0:
+; CHECK-LE-NEXT: sethi %hi(.LCPI4_0), %o0
+; CHECK-LE-NEXT: retl
+; CHECK-LE-NEXT: ldd [%o0+%lo(.LCPI4_0)], %f0
+;
+; CHECK-VIS-LABEL: neg_zero_double:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: fzero %f0
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: fnegd %f0, %f0
+ ret double -0.0
+}
+
+define float @pos_zero_float() nounwind {
+; CHECK-LABEL: pos_zero_float:
+; CHECK: ! %bb.0:
+; CHECK-NEXT: sethi %hi(.LCPI5_0), %o0
+; CHECK-NEXT: retl
+; CHECK-NEXT: ld [%o0+%lo(.LCPI5_0)], %f0
+;
+; CHECK-LE-LABEL: pos_zero_float:
+; CHECK-LE: ! %bb.0:
+; CHECK-LE-NEXT: sethi %hi(.LCPI5_0), %o0
+; CHECK-LE-NEXT: retl
+; CHECK-LE-NEXT: ld [%o0+%lo(.LCPI5_0)], %f0
+;
+; CHECK-VIS-LABEL: pos_zero_float:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: fzeros %f0
+ ret float +0.0
+}
+
+define float @neg_zero_float() nounwind {
+; CHECK-LABEL: neg_zero_float:
+; CHECK: ! %bb.0:
+; CHECK-NEXT: sethi %hi(.LCPI6_0), %o0
+; CHECK-NEXT: retl
+; CHECK-NEXT: ld [%o0+%lo(.LCPI6_0)], %f0
+;
+; CHECK-LE-LABEL: neg_zero_float:
+; CHECK-LE: ! %bb.0:
+; CHECK-LE-NEXT: sethi %hi(.LCPI6_0), %o0
+; CHECK-LE-NEXT: retl
+; CHECK-LE-NEXT: ld [%o0+%lo(.LCPI6_0)], %f0
+;
+; CHECK-VIS-LABEL: neg_zero_float:
+; CHECK-VIS: ! %bb.0:
+; CHECK-VIS-NEXT: fzeros %f0
+; CHECK-VIS-NEXT: retl
+; CHECK-VIS-NEXT: fnegs %f0, %f0
+ ret float -0.0
+}
More information about the llvm-commits
mailing list