Skip to content

Commit

Permalink
[SPIRV] Add trig function lowering (llvm#95973)
Browse files Browse the repository at this point in the history
This change is part of this proposal:
https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294

This is part 2 of 4 PRs. It sets the ground work for adding the
intrinsics.

Add SPIRV  Lower for `acos`, `asin`, `atan`, `cosh`, `sinh`, and `tanh`
llvm#70079
llvm#70080
llvm#70081
llvm#70083
llvm#70084
llvm#95966


There isn't any aarch64 change in this pr, but when you add a target
opcode it is visible in there validaiton tests.
  • Loading branch information
farzonl authored and AlexisPerry committed Jun 27, 2024
1 parent fdd0e5d commit 2a824e9
Show file tree
Hide file tree
Showing 13 changed files with 386 additions and 3 deletions.
9 changes: 7 additions & 2 deletions llvm/docs/GlobalISel/GenericOpcode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -592,11 +592,16 @@ G_FLOG, G_FLOG2, G_FLOG10

Calculate the base-e, base-2, or base-10 respectively.

G_FCEIL, G_FCOS, G_FSIN, G_FTAN, G_FSQRT, G_FFLOOR, G_FRINT, G_FNEARBYINT
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
G_FCEIL, G_FSQRT, G_FFLOOR, G_FRINT, G_FNEARBYINT
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

These correspond to the standard C functions of the same name.

G_FCOS, G_FSIN, G_FTAN, G_FACOS, G_FASIN, G_FATAN, G_FCOSH, G_FSINH, G_FTANH
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

These correspond to the standard C trigonometry functions of the same name.

G_INTRINSIC_TRUNC
^^^^^^^^^^^^^^^^^

Expand Down
20 changes: 19 additions & 1 deletion llvm/include/llvm/Support/TargetOpcodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -781,9 +781,27 @@ HANDLE_TARGET_OPCODE(G_FCOS)
/// Floating point sine.
HANDLE_TARGET_OPCODE(G_FSIN)

/// Floating point Tangent.
/// Floating point tangent.
HANDLE_TARGET_OPCODE(G_FTAN)

/// Floating point arccosine.
HANDLE_TARGET_OPCODE(G_FACOS)

/// Floating point arcsine.
HANDLE_TARGET_OPCODE(G_FASIN)

/// Floating point arctangent.
HANDLE_TARGET_OPCODE(G_FATAN)

/// Floating point hyperbolic cosine.
HANDLE_TARGET_OPCODE(G_FCOSH)

/// Floating point hyperbolic sine.
HANDLE_TARGET_OPCODE(G_FSINH)

/// Floating point hyperbolic tangent.
HANDLE_TARGET_OPCODE(G_FTANH)

/// Floating point square root.
HANDLE_TARGET_OPCODE(G_FSQRT)

Expand Down
42 changes: 42 additions & 0 deletions llvm/include/llvm/Target/GenericOpcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,48 @@ def G_FTAN : GenericInstruction {
let hasSideEffects = false;
}

// Floating point arccosine of a value.
def G_FACOS : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1);
let hasSideEffects = false;
}

// Floating point arcsine of a value.
def G_FASIN : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1);
let hasSideEffects = false;
}

// Floating point arctangent of a value.
def G_FATAN : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1);
let hasSideEffects = false;
}

// Floating point hyperbolic cosine of a value.
def G_FCOSH : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1);
let hasSideEffects = false;
}

// Floating point hyperbolic sine of a value.
def G_FSINH : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1);
let hasSideEffects = false;
}

// Floating point hyperbolic tangent of a value.
def G_FTANH : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1);
let hasSideEffects = false;
}

