Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions llvm/include/llvm/Support/TargetOpcodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,12 @@ HANDLE_TARGET_OPCODE(G_STRICT_FREM)
HANDLE_TARGET_OPCODE(G_STRICT_FMA)
HANDLE_TARGET_OPCODE(G_STRICT_FSQRT)
HANDLE_TARGET_OPCODE(G_STRICT_FLDEXP)
HANDLE_TARGET_OPCODE(G_STRICT_FPTOSI)
HANDLE_TARGET_OPCODE(G_STRICT_SITOFP)
HANDLE_TARGET_OPCODE(G_STRICT_UITOFP)
HANDLE_TARGET_OPCODE(G_STRICT_FPTOUI)
HANDLE_TARGET_OPCODE(G_STRICT_FPEXT)
HANDLE_TARGET_OPCODE(G_STRICT_FPTRUNC)

/// read_register intrinsic
HANDLE_TARGET_OPCODE(G_READ_REGISTER)
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/Target/GenericOpcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -1729,6 +1729,12 @@ 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_SITOFP: ConstrainedInstruction<G_SITOFP>;
def G_STRICT_UITOFP: ConstrainedInstruction<G_UITOFP>;
def G_STRICT_FPTOSI: ConstrainedInstruction<G_FPTOSI>;
def G_STRICT_FPTOUI: ConstrainedInstruction<G_FPTOUI>;
def G_STRICT_FPEXT: ConstrainedInstruction<G_FPEXT>;
def G_STRICT_FPTRUNC: ConstrainedInstruction<G_FPTRUNC>;

//------------------------------------------------------------------------------
// Memory intrinsics
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 @@ -2080,6 +2080,18 @@ 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_sitofp:
return TargetOpcode::G_STRICT_SITOFP;
case Intrinsic::experimental_constrained_uitofp:
return TargetOpcode::G_STRICT_UITOFP;
case Intrinsic::experimental_constrained_fptosi:
return TargetOpcode::G_STRICT_FPTOSI;
case Intrinsic::experimental_constrained_fptoui:
return TargetOpcode::G_STRICT_FPTOUI;
case Intrinsic::experimental_constrained_fpext:
return TargetOpcode::G_STRICT_FPEXT;
case Intrinsic::experimental_constrained_fptrunc:
return TargetOpcode::G_STRICT_FPTRUNC;
default:
return 0;
}
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 @@ -714,6 +714,18 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
case TargetOpcode::G_UITOFP:
return selectIToF(ResVReg, ResType, I, false, SPIRV::OpConvertUToF);

case TargetOpcode::G_STRICT_SITOFP:
return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertSToF);
case TargetOpcode::G_STRICT_UITOFP:
return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertUToF);
case TargetOpcode::G_STRICT_FPTOSI:
return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToS);
case TargetOpcode::G_STRICT_FPTOUI:
return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);
case TargetOpcode::G_STRICT_FPEXT:
case TargetOpcode::G_STRICT_FPTRUNC:
return selectUnOp(ResVReg, ResType, I, SPIRV::OpFConvert);

case TargetOpcode::G_CTPOP:
return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitCount);
case TargetOpcode::G_SMIN:
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,17 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
.legalForCartesianProduct(allIntScalarsAndVectors,
allFloatScalarsAndVectors);

getActionDefinitionsBuilder({G_STRICT_SITOFP, G_STRICT_UITOFP})
.legalForCartesianProduct(allFloatScalarsAndVectors,
allIntScalarsAndVectors);

getActionDefinitionsBuilder({G_STRICT_FPTOSI, G_STRICT_FPTOUI})
.legalForCartesianProduct(allIntScalarsAndVectors,
allFloatScalarsAndVectors);

getActionDefinitionsBuilder({G_STRICT_FPEXT, G_STRICT_FPTRUNC})
.legalForCartesianProduct(allFloatScalarsAndVectors);

getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
.legalForCartesianProduct(allFloatScalarsAndVectors,
allScalarsAndVectors);
Expand Down
230 changes: 230 additions & 0 deletions llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-convert.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
; 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 %}

