[llvm] [SPIR-V] Lower llvm.minimum/maximum instead of selecting fmin/fmax (PR #225667)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 23 03:15:06 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-spir-v
Author: Tim Besard (maleadt)
<details>
<summary>Changes</summary>
Fixes #<!-- -->225665. The SPIRV-LLVM-Translator equivalent is KhronosGroup/SPIRV-LLVM-Translator#<!-- -->4032.
`G_FMINIMUM`/`G_FMAXIMUM` were legal and selected to `fmin`/`fmax` (`NMin`/`NMax`), which neither propagate NaNs nor order signed zeros. This marks them `lower` so that they use the generic `LegalizerHelper::lowerFMinimumMaximum`. That expansion computes `fmin`/`fmax`, selects a NaN if the operands are unordered (skipped under `nnan`), and fixes up signed zeros with `G_IS_FPCLASS` (skipped under `nsz`). A `nnan nsz` call therefore still compiles to a single `fmin`/`fmax`.
```
%min = OpExtInst %float %ext fmin %a %b
%ord = OpOrdered %bool %a %b
%sel = OpSelect %float %ord %min %nan
... ; if %sel is zero, pick whichever operand is -0.0
```
Making the expansion selectable needed three more changes:
- `fcmp ord`/`uno` in shaders. The expansion relies on `fcmp ord`, but in shaders these were selected to `OpOrdered`/`OpUnordered`. Those require the `Kernel` capability, so any `fcmp ord`/`uno` in a Vulkan module was already invalid. In shaders they are now selected via `OpIsNan`. This is also a standalone fix, with its own test.
- `SPIRVPostLegalizer` now types `G_FCONSTANT` results from their immediate, `G_SELECT` results from the value operands instead of the condition, and untyped `COPY` results from their source. Previously these fell back to integer types or were left untyped.
- The `G_IS_FPCLASS` custom lowering now types an untyped source before bitcasting it. This happens with widened vectors.
In shaders, the signed-zero check makes `half`/`double` need `Int16`/`Int64`, the same as `llvm.is.fpclass` already does. `nsz` avoids this.
This supersedes the draft #<!-- -->180797, which took the same approach but didn't handle the untyped `G_IS_FPCLASS` source (its CI fails on it) or shaders, and had no tests. `minimumnum`/`maximumnum` are handled separately in #<!-- -->218641.
---
Patch is 60.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/225667.diff
11 Files Affected:
- (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+35-3)
- (modified) llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp (+23-2)
- (modified) llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp (+9-1)
- (added) llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/fminimum.ll (+27)
- (modified) llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fmaximum.ll (+80-16)
- (modified) llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fminimum.ll (+80-16)
- (added) llvm/test/CodeGen/SPIRV/instructions/fcmp-ord-uno-shader.ll (+68)
- (added) llvm/test/CodeGen/SPIRV/llvm-intrinsics/fminimum-fmaximum.ll (+215)
- (modified) llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp-intrinsics.ll (+10-2)
- (modified) llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmaximum.ll (+45-9)
- (modified) llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fminimum.ll (+45-9)
``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 0ea9e552ce2e3a..76362a30fad770 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1174,10 +1174,8 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::s_abs, GL::SAbs);
case TargetOpcode::G_FMINNUM:
- case TargetOpcode::G_FMINIMUM:
return selectExtInst(ResVReg, ResType, I, CL::fmin, GL::NMin);
case TargetOpcode::G_FMAXNUM:
- case TargetOpcode::G_FMAXIMUM:
return selectExtInst(ResVReg, ResType, I, CL::fmax, GL::NMax);
case TargetOpcode::G_FCOPYSIGN:
@@ -4583,7 +4581,41 @@ Register SPIRVInstructionSelector::buildI32ConstantInEntryBlock(
bool SPIRVInstructionSelector::selectFCmp(Register ResVReg,
SPIRVTypeInst ResType,
MachineInstr &I) const {
- unsigned CmpOp = getFCmpOpcode(I.getOperand(1).getPredicate());
+ auto Pred = I.getOperand(1).getPredicate();
+ // OpOrdered and OpUnordered require the Kernel capability. For shaders,
+ // express them as uno(a, b) = isnan(a) || isnan(b), ord(a, b) = !uno(a, b).
+ if (STI.isShader() &&
+ (Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO)) {
+ MachineBasicBlock &BB = *I.getParent();
+ Register ResTypeID = GR.getSPIRVTypeID(ResType);
+ Register IsNan[2];
+ for (unsigned Idx = 0; Idx < 2; ++Idx) {
+ IsNan[Idx] = createVirtualRegister(ResType, &GR, MRI, *I.getMF());
+ BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIsNan))
+ .addDef(IsNan[Idx])
+ .addUse(ResTypeID)
+ .addUse(I.getOperand(2 + Idx).getReg())
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ Register UnoReg =
+ Pred == CmpInst::FCMP_UNO
+ ? ResVReg
+ : createVirtualRegister(ResType, &GR, MRI, *I.getMF());
+ BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpLogicalOr))
+ .addDef(UnoReg)
+ .addUse(ResTypeID)
+ .addUse(IsNan[0])
+ .addUse(IsNan[1])
+ .constrainAllUses(TII, TRI, RBI);
+ if (Pred == CmpInst::FCMP_ORD)
+ BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpLogicalNot))
+ .addDef(ResVReg)
+ .addUse(ResTypeID)
+ .addUse(UnoReg)
+ .constrainAllUses(TII, TRI, RBI);
+ return true;
+ }
+ unsigned CmpOp = getFCmpOpcode(Pred);
return selectCmp(ResVReg, ResType, CmpOp, I);
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index b5d43a6074bc5e..38b54943ba25e9 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -599,8 +599,6 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
G_FNEARBYINT,
G_INTRINSIC_ROUND,
G_INTRINSIC_TRUNC,
- G_FMINIMUM,
- G_FMAXIMUM,
G_INTRINSIC_ROUNDEVEN})
.legalFor(allFloatScalars)
.legalFor(allowedFloatVectorTypes)
@@ -610,6 +608,17 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
.moreElementsToNextPow2(0);
// clang-format on
+ // OpenCL.std fmin/fmax and GLSL.std.450 NMin/NMax implement IEEE 754-2008
+ // minNum/maxNum, which do not propagate NaNs and do not order signed zeros.
+ // Expand fminimum/fmaximum in terms of them.
+ getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
+ .lowerFor(allFloatScalars)
+ .lowerFor(allowedFloatVectorTypes)
+ .fewerElementsIf(vectorElementCountIsGreaterThan(0, MaxVectorSize),
+ LegalizeMutations::changeElementCountTo(
+ 0, ElementCount::getFixed(MaxVectorSize)))
+ .moreElementsToNextPow2(0);
+
getActionDefinitionsBuilder(G_FCOPYSIGN)
.legalForCartesianProduct(allFloatScalarsAndVectors,
allFloatScalarsAndVectors);
@@ -1107,6 +1116,18 @@ bool SPIRVLegalizerInfo::legalizeIsFPClass(
unsigned BitSize = SrcTy.getScalarSizeInBits();
const fltSemantics &Semantics = getFltSemanticForLLT(SrcTy.getScalarType());
+ // If this G_IS_FPCLASS was created while lowering another instruction (e.g.
+ // G_FMINIMUM), its source may not have a SPIR-V type yet, but the OpBitcast
+ // below needs one.
+ if (!GR->getSPIRVTypeForVReg(SrcReg)) {
+ Type *LLVMSrcTy =
+ Type::getFloatingPointTy(MIRBuilder.getContext(), Semantics);
+ if (SrcTy.isVector())
+ LLVMSrcTy = VectorType::get(LLVMSrcTy, SrcTy.getElementCount());
+ setRegClassType(SrcReg, LLVMSrcTy, GR, MIRBuilder,
+ SPIRV::AccessQualifier::ReadWrite, /*EmitIR=*/true);
+ }
+
LLT IntTy = LLT::scalar(BitSize);
Type *LLVMIntTy = IntegerType::get(MIRBuilder.getContext(), BitSize);
if (SrcTy.isVector()) {
diff --git a/llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp
index 8136b054f007b1..45476c2a49171b 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPostLegalizer.cpp
@@ -312,6 +312,12 @@ static SPIRVTypeInst deduceResultTypeFromOperands(MachineInstr *I,
case TargetOpcode::G_ZEXT:
case TargetOpcode::G_TRUNC:
return deduceIntTypeFromResult(ResVReg, MIB, GR);
+ case TargetOpcode::G_FCONSTANT:
+ return GR->getOrCreateSPIRVType(I->getOperand(1).getFPImm()->getType(), MIB,
+ SPIRV::AccessQualifier::ReadWrite,
+ /*EmitIR=*/true);
+ case TargetOpcode::G_SELECT:
+ return deduceTypeFromOperandRange(I, MIB, GR, 2, 4);
case TargetOpcode::G_BUILD_VECTOR:
return deduceTypeFromOperandRange(I, MIB, GR, 1, I->getNumOperands());
case TargetOpcode::G_SHUFFLE_VECTOR:
@@ -424,7 +430,9 @@ static bool requiresSpirvType(MachineInstr &I, SPIRVGlobalRegistry *GR,
return false;
}
- if (!I.isPreISelOpcode()) {
+ // Lowerings often copy their result into the original destination register,
+ // which is new and untyped if it was itself created during legalization.
+ if (!I.isPreISelOpcode() && !I.isCopy()) {
LLVM_DEBUG(dbgs() << "Instruction is not a generic instruction.\n");
return false;
}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/fminimum.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/fminimum.ll
new file mode 100644
index 00000000000000..9d19b7a5e7dfc3
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/fminimum.ll
@@ -0,0 +1,27 @@
+; RUN: llc -verify-machineinstrs -O0 --spirv-ext=+SPV_EXT_long_vector -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 --spirv-ext=+SPV_EXT_long_vector -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; llvm.minimum on <5 x float> is widened to <8 x float> before being lowered, so
+; the signed-zero check operates on newly created, widened operands.
+
+; CHECK-DAG: %[[#F32:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#V8F32:]] = OpTypeVector %[[#F32]] 8
+; CHECK-DAG: %[[#V8I32:]] = OpTypeVector %[[#I32]] 8
+
+; CHECK: OpFunction
+; CHECK: %[[#A:]] = OpCompositeConstruct %[[#V8F32]]
+; CHECK: %[[#B:]] = OpCompositeConstruct %[[#V8F32]]
+; CHECK: %[[#Min:]] = OpExtInst %[[#V8F32]] %[[#]] fmin %[[#A]] %[[#B]]
+; CHECK: %[[#Ord:]] = OpOrdered %[[#]] %[[#A]] %[[#B]]
+; CHECK: %[[#NaNSel:]] = OpSelect %[[#V8F32]] %[[#Ord]] %[[#Min]] %[[#]]
+; CHECK: %[[#IsZero:]] = OpFOrdEqual %[[#]] %[[#NaNSel]] %[[#]]
+; CHECK: %[[#]] = OpBitcast %[[#V8I32]] %[[#A]]
+; CHECK: %[[#]] = OpBitcast %[[#V8I32]] %[[#B]]
+; CHECK: %[[#Res:]] = OpSelect %[[#V8F32]] %[[#IsZero]] %[[#]] %[[#NaNSel]]
+; CHECK: OpCompositeExtract %[[#F32]] %[[#Res]] 0
+; CHECK: OpReturnValue
+define <5 x float> @minimum_v5f32(<5 x float> %a, <5 x float> %b) {
+ %r = call <5 x float> @llvm.minimum.v5f32(<5 x float> %a, <5 x float> %b)
+ ret <5 x float> %r
+}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fmaximum.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fmaximum.ll
index 4de10f5e02fe0a..e87228ed2f153d 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fmaximum.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fmaximum.ll
@@ -38,22 +38,86 @@ entry:
; CHECK: %[[Vec17FloatItem14:.*]] = OpCompositeExtract %[[Float]] %[[ParamVec17Float]] 14
; CHECK: %[[Vec17FloatItem15:.*]] = OpCompositeExtract %[[Float]] %[[ParamVec17Float]] 15
; CHECK: %[[Vec17FloatItem16:.*]] = OpCompositeExtract %[[Float]] %[[ParamVec17Float]] 16
-; CHECK: %[[Vec17FloatR1:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatItem0]] %[[Vec17FloatItem1]]
-; CHECK: %[[Vec17FloatR2:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR1]] %[[Vec17FloatItem2]]
-; CHECK: %[[Vec17FloatR3:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR2]] %[[Vec17FloatItem3]]
-; CHECK: %[[Vec17FloatR4:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR3]] %[[Vec17FloatItem4]]
-; CHECK: %[[Vec17FloatR5:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR4]] %[[Vec17FloatItem5]]
-; CHECK: %[[Vec17FloatR6:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR5]] %[[Vec17FloatItem6]]
-; CHECK: %[[Vec17FloatR7:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR6]] %[[Vec17FloatItem7]]
-; CHECK: %[[Vec17FloatR8:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR7]] %[[Vec17FloatItem8]]
-; CHECK: %[[Vec17FloatR9:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR8]] %[[Vec17FloatItem9]]
-; CHECK: %[[Vec17FloatR10:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR9]] %[[Vec17FloatItem10]]
-; CHECK: %[[Vec17FloatR11:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR10]] %[[Vec17FloatItem11]]
-; CHECK: %[[Vec17FloatR12:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR11]] %[[Vec17FloatItem12]]
-; CHECK: %[[Vec17FloatR13:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR12]] %[[Vec17FloatItem13]]
-; CHECK: %[[Vec17FloatR14:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR13]] %[[Vec17FloatItem14]]
-; CHECK: %[[Vec17FloatR15:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR14]] %[[Vec17FloatItem15]]
-; CHECK: %[[Vec17FloatR16:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR15]] %[[Vec17FloatItem16]]
+; CHECK: %[[Vec17FloatR1MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatItem0]] %[[Vec17FloatItem1]]
+; CHECK: %[[Vec17FloatR1Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatItem0]] %[[Vec17FloatItem1]]
+; CHECK: %[[Vec17FloatR1NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR1Ord]] %[[Vec17FloatR1MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR1IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR1NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR1:.*]] = OpSelect %[[Float]] %[[Vec17FloatR1IsZero]] %[[#]] %[[Vec17FloatR1NaN]]
+; CHECK: %[[Vec17FloatR2MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR1]] %[[Vec17FloatItem2]]
+; CHECK: %[[Vec17FloatR2Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR1]] %[[Vec17FloatItem2]]
+; CHECK: %[[Vec17FloatR2NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR2Ord]] %[[Vec17FloatR2MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR2IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR2NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR2:.*]] = OpSelect %[[Float]] %[[Vec17FloatR2IsZero]] %[[#]] %[[Vec17FloatR2NaN]]
+; CHECK: %[[Vec17FloatR3MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR2]] %[[Vec17FloatItem3]]
+; CHECK: %[[Vec17FloatR3Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR2]] %[[Vec17FloatItem3]]
+; CHECK: %[[Vec17FloatR3NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR3Ord]] %[[Vec17FloatR3MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR3IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR3NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR3:.*]] = OpSelect %[[Float]] %[[Vec17FloatR3IsZero]] %[[#]] %[[Vec17FloatR3NaN]]
+; CHECK: %[[Vec17FloatR4MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR3]] %[[Vec17FloatItem4]]
+; CHECK: %[[Vec17FloatR4Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR3]] %[[Vec17FloatItem4]]
+; CHECK: %[[Vec17FloatR4NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR4Ord]] %[[Vec17FloatR4MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR4IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR4NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR4:.*]] = OpSelect %[[Float]] %[[Vec17FloatR4IsZero]] %[[#]] %[[Vec17FloatR4NaN]]
+; CHECK: %[[Vec17FloatR5MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR4]] %[[Vec17FloatItem5]]
+; CHECK: %[[Vec17FloatR5Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR4]] %[[Vec17FloatItem5]]
+; CHECK: %[[Vec17FloatR5NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR5Ord]] %[[Vec17FloatR5MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR5IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR5NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR5:.*]] = OpSelect %[[Float]] %[[Vec17FloatR5IsZero]] %[[#]] %[[Vec17FloatR5NaN]]
+; CHECK: %[[Vec17FloatR6MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR5]] %[[Vec17FloatItem6]]
+; CHECK: %[[Vec17FloatR6Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR5]] %[[Vec17FloatItem6]]
+; CHECK: %[[Vec17FloatR6NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR6Ord]] %[[Vec17FloatR6MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR6IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR6NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR6:.*]] = OpSelect %[[Float]] %[[Vec17FloatR6IsZero]] %[[#]] %[[Vec17FloatR6NaN]]
+; CHECK: %[[Vec17FloatR7MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR6]] %[[Vec17FloatItem7]]
+; CHECK: %[[Vec17FloatR7Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR6]] %[[Vec17FloatItem7]]
+; CHECK: %[[Vec17FloatR7NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR7Ord]] %[[Vec17FloatR7MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR7IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR7NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR7:.*]] = OpSelect %[[Float]] %[[Vec17FloatR7IsZero]] %[[#]] %[[Vec17FloatR7NaN]]
+; CHECK: %[[Vec17FloatR8MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR7]] %[[Vec17FloatItem8]]
+; CHECK: %[[Vec17FloatR8Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR7]] %[[Vec17FloatItem8]]
+; CHECK: %[[Vec17FloatR8NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR8Ord]] %[[Vec17FloatR8MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR8IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR8NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR8:.*]] = OpSelect %[[Float]] %[[Vec17FloatR8IsZero]] %[[#]] %[[Vec17FloatR8NaN]]
+; CHECK: %[[Vec17FloatR9MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR8]] %[[Vec17FloatItem9]]
+; CHECK: %[[Vec17FloatR9Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR8]] %[[Vec17FloatItem9]]
+; CHECK: %[[Vec17FloatR9NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR9Ord]] %[[Vec17FloatR9MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR9IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR9NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR9:.*]] = OpSelect %[[Float]] %[[Vec17FloatR9IsZero]] %[[#]] %[[Vec17FloatR9NaN]]
+; CHECK: %[[Vec17FloatR10MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR9]] %[[Vec17FloatItem10]]
+; CHECK: %[[Vec17FloatR10Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR9]] %[[Vec17FloatItem10]]
+; CHECK: %[[Vec17FloatR10NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR10Ord]] %[[Vec17FloatR10MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR10IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR10NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR10:.*]] = OpSelect %[[Float]] %[[Vec17FloatR10IsZero]] %[[#]] %[[Vec17FloatR10NaN]]
+; CHECK: %[[Vec17FloatR11MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR10]] %[[Vec17FloatItem11]]
+; CHECK: %[[Vec17FloatR11Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR10]] %[[Vec17FloatItem11]]
+; CHECK: %[[Vec17FloatR11NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR11Ord]] %[[Vec17FloatR11MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR11IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR11NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR11:.*]] = OpSelect %[[Float]] %[[Vec17FloatR11IsZero]] %[[#]] %[[Vec17FloatR11NaN]]
+; CHECK: %[[Vec17FloatR12MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR11]] %[[Vec17FloatItem12]]
+; CHECK: %[[Vec17FloatR12Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR11]] %[[Vec17FloatItem12]]
+; CHECK: %[[Vec17FloatR12NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR12Ord]] %[[Vec17FloatR12MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR12IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR12NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR12:.*]] = OpSelect %[[Float]] %[[Vec17FloatR12IsZero]] %[[#]] %[[Vec17FloatR12NaN]]
+; CHECK: %[[Vec17FloatR13MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR12]] %[[Vec17FloatItem13]]
+; CHECK: %[[Vec17FloatR13Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR12]] %[[Vec17FloatItem13]]
+; CHECK: %[[Vec17FloatR13NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR13Ord]] %[[Vec17FloatR13MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR13IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR13NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR13:.*]] = OpSelect %[[Float]] %[[Vec17FloatR13IsZero]] %[[#]] %[[Vec17FloatR13NaN]]
+; CHECK: %[[Vec17FloatR14MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR13]] %[[Vec17FloatItem14]]
+; CHECK: %[[Vec17FloatR14Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR13]] %[[Vec17FloatItem14]]
+; CHECK: %[[Vec17FloatR14NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR14Ord]] %[[Vec17FloatR14MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR14IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR14NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR14:.*]] = OpSelect %[[Float]] %[[Vec17FloatR14IsZero]] %[[#]] %[[Vec17FloatR14NaN]]
+; CHECK: %[[Vec17FloatR15MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR14]] %[[Vec17FloatItem15]]
+; CHECK: %[[Vec17FloatR15Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR14]] %[[Vec17FloatItem15]]
+; CHECK: %[[Vec17FloatR15NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR15Ord]] %[[Vec17FloatR15MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR15IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR15NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR15:.*]] = OpSelect %[[Float]] %[[Vec17FloatR15IsZero]] %[[#]] %[[Vec17FloatR15NaN]]
+; CHECK: %[[Vec17FloatR16MinMax:.*]] = OpExtInst %[[Float]] %[[#]] fmax %[[Vec17FloatR15]] %[[Vec17FloatItem16]]
+; CHECK: %[[Vec17FloatR16Ord:.*]] = OpOrdered %[[#]] %[[Vec17FloatR15]] %[[Vec17FloatItem16]]
+; CHECK: %[[Vec17FloatR16NaN:.*]] = OpSelect %[[Float]] %[[Vec17FloatR16Ord]] %[[Vec17FloatR16MinMax]] %[[#]]
+; CHECK: %[[Vec17FloatR16IsZero:.*]] = OpFOrdEqual %[[#]] %[[Vec17FloatR16NaN]] %[[#]]
+; CHECK: %[[Vec17FloatR16:.*]] = OpSelect %[[Float]] %[[Vec17FloatR16IsZero]] %[[#]] %[[Vec17FloatR16NaN]]
; CHECK: OpReturnValue %[[Vec17FloatR16]]
; CHECK: OpFunctionEnd
define spir_func float @test_vector_reduce_fmaximum_v17f32(<17 x float> %v) {
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fminimum.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fminimum.ll
index ccf43bdca3e9c2..df5be4d8a9250f 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fminimum.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_long_vector/llvm-vector-reduce/fminimum.ll
@@ -38,22 +38,86 @@ entry:
; CHECK: %[[Vec17FloatItem14:.*]] = OpCompositeExtract %[[Float]] %[[ParamVec17Float]] 14
; CHECK: %[[Vec17FloatItem15:.*]] = OpCompositeExtract %[[Float]] %[[ParamVec17Float]] 15
; CHECK: %[[Vec17FloatItem16:.*]] = OpCompositeExtract %[[Float]] %[[ParamVec17Float]] 16
-; CHECK: %[[Vec17FloatR1:.*]] = OpExtInst %[[Float]] %[[#]] fmin %[[Vec17FloatItem0]] %[[Vec17FloatItem1]]
-; CHECK: %[[Vec17FloatR2:.*]] = OpExtInst %[[Float]] %[[#]] fmin %[[Vec17FloatR1]] %[[Vec17FloatItem2]]
-; CHECK: %[[Vec17FloatR3:.*]] = OpExtInst %[[Float]] %[[#]] fmin %[[Vec17FloatR2]] %[[Vec17FloatItem3]]
-; CHECK: %[[Vec17FloatR4:.*]] = OpExtInst %[[Float]] %[[#]] fmin %[[Vec17FloatR3]] %[[Vec17FloatItem4]]
-; CHECK: %[[Vec17FloatR5:.*]] = OpExtInst %[[Float]] %[[#]] fmin %[[Vec17FloatR4]] %[[Vec17FloatItem5]]
-; CHECK: %[[Vec17FloatR6:.*]] = OpExtInst %[[Float]] %[[#]] fmin %[[Vec17FloatR5]] %[[Vec17FloatItem6]]
-; CHECK: %[[Vec17FloatR7:.*]] = OpExtInst %[[Float]] %[[#]] fmin %[[Vec17FloatR6]] %[[Vec17FloatItem7]]
-; CHECK: %[[Vec17FloatR8:.*]] = OpExtInst %[[Float]] %[[#]] fmin %[[Vec17FloatR7]] %[[Vec17FloatItem8]]
-; CHECK: %[[Vec...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/225667
More information about the llvm-commits
mailing list