// Floating point square root of a value.
// This returns NaN for negative nonzero values.
// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,12 @@ unsigned IRTranslator::getSimpleIntrinsicOpcode(Intrinsic::ID ID) {
switch (ID) {
default:
break;
case Intrinsic::acos:
return TargetOpcode::G_FACOS;
case Intrinsic::asin:
return TargetOpcode::G_FASIN;
case Intrinsic::atan:
return TargetOpcode::G_FATAN;
case Intrinsic::bswap:
return TargetOpcode::G_BSWAP;
case Intrinsic::bitreverse:
Expand All @@ -1891,6 +1897,8 @@ unsigned IRTranslator::getSimpleIntrinsicOpcode(Intrinsic::ID ID) {
return TargetOpcode::G_FCEIL;
case Intrinsic::cos:
return TargetOpcode::G_FCOS;
case Intrinsic::cosh:
return TargetOpcode::G_FCOSH;
case Intrinsic::ctpop:
return TargetOpcode::G_CTPOP;
case Intrinsic::exp:
Expand Down Expand Up @@ -1939,10 +1947,14 @@ unsigned IRTranslator::getSimpleIntrinsicOpcode(Intrinsic::ID ID) {
return TargetOpcode::G_INTRINSIC_ROUNDEVEN;
case Intrinsic::sin:
return TargetOpcode::G_FSIN;
case Intrinsic::sinh:
return TargetOpcode::G_FSINH;
case Intrinsic::sqrt:
return TargetOpcode::G_FSQRT;
case Intrinsic::tan:
return TargetOpcode::G_FTAN;
case Intrinsic::tanh:
return TargetOpcode::G_FTANH;
case Intrinsic::trunc:
return TargetOpcode::G_INTRINSIC_TRUNC;
case Intrinsic::readcyclecounter:
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,18 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::sin, GL::Sin);
case TargetOpcode::G_FTAN:
return selectExtInst(ResVReg, ResType, I, CL::tan, GL::Tan);
case TargetOpcode::G_FACOS:
return selectExtInst(ResVReg, ResType, I, CL::acos, GL::Acos);
case TargetOpcode::G_FASIN:
return selectExtInst(ResVReg, ResType, I, CL::asin, GL::Asin);
case TargetOpcode::G_FATAN:
return selectExtInst(ResVReg, ResType, I, CL::atan, GL::Atan);
case TargetOpcode::G_FCOSH:
return selectExtInst(ResVReg, ResType, I, CL::cosh, GL::Cosh);
case TargetOpcode::G_FSINH:
return selectExtInst(ResVReg, ResType, I, CL::sinh, GL::Sinh);
case TargetOpcode::G_FTANH:
return selectExtInst(ResVReg, ResType, I, CL::tanh, GL::Tanh);

case TargetOpcode::G_FSQRT:
return selectExtInst(ResVReg, ResType, I, CL::sqrt, GL::Sqrt);
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,12 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
G_FCOS,
G_FSIN,
G_FTAN,
G_FACOS,
G_FASIN,
G_FATAN,
G_FCOSH,
G_FSINH,
G_FTANH,
G_FSQRT,
G_FFLOOR,
G_FRINT,
Expand Down
18 changes: 18 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,24 @@
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FACOS (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_FASIN (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_FATAN (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_FCOSH (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_FSINH (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_FTANH (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_FSQRT (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
Expand Down
45 changes: 45 additions & 0 deletions llvm/test/CodeGen/SPIRV/hlsl-intrinsics/acos.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}

; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4

define noundef float @acos_float(float noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Acos %[[#arg0]]
%elt.acos = call float @llvm.acos.f32(float %a)
ret float %elt.acos
}

define noundef half @acos_half(half noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Acos %[[#arg0]]
%elt.acos = call half @llvm.acos.f16(half %a)
ret half %elt.acos
}

define noundef <4 x float> @acos_float4(<4 x float> noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] Acos %[[#arg0]]
%elt.acos = call <4 x float> @llvm.acos.v4f32(<4 x float> %a)
ret <4 x float> %elt.acos
}

define noundef <4 x half> @acos_half4(<4 x half> noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] Acos %[[#arg0]]
%elt.acos = call <4 x half> @llvm.acos.v4f16(<4 x half> %a)
ret <4 x half> %elt.acos
}

declare half @llvm.acos.f16(half)
declare float @llvm.acos.f32(float)
declare <4 x half> @llvm.acos.v4f16(<4 x half>)
declare <4 x float> @llvm.acos.v4f32(<4 x float>)
45 changes: 45 additions & 0 deletions llvm/test/CodeGen/SPIRV/hlsl-intrinsics/asin.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}

; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4

define noundef float @asin_float(float noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Asin %[[#arg0]]
%elt.asin = call float @llvm.asin.f32(float %a)
ret float %elt.asin
}

define noundef half @asin_half(half noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Asin %[[#arg0]]
%elt.asin = call half @llvm.asin.f16(half %a)
ret half %elt.asin
}

define noundef <4 x float> @asin_float4(<4 x float> noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] Asin %[[#arg0]]
%elt.asin = call <4 x float> @llvm.asin.v4f32(<4 x float> %a)
ret <4 x float> %elt.asin
}

define noundef <4 x half> @asin_half4(<4 x half> noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] Asin %[[#arg0]]
%elt.asin = call <4 x half> @llvm.asin.v4f16(<4 x half> %a)
ret <4 x half> %elt.asin
}

declare half @llvm.asin.f16(half)
declare float @llvm.asin.f32(float)
declare <4 x half> @llvm.asin.v4f16(<4 x half>)
declare <4 x float> @llvm.asin.v4f32(<4 x float>)
45 changes: 45 additions & 0 deletions llvm/test/CodeGen/SPIRV/hlsl-intrinsics/atan.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}

; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4

define noundef float @atan_float(float noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Atan %[[#arg0]]
%elt.atan = call float @llvm.atan.f32(float %a)
ret float %elt.atan
}

define noundef half @atan_half(half noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Atan %[[#arg0]]
%elt.atan = call half @llvm.atan.f16(half %a)
ret half %elt.atan
}

define noundef <4 x float> @atan_float4(<4 x float> noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] Atan %[[#arg0]]
%elt.atan = call <4 x float> @llvm.atan.v4f32(<4 x float> %a)
ret <4 x float> %elt.atan
}

define noundef <4 x half> @atan_half4(<4 x half> noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] Atan %[[#arg0]]
%elt.atan = call <4 x half> @llvm.atan.v4f16(<4 x half> %a)
ret <4 x half> %elt.atan
}

declare half @llvm.atan.f16(half)
declare float @llvm.atan.f32(float)
declare <4 x half> @llvm.atan.v4f16(<4 x half>)
declare <4 x float> @llvm.atan.v4f32(<4 x float>)
45 changes: 45 additions & 0 deletions llvm/test/CodeGen/SPIRV/hlsl-intrinsics/cosh.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}

; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4

define noundef float @cosh_float(float noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Cosh %[[#arg0]]
%elt.cosh = call float @llvm.cosh.f32(float %a)
ret float %elt.cosh
}

define noundef half @cosh_half(half noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Cosh %[[#arg0]]
%elt.cosh = call half @llvm.cosh.f16(half %a)
ret half %elt.cosh
}

define noundef <4 x float> @cosh_float4(<4 x float> noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] Cosh %[[#arg0]]
%elt.cosh = call <4 x float> @llvm.cosh.v4f32(<4 x float> %a)
ret <4 x float> %elt.cosh
}

define noundef <4 x half> @cosh_half4(<4 x half> noundef %a) {
entry:
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] Cosh %[[#arg0]]
%elt.cosh = call <4 x half> @llvm.cosh.v4f16(<4 x half> %a)
ret <4 x half> %elt.cosh
}

declare half @llvm.cosh.f16(half)
declare float @llvm.cosh.f32(float)
declare <4 x half> @llvm.cosh.v4f16(<4 x half>)
declare <4 x float> @llvm.cosh.v4f32(<4 x float>)
Loading

0 comments on commit 2a824e9

Please sign in to comment.