[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