Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/include/llvm/Support/TargetOpcodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ HANDLE_TARGET_OPCODE(G_FMA)

/// Generic FP multiply and add. Behaves as separate fmul and fadd.
HANDLE_TARGET_OPCODE(G_FMAD)
HANDLE_TARGET_OPCODE(G_STRICT_FMAD)

/// Generic FP division.
HANDLE_TARGET_OPCODE(G_FDIV)
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Target/GenericOpcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -1716,6 +1716,7 @@ def G_STRICT_FREM : ConstrainedInstruction<G_FREM>;
def G_STRICT_FMA : ConstrainedInstruction<G_FMA>;
def G_STRICT_FSQRT : ConstrainedInstruction<G_FSQRT>;
def G_STRICT_FLDEXP : ConstrainedInstruction<G_FLDEXP>;
def G_STRICT_FMAD : ConstrainedInstruction<G_FMAD>;

//------------------------------------------------------------------------------
// Memory intrinsics
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,8 @@ static unsigned getConstrainedOpcode(Intrinsic::ID ID) {
return TargetOpcode::G_STRICT_FSQRT;
case Intrinsic::experimental_constrained_ldexp:
return TargetOpcode::G_STRICT_FLDEXP;
case Intrinsic::experimental_constrained_fmuladd:
return TargetOpcode::G_STRICT_FMAD;
default:
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4523,6 +4523,7 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
return Legalized;
}
case TargetOpcode::G_FMAD:
case TargetOpcode::G_STRICT_FMAD:
return lowerFMad(MI);
case TargetOpcode::G_FFLOOR:
return lowerFFloor(MI);
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
getActionDefinitionsBuilder({G_FMA, G_STRICT_FMA})
.legalFor(allFloatScalarsAndVectors);

getActionDefinitionsBuilder(G_STRICT_FMAD)
.legalFor(allFloatScalarsAndVectors)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the G_STRICT_FMAD is applied to a float or vector of floats, it will not be lowered. Is that what you want?

If you want it lowered all of the time, remove this line. I expect that is what you want based on earlier PRs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@s-perron I understood and I modified the legalizer info to directly lower the intrinsic as expected.

.lower();

getActionDefinitionsBuilder(G_STRICT_FLDEXP)
.legalForCartesianProduct(allFloatScalarsAndVectors, allIntScalars);

Expand Down
64 changes: 64 additions & 0 deletions llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-fmuladd.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
; RUN: llc -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}

; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTE
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTZ
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTP
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTN
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTE

; CHECK: OpFMul %[[#]] %[[#]] %[[#]]
; CHECK: OpFAdd %[[#]] %[[#]] %[[#]]
define spir_kernel void @test_f32(float %a) {
entry:
%r = tail call float @llvm.experimental.constrained.fmuladd.f32(
float %a, float %a, float %a,
metadata !"round.tonearest", metadata !"fpexcept.strict")
ret void
}

; CHECK: OpFMul %[[#]] %[[#]] %[[#]]
; CHECK: OpFAdd %[[#]] %[[#]] %[[#]]
define spir_kernel void @test_f64(double %a) {
entry:
%r = tail call double @llvm.experimental.constrained.fmuladd.f64(
double %a, double %a, double %a,
metadata !"round.towardzero", metadata !"fpexcept.strict")
ret void
}

; CHECK: OpFMul %[[#]] %[[#]] %[[#]]
; CHECK: OpFAdd %[[#]] %[[#]] %[[#]]
define spir_kernel void @test_v2f32(<2 x float> %a) {
entry:
%r = tail call <2 x float> @llvm.experimental.constrained.fmuladd.v2f32(
<2 x float> %a, <2 x float> %a, <2 x float> %a,
metadata !"round.upward", metadata !"fpexcept.strict")
ret void
}

; CHECK: OpFMul %[[#]] %[[#]] %[[#]]
; CHECK: OpFAdd %[[#]] %[[#]] %[[#]]
define spir_kernel void @test_v4f32(<4 x float> %a) {
entry:
%r = tail call <4 x float> @llvm.experimental.constrained.fmuladd.v4f32(
<4 x float> %a, <4 x float> %a, <4 x float> %a,
metadata !"round.downward", metadata !"fpexcept.strict")
ret void
}

; CHECK: OpFMul %[[#]] %[[#]] %[[#]]
; CHECK: OpFAdd %[[#]] %[[#]] %[[#]]
define spir_kernel void @test_v2f64(<2 x double> %a) {
entry:
%r = tail call <2 x double> @llvm.experimental.constrained.fmuladd.v2f64(
<2 x double> %a, <2 x double> %a, <2 x double> %a,
metadata !"round.tonearest", metadata !"fpexcept.strict")
ret void
}

declare float @llvm.experimental.constrained.fmuladd.f32(float, float, float, metadata, metadata)
declare double @llvm.experimental.constrained.fmuladd.f64(double, double, double, metadata, metadata)
declare <2 x float> @llvm.experimental.constrained.fmuladd.v2f32(<2 x float>, <2 x float>, <2 x float>, metadata, metadata)
declare <4 x float> @llvm.experimental.constrained.fmuladd.v4f32(<4 x float>, <4 x float>, <4 x float>, metadata, metadata)
declare <2 x double> @llvm.experimental.constrained.fmuladd.v2f64(<2 x double>, <2 x double>, <2 x double>, metadata, metadata)
Loading