[llvm] [NFC] Add useFPRegsForHalfType(). (PR #74147)

Harald van Dijk via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 1 13:42:19 PST 2023


https://github.com/hvdijk created https://github.com/llvm/llvm-project/pull/74147

Currently, half operations can be promoted in one of two ways.

* If softPromoteHalfType() returns false, fp16 values are passed around in fp32 registers, and whole chains of fp16 operations are promoted to fp32 in one go.
* If softPromoteHalfType() returns true, fp16 values are passed around in i16 registers, and individual fp16 operations are promoted to fp32 and the result truncated to fp16 right away.

The softPromoteHalfType behavior is necessary for correctness, but changing this for an existing target breaks the ABI. Therefore, this commit adds a third option:

* If softPromoteHalfType() returns true and useFPRegsForHalfType() returns true as well, fp16 values are passed around in fp32 registers, but individual fp16 operations are promoted to fp32 and the result truncated to fp16 right away.

This change does not yet update any target to make use of it.

>From 6b65afa6b09f1d97679f25116f8f8c06fad6c70f Mon Sep 17 00:00:00 2001
From: Harald van Dijk <harald at gigawatt.nl>
Date: Fri, 1 Dec 2023 14:50:32 +0000
Subject: [PATCH] [NFC] Add useFPRegsForHalfType().

Currently, half operations can be promoted in one of two ways.

* If softPromoteHalfType() returns false, fp16 values are passed around
  in fp32 registers, and whole chains of fp16 operations are promoted to
  fp32 in one go.
* If softPromoteHalfType() returns true, fp16 values are passed around
  in i16 registers, and individual fp16 operations are promoted to fp32
  and the result truncated to fp16 right away.

The softPromoteHalfType behavior is necessary for correctness, but
changing this for an existing target breaks the ABI. Therefore, this
commit adds a third option:

* If softPromoteHalfType() returns true and useFPRegsForHalfType()
  returns true as well, fp16 values are passed around in fp32 registers,
  but individual fp16 operations are promoted to fp32 and the result
  truncated to fp16 right away.

This change does not yet update any target to make use of it.
---
 llvm/include/llvm/CodeGen/TargetLowering.h | 14 ++++++++++----
 llvm/lib/CodeGen/TargetLoweringBase.cpp    | 13 +++++++++----
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 77ee6b89ed8a34f..a559de5d707bfbe 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -505,12 +505,18 @@ class TargetLoweringBase {
     return TypePromoteInteger;
   }
 
-  // Return true if the half type should be passed around as i16, but promoted
-  // to float around arithmetic. The default behavior is to pass around as
-  // float and convert around loads/stores/bitcasts and other places where
-  // the size matters.
+  // Return true if the half type should be promoted using soft promotion rules
+  // where each operation is promoted to f32 individually, then converted to
+  // fp16. The default behavior is to promote links of operations, keeping
+  // intermediate results in f32 precision and range.
   virtual bool softPromoteHalfType() const { return false; }
 
+  // Return true if, for soft-promoted half, the half type should be passed
+  // around as f32. The default behavior is to pass around as i16. If
+  // soft-promoted half is not used, this function is ignored and values are
+  // always passed as f32.
+  virtual bool useFPRegsForHalfType() const { return false; }
+
   // There are two general methods for expanding a BUILD_VECTOR node:
   //  1. Use SCALAR_TO_VECTOR on the defined scalar values and then shuffle
   //     them together.
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 2648c16bcd8d903..91e61d824edd635 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1422,15 +1422,20 @@ void TargetLoweringBase::computeRegisterProperties(
   // conversions).
   if (!isTypeLegal(MVT::f16)) {
     // Allow targets to control how we legalize half.
-    if (softPromoteHalfType()) {
+    bool SoftPromoteHalfType = softPromoteHalfType();
+    bool UseFPRegsForHalfType = !SoftPromoteHalfType || useFPRegsForHalfType();
+
+    if (!UseFPRegsForHalfType) {
       NumRegistersForVT[MVT::f16] = NumRegistersForVT[MVT::i16];
       RegisterTypeForVT[MVT::f16] = RegisterTypeForVT[MVT::i16];
-      TransformToType[MVT::f16] = MVT::f32;
-      ValueTypeActions.setTypeAction(MVT::f16, TypeSoftPromoteHalf);
     } else {
       NumRegistersForVT[MVT::f16] = NumRegistersForVT[MVT::f32];
       RegisterTypeForVT[MVT::f16] = RegisterTypeForVT[MVT::f32];
-      TransformToType[MVT::f16] = MVT::f32;
+    }
+    TransformToType[MVT::f16] = MVT::f32;
+    if (SoftPromoteHalfType) {
+      ValueTypeActions.setTypeAction(MVT::f16, TypeSoftPromoteHalf);
+    } else {
       ValueTypeActions.setTypeAction(MVT::f16, TypePromoteFloat);
     }
   }



More information about the llvm-commits mailing list