[llvm] [AMDGPU][GlobalISel] Legalize BF16 fneg and fabs (PR #214050)

Chinmay Deshpande via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 12:47:46 PDT 2026


https://github.com/chinmaydd created https://github.com/llvm/llvm-project/pull/214050

Restore the BF16 semantic types omitted by the extended LLT migration and preserve packed vector legalization.

>From a967e376765da9ddbfedf56c8b6f5b071127e0df Mon Sep 17 00:00:00 2001
From: Chinmay Deshpande <chdeshpa at amd.com>
Date: Tue, 4 Aug 2026 12:39:22 -0700
Subject: [PATCH] [AMDGPU][GlobalISel] Legalize BF16 fneg and fabs

Restore the BF16 semantic types omitted by the extended LLT migration and preserve packed vector legalization.

Co-authored-by: Cursor <cursoragent at cursor.com>
---
 .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp |   4 +-
 .../AMDGPU/GlobalISel/legalize-fabs.mir       | 112 ++++++++++++++++++
 .../AMDGPU/GlobalISel/legalize-fneg.mir       | 112 ++++++++++++++++++
 3 files changed, 227 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index 859a43493c604..7fc0959f43a2f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -1061,8 +1061,10 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
 
   auto &FNegAbs = getActionDefinitionsBuilder({G_FNEG, G_FABS});
   FNegAbs.legalFor(FPTypesPK16)
+      .legalFor({BF16, V2BF16})
       .legalFor(ST.hasAnyPackedFP32Ops(), {V2F32})
-      .clampMaxNumElementsStrict(0, F16, 2);
+      .clampMaxNumElementsStrict(0, F16, 2)
+      .clampMaxNumElementsStrict(0, BF16, 2);
   if (ST.hasAnyPackedFP32Ops())
     FNegAbs.clampMaxNumElementsStrict(0, F32, 2);
   FNegAbs.scalarize(0);
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fabs.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fabs.mir
index 467ca6a16e9b1..1f1c406e7e962 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fabs.mir
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fabs.mir
@@ -356,3 +356,115 @@ body: |
     %1:_(<4 x f16>) = G_FABS %0
     $vgpr0_vgpr1 = COPY %1
 ...
+
+---
+name: test_fabs_bf16
+body: |
+  bb.0:
+    liveins: $vgpr0
+
+    ; SI-LABEL: name: test_fabs_bf16
+    ; SI: liveins: $vgpr0
+    ; SI-NEXT: {{  $}}
+    ; SI-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $vgpr0
+    ; SI-NEXT: [[TRUNC:%[0-9]+]]:_(bf16) = G_TRUNC [[COPY]](i32)
+    ; SI-NEXT: [[FABS:%[0-9]+]]:_(bf16) = G_FABS [[TRUNC]]
+    ; SI-NEXT: [[ANYEXT:%[0-9]+]]:_(i32) = G_ANYEXT [[FABS]](bf16)
+    ; SI-NEXT: $vgpr0 = COPY [[ANYEXT]](i32)
+    ;
+    ; VI-LABEL: name: test_fabs_bf16
+    ; VI: liveins: $vgpr0
+    ; VI-NEXT: {{  $}}
+    ; VI-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $vgpr0
+    ; VI-NEXT: [[TRUNC:%[0-9]+]]:_(bf16) = G_TRUNC [[COPY]](i32)
+    ; VI-NEXT: [[FABS:%[0-9]+]]:_(bf16) = G_FABS [[TRUNC]]
+    ; VI-NEXT: [[ANYEXT:%[0-9]+]]:_(i32) = G_ANYEXT [[FABS]](bf16)
+    ; VI-NEXT: $vgpr0 = COPY [[ANYEXT]](i32)
+    ;
+    ; GFX9-LABEL: name: test_fabs_bf16
+    ; GFX9: liveins: $vgpr0
+    ; GFX9-NEXT: {{  $}}
+    ; GFX9-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $vgpr0
+    ; GFX9-NEXT: [[TRUNC:%[0-9]+]]:_(bf16) = G_TRUNC [[COPY]](i32)
+    ; GFX9-NEXT: [[FABS:%[0-9]+]]:_(bf16) = G_FABS [[TRUNC]]
+    ; GFX9-NEXT: [[ANYEXT:%[0-9]+]]:_(i32) = G_ANYEXT [[FABS]](bf16)
+    ; GFX9-NEXT: $vgpr0 = COPY [[ANYEXT]](i32)
+    %0:_(i32) = COPY $vgpr0
+    %1:_(i16) = G_TRUNC %0
+    %2:_(bf16) = G_BITCAST %1
+    %3:_(bf16) = G_FABS %2
+    %4:_(i16) = G_BITCAST %3
+    %5:_(i32) = G_ANYEXT %4
+    $vgpr0 = COPY %5
+...
+
+---
+name: test_fabs_v2bf16
+body: |
+  bb.0:
+    liveins: $vgpr0
+
+    ; SI-LABEL: name: test_fabs_v2bf16
+    ; SI: liveins: $vgpr0
+    ; SI-NEXT: {{  $}}
+    ; SI-NEXT: [[COPY:%[0-9]+]]:_(<2 x bf16>) = COPY $vgpr0
+    ; SI-NEXT: [[FABS:%[0-9]+]]:_(<2 x bf16>) = G_FABS [[COPY]]
+    ; SI-NEXT: $vgpr0 = COPY [[FABS]](<2 x bf16>)
+    ;
+    ; VI-LABEL: name: test_fabs_v2bf16
+    ; VI: liveins: $vgpr0
+    ; VI-NEXT: {{  $}}
+    ; VI-NEXT: [[COPY:%[0-9]+]]:_(<2 x bf16>) = COPY $vgpr0
+    ; VI-NEXT: [[FABS:%[0-9]+]]:_(<2 x bf16>) = G_FABS [[COPY]]
+    ; VI-NEXT: $vgpr0 = COPY [[FABS]](<2 x bf16>)
+    ;
+    ; GFX9-LABEL: name: test_fabs_v2bf16
+    ; GFX9: liveins: $vgpr0
+    ; GFX9-NEXT: {{  $}}
+    ; GFX9-NEXT: [[COPY:%[0-9]+]]:_(<2 x bf16>) = COPY $vgpr0
+    ; GFX9-NEXT: [[FABS:%[0-9]+]]:_(<2 x bf16>) = G_FABS [[COPY]]
+    ; GFX9-NEXT: $vgpr0 = COPY [[FABS]](<2 x bf16>)
+    %0:_(<2 x bf16>) = COPY $vgpr0
+    %1:_(<2 x bf16>) = G_FABS %0
+    $vgpr0 = COPY %1
+...
+
+---
+name: test_fabs_v4bf16
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1
+
+    ; SI-LABEL: name: test_fabs_v4bf16
+    ; SI: liveins: $vgpr0_vgpr1
+    ; SI-NEXT: {{  $}}
+    ; SI-NEXT: [[COPY:%[0-9]+]]:_(<4 x bf16>) = COPY $vgpr0_vgpr1
+    ; SI-NEXT: [[UV:%[0-9]+]]:_(<2 x bf16>), [[UV1:%[0-9]+]]:_(<2 x bf16>) = G_UNMERGE_VALUES [[COPY]](<4 x bf16>)
+    ; SI-NEXT: [[FABS:%[0-9]+]]:_(<2 x bf16>) = G_FABS [[UV]]
+    ; SI-NEXT: [[FABS1:%[0-9]+]]:_(<2 x bf16>) = G_FABS [[UV1]]
+    ; SI-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x bf16>) = G_CONCAT_VECTORS [[FABS]](<2 x bf16>), [[FABS1]](<2 x bf16>)
+    ; SI-NEXT: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x bf16>)
+    ;
+    ; VI-LABEL: name: test_fabs_v4bf16
+    ; VI: liveins: $vgpr0_vgpr1
+    ; VI-NEXT: {{  $}}
+    ; VI-NEXT: [[COPY:%[0-9]+]]:_(<4 x bf16>) = COPY $vgpr0_vgpr1
+    ; VI-NEXT: [[UV:%[0-9]+]]:_(<2 x bf16>), [[UV1:%[0-9]+]]:_(<2 x bf16>) = G_UNMERGE_VALUES [[COPY]](<4 x bf16>)
+    ; VI-NEXT: [[FABS:%[0-9]+]]:_(<2 x bf16>) = G_FABS [[UV]]
+    ; VI-NEXT: [[FABS1:%[0-9]+]]:_(<2 x bf16>) = G_FABS [[UV1]]
+    ; VI-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x bf16>) = G_CONCAT_VECTORS [[FABS]](<2 x bf16>), [[FABS1]](<2 x bf16>)
+    ; VI-NEXT: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x bf16>)
+    ;
+    ; GFX9-LABEL: name: test_fabs_v4bf16
+    ; GFX9: liveins: $vgpr0_vgpr1
+    ; GFX9-NEXT: {{  $}}
+    ; GFX9-NEXT: [[COPY:%[0-9]+]]:_(<4 x bf16>) = COPY $vgpr0_vgpr1
+    ; GFX9-NEXT: [[UV:%[0-9]+]]:_(<2 x bf16>), [[UV1:%[0-9]+]]:_(<2 x bf16>) = G_UNMERGE_VALUES [[COPY]](<4 x bf16>)
+    ; GFX9-NEXT: [[FABS:%[0-9]+]]:_(<2 x bf16>) = G_FABS [[UV]]
+    ; GFX9-NEXT: [[FABS1:%[0-9]+]]:_(<2 x bf16>) = G_FABS [[UV1]]
+    ; GFX9-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x bf16>) = G_CONCAT_VECTORS [[FABS]](<2 x bf16>), [[FABS1]](<2 x bf16>)
+    ; GFX9-NEXT: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x bf16>)
+    %0:_(<4 x bf16>) = COPY $vgpr0_vgpr1
+    %1:_(<4 x bf16>) = G_FABS %0
+    $vgpr0_vgpr1 = COPY %1
+...
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fneg.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fneg.mir
index 1ecd2aff69866..7bf86a7c7973d 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fneg.mir
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fneg.mir
@@ -354,3 +354,115 @@ body: |
     %1:_(<4 x f16>) = G_FNEG %0
     $vgpr0_vgpr1 = COPY %1
 ...
