[llvm] [DAG] Add ISD::FSQRT handling to computeKnownFPClass (PR #213620)
Varad Rahul Kamthe via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 3 04:23:28 PDT 2026
https://github.com/varadk27 updated https://github.com/llvm/llvm-project/pull/213620
>From bda910d3fe47bc71309f2ddddca4d8f8a8d8a008 Mon Sep 17 00:00:00 2001
From: Varad Kamthe <varadk.2704 at gmail.com>
Date: Mon, 3 Aug 2026 14:05:20 +0530
Subject: [PATCH 1/2] [DAG] Add ISD::FSQRT handling to computeKnownFPClass
Ports the ISD::FSQRT case from ValueTracking.cpp's computeKnownFPClass
to the SelectionDAG version, per #189583.
sqrt can never produce a negative normal or -infinity; with nnan set,
it also can't produce NaN. Unlike an earlier attempt (#195405), this
does not treat nsz as proof that the result can't be negative zero,
since nsz is a fast-math hint rather than a guarantee -- doing so risks
promoting a value to poison.
Fixes #189583
---
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 19 +++
.../CodeGen/RISCV/fold-is-fpclass-sqrt.ll | 124 ++++++++++++++++++
2 files changed, 143 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/fold-is-fpclass-sqrt.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 683cf2517b2f5..21f2727927e60 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6191,6 +6191,25 @@ KnownFPClass SelectionDAG::computeKnownFPClass(SDValue Op,
Known.fneg();
break;
}
+ case ISD::FSQRT: {
+ FPClassTest InterestedSrcs = InterestedClasses;
+ if (InterestedClasses & fcNan)
+ InterestedSrcs |= KnownFPClass::OrderedLessThanZeroMask;
+
+ KnownFPClass KnownSrc = computeKnownFPClass(Op.getOperand(0), DemandedElts,
+ InterestedSrcs, Depth + 1);
+
+ const fltSemantics &FltSem =
+ Op.getValueType().getScalarType().getFltSemantics();
+ DenormalMode Mode = getMachineFunction().getDenormalMode(FltSem);
+
+ Known = KnownFPClass::sqrt(KnownSrc, Mode);
+
+ if (Op->getFlags().hasNoNaNs())
+ Known.knownNot(fcNan);
+
+ break;
+ }
case ISD::BUILD_VECTOR: {
assert(!VT.isScalableVector());
bool First = true;
diff --git a/llvm/test/CodeGen/RISCV/fold-is-fpclass-sqrt.ll b/llvm/test/CodeGen/RISCV/fold-is-fpclass-sqrt.ll
new file mode 100644
index 0000000000000..9472259c62cc9
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/fold-is-fpclass-sqrt.ll
@@ -0,0 +1,124 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -mattr=+f,+d,+v -target-abi=lp64d < %s | FileCheck %s
+
+define i1 @sqrt_nnan_check_f32(float %a0) {
+; CHECK-LABEL: sqrt_nnan_check_f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a0, 0
+; CHECK-NEXT: ret
+ %sqr = call nnan float @llvm.sqrt.f32(float %a0)
+ %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 3)
+ ret i1 %res
+}
+
+define i1 @sqrt_neginf_f32(float %a0) {
+; CHECK-LABEL: sqrt_neginf_f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a0, 0
+; CHECK-NEXT: ret
+ %sqr = call float @llvm.sqrt.f32(float %a0)
+ %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 4)
+ ret i1 %res
+}
+
+define i1 @sqrt_negnormal_f32(float %a0) {
+; CHECK-LABEL: sqrt_negnormal_f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a0, 0
+; CHECK-NEXT: ret
+ %sqr = call float @llvm.sqrt.f32(float %a0)
+ %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 8)
+ ret i1 %res
+}
+
+define i1 @sqrt_nsz_negzero_f32(float %a0) {
+; CHECK-LABEL: sqrt_nsz_negzero_f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: fsqrt.s fa5, fa0
+; CHECK-NEXT: fclass.s a0, fa5
+; CHECK-NEXT: slli a0, a0, 60
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: ret
+ %sqr = call nsz float @llvm.sqrt.f32(float %a0)
+ %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 32)
+ ret i1 %res
+}
+
+define i1 @sqrt_posinf_f32(float %a0) {
+; CHECK-LABEL: sqrt_posinf_f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: fsqrt.s fa5, fa0
+; CHECK-NEXT: fclass.s a0, fa5
+; CHECK-NEXT: slli a0, a0, 56
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: ret
+ %sqr = call float @llvm.sqrt.f32(float %a0)
+ %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 512)
+ ret i1 %res
+}
+
+declare float @llvm.sqrt.f32(float)
+declare i1 @llvm.is.fpclass.f32(float, i32)
+
+declare <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float>)
+declare <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float>, i32)
+
+define <vscale x 2 x i1> @vsqrt_nnan_check_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_nnan_check_nxv2f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetvli a0, zero, e8, mf4, ta, ma
+; CHECK-NEXT: vmclr.m v0
+; CHECK-NEXT: ret
+ %sqr = call nnan <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+ %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 3)
+ ret <vscale x 2 x i1> %res
+}
+
+define <vscale x 2 x i1> @vsqrt_neginf_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_neginf_nxv2f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetvli a0, zero, e8, mf4, ta, ma
+; CHECK-NEXT: vmclr.m v0
+; CHECK-NEXT: ret
+ %sqr = call <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+ %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 4)
+ ret <vscale x 2 x i1> %res
+}
+
+define <vscale x 2 x i1> @vsqrt_negnormal_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_negnormal_nxv2f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetvli a0, zero, e8, mf4, ta, ma
+; CHECK-NEXT: vmclr.m v0
+; CHECK-NEXT: ret
+ %sqr = call <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+ %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 8)
+ ret <vscale x 2 x i1> %res
+}
+
+define <vscale x 2 x i1> @vsqrt_nsz_negzero_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_nsz_negzero_nxv2f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma
+; CHECK-NEXT: vfsqrt.v v8, v8
+; CHECK-NEXT: vfclass.v v8, v8
+; CHECK-NEXT: vmseq.vi v0, v8, 8
+; CHECK-NEXT: ret
+ %sqr = call nsz <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+ %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 32)
+ ret <vscale x 2 x i1> %res
+}
+
+define <vscale x 2 x i1> @vsqrt_posinf_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_posinf_nxv2f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma
+; CHECK-NEXT: vfsqrt.v v8, v8
+; CHECK-NEXT: vfclass.v v8, v8
+; CHECK-NEXT: li a0, 128
+; CHECK-NEXT: vmseq.vx v0, v8, a0
+; CHECK-NEXT: ret
+ %sqr = call <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+ %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 512)
+ ret <vscale x 2 x i1> %res
+}
>From 5507a8e4c142420915f3b8408a1e0d5644a942b9 Mon Sep 17 00:00:00 2001
From: Varad Kamthe <varadk.2704 at gmail.com>
Date: Mon, 3 Aug 2026 16:52:48 +0530
Subject: [PATCH 2/2] [DAG] Move nnan/ninf flag handling into scope_exit,
matching IR version
Per review feedback, replaces the manual nnan check in the FSQRT case
with a generic scope_exit-based mechanism applied before the switch,
mirroring ValueTracking.cpp's computeKnownFPClass.
Wraps the switch in an explicit nested block so the scope_exit
destructor runs before the function's return statement, rather than
racing NRVO -- without this, the flag-based exclusion could silently
fail to apply depending on whether the compiler elides the copy.
Diff looks larger than expected because wrapping the switch requires
reindenting the whole block; no logic inside the switch changed.
---
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 329 +++++++++---------
1 file changed, 170 insertions(+), 159 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 21f2727927e60..bd95f8ac4c16a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -20,6 +20,7 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
@@ -6178,186 +6179,196 @@ KnownFPClass SelectionDAG::computeKnownFPClass(SDValue Op,
if (!DemandedElts)
return Known;
- unsigned Opcode = Op.getOpcode();
- switch (Opcode) {
- case ISD::POISON: {
- Known.KnownFPClasses = fcNone;
- Known.SignBit = false;
- break;
- }
- case ISD::FNEG: {
- Known = computeKnownFPClass(Op.getOperand(0), DemandedElts,
- InterestedClasses, Depth + 1);
- Known.fneg();
- break;
- }
- case ISD::FSQRT: {
- FPClassTest InterestedSrcs = InterestedClasses;
- if (InterestedClasses & fcNan)
- InterestedSrcs |= KnownFPClass::OrderedLessThanZeroMask;
+ {
+ FPClassTest KnownNotFromFlags = fcNone;
+ if (Op->getFlags().hasNoNaNs())
+ KnownNotFromFlags |= fcNan;
+ if (Op->getFlags().hasNoInfs())
+ KnownNotFromFlags |= fcInf;
- KnownFPClass KnownSrc = computeKnownFPClass(Op.getOperand(0), DemandedElts,
- InterestedSrcs, Depth + 1);
+ llvm::scope_exit ClearClassesFromFlags(
+ [=, &Known] { Known.knownNot(KnownNotFromFlags); });
- const fltSemantics &FltSem =
- Op.getValueType().getScalarType().getFltSemantics();
- DenormalMode Mode = getMachineFunction().getDenormalMode(FltSem);
+ unsigned Opcode = Op.getOpcode();
+ switch (Opcode) {
+ case ISD::POISON: {
+ Known.KnownFPClasses = fcNone;
+ Known.SignBit = false;
+ break;
+ }
+ case ISD::FNEG: {
+ Known = computeKnownFPClass(Op.getOperand(0), DemandedElts,
+ InterestedClasses, Depth + 1);
+ Known.fneg();
+ break;
+ }
+ case ISD::FSQRT: {
+ FPClassTest InterestedSrcs = InterestedClasses;
+ if (InterestedClasses & fcNan)
+ InterestedSrcs |= KnownFPClass::OrderedLessThanZeroMask;
- Known = KnownFPClass::sqrt(KnownSrc, Mode);
+ KnownFPClass KnownSrc = computeKnownFPClass(
+ Op.getOperand(0), DemandedElts, InterestedSrcs, Depth + 1);
- if (Op->getFlags().hasNoNaNs())
- Known.knownNot(fcNan);
+ const fltSemantics &FltSem =
+ Op.getValueType().getScalarType().getFltSemantics();
+ DenormalMode Mode = getMachineFunction().getDenormalMode(FltSem);
- break;
- }
- case ISD::BUILD_VECTOR: {
- assert(!VT.isScalableVector());
- bool First = true;
- for (unsigned I = 0, E = Op.getNumOperands(); I != E; ++I) {
- if (!DemandedElts[I])
- continue;
+ Known = KnownFPClass::sqrt(KnownSrc, Mode);
+ break;
+ }
+ case ISD::BUILD_VECTOR: {
+ assert(!VT.isScalableVector());
+ bool First = true;
+ for (unsigned I = 0, E = Op.getNumOperands(); I != E; ++I) {
+ if (!DemandedElts[I])
+ continue;
+
+ if (First) {
+ Known = computeKnownFPClass(Op.getOperand(I), InterestedClasses,
+ Depth + 1);
+ First = false;
+ } else {
+ Known |= computeKnownFPClass(Op.getOperand(I), InterestedClasses,
+ Depth + 1);
+ }
- if (First) {
- Known =
- computeKnownFPClass(Op.getOperand(I), InterestedClasses, Depth + 1);
- First = false;
+ if (Known.isUnknown())
+ break;
+ }
+ break;
+ }
+ case ISD::EXTRACT_VECTOR_ELT: {
+ SDValue Src = Op.getOperand(0);
+ auto *CIdx = dyn_cast<ConstantSDNode>(Op.getOperand(1));
+ EVT SrcVT = Src.getValueType();
+ if (SrcVT.isFixedLengthVector() && CIdx) {
+ if (CIdx->getAPIntValue().ult(SrcVT.getVectorNumElements())) {
+ APInt DemandedSrcElts = APInt::getOneBitSet(
+ SrcVT.getVectorNumElements(), CIdx->getZExtValue());
+ Known = computeKnownFPClass(Src, DemandedSrcElts, InterestedClasses,
+ Depth + 1);
+ } else {
+ // Out of bounds index is poison.
+ Known.KnownFPClasses = fcNone;
+ }
} else {
- Known |=
- computeKnownFPClass(Op.getOperand(I), InterestedClasses, Depth + 1);
+ Known = computeKnownFPClass(Src, InterestedClasses, Depth + 1);
}
-
- if (Known.isUnknown())
+ break;
+ }
+ case ISD::SPLAT_VECTOR: {
+ Known =
+ computeKnownFPClass(Op.getOperand(0), InterestedClasses, Depth + 1);
+ break;
+ }
+ case ISD::BITCAST: {
+ // FIXME: It should not be necessary to check for an elementwise bitcast.
+ // If a bitcast is not elementwise between vector / scalar types,
+ // computeKnownBits already splices the known bits of the source elements
+ // appropriately so as to line up with the bits of the result's demanded
+ // elements.
+ EVT SrcVT = Op.getOperand(0).getValueType();
+ if (VT.isScalableVector() || SrcVT.isScalableVector())
+ break;
+ unsigned VTNumElts = VT.isVector() ? VT.getVectorNumElements() : 1;
+ unsigned SrcVTNumElts =
+ SrcVT.isVector() ? SrcVT.getVectorNumElements() : 1;
+ if (VTNumElts != SrcVTNumElts)
break;
+
+ KnownBits Bits = computeKnownBits(Op, DemandedElts, Depth + 1);
+ Known = KnownFPClass::bitcast(VT.getFltSemantics(), Bits);
+ break;
}
- break;
- }
- case ISD::EXTRACT_VECTOR_ELT: {
- SDValue Src = Op.getOperand(0);
- auto *CIdx = dyn_cast<ConstantSDNode>(Op.getOperand(1));
- EVT SrcVT = Src.getValueType();
- if (SrcVT.isFixedLengthVector() && CIdx) {
- if (CIdx->getAPIntValue().ult(SrcVT.getVectorNumElements())) {
- APInt DemandedSrcElts = APInt::getOneBitSet(
- SrcVT.getVectorNumElements(), CIdx->getZExtValue());
+ case ISD::FABS: {
+ Known = computeKnownFPClass(Op.getOperand(0), DemandedElts,
+ InterestedClasses, Depth + 1);
+ Known.fabs();
+ break;
+ }
+ case ISD::FCOPYSIGN: {
+ Known = computeKnownFPClass(Op.getOperand(0), DemandedElts,
+ InterestedClasses, Depth + 1);
+ KnownFPClass KnownSign = computeKnownFPClass(
+ Op.getOperand(1), DemandedElts, InterestedClasses, Depth + 1);
+ Known.copysign(KnownSign);
+ break;
+ }
+ case ISD::AssertNoFPClass: {
+ Known = computeKnownFPClass(Op.getOperand(0), DemandedElts,
+ InterestedClasses, Depth + 1);
+ FPClassTest AssertedClasses =
+ static_cast<FPClassTest>(Op->getConstantOperandVal(1));
+ Known.KnownFPClasses &= ~AssertedClasses;
+ break;
+ }
+ case ISD::EXTRACT_SUBVECTOR: {
+ SDValue Src = Op.getOperand(0);
+ EVT SrcVT = Src.getValueType();
+ if (SrcVT.isFixedLengthVector()) {
+ unsigned Idx = Op.getConstantOperandVal(1);
+ unsigned NumSrcElts = SrcVT.getVectorNumElements();
+
+ APInt DemandedSrcElts = DemandedElts.zextOrTrunc(NumSrcElts).shl(Idx);
Known = computeKnownFPClass(Src, DemandedSrcElts, InterestedClasses,
Depth + 1);
} else {
- // Out of bounds index is poison.
- Known.KnownFPClasses = fcNone;
+ Known = computeKnownFPClass(Src, InterestedClasses, Depth + 1);
}
- } else {
- Known = computeKnownFPClass(Src, InterestedClasses, Depth + 1);
+ break;
}
- break;
- }
- case ISD::SPLAT_VECTOR: {
- Known = computeKnownFPClass(Op.getOperand(0), InterestedClasses, Depth + 1);
- break;
- }
- case ISD::BITCAST: {
- // FIXME: It should not be necessary to check for an elementwise bitcast.
- // If a bitcast is not elementwise between vector / scalar types,
- // computeKnownBits already splices the known bits of the source elements
- // appropriately so as to line up with the bits of the result's demanded
- // elements.
- EVT SrcVT = Op.getOperand(0).getValueType();
- if (VT.isScalableVector() || SrcVT.isScalableVector())
+ case ISD::INSERT_SUBVECTOR: {
+ SDValue BaseVector = Op.getOperand(0);
+ SDValue SubVector = Op.getOperand(1);
+ EVT BaseVT = BaseVector.getValueType();
+ if (BaseVT.isFixedLengthVector()) {
+ unsigned Idx = Op.getConstantOperandVal(2);
+ unsigned NumBaseElts = BaseVT.getVectorNumElements();
+ unsigned NumSubElts = SubVector.getValueType().getVectorNumElements();
+
+ APInt DemandedMask =
+ APInt::getBitsSet(NumBaseElts, Idx, Idx + NumSubElts);
+ APInt DemandedSrcElts = DemandedElts & ~DemandedMask;
+ APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);
+
+ if (!DemandedSrcElts.isZero())
+ Known = computeKnownFPClass(BaseVector, DemandedSrcElts,
+ InterestedClasses, Depth + 1);
+ if (!DemandedSubElts.isZero()) {
+ KnownFPClass SubKnown = computeKnownFPClass(
+ SubVector, DemandedSubElts, InterestedClasses, Depth + 1);
+ Known = DemandedSrcElts.isZero() ? SubKnown : (Known | SubKnown);
+ }
+ } else {
+ Known = computeKnownFPClass(SubVector, InterestedClasses, Depth + 1);
+ if (!Known.isUnknown())
+ Known |=
+ computeKnownFPClass(BaseVector, InterestedClasses, Depth + 1);
+ }
break;
- unsigned VTNumElts = VT.isVector() ? VT.getVectorNumElements() : 1;
- unsigned SrcVTNumElts = SrcVT.isVector() ? SrcVT.getVectorNumElements() : 1;
- if (VTNumElts != SrcVTNumElts)
+ }
+ case ISD::SELECT:
+ case ISD::VSELECT: {
+ // TODO: Add adjustKnownFPClassForSelectArm clamp recognition as in
+ // IR-level ValueTracking.
+ KnownFPClass KnownFalseClass = computeKnownFPClass(
+ Op.getOperand(2), DemandedElts, InterestedClasses, Depth + 1);
+ if (KnownFalseClass.isUnknown())
+ break;
+ KnownFPClass KnownTrueClass = computeKnownFPClass(
+ Op.getOperand(1), DemandedElts, InterestedClasses, Depth + 1);
+ Known = KnownTrueClass.intersectWith(KnownFalseClass);
break;
-
- KnownBits Bits = computeKnownBits(Op, DemandedElts, Depth + 1);
- Known = KnownFPClass::bitcast(VT.getFltSemantics(), Bits);
- break;
- }
- case ISD::FABS: {
- Known = computeKnownFPClass(Op.getOperand(0), DemandedElts,
- InterestedClasses, Depth + 1);
- Known.fabs();
- break;
- }
- case ISD::FCOPYSIGN: {
- Known = computeKnownFPClass(Op.getOperand(0), DemandedElts,
- InterestedClasses, Depth + 1);
- KnownFPClass KnownSign = computeKnownFPClass(Op.getOperand(1), DemandedElts,
- InterestedClasses, Depth + 1);
- Known.copysign(KnownSign);
- break;
- }
- case ISD::AssertNoFPClass: {
- Known = computeKnownFPClass(Op.getOperand(0), DemandedElts,
- InterestedClasses, Depth + 1);
- FPClassTest AssertedClasses =
- static_cast<FPClassTest>(Op->getConstantOperandVal(1));
- Known.KnownFPClasses &= ~AssertedClasses;
- break;
- }
- case ISD::EXTRACT_SUBVECTOR: {
- SDValue Src = Op.getOperand(0);
- EVT SrcVT = Src.getValueType();
- if (SrcVT.isFixedLengthVector()) {
- unsigned Idx = Op.getConstantOperandVal(1);
- unsigned NumSrcElts = SrcVT.getVectorNumElements();
-
- APInt DemandedSrcElts = DemandedElts.zextOrTrunc(NumSrcElts).shl(Idx);
- Known = computeKnownFPClass(Src, DemandedSrcElts, InterestedClasses,
- Depth + 1);
- } else {
- Known = computeKnownFPClass(Src, InterestedClasses, Depth + 1);
}
- break;
- }
- case ISD::INSERT_SUBVECTOR: {
- SDValue BaseVector = Op.getOperand(0);
- SDValue SubVector = Op.getOperand(1);
- EVT BaseVT = BaseVector.getValueType();
- if (BaseVT.isFixedLengthVector()) {
- unsigned Idx = Op.getConstantOperandVal(2);
- unsigned NumBaseElts = BaseVT.getVectorNumElements();
- unsigned NumSubElts = SubVector.getValueType().getVectorNumElements();
-
- APInt DemandedMask =
- APInt::getBitsSet(NumBaseElts, Idx, Idx + NumSubElts);
- APInt DemandedSrcElts = DemandedElts & ~DemandedMask;
- APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);
-
- if (!DemandedSrcElts.isZero())
- Known = computeKnownFPClass(BaseVector, DemandedSrcElts,
- InterestedClasses, Depth + 1);
- if (!DemandedSubElts.isZero()) {
- KnownFPClass SubKnown = computeKnownFPClass(
- SubVector, DemandedSubElts, InterestedClasses, Depth + 1);
- Known = DemandedSrcElts.isZero() ? SubKnown : (Known | SubKnown);
+ default:
+ if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
+ Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID) {
+ TLI->computeKnownFPClassForTargetNode(Op, Known, DemandedElts, *this,
+ Depth);
}
- } else {
- Known = computeKnownFPClass(SubVector, InterestedClasses, Depth + 1);
- if (!Known.isUnknown())
- Known |= computeKnownFPClass(BaseVector, InterestedClasses, Depth + 1);
- }
- break;
- }
- case ISD::SELECT:
- case ISD::VSELECT: {
- // TODO: Add adjustKnownFPClassForSelectArm clamp recognition as in
- // IR-level ValueTracking.
- KnownFPClass KnownFalseClass = computeKnownFPClass(
- Op.getOperand(2), DemandedElts, InterestedClasses, Depth + 1);
- if (KnownFalseClass.isUnknown())
break;
- KnownFPClass KnownTrueClass = computeKnownFPClass(
- Op.getOperand(1), DemandedElts, InterestedClasses, Depth + 1);
- Known = KnownTrueClass.intersectWith(KnownFalseClass);
- break;
- }
- default:
- if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
- Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID) {
- TLI->computeKnownFPClassForTargetNode(Op, Known, DemandedElts, *this,
- Depth);
}
- break;
}
return Known;
More information about the llvm-commits
mailing list