define float @sitofp_f32_i32(i32 %in) {
; CHECK-DAG: OpName %[[#]] "conv"
; CHECK-DAG: OpConvertSToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTE
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv = tail call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %in, metadata !"round.tonearest", metadata !"fpexcept.strict")
ret float %conv
}

define float @sitofp_f32_i16(i16 %in) {
; CHECK-DAG: OpName %[[#]] "conv1"
Copy link
Contributor

Choose a reason for hiding this comment

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

No check label, and don't need CHECK-DAG. Can you just use update_llc_test_checks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@arsenm I tried running utils/update_llc_test_checks.py on constrained-convert.ll. Instead of regenerating the CHECK: directives, it only inserted the autogenerated note at the top and the file end marker, while removing the existing checks in between. Could you clarify the correct way to use the script here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Did it print a warning on error? Somehow only 2 spirv tests are using update_llc_test_checks. Is it getting confused by the second run line?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@arsenm Yes, it did print a warning message: WARNING: Skipping non-llc RUN line.
When I removed the second RUN line, the warning disappeared, but the issue still persists — the script removes the existing CHECK: directives and only adds the autogenerated note at the top and the file end marker.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Gentle reminder @arsenm any updates on this PR?

; CHECK-DAG: OpConvertSToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTZ
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv1 = tail call float @llvm.experimental.constrained.sitofp.f32.i16(i16 %in, metadata !"round.towardzero", metadata !"fpexcept.strict")
ret float %conv1
}

define double @sitofp_f64_i16(i16 %in) {
; CHECK-DAG: OpName %[[#]] "conv2"
; CHECK-DAG: OpConvertSToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTP
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv2 = tail call double @llvm.experimental.constrained.sitofp.f64.i16(i16 %in, metadata !"round.upward", metadata !"fpexcept.strict")
ret double %conv2
}

define double @sitofp_f64_i32(i16 %in) {
; CHECK-DAG: OpName %[[#]] "conv3"
; CHECK-DAG: OpConvertSToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTN
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv3 = tail call double @llvm.experimental.constrained.sitofp.f64.i32(i16 %in, metadata !"round.downward", metadata !"fpexcept.strict")
ret double %conv3
}

define <4 x double> @sitofp_v4f64_v4i32(<4 x i16> %in) {
; CHECK-DAG: OpName %[[#]] "conv4"
; CHECK-DAG: OpConvertSToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTE
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv4 = tail call <4 x double> @llvm.experimental.constrained.sitofp.v4f64.v4i32(<4 x i16> %in, metadata !"round.tonearest", metadata !"fpexcept.strict")
ret <4 x double> %conv4
}

define float @uitofp_f32_i32(i32 %in) {
; CHECK-DAG: OpName %[[#]] "conv5"
; CHECK-DAG: OpConvertUToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTE
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv5 = tail call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %in, metadata !"round.tonearest", metadata !"fpexcept.strict")
ret float %conv5
}

define double @uitofp_f64_i32(i32 %in) {
; CHECK-DAG: OpName %[[#]] "conv6"
; CHECK-DAG: OpConvertUToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTZ
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv6 = tail call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %in, metadata !"round.towardzero", metadata !"fpexcept.strict")
ret double %conv6
}

define float @uitofp_f32_i16(i16 %in) {
; CHECK-DAG: OpName %[[#]] "conv7"
; CHECK-DAG: OpConvertUToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTP
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv7 = tail call float @llvm.experimental.constrained.uitofp.f32.i16(i16 %in, metadata !"round.upward", metadata !"fpexcept.strict")
ret float %conv7
}

define double @uitofp_f64_i16(i16 %in) {
; CHECK-DAG: OpName %[[#]] "conv8"
; CHECK-DAG: OpConvertUToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTN
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv8 = tail call double @llvm.experimental.constrained.uitofp.f64.i16(i16 %in, metadata !"round.downward", metadata !"fpexcept.strict")
ret double %conv8
}

define <4 x float> @uitofp_v4f32_v4i32(<4 x i32> %in) {
; CHECK-DAG: OpName %[[#]] "conv9"
; CHECK-DAG: OpConvertUToF %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTE
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv9 = tail call <4 x float> @llvm.experimental.constrained.uitofp.v4f32.v4i32(<4 x i32> %in, metadata !"round.tonearest", metadata !"fpexcept.strict")
ret <4 x float> %conv9
}

define i32 @fptosi_i32_f32(float %in) {
; CHECK-DAG: OpName %[[#]] "conv10"
; CHECK-DAG: OpConvertFToS %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv10 = tail call i32 @llvm.experimental.constrained.fptosi.i32.f32(float %in, metadata !"fpexcept.strict")
ret i32 %conv10
}

define i32 @fptosi_i32_f64(double %in) {
; CHECK-DAG: OpName %[[#]] "conv11"
; CHECK-DAG: OpConvertFToS %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv11 = tail call i32 @llvm.experimental.constrained.fptosi.i32.f64(double %in, metadata !"fpexcept.strict")
ret i32 %conv11
}

define i16 @fptosi_i16_f32(float %in) {
; CHECK-DAG: OpName %[[#]] "conv12"
; CHECK-DAG: OpConvertFToS %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv12 = tail call i16 @llvm.experimental.constrained.fptosi.i16.f64(float %in, metadata !"fpexcept.strict")
ret i16 %conv12
}

define i16 @fptosi_i16_f64(double %in) {
; CHECK-DAG: OpName %[[#]] "conv13"
; CHECK-DAG: OpConvertFToS %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv13 = tail call i16 @llvm.experimental.constrained.fptosi.i16.f64(double %in, metadata !"fpexcept.strict")
ret i16 %conv13
}

define <4 x i16> @fptosi_v4i16_v4f64(<4 x double> %in) {
; CHECK-DAG: OpName %[[#]] "conv14"
; CHECK-DAG: OpConvertFToS %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv14 = tail call <4 x i16> @llvm.experimental.constrained.fptosi.v4i16.v4f64(<4 x double> %in, metadata !"fpexcept.strict")
ret <4 x i16> %conv14
}

define i32 @fptoui_i32_f32(float %in) {
; CHECK-DAG: OpName %[[#]] "conv15"
; CHECK-DAG: OpConvertFToU %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv15 = tail call i32 @llvm.experimental.constrained.fptoui.i32.f32(float %in, metadata !"fpexcept.strict")
ret i32 %conv15
}

define i32 @fptoui_i32_f64(double %in) {
; CHECK-DAG: OpName %[[#]] "conv16"
; CHECK-DAG: OpConvertFToU %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv16 = tail call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %in, metadata !"fpexcept.strict")
ret i32 %conv16
}

define i16 @fptoui_i16_f32(float %in) {
; CHECK-DAG: OpName %[[#]] "conv17"
; CHECK-DAG: OpConvertFToU %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv17 = tail call i16 @llvm.experimental.constrained.fptoui.i16.f32(float %in, metadata !"fpexcept.strict")
ret i16 %conv17
}

define i16 @fptoui_i16_f64(double %in) {
; CHECK-DAG: OpName %[[#]] "conv18"
; CHECK-DAG: OpConvertFToU %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv18 = tail call i16 @llvm.experimental.constrained.fptoui.i16.f64(double %in, metadata !"fpexcept.strict")
ret i16 %conv18
}

define <4 x i32> @fptoui_v4i32_v4f64(<4 x double> %in) {
; CHECK-DAG: OpName %[[#]] "conv19"
; CHECK-DAG: OpConvertFToU %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv19 = tail call <4 x i32> @llvm.experimental.constrained.fptoui.v4i32.v4f64(<4 x double> %in, metadata !"fpexcept.strict")
ret <4 x i32> %conv19
}

define double @fpext_f64_f32(float %in) {
; CHECK-DAG: OpName %[[#]] "conv20"
; CHECK-DAG: OpFConvert %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv20 = tail call double @llvm.experimental.constrained.fpext.f64.f32(float %in, metadata !"fpexcept.strict")
ret double %conv20
}

define <4 x double> @fpext_v4f64_v4f32(<4 x float> %in) {
; CHECK-DAG: OpName %[[#]] "conv21"
; CHECK-DAG: OpFConvert %[[#]] %[[#]]
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv21 = tail call <4 x double> @llvm.experimental.constrained.fpext.v4f64.v4f32(<4 x float> %in, metadata !"fpexcept.strict")
ret <4 x double> %conv21
}

define <4 x float> @fptrunc_v4f32_v4f64(<4 x double> %in) {
; CHECK-DAG: OpName %[[#]] "conv22"
; CHECK-DAG: OpFConvert %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTZ
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv22 = tail call <4 x float> @llvm.experimental.constrained.fptrunc.v4f32.v4f64(<4 x double> %in, metadata !"round.towardzero", metadata !"fpexcept.strict")
ret <4 x float> %conv22
}

define float @fptrunc_f32_f64(double %in) {
; CHECK-DAG: OpName %[[#]] "conv23"
; CHECK-DAG: OpFConvert %[[#]] %[[#]]
; CHECK-DAG: OpDecorate %[[#]] FPRoundingMode RTE
; CHECK-DAG: OpReturnValue %[[#]]
entry:
%conv23 = tail call float @llvm.experimental.constrained.fptrunc.f32.f64(double %in, metadata !"round.tonearest", metadata !"fpexcept.strict")
ret float %conv23
}
Loading