Skip to content

Commit 4f339ee

Browse files
Qi-Ye-079vmaksimo
andauthored
[SPIR-V] Add SPV_INTEL_bfloat16_arithmetic for Opencl.std instructions with bfloat16 type (#205128)
For `OpExtInst`, add check for bfloat16 type when it's an OpenCL.std extended instruction, and add requirements for SPV_INTEL_bfloat16_arithmetic if so. Add such check and extension requirement since OpenCL.std extended instruction set can operate on IEEE-754 FP types only, as per the revision from [OpenCL.std spec](https://registry.khronos.org/SPIR-V/specs/unified1/OpenCL.ExtendedInstructionSet.100.html#_changes_from_version_1_0_revision_8) --------- Co-authored-by: Viktoria Maximova <viktoria.maksimova@intel.com>
1 parent b7091e6 commit 4f339ee

2 files changed

Lines changed: 134 additions & 5 deletions

File tree

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17-
// TODO: uses or report_fatal_error (which is also deprecated) /
18-
// ReportFatalUsageError in this file should be refactored, as per LLVM
19-
// best practices, to rely on the Diagnostic infrastructure.
17+
// TODO: Per LLVM best practices, the report_fatal_error (deprecated) /
18+
// ReportFatalUsageError calls in this file should be replaced with the
19+
// Diagnostic infrastructure (e.g. the reportUnsupported function below).
2020

2121
#include "SPIRVModuleAnalysis.h"
2222
#include "MCTargetDesc/SPIRVBaseInfo.h"
@@ -56,6 +56,12 @@ char llvm::SPIRVModuleAnalysis::ID = 0;
5656
INITIALIZE_PASS(SPIRVModuleAnalysis, DEBUG_TYPE, "SPIRV module analysis", true,
5757
true)
5858

59+
static void reportUnsupported(const MachineInstr &MI, const char *Msg) {
60+
const Function &Func = MI.getMF()->getFunction();
61+
Func.getContext().diagnose(
62+
DiagnosticInfoUnsupported(Func, Msg, MI.getDebugLoc()));
63+
}
64+
5965
// Retrieve an unsigned from an MDNode with a list of them as operands.
6066
static unsigned getMetadataUInt(MDNode *MdNode, unsigned OpIndex,
6167
unsigned DefaultVal = 0) {
@@ -1662,8 +1668,40 @@ void addInstrRequirements(const MachineInstr &MI,
16621668
addPrintfRequirements(MI, Reqs, ST);
16631669
break;
16641670
}
1665-
// TODO: handle bfloat16 extended instructions when
1666-
// SPV_INTEL_bfloat16_arithmetic is enabled.
1671+
if (MI.getOperand(2).getImm() ==
1672+
static_cast<int64_t>(SPIRV::InstructionSet::OpenCL_std)) {
1673+
const MachineFunction *MF = MI.getMF();
1674+
const MachineRegisterInfo &MRI = MF->getRegInfo();
1675+
SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
1676+
1677+
auto IsBFloat16 = [&](SPIRVTypeInst TypeDef) {
1678+
if (TypeDef && TypeDef->getOpcode() == SPIRV::OpTypeVector)
1679+
TypeDef = MRI.getVRegDef(TypeDef->getOperand(1).getReg());
1680+
return isBFloat16Type(TypeDef);
1681+
};
1682+
1683+
// Result type is operand 1; arguments start at operand 4.
1684+
bool UsesBFloat16 = IsBFloat16(MRI.getVRegDef(MI.getOperand(1).getReg()));
1685+
for (unsigned I = 4, E = MI.getNumOperands(); I < E && !UsesBFloat16;
1686+
++I) {
1687+
const MachineOperand &MO = MI.getOperand(I);
1688+
if (MO.isReg())
1689+
UsesBFloat16 = IsBFloat16(GR->getResultType(
1690+
MO.getReg(), const_cast<MachineFunction *>(MF)));
1691+
}
1692+
1693+
if (UsesBFloat16) {
1694+
if (!ST.canUseExtension(
1695+
SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic)) {
1696+
reportUnsupported(
1697+
MI, "OpenCL Extended instructions with bfloat16 require the "
1698+
"following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic");
1699+
break;
1700+
}
1701+
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
1702+
Reqs.addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
1703+
}
1704+
}
16671705
break;
16681706
}
16691707
case SPIRV::OpAliasDomainDeclINTEL:
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
; RUN: split-file %s %t
2+
3+
; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_bfloat16 %t/bf16_result_operand.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=RESULT-OPERAND-ERROR
4+
; RESULT-OPERAND-ERROR: error: <unknown>:0:0: in function test_fabs bfloat (bfloat): OpenCL Extended instructions with bfloat16 require the
5+
; RESULT-OPERAND-ERROR-SAME: following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic
6+
7+
; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_bfloat16 %t/bf16_result.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=RESULT-ERROR
8+
; RESULT-ERROR: error: <unknown>:0:0: in function test_nan bfloat (i16): OpenCL Extended instructions with bfloat16 require the
9+
; RESULT-ERROR-SAME: following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic
10+
11+
; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_bfloat16 %t/bf16_operand.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=OPERAND-ERROR
12+
; OPERAND-ERROR: error: <unknown>:0:0: in function test_ilogb i32 (bfloat): OpenCL Extended instructions with bfloat16 require the
13+
; OPERAND-ERROR-SAME: following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic
14+
15+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_arithmetic,+SPV_KHR_bfloat16 %t/bf16_result_operand.ll -o - | FileCheck %s --check-prefixes=COMMON,BF16_RESULT_OPERAND
16+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_arithmetic,+SPV_KHR_bfloat16 %t/bf16_result.ll -o - | FileCheck %s --check-prefixes=COMMON,BF16_RESULT
17+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_arithmetic,+SPV_KHR_bfloat16 %t/bf16_operand.ll -o - | FileCheck %s --check-prefixes=COMMON,BF16_OPERAND
18+
19+
; TODO: re-enable spirv-val once it can verify SPV_INTEL_bfloat16_arithmetic with bfloat16 type on ExtInst
20+
; RUNx: %if spirv-tools %{ llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_arithmetic,+SPV_KHR_bfloat16 %t/bf16_result_operand.ll -o - -filetype=obj | spirv-val %}
21+
; RUNx: %if spirv-tools %{ llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_arithmetic,+SPV_KHR_bfloat16 %t/bf16_result.ll -o - -filetype=obj | spirv-val %}
22+
; RUNx: %if spirv-tools %{ llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_arithmetic,+SPV_KHR_bfloat16 %t/bf16_operand.ll -o - -filetype=obj | spirv-val %}
23+
24+
; COMMON-DAG: OpCapability BFloat16ArithmeticINTEL
25+
; COMMON-DAG: OpCapability BFloat16TypeKHR
26+
; COMMON-DAG: OpExtension "SPV_KHR_bfloat16"
27+
; COMMON-DAG: OpExtension "SPV_INTEL_bfloat16_arithmetic"
28+
; COMMON-DAG: [[EXTSET:%.*]] = OpExtInstImport "OpenCL.std"
29+
; COMMON-DAG: [[BFLOAT:%.*]] = OpTypeFloat 16 0
30+
; COMMON-DAG: [[BFLOATV:%.*]] = OpTypeVector [[BFLOAT]] 4
31+
32+
; BF16_RESULT_OPERAND: [[OP:%.*]] = OpFunctionParameter [[BFLOAT]]
33+
; BF16_RESULT_OPERAND: OpExtInst [[BFLOAT]] [[EXTSET]] fabs [[OP]]
34+
; BF16_RESULT_OPERAND: [[OPV:%.*]] = OpFunctionParameter [[BFLOATV]]
35+
; BF16_RESULT_OPERAND: OpExtInst [[BFLOATV]] [[EXTSET]] fabs [[OPV]]
36+
37+
; BF16_RESULT-DAG: [[INT:%.*]] = OpTypeInt 16 0
38+
; BF16_RESULT-DAG: [[INTV:%.*]] = OpTypeVector [[INT]] 4
39+
; BF16_RESULT: [[OP:%.*]] = OpFunctionParameter [[INT]]
40+
; BF16_RESULT: OpExtInst [[BFLOAT]] [[EXTSET]] nan [[OP]]
41+
; BF16_RESULT: [[OPV:%.*]] = OpFunctionParameter [[INTV]]
42+
; BF16_RESULT: OpExtInst [[BFLOATV]] [[EXTSET]] nan [[OPV]]
43+
44+
; BF16_OPERAND-DAG: [[INT:%.*]] = OpTypeInt 32 0
45+
; BF16_OPERAND-DAG: [[INTV:%.*]] = OpTypeVector [[INT]] 4
46+
; BF16_OPERAND: [[OP:%.*]] = OpFunctionParameter [[BFLOAT]]
47+
; BF16_OPERAND: OpExtInst [[INT]] [[EXTSET]] ilogb [[OP]]
48+
; BF16_OPERAND: [[OPV:%.*]] = OpFunctionParameter [[BFLOATV]]
49+
; BF16_OPERAND: OpExtInst [[INTV]] [[EXTSET]] ilogb [[OPV]]
50+
51+
;--- bf16_result_operand.ll
52+
define spir_func bfloat @test_fabs(bfloat %x) {
53+
%r = call bfloat @llvm.fabs.bf16(bfloat %x)
54+
ret bfloat %r
55+
}
56+
57+
define spir_func <4 x bfloat> @test_fabsv(<4 x bfloat> %x) {
58+
%r = call <4 x bfloat> @llvm.fabs.v4bf16(<4 x bfloat> %x)
59+
ret <4 x bfloat> %r
60+
}
61+
62+
declare bfloat @llvm.fabs.bf16(bfloat)
63+
declare <4 x bfloat> @llvm.fabs.v4bf16(<4 x bfloat>)
64+
65+
;--- bf16_result.ll
66+
define spir_func bfloat @test_nan(i16 %x) {
67+
%r = call bfloat @_Z3nant(i16 %x)
68+
ret bfloat %r
69+
}
70+
71+
define spir_func <4 x bfloat> @test_nanv(<4 x i16> %x) {
72+
%r = call <4 x bfloat> @_Z3nanDv4_t(<4 x i16> %x)
73+
ret <4 x bfloat> %r
74+
}
75+
76+
declare bfloat @_Z3nant(i16)
77+
declare <4 x bfloat> @_Z3nanDv4_t(<4 x i16>)
78+
79+
;--- bf16_operand.ll
80+
define spir_func i32 @test_ilogb(bfloat %x) {
81+
%r = call i32 @_Z5ilogbDF16_(bfloat %x)
82+
ret i32 %r
83+
}
84+
85+
define spir_func <4 x i32> @test_ilogbv(<4 x bfloat> %x) {
86+
%r = call <4 x i32> @_Z5ilogbDv4_DF16_(<4 x bfloat> %x)
87+
ret <4 x i32> %r
88+
}
89+
90+
declare i32 @_Z5ilogbDF16_(bfloat)
91+
declare <4 x i32> @_Z5ilogbDv4_DF16_(<4 x bfloat>)

0 commit comments

Comments
 (0)