[llvm] [InstCombine] Support DemandElts in SimplifyDemandedFPClass (PR #174176)
Stefan Weigl-Bosker via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 2 08:29:43 PST 2026
https://github.com/sweiglbosker updated https://github.com/llvm/llvm-project/pull/174176
>From 7c14e9e04f18a90beefe615252020b2c57e2c2ba Mon Sep 17 00:00:00 2001
From: Stefan Weigl-Bosker <stefan at s00.xyz>
Date: Thu, 1 Jan 2026 22:15:29 -0500
Subject: [PATCH 1/2] [InstCombine] Support DemandElts in
SimplifyDemandedFPClass
---
.../InstCombine/InstCombineInternal.h | 25 ++
.../InstCombineSimplifyDemanded.cpp | 71 +++--
.../simplify-demanded-fpclass-vector.ll | 255 ++++++++++++++++++
3 files changed, 328 insertions(+), 23 deletions(-)
create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 9bdd8cb71f7f3..4f4023ce8616c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -211,6 +211,15 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
Depth);
}
+ KnownFPClass computeKnownFPClass(Value *Val, const APInt &DemandedElts,
+ FastMathFlags FMF,
+ FPClassTest Interested = fcAllFlags,
+ const Instruction *CtxI = nullptr,
+ unsigned Depth = 0) const {
+ return llvm::computeKnownFPClass(
+ Val, DemandedElts, FMF, Interested,
+ getSimplifyQuery().getWithInstruction(CtxI), Depth);
+ }
KnownFPClass computeKnownFPClass(Value *Val,
FPClassTest Interested = fcAllFlags,
const Instruction *CtxI = nullptr,
@@ -219,6 +228,14 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
Val, Interested, getSimplifyQuery().getWithInstruction(CtxI), Depth);
}
+ KnownFPClass computeKnownFPClass(Value *Val, const APInt &DemandedElts,
+ FPClassTest Interested = fcAllFlags,
+ const Instruction *CtxI = nullptr,
+ unsigned Depth = 0) const {
+ return llvm::computeKnownFPClass(
+ Val, DemandedElts, Interested,
+ getSimplifyQuery().getWithInstruction(CtxI), Depth);
+ }
/// Check if fmul \p MulVal, +0.0 will yield +0.0 (or signed zero is
/// ignorable).
bool fmulByZeroIsZero(Value *MulVal, FastMathFlags FMF,
@@ -614,7 +631,15 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
Value *SimplifyDemandedUseFPClass(Value *V, FPClassTest DemandedMask,
KnownFPClass &Known, Instruction *CxtI,
unsigned Depth = 0);
+ Value *SimplifyDemandedUseFPClass(Value *V, const APInt &DemandedElts,
+ FPClassTest DemandedMask,
+ KnownFPClass &Known, Instruction *CxtI,
+ unsigned Depth = 0);
+ bool SimplifyDemandedFPClass(Instruction *I, unsigned Op,
+ FPClassTest DemandedMask, KnownFPClass &Known,
+ unsigned Depth = 0);
bool SimplifyDemandedFPClass(Instruction *I, unsigned Op,
+ const APInt &DemandedElts,
FPClassTest DemandedMask, KnownFPClass &Known,
unsigned Depth = 0);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 47b66a4e0f37d..24595c011bf20 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,12 +2033,23 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
KnownFPClass &Known,
Instruction *CxtI,
unsigned Depth) {
+ auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
+ APInt DemandedElts =
+ FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
+
+ return SimplifyDemandedUseFPClass(V, DemandedElts, DemandedMask, Known, CxtI,
+ Depth);
+}
+
+Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
+ Value *V, const APInt &DemandedElts, FPClassTest DemandedMask,
+ KnownFPClass &Known, Instruction *CxtI, unsigned Depth) {
assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
Type *VTy = V->getType();
assert(Known == KnownFPClass() && "expected uninitialized state");
- if (DemandedMask == fcNone)
+ if (DemandedMask == fcNone || !DemandedElts)
return isa<UndefValue>(V) ? nullptr : PoisonValue::get(VTy);
if (Depth == MaxAnalysisRecursionDepth)
@@ -2047,7 +2058,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
Instruction *I = dyn_cast<Instruction>(V);
if (!I) {
// Handle constants and arguments
- Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
+ Known = computeKnownFPClass(V, DemandedElts, fcAllFlags, CxtI, Depth + 1);
FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
if (ValidResults == fcNone)
@@ -2080,8 +2091,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
switch (I->getOpcode()) {
case Instruction::FNeg: {
- if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
- Depth + 1))
+ if (SimplifyDemandedFPClass(I, 0, DemandedElts, llvm::fneg(DemandedMask),
+ Known, Depth + 1))
return I;
Known.fneg();
break;
@@ -2090,19 +2101,22 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
CallInst *CI = cast<CallInst>(I);
switch (CI->getIntrinsicID()) {
case Intrinsic::fabs:
- if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), Known,
+ if (SimplifyDemandedFPClass(I, 0, DemandedElts,
+ llvm::inverse_fabs(DemandedMask), Known,
Depth + 1))
return I;
Known.fabs();
break;
case Intrinsic::arithmetic_fence:
- if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+ if (SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMask, Known,
+ Depth + 1))
return I;
break;
case Intrinsic::copysign: {
// Flip on more potentially demanded classes
const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
- if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
+ if (SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMaskAnySign,
+ Known, Depth + 1))
return I;
if ((DemandedMask & fcNegative) == DemandedMask) {
@@ -2117,8 +2131,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
return I;
}
- KnownFPClass KnownSign =
- computeKnownFPClass(I->getOperand(1), fcAllFlags, CxtI, Depth + 1);
+ KnownFPClass KnownSign = computeKnownFPClass(
+ I->getOperand(1), DemandedElts, fcAllFlags, CxtI, Depth + 1);
Known.copysign(KnownSign);
break;
}
@@ -2170,7 +2184,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
// TODO: This could really make use of KnownFPClass of specific value
// range, (i.e., close enough to 1)
- if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownSrc, Depth + 1))
+ if (SimplifyDemandedFPClass(I, 0, DemandedElts, SrcDemandedMask, KnownSrc,
+ Depth + 1))
return I;
/// Propagate nnan-ness to simplify edge case checks.
@@ -2255,7 +2270,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
KnownFPClass KnownSrc;
// Simplify upstream operations before trying to simplify this call.
- if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownSrc, Depth + 1))
+ if (SimplifyDemandedFPClass(I, 0, DemandedElts, SrcDemandedMask,
+ KnownSrc, Depth + 1))
return I;
// Perform the canonicalization to see if this folded to a constant.
@@ -2281,7 +2297,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
[[fallthrough]];
}
default:
- Known = computeKnownFPClass(I, DemandedMask, CxtI, Depth + 1);
+ Known =
+ computeKnownFPClass(I, DemandedElts, DemandedMask, CxtI, Depth + 1);
break;
}
@@ -2289,8 +2306,10 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
}
case Instruction::Select: {
KnownFPClass KnownLHS, KnownRHS;
- if (SimplifyDemandedFPClass(I, 2, DemandedMask, KnownRHS, Depth + 1) ||
- SimplifyDemandedFPClass(I, 1, DemandedMask, KnownLHS, Depth + 1))
+ if (SimplifyDemandedFPClass(I, 2, DemandedElts, DemandedMask, KnownRHS,
+ Depth + 1) ||
+ SimplifyDemandedFPClass(I, 1, DemandedElts, DemandedMask, KnownLHS,
+ Depth + 1))
return I;
if (KnownLHS.isKnownNever(DemandedMask))
@@ -2304,24 +2323,29 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
}
case Instruction::ExtractElement: {
// TODO: Handle demanded element mask
- if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+ if (SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMask, Known,
+ Depth + 1))
return I;
break;
}
case Instruction::InsertElement: {
KnownFPClass KnownInserted, KnownVec;
- if (SimplifyDemandedFPClass(I, 1, DemandedMask, KnownInserted, Depth + 1) ||
- SimplifyDemandedFPClass(I, 0, DemandedMask, KnownVec, Depth + 1))
- return I;
+ if (SimplifyDemandedFPClass(I, 1, DemandedElts, DemandedMask, KnownInserted,
+ Depth + 1) ||
+ SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMask, KnownVec,
+ Depth + 1))
+ return I;
// TODO: Use demanded elements logic from computeKnownFPClass
Known = KnownVec | KnownInserted;
break;
}
case Instruction::ShuffleVector: {
KnownFPClass KnownLHS, KnownRHS;
- if (SimplifyDemandedFPClass(I, 1, DemandedMask, KnownRHS, Depth + 1) ||
- SimplifyDemandedFPClass(I, 0, DemandedMask, KnownLHS, Depth + 1))
+ if (SimplifyDemandedFPClass(I, 1, DemandedElts, DemandedMask, KnownRHS,
+ Depth + 1) ||
+ SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMask, KnownLHS,
+ Depth + 1))
return I;
// TODO: This is overly conservative and should consider demanded elements,
@@ -2330,7 +2354,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
break;
}
default:
- Known = computeKnownFPClass(I, DemandedMask, CxtI, Depth + 1);
+ Known = computeKnownFPClass(I, DemandedElts, DemandedMask, CxtI, Depth + 1);
break;
}
@@ -2338,12 +2362,13 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
}
bool InstCombinerImpl::SimplifyDemandedFPClass(Instruction *I, unsigned OpNo,
+ const APInt &DemandedElts,
FPClassTest DemandedMask,
KnownFPClass &Known,
unsigned Depth) {
Use &U = I->getOperandUse(OpNo);
- Value *NewVal =
- SimplifyDemandedUseFPClass(U.get(), DemandedMask, Known, I, Depth);
+ Value *NewVal = SimplifyDemandedUseFPClass(U.get(), DemandedElts,
+ DemandedMask, Known, I, Depth);
if (!NewVal)
return false;
if (Instruction *OpInst = dyn_cast<Instruction>(U))
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
new file mode 100644
index 0000000000000..5532140cb1dd8
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
@@ -0,0 +1,255 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+declare <2 x float> @extern_vec()
+declare <2 x float> @extern_vec_func(<2 x float>)
+; can't fold to fneg(fabs(x))
+define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_copysign_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; can fold to fneg(fabs(x))
+define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_copysign_nnan_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_copysign_nnan_flag_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan <2 x float> [[TMP1]]
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %copysign = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; can fold to fneg(fabs(x)), finitely-bounded no-positives variant
+define nofpclass(pnorm psub pzero) <2 x float> @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(pzero psub pnorm) <2 x float> @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan ninf <2 x float> [[TMP1]]
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %copysign = call nnan ninf <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; can't fold to fneg(fabs(x)) (nonan variant)
+define nofpclass(nan pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_nonan_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_nonan_copysign_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg <2 x float> [[TMP1]]
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; can't fold to fabs(x)
+define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_copysign_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; can fold to fabs(x)
+define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_copysign_nnan_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_copysign_nnan_flag_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %copysign = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; can fold to fabs(x) (nonan variant)
+define nofpclass(nan ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_nonan_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_nonan_copysign_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; nopositives + fabs(sign) + select pinf: can fold to fabs(x)
+define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %sign) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[SIGN:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT: ret <2 x float> [[TMP1]]
+;
+ %select = select <2 x i1> %cond,
+ <2 x float> %x,
+ <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+ %fabs.sign = call <2 x float> @llvm.fabs.v2f32(<2 x float> %sign)
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %fabs.sign)
+ ret <2 x float> %copysign
+}
+
+; no negatives, no inf: can fold to copysign(x, unknown.sign)
+define nofpclass(inf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %select = select <2 x i1> %cond,
+ <2 x float> %x,
+ <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; no positives, no inf: can fold to copysign(x, unknown.sign)
+define nofpclass(inf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(inf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %select = select <2 x i1> %cond,
+ <2 x float> %x,
+ <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; Can't fold because it could have nan payload bits (no negatives case)
+define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> splat (float 0x7FF0000000000000)
+; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[SELECT]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %select = select <2 x i1> %cond,
+ <2 x float> %x,
+ <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; Can't fold because it could be nan (no positives case)
+define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> splat (float 0x7FF0000000000000)
+; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[SELECT]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %select = select <2 x i1> %cond,
+ <2 x float> %x,
+ <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; Could fold to copysign with constant (no negatives, nonan)
+define nofpclass(nan ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT: [[COPYSIGN:%.*]] = select <2 x i1> [[COND]], <2 x float> [[TMP1]], <2 x float> splat (float 0x7FF0000000000000)
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %select = select <2 x i1> %cond,
+ <2 x float> %x,
+ <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; Could fold to copysign(x) with constant (no positives, nonan)
+define nofpclass(nan pinf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT: [[DOTNEG:%.*]] = fneg <2 x float> [[TMP1]]
+; CHECK-NEXT: [[COPYSIGN:%.*]] = select <2 x i1> [[COND]], <2 x float> [[DOTNEG]], <2 x float> splat (float 0xFFF0000000000000)
+; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
+;
+ %select = select <2 x i1> %cond,
+ <2 x float> %x,
+ <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+ %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+ ret <2 x float> %copysign
+}
+
+; should fold to -inf splat
+define nofpclass(pinf) <2 x float> @vec_ret_nofpclass_pinf__nofpclass_call_only_inf(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(pinf) <2 x float> @vec_ret_nofpclass_pinf__nofpclass_call_only_inf(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT: ret <2 x float> splat (float 0xFFF0000000000000)
+;
+entry:
+ %must.be.inf = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
+ ret <2 x float> %must.be.inf
+}
+
+; should fold to +inf splat
+define nofpclass(ninf) <2 x float> @vec_ret_nofpclass_ninf__nofpclass_call_only_inf(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(ninf) <2 x float> @vec_ret_nofpclass_ninf__nofpclass_call_only_inf(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT: ret <2 x float> splat (float 0x7FF0000000000000)
+;
+entry:
+ %must.be.inf = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
+ ret <2 x float> %must.be.inf
+}
+
+; should fold to +0 splat
+define nofpclass(nzero) <2 x float> @vec_ret_nofpclass_nzero__nofpclass_call_only_zero(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(nzero) <2 x float> @vec_ret_nofpclass_nzero__nofpclass_call_only_zero(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT: ret <2 x float> zeroinitializer
+;
+entry:
+ %must.be.zero = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
+ ret <2 x float> %must.be.zero
+}
+
+; should fold to -0 splat
+define nofpclass(pzero) <2 x float> @vec_ret_nofpclass_pzero__nofpclass_call_only_zero(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(pzero) <2 x float> @vec_ret_nofpclass_pzero__nofpclass_call_only_zero(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT: ret <2 x float> splat (float -0.000000e+00)
+;
+entry:
+ %must.be.zero = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
+ ret <2 x float> %must.be.zero
+}
+
+; should keep payloads, not canonicalize
+define nofpclass(qnan) <2 x float> @vec_ret_nofpclass_qnan__nofpclass_call_only_nan(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(qnan) <2 x float> @vec_ret_nofpclass_qnan__nofpclass_call_only_nan(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT: ret <2 x float> [[MUST_BE_NAN]]
+;
+entry:
+ %must.be.nan = call nofpclass(inf zero sub norm) <2 x float> @extern_vec()
+ ret <2 x float> %must.be.nan
+}
+
+
>From ba8f718163392b62ea44e4c2afc642aeb28c4026 Mon Sep 17 00:00:00 2001
From: Stefan Weigl-Bosker <stefan at s00.xyz>
Date: Fri, 2 Jan 2026 11:29:33 -0500
Subject: [PATCH 2/2] remove tests
---
.../simplify-demanded-fpclass-vector.ll | 255 ------------------
1 file changed, 255 deletions(-)
delete mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
deleted file mode 100644
index 5532140cb1dd8..0000000000000
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
+++ /dev/null
@@ -1,255 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -S -passes=instcombine < %s | FileCheck %s
-
-declare <2 x float> @extern_vec()
-declare <2 x float> @extern_vec_func(<2 x float>)
-; can't fold to fneg(fabs(x))
-define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_copysign_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; can fold to fneg(fabs(x))
-define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_copysign_nnan_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_copysign_nnan_flag_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan <2 x float> [[TMP1]]
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %copysign = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; can fold to fneg(fabs(x)), finitely-bounded no-positives variant
-define nofpclass(pnorm psub pzero) <2 x float> @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(pzero psub pnorm) <2 x float> @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan ninf <2 x float> [[TMP1]]
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %copysign = call nnan ninf <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; can't fold to fneg(fabs(x)) (nonan variant)
-define nofpclass(nan pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_nonan_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_nonan_copysign_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg <2 x float> [[TMP1]]
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; can't fold to fabs(x)
-define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_copysign_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; can fold to fabs(x)
-define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_copysign_nnan_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_copysign_nnan_flag_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %copysign = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; can fold to fabs(x) (nonan variant)
-define nofpclass(nan ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_nonan_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_nonan_copysign_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; nopositives + fabs(sign) + select pinf: can fold to fabs(x)
-define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %sign) {
-; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[SIGN:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT: ret <2 x float> [[TMP1]]
-;
- %select = select <2 x i1> %cond,
- <2 x float> %x,
- <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
- %fabs.sign = call <2 x float> @llvm.fabs.v2f32(<2 x float> %sign)
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %fabs.sign)
- ret <2 x float> %copysign
-}
-
-; no negatives, no inf: can fold to copysign(x, unknown.sign)
-define nofpclass(inf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %select = select <2 x i1> %cond,
- <2 x float> %x,
- <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; no positives, no inf: can fold to copysign(x, unknown.sign)
-define nofpclass(inf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(inf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %select = select <2 x i1> %cond,
- <2 x float> %x,
- <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; Can't fold because it could have nan payload bits (no negatives case)
-define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> splat (float 0x7FF0000000000000)
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[SELECT]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %select = select <2 x i1> %cond,
- <2 x float> %x,
- <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; Can't fold because it could be nan (no positives case)
-define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> splat (float 0x7FF0000000000000)
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[SELECT]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %select = select <2 x i1> %cond,
- <2 x float> %x,
- <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; Could fold to copysign with constant (no negatives, nonan)
-define nofpclass(nan ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT: [[COPYSIGN:%.*]] = select <2 x i1> [[COND]], <2 x float> [[TMP1]], <2 x float> splat (float 0x7FF0000000000000)
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %select = select <2 x i1> %cond,
- <2 x float> %x,
- <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; Could fold to copysign(x) with constant (no positives, nonan)
-define nofpclass(nan pinf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT: [[DOTNEG:%.*]] = fneg <2 x float> [[TMP1]]
-; CHECK-NEXT: [[COPYSIGN:%.*]] = select <2 x i1> [[COND]], <2 x float> [[DOTNEG]], <2 x float> splat (float 0xFFF0000000000000)
-; CHECK-NEXT: ret <2 x float> [[COPYSIGN]]
-;
- %select = select <2 x i1> %cond,
- <2 x float> %x,
- <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
- %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
- ret <2 x float> %copysign
-}
-
-; should fold to -inf splat
-define nofpclass(pinf) <2 x float> @vec_ret_nofpclass_pinf__nofpclass_call_only_inf(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(pinf) <2 x float> @vec_ret_nofpclass_pinf__nofpclass_call_only_inf(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT: ret <2 x float> splat (float 0xFFF0000000000000)
-;
-entry:
- %must.be.inf = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
- ret <2 x float> %must.be.inf
-}
-
-; should fold to +inf splat
-define nofpclass(ninf) <2 x float> @vec_ret_nofpclass_ninf__nofpclass_call_only_inf(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(ninf) <2 x float> @vec_ret_nofpclass_ninf__nofpclass_call_only_inf(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT: ret <2 x float> splat (float 0x7FF0000000000000)
-;
-entry:
- %must.be.inf = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
- ret <2 x float> %must.be.inf
-}
-
-; should fold to +0 splat
-define nofpclass(nzero) <2 x float> @vec_ret_nofpclass_nzero__nofpclass_call_only_zero(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(nzero) <2 x float> @vec_ret_nofpclass_nzero__nofpclass_call_only_zero(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT: ret <2 x float> zeroinitializer
-;
-entry:
- %must.be.zero = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
- ret <2 x float> %must.be.zero
-}
-
-; should fold to -0 splat
-define nofpclass(pzero) <2 x float> @vec_ret_nofpclass_pzero__nofpclass_call_only_zero(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(pzero) <2 x float> @vec_ret_nofpclass_pzero__nofpclass_call_only_zero(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT: ret <2 x float> splat (float -0.000000e+00)
-;
-entry:
- %must.be.zero = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
- ret <2 x float> %must.be.zero
-}
-
-; should keep payloads, not canonicalize
-define nofpclass(qnan) <2 x float> @vec_ret_nofpclass_qnan__nofpclass_call_only_nan(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(qnan) <2 x float> @vec_ret_nofpclass_qnan__nofpclass_call_only_nan(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT: ret <2 x float> [[MUST_BE_NAN]]
-;
-entry:
- %must.be.nan = call nofpclass(inf zero sub norm) <2 x float> @extern_vec()
- ret <2 x float> %must.be.nan
-}
-
-
More information about the llvm-commits
mailing list