+
+---
+name: test_fneg_bf16
+body: |
+  bb.0:
+    liveins: $vgpr0
+
+    ; SI-LABEL: name: test_fneg_bf16
+    ; SI: liveins: $vgpr0
+    ; SI-NEXT: {{  $}}
+    ; SI-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $vgpr0
+    ; SI-NEXT: [[TRUNC:%[0-9]+]]:_(bf16) = G_TRUNC [[COPY]](i32)
+    ; SI-NEXT: [[FNEG:%[0-9]+]]:_(bf16) = G_FNEG [[TRUNC]]
+    ; SI-NEXT: [[ANYEXT:%[0-9]+]]:_(i32) = G_ANYEXT [[FNEG]](bf16)
+    ; SI-NEXT: $vgpr0 = COPY [[ANYEXT]](i32)
+    ;
+    ; VI-LABEL: name: test_fneg_bf16
+    ; VI: liveins: $vgpr0
+    ; VI-NEXT: {{  $}}
+    ; VI-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $vgpr0
+    ; VI-NEXT: [[TRUNC:%[0-9]+]]:_(bf16) = G_TRUNC [[COPY]](i32)
+    ; VI-NEXT: [[FNEG:%[0-9]+]]:_(bf16) = G_FNEG [[TRUNC]]
+    ; VI-NEXT: [[ANYEXT:%[0-9]+]]:_(i32) = G_ANYEXT [[FNEG]](bf16)
+    ; VI-NEXT: $vgpr0 = COPY [[ANYEXT]](i32)
+    ;
+    ; GFX9-LABEL: name: test_fneg_bf16
+    ; GFX9: liveins: $vgpr0
+    ; GFX9-NEXT: {{  $}}
+    ; GFX9-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $vgpr0
+    ; GFX9-NEXT: [[TRUNC:%[0-9]+]]:_(bf16) = G_TRUNC [[COPY]](i32)
+    ; GFX9-NEXT: [[FNEG:%[0-9]+]]:_(bf16) = G_FNEG [[TRUNC]]
+    ; GFX9-NEXT: [[ANYEXT:%[0-9]+]]:_(i32) = G_ANYEXT [[FNEG]](bf16)
+    ; GFX9-NEXT: $vgpr0 = COPY [[ANYEXT]](i32)
+    %0:_(i32) = COPY $vgpr0
+    %1:_(i16) = G_TRUNC %0
+    %2:_(bf16) = G_BITCAST %1
+    %3:_(bf16) = G_FNEG %2
+    %4:_(i16) = G_BITCAST %3
+    %5:_(i32) = G_ANYEXT %4
+    $vgpr0 = COPY %5
+...
+
+---
+name: test_fneg_v2bf16
+body: |
+  bb.0:
+    liveins: $vgpr0
+
+    ; SI-LABEL: name: test_fneg_v2bf16
+    ; SI: liveins: $vgpr0
+    ; SI-NEXT: {{  $}}
+    ; SI-NEXT: [[COPY:%[0-9]+]]:_(<2 x bf16>) = COPY $vgpr0
+    ; SI-NEXT: [[FNEG:%[0-9]+]]:_(<2 x bf16>) = G_FNEG [[COPY]]
+    ; SI-NEXT: $vgpr0 = COPY [[FNEG]](<2 x bf16>)
+    ;
+    ; VI-LABEL: name: test_fneg_v2bf16
+    ; VI: liveins: $vgpr0
+    ; VI-NEXT: {{  $}}
+    ; VI-NEXT: [[COPY:%[0-9]+]]:_(<2 x bf16>) = COPY $vgpr0
+    ; VI-NEXT: [[FNEG:%[0-9]+]]:_(<2 x bf16>) = G_FNEG [[COPY]]
+    ; VI-NEXT: $vgpr0 = COPY [[FNEG]](<2 x bf16>)
+    ;
+    ; GFX9-LABEL: name: test_fneg_v2bf16
+    ; GFX9: liveins: $vgpr0
+    ; GFX9-NEXT: {{  $}}
+    ; GFX9-NEXT: [[COPY:%[0-9]+]]:_(<2 x bf16>) = COPY $vgpr0
+    ; GFX9-NEXT: [[FNEG:%[0-9]+]]:_(<2 x bf16>) = G_FNEG [[COPY]]
+    ; GFX9-NEXT: $vgpr0 = COPY [[FNEG]](<2 x bf16>)
+    %0:_(<2 x bf16>) = COPY $vgpr0
+    %1:_(<2 x bf16>) = G_FNEG %0
+    $vgpr0 = COPY %1
+...
+
+---
+name: test_fneg_v4bf16
+body: |
+  bb.0:
+    liveins: $vgpr0_vgpr1
+
+    ; SI-LABEL: name: test_fneg_v4bf16
+    ; SI: liveins: $vgpr0_vgpr1
+    ; SI-NEXT: {{  $}}
+    ; SI-NEXT: [[COPY:%[0-9]+]]:_(<4 x bf16>) = COPY $vgpr0_vgpr1
+    ; SI-NEXT: [[UV:%[0-9]+]]:_(<2 x bf16>), [[UV1:%[0-9]+]]:_(<2 x bf16>) = G_UNMERGE_VALUES [[COPY]](<4 x bf16>)
+    ; SI-NEXT: [[FNEG:%[0-9]+]]:_(<2 x bf16>) = G_FNEG [[UV]]
+    ; SI-NEXT: [[FNEG1:%[0-9]+]]:_(<2 x bf16>) = G_FNEG [[UV1]]
+    ; SI-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x bf16>) = G_CONCAT_VECTORS [[FNEG]](<2 x bf16>), [[FNEG1]](<2 x bf16>)
+    ; SI-NEXT: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x bf16>)
+    ;
+    ; VI-LABEL: name: test_fneg_v4bf16
+    ; VI: liveins: $vgpr0_vgpr1
+    ; VI-NEXT: {{  $}}
+    ; VI-NEXT: [[COPY:%[0-9]+]]:_(<4 x bf16>) = COPY $vgpr0_vgpr1
+    ; VI-NEXT: [[UV:%[0-9]+]]:_(<2 x bf16>), [[UV1:%[0-9]+]]:_(<2 x bf16>) = G_UNMERGE_VALUES [[COPY]](<4 x bf16>)
+    ; VI-NEXT: [[FNEG:%[0-9]+]]:_(<2 x bf16>) = G_FNEG [[UV]]
+    ; VI-NEXT: [[FNEG1:%[0-9]+]]:_(<2 x bf16>) = G_FNEG [[UV1]]
+    ; VI-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x bf16>) = G_CONCAT_VECTORS [[FNEG]](<2 x bf16>), [[FNEG1]](<2 x bf16>)
+    ; VI-NEXT: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x bf16>)
+    ;
+    ; GFX9-LABEL: name: test_fneg_v4bf16
+    ; GFX9: liveins: $vgpr0_vgpr1
+    ; GFX9-NEXT: {{  $}}
+    ; GFX9-NEXT: [[COPY:%[0-9]+]]:_(<4 x bf16>) = COPY $vgpr0_vgpr1
+    ; GFX9-NEXT: [[UV:%[0-9]+]]:_(<2 x bf16>), [[UV1:%[0-9]+]]:_(<2 x bf16>) = G_UNMERGE_VALUES [[COPY]](<4 x bf16>)
+    ; GFX9-NEXT: [[FNEG:%[0-9]+]]:_(<2 x bf16>) = G_FNEG [[UV]]
+    ; GFX9-NEXT: [[FNEG1:%[0-9]+]]:_(<2 x bf16>) = G_FNEG [[UV1]]
+    ; GFX9-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x bf16>) = G_CONCAT_VECTORS [[FNEG]](<2 x bf16>), [[FNEG1]](<2 x bf16>)
+    ; GFX9-NEXT: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x bf16>)
+    %0:_(<4 x bf16>) = COPY $vgpr0_vgpr1
+    %1:_(<4 x bf16>) = G_FNEG %0
+    $vgpr0_vgpr1 = COPY %1
+...



More information about the llvm-commits mailing list