You are an LLVM compiler expert specializing in test case generation and bug detection. You are conducting LLVM code review now. ## Context Maintainers provided a patch, but patches often have edge cases or introduce new issues. ## Your Task You will work in two phases: - Phase 1: Analyze the fix to identify potential issues, gaps, and edge cases. Propose test strategies. - Phase 2: Generate targeted test cases by modifying existing tests to target identified issues ## You Will Receive - Original patch description and related test case(s) - The code region that was modified (the patch) - Information about the optimization pass and component involved ## Tools You Can Use You have multiple tools for each phase, but you should try to avoid using them with same inputs repeatedly to reduce redundant calls. **CRITICAL**: You MUST use tool call every action in Phase 1 and Phase 2.
# Phase 1: Analyze the Fix
This is a patch for ValueTracking:
ValueTracking: Improve frexp known range from dominating conditions
Try to restrict the known range of the exponent result of llvm.frexp
based on dominating conditions. Identify comparisons that imply the
incoming value cannot introduce an overflow in a downstream ldexp
use. This pattern appears in the implementation of some complex math
functions and allows finite only math to prune out more edge case
paths.
One attributor test for ldexp regresses due to the switch from
computeKnownBits to computeConstantRange. computeConstantRange
does not try to handle non-splat vector constants for the binary
operators.
As a side effect, this also improves knowing that ldexp can't
introduce overflow for the 0 case.
diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
index 7e018d25d2d1d..956141b9449a2 100644
--- a/llvm/include/llvm/Support/KnownFPClass.h
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -20,6 +20,7 @@
namespace llvm {
class APFloat;
+class APInt;
struct fltSemantics;
struct KnownBits;
@@ -448,10 +449,17 @@ struct KnownFPClass {
static LLVM_ABI KnownFPClass frexp_mant(
const KnownFPClass &Src, DenormalMode Mode = DenormalMode::getDynamic());
- /// Propagate known class for ldexp
+ /// Propagate known class for ldexp, assuming the exponent is known to be
+ /// within [\p ConstantRangeMin, \p ConstantRangeMax]
+ ///
+ // TODO: This really ought to use ConstantRange, but it's in IR not Support.
static LLVM_ABI KnownFPClass
- ldexp(const KnownFPClass &Src, const KnownBits &N, const fltSemantics &Flt,
+ ldexp(const KnownFPClass &Src, const APInt &ConstantRangeMin,
+ const APInt &ConstantRangeMax, const fltSemantics &Flt,
DenormalMode Mode = DenormalMode::getDynamic());
+ static LLVM_ABI KnownFPClass ldexp(
+ const KnownFPClass &Src, const KnownBits &ExpBits,
+ const fltSemantics &Flt, DenormalMode Mode = DenormalMode::getDynamic());
/// Propagate known class for powi
static LLVM_ABI KnownFPClass powi(const KnownFPClass &Src,
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 7dd23f24dfcc7..5869ab28c6226 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4867,6 +4867,49 @@ static void computeKnownFPClassFromCond(const Value *V, Value *Cond,
}
}
+/// Compute the minimum and maximum values (inclusive) for the exponent of \p V,
+/// assuming it is not nan.
+static std::pair<int, int>
+computeKnownExponentRangeFromContext(const Value *V, const SimplifyQuery &Q) {
+ if (!Q.CxtI || !Q.DC || !Q.DT)
+ return {APFloat::IEK_NaN, APFloat::IEK_Inf};
+
+ for (CondBrInst *BI : Q.DC->conditionsFor(V)) {
+ CmpPredicate Pred;
+ const APFloat *LimitC;
+ if (!match(BI->getCondition(),
+ m_FCmp(Pred, m_FAbs(m_Specific(V)), m_Finite(LimitC))))
+ continue;
+
+ if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO ||
+ Pred == FCmpInst::FCMP_TRUE || Pred == FCmpInst::FCMP_FALSE)
+ continue;
+
+ APFloat::cmpResult CmpOne =
+ LimitC->compare(APFloat::getOne(LimitC->getSemantics()));
+ if (CmpOne > APFloat::cmpEqual)
+ continue;
+
+ // If fabs(x) <= K, K <= 1.0 => exponent min exp range
+ // if fabs(x) >= K, K <= 1.0 swap the successor
+ bool IsLessEqual =
+ Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE ||
+ Pred == FCmpInst::FCMP_ULT || Pred == FCmpInst::FCMP_ULE ||
+ Pred == FCmpInst::FCMP_OEQ || Pred == FCmpInst::FCMP_UEQ;
+
+ BasicBlockEdge Edge1(BI->getParent(),
+ BI->getSuccessor(IsLessEqual ? 0 : 1));
+ if (Q.DT->dominates(Edge1, Q.CxtI->getParent())) {
+ int Exp = ilogb(*LimitC);
+
+ // TODO: Figure out lower bound to detect no-underflow.
+ return {APFloat::IEK_NaN, Exp};
+ }
+ }
+
+ return {APFloat::IEK_NaN, APFloat::IEK_Inf};
+}
+
static KnownFPClass computeKnownFPClassFromContext(const Value *V,
const SimplifyQuery &Q) {
KnownFPClass KnownFromContext;
@@ -4990,6 +5033,7 @@ static constexpr KnownFPClass::MinMaxKind getMinMaxKind(Intrinsic::ID IID) {
static bool isAbsoluteValueULEOne(const Value *V) {
// TODO: Handle frexp
// TODO: Other rounding intrinsics?
+ // TODO: Try computeKnownExponentRangeFromContext
// fabs(x - floor(x)) <= 1
const Value *SubFloorX;
@@ -5507,11 +5551,12 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
// Can refine inf/zero handling based on the exponent operand.
const FPClassTest ExpInfoMask = fcZero | fcSubnormal | fcInf;
- KnownBits ExpBits;
- if ((KnownSrc.KnownFPClasses & ExpInfoMask) != fcNone) {
- const Value *ExpArg = II->getArgOperand(1);
- ExpBits = computeKnownBits(ExpArg, DemandedElts, Q, Depth + 1);
- }
+ const Value *ExpArg = II->getArgOperand(1);
+ ConstantRange ExpKnownRange =
+ ((KnownSrc.KnownFPClasses & ExpInfoMask) != fcNone)
+ ? computeConstantRange(ExpArg, /*ForSigned=*/true, Q, Depth + 1)
+ : ConstantRange::getFull(
+ ExpArg->getType()->getScalarSizeInBits());
const fltSemantics &Flt =
II->getType()->getScalarType()->getFltSemantics();
@@ -5520,7 +5565,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
DenormalMode Mode =
F ? F->getDenormalMode(Flt) : DenormalMode::getDynamic();
- Known = KnownFPClass::ldexp(KnownSrc, ExpBits, Flt, Mode);
+ Known = KnownFPClass::ldexp(KnownSrc, ExpKnownRange.getSignedMin(),
+ ExpKnownRange.getSignedMax(), Flt, Mode);
break;
}
case Intrinsic::arithmetic_fence: {
@@ -10474,9 +10520,17 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool ForSigned,
MinExp -= (APFloat::semanticsPrecision(FltSem) - 1);
int MaxExp = APFloat::semanticsMaxExponent(FltSem) + 1;
+
+ auto [AdjustedMin, AdjustedMax] =
+ computeKnownExponentRangeFromContext(FrexpSrc, SQ);
+
+ MinExp = std::max(AdjustedMin, MinExp);
+ MaxExp = std::min(AdjustedMax, MaxExp);
+
CR = ConstantRange::getNonEmpty(
- APInt(BitWidth, MinExp, /*isSigned=*/true),
- APInt(BitWidth, MaxExp + 1, /*isSigned=*/true));
+ APInt(BitWidth, static_cast<int64_t>(MinExp), /*isSigned=*/true),
+ APInt(BitWidth, static_cast<int64_t>(MaxExp) + 1,
+ /*isSigned=*/true));
}
}
}
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 38762f05d74ac..4fb1d4cd4723e 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -789,7 +789,8 @@ KnownFPClass KnownFPClass::frexp_mant(const KnownFPClass &KnownSrc,
}
KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
- const KnownBits &ExpBits,
+ const APInt &ConstantRangeExpMin,
+ const APInt &ConstantRangeExpMax,
const fltSemantics &Flt, DenormalMode Mode) {
KnownFPClass Known;
Known.propagateNaN(KnownSrc, /*PropagateSign=*/true);
@@ -807,20 +808,19 @@ KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
unsigned Precision = APFloat::semanticsPrecision(Flt);
const int MantissaBits = Precision - 1;
-
- if (ExpBits.getSignedMinValue().sge(static_cast<int64_t>(MantissaBits)))
+ if (ConstantRangeExpMin.sge(MantissaBits))
Known.knownNot(fcSubnormal);
- if (ExpBits.isConstant() && ExpBits.getConstant().isZero()) {
+ if (ConstantRangeExpMin.isZero() && ConstantRangeExpMax.isZero()) {
// ldexp(x, 0) -> x, so propagate everything.
Known.propagateCanonicalizingSrc(KnownSrc, Mode);
- } else if (ExpBits.isNegative()) {
+ } else if (ConstantRangeExpMax.isNonPositive()) {
// If we know the power is <= 0, can't introduce inf
if (KnownSrc.isKnownNeverPosInfinity())
Known.knownNot(fcPosInf);
if (KnownSrc.isKnownNeverNegInfinity())
Known.knownNot(fcNegInf);
- } else if (ExpBits.isNonNegative()) {
+ } else if (ConstantRangeExpMin.isNonNegative()) {
// If we know the power is >= 0, can't introduce subnormal or zero
if (KnownSrc.isKnownNeverPosSubnormal())
Known.knownNot(fcPosSubnormal);
@@ -835,6 +835,13 @@ KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
return Known;
}
+KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
+ const KnownBits &ExpBits,
+ const fltSemantics &Flt, DenormalMode Mode) {
+ return ldexp(KnownSrc, ExpBits.getSignedMinValue(),
+ ExpBits.getSignedMaxValue(), Flt, Mode);
+}
+
KnownFPClass KnownFPClass::powi(const KnownFPClass &KnownSrc,
const KnownBits &ExponentKnownBits) {
KnownFPClass Known;
---
## Subsystem Knowledge for ValueTracking
For reference, here are some key points about the ValueTracking you should consider (but do not limit to these) in your analysis:
# Subsystem Knowledge for ValueTracking
## Elements Frequently Missed
* **Poison-Generating Flags on Instructions**: Flags that can generate poison values (such as `samesign`, `nsw`, `nnan`, `ninf`) are frequently overlooked when they are attached directly to instructions like `icmp`, `phi`, or `sub`. The analysis often mistakenly assumes an instruction's result is safe solely because its incoming operands are safe, ignoring the flags.
* **Mismatched Flags Between Paired Instructions**: When analyzing instruction pairs (e.g., an `fcmp` followed by a `select`), the compiler frequently misses discrepancies in Fast-Math Flags (FMF) or poison-generating flags between the two instructions. It incorrectly applies the relaxed semantics of one instruction to the entire pattern.
* **IEEE-754 Floating-Point Edge Cases**: Specific floating-point behaviors are frequently missed during value tracking and constant folding, including:
* **NaN Dropping Semantics**: Operations like `minnum` and `maxnum` discard NaN operands, meaning the sign bit of a NaN operand does not propagate to the result.
* **Signed Zeros**: The distinction between `+0.0` and `-0.0` is ignored during strict vs. non-strict inequality transformations, even when the `nsz` (no signed zeros) flag is absent.
* **Division by Negative Zero**: Dividing a positive number by `-0.0` yields `-Inf` (a strictly negative value), which is missed when analyzing the signs of the operands.
* **Zero Multiplied by Infinity**: The cross-operand scenario where one operand is `0` and the other is `Inf` results in `NaN`, which is missed if the compiler only checks operands individually.
* **Poison Elements in Vector Constants**: Partially poisonous vector constants (e.g., `<0, poison>`) are frequently treated as perfectly safe equivalent values (like a pure zero vector) during algebraic simplifications, leading to the unintended introduction of poison into well-defined execution paths.
* **1-bit Integer Boundary Conditions**: The wrap-around behavior specific to 1-bit integers (`i1`) is missed during constant range calculations. Adding 1 to the maximum value of an `i1` wraps around to the lower bound, erroneously creating an empty range.
* **Speculative Execution Safety Context**: The implicit properties that make an instruction safe to execute speculatively (e.g., a pointer being non-null, or a divisor being non-zero) are missed when the compiler substitutes operands based on conditional equivalence.
## Patterns Not Well Handled
### Pattern 1: Select-Based Min/Max and Conditional Pattern Matching
The optimization pass struggles to safely transform `select` instructions driven by comparisons (`icmp` or `fcmp`) into higher-level intrinsics like `minnum`, `maxnum`, `smin`, or `smax`. The pattern matching logic frequently fails to respect the strict semantics of the original `select` instruction. It improperly hoists fast-math flags from the comparison to the entire pattern, ignores mismatched signed zeros, and fails to preserve ordered/unordered predicates when NaNs are possible. Furthermore, it fails to recognize that a `select` instruction acts as a "poison shield" (conditionally ignoring poison values from unselected branches), whereas the resulting intrinsics evaluate unconditionally and propagate poison.
### Pattern 2: Poison and Undef Propagation in Control Flow and Simplification
Transformations that simplify control flow, invert logic, or eliminate defensive instructions (like `freeze`) do not handle poison propagation well. The compiler often assumes that if the inputs to an expression tree are well-defined, the output is well-defined. This high-level assumption breaks down when the compiler swaps `select` operands involving partially poisonous vectors, replaces conditional selects with logical `xor` operations without checking for mismatched poison-generating flags, or ignores poison-generating flags on `phi` nodes. These flawed transformations consistently result in optimized code that is "more poisonous" than the original IR.
### Pattern 3: Floating-Point Property Deduction
The compiler's ValueTracking subsystem poorly handles the deduction of floating-point properties (such as sign bits, NaN possibilities, and value ranges) when combining multiple operations. It attempts to apply standard algebraic rules to floating-point arithmetic without adequately accounting for IEEE-754 edge cases. For example, it incorrectly deduces that a multiplication cannot produce `NaN` if neither operand is *always* zero or infinity, missing the case where they dynamically evaluate to zero and infinity simultaneously. Similarly, it incorrectly assumes the result of a division cannot be negative if neither operand is strictly negative, failing to account for division by negative zero.
### Pattern 4: Context-Blind Operand Substitution in Speculative Execution
The optimization pass does not well handle the substitution of variables with constants in speculatively executed instructions. When the compiler identifies that a variable is equivalent to a constant (e.g., `ptr == null`) within a specific conditional branch, it attempts to substitute the constant into instructions that use that variable. However, it performs this substitution blindly on instructions that are executed unconditionally (speculatively) outside the branch. This pattern destroys the very properties (like dereferenceability) that made the speculative execution safe in the first place, immediately introducing Undefined Behavior into the optimized program.
**CRITICAL**: Subsystem knowledge is **ONLY** a reference for you to understand this component.
Do NOT start your analysis from these patterns. Start from the patch semantics. Use these **ONLY** to cross-check your reasoning.
## Your Task for Phase 1
In this phase, you will review and analyze the fix above carefully and identify potential issues, edge cases, or gaps that the fix might miss. According to the analysis, propose mutation strategies for exposing the issue. These strategies will be used in Phase 2 to mutate existing test cases to target the identified issues.
Follow this structured workflow:
### Step 1: Context Gathering
In this step, you should gather enough context to construct semantics model of this fix for future analysis. Your goal is to understand the complete flow of this optimization. To achieve this, you should look at the nearby code regions, or try to find similar code regions in the LLVM codebase to understand the semantics of this fix.
You can use search tools:
- Use the `find` and `list` tools to find relevant files in the LLVM code.
- Use the `read` and `grep` tools to understand the context of the fix.
### Step 2: Fix Segmentation and Analysis
Based on the model built for this fix, you should segment the fix into smaller parts and analyze the semantics of each part. Follow this structured workflow for segmentation and analysis:
- **Segmentation**: Break down the fix into smaller segments or key changes, especially focusing on code regions related to semantics changes.
- **Analysis**: For each segment, analyze the semantics and identify any assumptions or preconditions that the fix relies on.
#### Tips for this step
- You can use the `langref` tool to query the LLVM Language Reference Manual for specific instructions, semantics, or optimization details relevant to the fix.
- You can pay attention to the commit message and annotations in the code, such as comments or specific patterns that indicate important semantics or assumptions.
### Step 3: Formal Semantic Modeling
- Define the exact semantic contract that this fix claims to satisfy.
- Explicitly list the preconditions under which the contract is assumed to hold.
- Identify how these preconditions may be violated.
### Step 4: Identify Potential Issues and Propose Test Strategies
Based on your analysis, propose around 5 specific test strategies that can be used to expose the issue. When proposing test strategies, consider the following:
- **Focus**: Focus on the assumptions and preconditions you identified.
- **Scenarios**: Think about specific input characteristics or scenarios that could violate these assumptions.
- **Mutations**: Propose mutations that can be applied to existing test cases to create new test cases targeting these scenarios.
Once you have analyzed the fix and identified potential issues or edge cases, use the `stop` tool to specify proposed test strategies along with detailed reasoning.
Follow this structure for reasoning:
### 1. Fix Understanding
- What optimization or transformation does this fix enable or correct?
- What are the key changes made in the patch?
### 2. Formal Semantic Modeling
- What is the exact semantic function before the fix?
- What is the exact semantic function after the fix?
- Under what conditions might they differ?
- Provide at least one concrete numerical instantiation to illustrate the difference.
### 3. Assumptions and Preconditions Identified
- What assumptions does the fix make about the input?
- What preconditions must hold for this fix to be correct?
### 4. Potential Cases to Break Assumptions
For each assumption and precondition identified, describe specific scenarios or input characteristics that could violate them. The potential cases should only focus on the semantics related to the analysis above.
### 5. Test Strategies
For each potential issue you identified, propose specific test strategies with the following structure:
- Name: [Name]
- Target: [What to mutate]
- Rationale: [Why this might expose an issue]
- Expected Issue: [What incorrect behavior might occur]
---
## Tools that you can use
- `findN`: Search for files in the LLVM codebase related to the component or optimization pass to understand the context of the fix and find relevant tests.
- `listN`: List files in the LLVM codebase to find relevant tests or code regions.
- `readN`: Read the content of a file in the LLVM codebase to understand existing tests or the fix.
- `grepN`: Search for specific patterns in the codebase to find relevant tests or code regions.
- `langref`: Query the LLVM Language Reference Manual for specific instructions, semantics, or optimization details relevant to the fix.
- `stop`: End Phase 1 by submitting the identified issues and proposed test strategies.{"args":"-nRI 'computeKnownExponentRangeFromContext\\|KnownFPClass::ldexp\\|conditionsFor(V)\\|Intrinsic::frexp\\|Intrinsic::ldexp' llvm/lib llvm/include","k":1}llvm/include/llvm/CodeGen/BasicTTIImpl.h:2416: case Intrinsic::ldexp:
llvm/include/llvm/IR/IRBuilder.h:1087: return CreateIntrinsic(Intrinsic::ldexp, {Src->getType(), Exp->getType()},llvm/lib/Analysis/ConstantFolding.cpp:1858: case Intrinsic::ldexp:
llvm/lib/Analysis/ConstantFolding.cpp:1861: case Intrinsic::frexp:
llvm/lib/Analysis/ConstantFolding.cpp:3719: case Intrinsic::ldexp: {
llvm/lib/Analysis/ConstantFolding.cpp:4590: case Intrinsic::frexp: {
llvm/lib/Analysis/InstructionSimplify.cpp:7156: case Intrinsic::ldexp:
llvm/lib/Analysis/ValueTracking.cpp:1043: for (CondBrInst *BI : Q.DC->conditionsFor(V)) {
llvm/lib/Analysis/ValueTracking.cpp:10503: } else if (match(I, m_ExtractValue<1>(m_Intrinsic<Intrinsic::frexp>(
llvm/lib/Analysis/ValueTracking.cpp:10525: computeKnownExponentRangeFromContext(FrexpSrc, SQ);
llvm/lib/Analysis/ValueTracking.cpp:2683: for (CondBrInst *BI : Q.DC->conditionsFor(V)) {
llvm/lib/Analysis/ValueTracking.cpp:4098: for (CondBrInst *BI : Q.DC->conditionsFor(V)) {
llvm/lib/Analysis/ValueTracking.cpp:4873:computeKnownExponentRangeFromContext(const Value *V, const SimplifyQuery &Q) {
llvm/lib/Analysis/ValueTracking.cpp:4877: for (CondBrInst *BI : Q.DC->conditionsFor(V)) {
llvm/lib/Analysis/ValueTracking.cpp:4926: for (CondBrInst *BI : Q.DC->conditionsFor(V)) {
llvm/lib/Analysis/ValueTracking.cpp:5036: // TODO: Try computeKnownExponentRangeFromContext
llvm/lib/Analysis/ValueTracking.cpp:5547: case Intrinsic::ldexp: {
llvm/lib/Analysis/ValueTracking.cpp:5568: Known = KnownFPClass::ldexp(KnownSrc, ExpKnownRange.getSignedMin(),
llvm/lib/Analysis/ValueTracking.cpp:6056: case Intrinsic::frexp: {
llvm/lib/Analysis/ValueTracking.cpp:8237: case Intrinsic::frexp:
llvm/lib/Analysis/VectorUtils.cpp:212: case Intrinsic::ldexp:
llvm/lib/Analysis/VectorUtils.cpp:228: case Intrinsic::frexp:
llvm/lib/Analysis/VectorUtils.cpp:90: case Intrinsic::frexp:
llvm/lib/Analysis/VectorUtils.cpp:91: case Intrinsic::ldexp:
llvm/lib/CodeGen/ExpandIRInsts.cpp:324: Value *Frexp = B.CreateIntrinsic(Intrinsic::frexp, {Ty, ExTy}, Src);
llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp:1502: Known = KnownFPClass::ldexp(KnownSrc, ExpBits, Flt, Mode);
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp:2020: case Intrinsic::ldexp:
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp:2416: case Intrinsic::frexp: {
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:7138: case Intrinsic::ldexp:
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:7147: case Intrinsic::frexp: {
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:7161: case Intrinsic::frexp:
llvm/lib/IR/AutoUpgrade.cpp:1420: F->getParent(), Intrinsic::ldexp,
llvm/lib/Support/KnownFPClass.cpp:791:KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
llvm/lib/Support/KnownFPClass.cpp:838:KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp:140: F.getParent(), Intrinsic::ldexp,
llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp:510: Value *Frexp = Builder.CreateIntrinsic(Intrinsic::frexp,
llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp:711: CI->getModule(), Intrinsic::ldexp,
llvm/lib/Transforms/Coroutines/MaterializationUtils.cpp:255: case Intrinsic::ldexp:
llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp:3133: if (II->getIntrinsicID() == Intrinsic::ldexp) {
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:3294: case Intrinsic::ldexp: {
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:3330: if (match(Src, m_OneUse(m_Intrinsic<Intrinsic::ldexp>(
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:4356: case Intrinsic::frexp: {
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:4361: m_ExtractValue<0>(m_Intrinsic<Intrinsic::frexp>(m_Value())))) {
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:1130: m_AllowReassoc(m_OneUse(m_Intrinsic<Intrinsic::ldexp>(
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:1133: I, Builder.CreateIntrinsic(Intrinsic::ldexp,
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp:396: if (TII->getIntrinsicID() == Intrinsic::ldexp) {
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp:411: TII->getType(), Intrinsic::ldexp, {SelectVal, SelectExp}, FMF);
llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp:3249: case Intrinsic::ldexp: {
llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp:3281: Known = KnownFPClass::ldexp(KnownSrc, KnownExpBits, FltSem, Mode);
llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp:3510: case Intrinsic::frexp: {
llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:4767: if (match(&EV, m_ExtractValue<0>(m_Intrinsic<Intrinsic::frexp>(m_Select(
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp:2215: return copyFlags(*Pow, B.CreateIntrinsic(Intrinsic::ldexp,
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp:2515: return copyFlags(*CI, B.CreateIntrinsic(Intrinsic::ldexp,{"args":"-nRI 'frexp\\|ldexp' llvm/test | head","k":1}Error: llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:4:declare float @llvm.ldexp.f32.i32(float, i32)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:5:declare float @llvm.ldexp.f32.i64(float, i64)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:6:declare <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float>, <2 x i32>)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:7:declare double @llvm.ldexp.f64.i32(double, i32)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:8:declare half @llvm.ldexp.f16.i32(half, i32)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:9:declare bfloat @llvm.ldexp.bf16.i32(bfloat, i32)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:12:define float @ret_ldexp_f32(float %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:13:; CHECK-LABEL: define float @ret_ldexp_f32
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:15:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 [[ARG1]]) #[[ATTR10:[0-9]+]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:18: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:22:define float @ret_ldexp_f32_0(float %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:23:; CHECK-LABEL: define float @ret_ldexp_f32_0
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:25:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:28: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:32:define float @ret_ldexp_f32_0_nopsub(float nofpclass(psub) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:33:; CHECK-LABEL: define nofpclass(psub) float @ret_ldexp_f32_0_nopsub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:35:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(psub) float @llvm.ldexp.f32.i32(float nofpclass(psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:38: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:42:define float @ret_ldexp_f32_0_nonsub(float nofpclass(nsub) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:43:; CHECK-LABEL: define nofpclass(nsub) float @ret_ldexp_f32_0_nonsub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:45:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nsub) float @llvm.ldexp.f32.i32(float nofpclass(nsub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:48: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:52:define float @ret_ldexp_f32_0_nosub(float nofpclass(sub) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:53:; CHECK-LABEL: define nofpclass(sub) float @ret_ldexp_f32_0_nosub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:55:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) float @llvm.ldexp.f32.i32(float nofpclass(sub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:58: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:62:define float @ret_ldexp_f32_0_nosub_nosnan(float nofpclass(sub snan) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:63:; CHECK-LABEL: define nofpclass(snan sub) float @ret_ldexp_f32_0_nosub_nosnan
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:65:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan sub) float @llvm.ldexp.f32.i32(float nofpclass(snan sub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:68: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:72:define float @ret_ldexp_f32_0_nopsub_nopzero(float nofpclass(psub pzero) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:73:; CHECK-LABEL: define nofpclass(pzero psub) float @ret_ldexp_f32_0_nopsub_nopzero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:75:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pzero psub) float @llvm.ldexp.f32.i32(float nofpclass(pzero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:78: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:82:define float @ret_ldexp_f32_0_nonsub_nonzero(float nofpclass(nsub nzero) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:83:; CHECK-LABEL: define nofpclass(nzero nsub) float @ret_ldexp_f32_0_nonsub_nonzero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:85:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero nsub) float @llvm.ldexp.f32.i32(float nofpclass(nzero nsub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:88: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:92:define float @ret_ldexp_f32_0_nosub_nozero(float nofpclass(sub zero) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:93:; CHECK-LABEL: define nofpclass(zero sub) float @ret_ldexp_f32_0_nosub_nozero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:95:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero sub) float @llvm.ldexp.f32.i32(float nofpclass(zero sub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:98: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:102:define float @ret_ldexp_f32_0_nopsub_daz(float nofpclass(psub) %arg0) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:103:; CHECK-LABEL: define nofpclass(psub) float @ret_ldexp_f32_0_nopsub_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:105:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(psub) float @llvm.ldexp.f32.i32(float nofpclass(psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:108: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:112:define float @ret_ldexp_f32_0_nonsub_daz(float nofpclass(nsub) %arg0) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:113:; CHECK-LABEL: define nofpclass(nsub) float @ret_ldexp_f32_0_nonsub_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:115:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nsub) float @llvm.ldexp.f32.i32(float nofpclass(nsub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:118: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:122:define float @ret_ldexp_f32_0_nosub_daz(float nofpclass(sub) %arg0) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:123:; CHECK-LABEL: define nofpclass(sub) float @ret_ldexp_f32_0_nosub_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:125:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) float @llvm.ldexp.f32.i32(float nofpclass(sub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:128: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:132:define float @ret_ldexp_f32_0_nosub_nosnan_daz(float nofpclass(sub snan) %arg0) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:133:; CHECK-LABEL: define nofpclass(snan sub) float @ret_ldexp_f32_0_nosub_nosnan_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:135:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan sub) float @llvm.ldexp.f32.i32(float nofpclass(snan sub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:138: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:142:define float @ret_ldexp_f32_0_nopsub_nozero_daz(float nofpclass(psub pzero) %arg0) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:143:; CHECK-LABEL: define nofpclass(pzero psub) float @ret_ldexp_f32_0_nopsub_nozero_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:145:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pzero psub) float @llvm.ldexp.f32.i32(float nofpclass(pzero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:148: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:152:define float @ret_ldexp_f32_0_nonsub_nonzero_daz(float nofpclass(nsub nzero) %arg0) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:153:; CHECK-LABEL: define nofpclass(nzero nsub) float @ret_ldexp_f32_0_nonsub_nonzero_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:155:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero nsub) float @llvm.ldexp.f32.i32(float nofpclass(nzero nsub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:158: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:162:define float @ret_ldexp_f32_0_nosub_nozero_daz(float nofpclass(sub zero) %arg0) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:163:; CHECK-LABEL: define nofpclass(zero sub) float @ret_ldexp_f32_0_nosub_nozero_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:165:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero sub) float @llvm.ldexp.f32.i32(float nofpclass(zero sub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:168: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:172:define float @ret_ldexp_f32_0_nopsub_dapz(float nofpclass(psub) %arg0) #2 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:173:; CHECK-LABEL: define nofpclass(psub) float @ret_ldexp_f32_0_nopsub_dapz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:175:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(psub) float @llvm.ldexp.f32.i32(float nofpclass(psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:178: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:182:define float @ret_ldexp_f32_0_nonsub_dapz(float nofpclass(nsub) %arg0) #2 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:183:; CHECK-LABEL: define nofpclass(nsub) float @ret_ldexp_f32_0_nonsub_dapz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:185:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nsub) float @llvm.ldexp.f32.i32(float nofpclass(nsub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:188: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:192:define float @ret_ldexp_f32_0_nosub_dapz(float nofpclass(sub) %arg0) #2 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:193:; CHECK-LABEL: define nofpclass(sub) float @ret_ldexp_f32_0_nosub_dapz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:195:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) float @llvm.ldexp.f32.i32(float nofpclass(sub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:198: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:202:define float @ret_ldexp_f32_0_nopsub_nozero_dapz(float nofpclass(psub zero) %arg0) #2 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:203:; CHECK-LABEL: define nofpclass(nzero psub) float @ret_ldexp_f32_0_nopsub_nozero_dapz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:205:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero psub) float @llvm.ldexp.f32.i32(float nofpclass(zero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:208: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:212:define float @ret_ldexp_f32_0_nonsub_nonzero_dapz(float nofpclass(nsub nzero) %arg0) #2 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:213:; CHECK-LABEL: define nofpclass(nzero nsub) float @ret_ldexp_f32_0_nonsub_nonzero_dapz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:215:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero nsub) float @llvm.ldexp.f32.i32(float nofpclass(nzero nsub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:218: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:222:define float @ret_ldexp_f32_0_nosub_nozero_dapz(float nofpclass(sub zero) %arg0) #2 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:223:; CHECK-LABEL: define nofpclass(zero sub) float @ret_ldexp_f32_0_nosub_nozero_dapz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:225:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero sub) float @llvm.ldexp.f32.i32(float nofpclass(zero sub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:228: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:232:define float @ret_ldexp_f32_0_nopsub_nozero_dapz_dapz(float nofpclass(psub zero) %arg0) #2 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:233:; CHECK-LABEL: define nofpclass(nzero psub) float @ret_ldexp_f32_0_nopsub_nozero_dapz_dapz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:235:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero psub) float @llvm.ldexp.f32.i32(float nofpclass(zero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:238: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:242:define float @ret_ldexp_f32_0_nopsub_nozero_daz_ieee(float nofpclass(psub zero) %arg0) #3 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:243:; CHECK-LABEL: define nofpclass(pzero psub) float @ret_ldexp_f32_0_nopsub_nozero_daz_ieee
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:245:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pzero psub) float @llvm.ldexp.f32.i32(float nofpclass(zero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:248: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:252:define float @ret_ldexp_f32_0_nopsub_nozero_daz_dynamic(float nofpclass(psub zero) %arg0) #4 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:253:; CHECK-LABEL: define nofpclass(psub) float @ret_ldexp_f32_0_nopsub_nozero_daz_dynamic
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:255:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(psub) float @llvm.ldexp.f32.i32(float nofpclass(zero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:258: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:262:define float @ret_ldexp_f32_0_nopsub_nozero_ieee_daz(float nofpclass(psub zero) %arg0) #5 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:263:; CHECK-LABEL: define nofpclass(pzero psub) float @ret_ldexp_f32_0_nopsub_nozero_ieee_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:265:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pzero psub) float @llvm.ldexp.f32.i32(float nofpclass(zero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:268: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:272:define float @ret_ldexp_f32_0_nopsub_nozero_dynamic_daz(float nofpclass(psub zero) %arg0) #6 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:273:; CHECK-LABEL: define nofpclass(psub) float @ret_ldexp_f32_0_nopsub_nozero_dynamic_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:275:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(psub) float @llvm.ldexp.f32.i32(float nofpclass(zero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:278: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:282:define float @ret_ldexp_f32_0_nopsub_nozero_dynamic_dapz(float nofpclass(psub zero) %arg0) #7 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:283:; CHECK-LABEL: define nofpclass(psub) float @ret_ldexp_f32_0_nopsub_nozero_dynamic_dapz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:285:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(psub) float @llvm.ldexp.f32.i32(float nofpclass(zero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:288: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:292:define float @ret_ldexp_f32_0_nopsub_nozero_dapz_dynamic(float nofpclass(psub zero) %arg0) #8 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:293:; CHECK-LABEL: define nofpclass(psub) float @ret_ldexp_f32_0_nopsub_nozero_dapz_dynamic
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:295:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(psub) float @llvm.ldexp.f32.i32(float nofpclass(zero psub) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:298: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:302:define float @ret_ldexp_f32_0_nopnorm(float nofpclass(pnorm) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:303:; CHECK-LABEL: define nofpclass(pnorm) float @ret_ldexp_f32_0_nopnorm
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:305:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pnorm) float @llvm.ldexp.f32.i32(float nofpclass(pnorm) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:308: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:312:define float @ret_ldexp_f32_0_nnorm(float nofpclass(nnorm) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:313:; CHECK-LABEL: define nofpclass(nnorm) float @ret_ldexp_f32_0_nnorm
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:315:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nnorm) float @llvm.ldexp.f32.i32(float nofpclass(nnorm) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:318: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:322:define float @ret_ldexp_f32_0_nopnorm_nonsub(float nofpclass(pnorm nsub) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:323:; CHECK-LABEL: define nofpclass(nsub pnorm) float @ret_ldexp_f32_0_nopnorm_nonsub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:325:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nsub pnorm) float @llvm.ldexp.f32.i32(float nofpclass(nsub pnorm) [[ARG0]], i32 noundef 0) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:328: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 0)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:332:define <2 x float> @ret_ldexp_v2f32_0(<2 x float> %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:333:; CHECK-LABEL: define <2 x float> @ret_ldexp_v2f32_0
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:335:; CHECK-NEXT: [[CALL:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[ARG0]], <2 x i32> <i32 undef, i32 0>) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:338: %call = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %arg0, <2 x i32> <i32 undef, i32 0>)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:342:define float @ret_ldexp_f32_i64(float %arg0, i64 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:343:; CHECK-LABEL: define float @ret_ldexp_f32_i64
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:345:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i64(float [[ARG0]], i64 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:348: %call = call float @llvm.ldexp.f32.i64(float %arg0, i64 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:352:define <2 x float> @ret_ldexp_v2f32(<2 x float> %arg0, <2 x i32> %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:353:; CHECK-LABEL: define <2 x float> @ret_ldexp_v2f32
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:355:; CHECK-NEXT: [[CALL:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[ARG0]], <2 x i32> [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:358: %call = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %arg0, <2 x i32> %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:362:define float @ret_ldexp_f32_nonan(float nofpclass(nan) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:363:; CHECK-LABEL: define nofpclass(nan) float @ret_ldexp_f32_nonan
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:365:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @llvm.ldexp.f32.i32(float nofpclass(nan) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:368: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:372:define float @ret_ldexp_f32_nosnan(float nofpclass(snan) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:373:; CHECK-LABEL: define nofpclass(snan) float @ret_ldexp_f32_nosnan
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:375:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan) float @llvm.ldexp.f32.i32(float nofpclass(snan) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:378: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:382:define float @ret_ldexp_f32_noqnan(float nofpclass(qnan) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:383:; CHECK-LABEL: define float @ret_ldexp_f32_noqnan
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:385:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(qnan) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:388: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:392:define float @ret_ldexp_f32_noneg(float nofpclass(ninf nsub nnorm) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:393:; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @ret_ldexp_f32_noneg
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:395:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nsub nnorm) float @llvm.ldexp.f32.i32(float nofpclass(ninf nsub nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:398: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:402:define float @ret_ldexp_f32_noneg_nonzero(float nofpclass(ninf nsub nnorm nzero) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:403:; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_ldexp_f32_noneg_nonzero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:405:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.ldexp.f32.i32(float nofpclass(ninf nzero nsub nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:408: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:412:define float @ret_ldexp_f32_noneg_nozero(float nofpclass(ninf nsub nnorm) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:413:; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @ret_ldexp_f32_noneg_nozero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:415:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nsub nnorm) float @llvm.ldexp.f32.i32(float nofpclass(ninf nsub nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:418: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:422:define float @ret_ldexp_f32_nonzero(float nofpclass(nzero) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:423:; CHECK-LABEL: define float @ret_ldexp_f32_nonzero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:425:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(nzero) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:428: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:432:define float @ret_ldexp_f32_nopzero(float nofpclass(pzero) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:433:; CHECK-LABEL: define float @ret_ldexp_f32_nopzero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:435:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(pzero) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:438: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:442:define float @ret_ldexp_f32_noneg_ftz_daz(float nofpclass(ninf nsub nnorm) %arg0, i32 %arg1) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:443:; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @ret_ldexp_f32_noneg_ftz_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:445:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nsub nnorm) float @llvm.ldexp.f32.i32(float nofpclass(ninf nsub nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:448: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:452:define float @ret_ldexp_f32_noneg_nonzero_ftz_daz(float nofpclass(ninf nsub nnorm nzero) %arg0, i32 %arg1) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:453:; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_ldexp_f32_noneg_nonzero_ftz_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:455:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.ldexp.f32.i32(float nofpclass(ninf nzero nsub nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:458: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:462:define float @ret_ldexp_f32_noneg_nonzero_ftpz_dapz(float nofpclass(ninf nsub nnorm nzero) %arg0, i32 %arg1) #2 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:463:; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_ldexp_f32_noneg_nonzero_ftpz_dapz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:465:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.ldexp.f32.i32(float nofpclass(ninf nzero nsub nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:468: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:472:define float @ret_ldexp_f32_noninf_nonnorm(float nofpclass(ninf nnorm) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:473:; CHECK-LABEL: define float @ret_ldexp_f32_noninf_nonnorm
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:475:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(ninf nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:478: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:482:define float @ret_ldexp_f32_noninf_nonnorm_ftz_daz(float nofpclass(ninf nnorm) %arg0, i32 %arg1) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:483:; CHECK-LABEL: define float @ret_ldexp_f32_noninf_nonnorm_ftz_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:485:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(ninf nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:488: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:492:define float @ret_ldexp_f32_noneg_ftz_ieee(float nofpclass(ninf nsub nnorm) %arg0, i32 %arg1) #3 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:493:; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @ret_ldexp_f32_noneg_ftz_ieee
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:495:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nsub nnorm) float @llvm.ldexp.f32.i32(float nofpclass(ninf nsub nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:498: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:502:define float @ret_ldexp_f32_noneg_nonzero_ftz_ieee(float nofpclass(ninf nsub nnorm nzero) %arg0, i32 %arg1) #3 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:503:; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_ldexp_f32_noneg_nonzero_ftz_ieee
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:505:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.ldexp.f32.i32(float nofpclass(ninf nzero nsub nnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:508: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:512:define float @ret_ldexp_f32_nopos(float nofpclass(pinf psub pnorm) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:513:; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @ret_ldexp_f32_nopos
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:515:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pinf psub pnorm) float @llvm.ldexp.f32.i32(float nofpclass(pinf psub pnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:518: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:522:define float @ret_ldexp_f32_nopos_nopzero(float nofpclass(pinf psub pnorm pzero) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:523:; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_ldexp_f32_nopos_nopzero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:525:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pinf pzero psub pnorm) float @llvm.ldexp.f32.i32(float nofpclass(pinf pzero psub pnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:528: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:532:define float @ret_ldexp_f32_nopos_nozero(float nofpclass(pinf psub pnorm zero) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:533:; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_ldexp_f32_nopos_nozero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:535:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pinf pzero psub pnorm) float @llvm.ldexp.f32.i32(float nofpclass(pinf zero psub pnorm) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:538: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:542:define float @ret_ldexp_f32_nozero(float nofpclass(zero) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:543:; CHECK-LABEL: define float @ret_ldexp_f32_nozero
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:545:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(zero) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:548: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:552:define float @ret_ldexp_f32_noinf(float nofpclass(inf) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:553:; CHECK-LABEL: define float @ret_ldexp_f32_noinf
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:555:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(inf) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:558: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:562:define float @ret_ldexp_f32_noinf_nonan(float nofpclass(inf nan) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:563:; CHECK-LABEL: define nofpclass(nan) float @ret_ldexp_f32_noinf_nonan
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:565:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @llvm.ldexp.f32.i32(float nofpclass(nan inf) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:568: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:572:define float @ret_ldexp_f32_known_pos_exp(float %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:573:; CHECK-LABEL: define float @ret_ldexp_f32_known_pos_exp
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:576:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:580: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:584:define float @ret_ldexp_f32_known_neg_exp(float %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:585:; CHECK-LABEL: define float @ret_ldexp_f32_known_neg_exp
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:588:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:592: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:596:define float @ret_ldexp_f32_known_pos_exp_nosub(float nofpclass(sub) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:597:; CHECK-LABEL: define nofpclass(sub) float @ret_ldexp_f32_known_pos_exp_nosub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:600:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) float @llvm.ldexp.f32.i32(float nofpclass(sub) [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:604: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:608:define float @ret_ldexp_f32_known_neg_exp_nosub(float nofpclass(sub) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:609:; CHECK-LABEL: define float @ret_ldexp_f32_known_neg_exp_nosub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:612:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(sub) [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:616: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:620:define float @ret_ldexp_f32_known_pos_exp_nopsub(float nofpclass(psub) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:621:; CHECK-LABEL: define nofpclass(psub) float @ret_ldexp_f32_known_pos_exp_nopsub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:624:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(psub) float @llvm.ldexp.f32.i32(float nofpclass(psub) [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:628: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:632:define float @ret_ldexp_f32_known_neg_exp_nopsub(float nofpclass(psub) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:633:; CHECK-LABEL: define float @ret_ldexp_f32_known_neg_exp_nopsub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:636:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(psub) [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:640: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:644:define float @ret_ldexp_f32_known_pos_exp_nonsub(float nofpclass(nsub) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:645:; CHECK-LABEL: define nofpclass(nsub) float @ret_ldexp_f32_known_pos_exp_nonsub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:648:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nsub) float @llvm.ldexp.f32.i32(float nofpclass(nsub) [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:652: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:656:define float @ret_ldexp_f32_known_neg_exp_nonsub(float nofpclass(nsub) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:657:; CHECK-LABEL: define float @ret_ldexp_f32_known_neg_exp_nonsub
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:660:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(nsub) [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:664: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:668:define float @ret_ldexp_f32_known_pos_exp_noinf(float nofpclass(inf) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:669:; CHECK-LABEL: define float @ret_ldexp_f32_known_pos_exp_noinf
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:672:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(inf) [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:676: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:680:define float @ret_ldexp_f32_known_neg_exp_noinf(float nofpclass(inf) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:681:; CHECK-LABEL: define nofpclass(inf) float @ret_ldexp_f32_known_neg_exp_noinf
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:684:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf) float @llvm.ldexp.f32.i32(float nofpclass(inf) [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:688: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:692:define <2 x float> @ret_ldexp_v2f32_known_pos_exp_noinf(<2 x float> nofpclass(inf) %arg0, <2 x i32> %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:693:; CHECK-LABEL: define <2 x float> @ret_ldexp_v2f32_known_pos_exp_noinf
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:696:; CHECK-NEXT: [[CALL:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> nofpclass(inf) [[ARG0]], <2 x i32> [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:700: %call = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %arg0, <2 x i32> %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:704:define <2 x float> @ret_ldexp_v2f32_known_neg_exp_noinf(<2 x float> nofpclass(inf) %arg0, <2 x i32> %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:705:; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_ldexp_v2f32_known_neg_exp_noinf
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:708:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf) <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> nofpclass(inf) [[ARG0]], <2 x i32> [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:712: %call = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %arg0, <2 x i32> %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:716:define float @ret_ldexp_f32_known_pos_exp_nopinf(float nofpclass(pinf) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:717:; CHECK-LABEL: define float @ret_ldexp_f32_known_pos_exp_nopinf
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:720:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(pinf) [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:724: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:728:define float @ret_ldexp_f32_known_neg_exp_nopinf(float nofpclass(pinf) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:729:; CHECK-LABEL: define nofpclass(pinf) float @ret_ldexp_f32_known_neg_exp_nopinf
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:732:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pinf) float @llvm.ldexp.f32.i32(float nofpclass(pinf) [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:736: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:740:define float @ret_ldexp_f32_known_pos_exp_noninf(float nofpclass(ninf) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:741:; CHECK-LABEL: define float @ret_ldexp_f32_known_pos_exp_noninf
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:744:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(ninf) [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:748: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:752:define float @ret_ldexp_f32_known_neg_exp_noninf(float nofpclass(ninf) %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:753:; CHECK-LABEL: define nofpclass(ninf) float @ret_ldexp_f32_known_neg_exp_noninf
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:756:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf) float @llvm.ldexp.f32.i32(float nofpclass(ninf) [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:760: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:764:define float @ret_ldexp_f32_known_pos_exp_nopsub_nopzero_daz(float nofpclass(psub pzero) %arg0, i32 %arg1) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:765:; CHECK-LABEL: define nofpclass(pzero psub) float @ret_ldexp_f32_known_pos_exp_nopsub_nopzero_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:768:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pzero psub) float @llvm.ldexp.f32.i32(float nofpclass(pzero psub) [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:772: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:776:define float @ret_ldexp_f32_known_neg_exp_nopsub_nopzero_daz(float nofpclass(psub pzero) %arg0, i32 %arg1) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:777:; CHECK-LABEL: define float @ret_ldexp_f32_known_neg_exp_nopsub_nopzero_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:780:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(pzero psub) [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:784: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:788:define float @ret_ldexp_f32_known_pos_exp_nonsub_nonzero_daz(float nofpclass(nsub nzero) %arg0, i32 %arg1) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:789:; CHECK-LABEL: define nofpclass(nzero nsub) float @ret_ldexp_f32_known_pos_exp_nonsub_nonzero_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:792:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero nsub) float @llvm.ldexp.f32.i32(float nofpclass(nzero nsub) [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:796: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:800:define float @ret_ldexp_f32_known_neg_exp_nonsub_nonzero_daz(float nofpclass(nsub nzero) %arg0, i32 %arg1) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:801:; CHECK-LABEL: define float @ret_ldexp_f32_known_neg_exp_nonsub_nonzero_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:804:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(nzero nsub) [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:808: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:812:define float @ret_ldexp_f32_known_pos_exp_nosub_nozero_daz(float nofpclass(sub zero) %arg0, i32 %arg1) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:813:; CHECK-LABEL: define nofpclass(zero sub) float @ret_ldexp_f32_known_pos_exp_nosub_nozero_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:816:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero sub) float @llvm.ldexp.f32.i32(float nofpclass(zero sub) [[ARG0]], i32 [[AND_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:820: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %and.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:824:define float @ret_ldexp_f32_known_neg_exp_nosub_nozero_daz(float nofpclass(sub zero) %arg0, i32 %arg1) #1 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:825:; CHECK-LABEL: define float @ret_ldexp_f32_known_neg_exp_nosub_nozero_daz
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:828:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float nofpclass(zero sub) [[ARG0]], i32 [[OR_ARG1]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:832: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %or.arg1)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:836:define float @ret_ldexp_f32_22(float %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:837:; CHECK-LABEL: define float @ret_ldexp_f32_22
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:839:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 noundef 22) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:842: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 22)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:846:define float @ret_ldexp_f32_23(float %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:847:; CHECK-LABEL: define nofpclass(sub) float @ret_ldexp_f32_23
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:849:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) float @llvm.ldexp.f32.i32(float [[ARG0]], i32 noundef 23) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:852: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 23)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:856:define float @ret_ldexp_f32_24(float %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:857:; CHECK-LABEL: define nofpclass(sub) float @ret_ldexp_f32_24
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:859:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) float @llvm.ldexp.f32.i32(float [[ARG0]], i32 noundef 24) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:862: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 24)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:866:define float @ret_ldexp_f32_min24(float %arg0, i32 %arg1) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:867:; CHECK-LABEL: define float @ret_ldexp_f32_min24
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:870:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 [[MIN]]) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:874: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %min)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:878:define float @ret_ldexp_f32_23_nnan(float nofpclass(nan) %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:879:; CHECK-LABEL: define nofpclass(nan sub) float @ret_ldexp_f32_23_nnan
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:881:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan sub) float @llvm.ldexp.f32.i32(float nofpclass(nan) [[ARG0]], i32 noundef 23) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:884: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 23)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:888:define double @ret_ldexp_f64_24(double %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:889:; CHECK-LABEL: define double @ret_ldexp_f64_24
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:891:; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.ldexp.f64.i32(double [[ARG0]], i32 noundef 24) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:894: %call = call double @llvm.ldexp.f64.i32(double %arg0, i32 24)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:898:define double @ret_ldexp_f64_51(double %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:899:; CHECK-LABEL: define double @ret_ldexp_f64_51
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:901:; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.ldexp.f64.i32(double [[ARG0]], i32 noundef 51) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:904: %call = call double @llvm.ldexp.f64.i32(double %arg0, i32 51)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:908:define double @ret_ldexp_f64_52(double %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:909:; CHECK-LABEL: define nofpclass(sub) double @ret_ldexp_f64_52
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:911:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) double @llvm.ldexp.f64.i32(double [[ARG0]], i32 noundef 52) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:914: %call = call double @llvm.ldexp.f64.i32(double %arg0, i32 52)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:918:define double @ret_ldexp_f64_53(double %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:919:; CHECK-LABEL: define nofpclass(sub) double @ret_ldexp_f64_53
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:921:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) double @llvm.ldexp.f64.i32(double [[ARG0]], i32 noundef 53) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:924: %call = call double @llvm.ldexp.f64.i32(double %arg0, i32 53)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:928:define half @ret_ldexp_f16_8(half %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:929:; CHECK-LABEL: define half @ret_ldexp_f16_8
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:931:; CHECK-NEXT: [[CALL:%.*]] = call half @llvm.ldexp.f16.i32(half [[ARG0]], i32 noundef 8) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:934: %call = call half @llvm.ldexp.f16.i32(half %arg0, i32 8)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:938:define half @ret_ldexp_f16_9(half %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:939:; CHECK-LABEL: define half @ret_ldexp_f16_9
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:941:; CHECK-NEXT: [[CALL:%.*]] = call half @llvm.ldexp.f16.i32(half [[ARG0]], i32 noundef 9) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:944: %call = call half @llvm.ldexp.f16.i32(half %arg0, i32 9)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:948:define half @ret_ldexp_f16_10(half %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:949:; CHECK-LABEL: define nofpclass(sub) half @ret_ldexp_f16_10
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:951:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) half @llvm.ldexp.f16.i32(half [[ARG0]], i32 noundef 10) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:954: %call = call half @llvm.ldexp.f16.i32(half %arg0, i32 10)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:958:define bfloat @ret_ldexp_bf16_6(bfloat %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:959:; CHECK-LABEL: define bfloat @ret_ldexp_bf16_6
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:961:; CHECK-NEXT: [[CALL:%.*]] = call bfloat @llvm.ldexp.bf16.i32(bfloat [[ARG0]], i32 noundef 6) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:964: %call = call bfloat @llvm.ldexp.bf16.i32(bfloat %arg0, i32 6)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:968:define bfloat @ret_ldexp_bf16_7(bfloat %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:969:; CHECK-LABEL: define nofpclass(sub) bfloat @ret_ldexp_bf16_7
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:971:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) bfloat @llvm.ldexp.bf16.i32(bfloat [[ARG0]], i32 noundef 7) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:974: %call = call bfloat @llvm.ldexp.bf16.i32(bfloat %arg0, i32 7)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:978:define bfloat @ret_ldexp_bf16_8(bfloat %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:979:; CHECK-LABEL: define nofpclass(sub) bfloat @ret_ldexp_bf16_8
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:981:; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(sub) bfloat @llvm.ldexp.bf16.i32(bfloat [[ARG0]], i32 noundef 8) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:984: %call = call bfloat @llvm.ldexp.bf16.i32(bfloat %arg0, i32 8)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:988:define float @ret_ldexp_f32_neg22(float %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:989:; CHECK-LABEL: define float @ret_ldexp_f32_neg22
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:991:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 noundef -22) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:994: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 -22)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:998:define float @ret_ldexp_f32_neg23(float %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:999:; CHECK-LABEL: define float @ret_ldexp_f32_neg23
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1001:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 noundef -23) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1004: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 -23)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1008:define float @ret_ldexp_f32_neg24(float %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1009:; CHECK-LABEL: define float @ret_ldexp_f32_neg24
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1011:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 noundef -24) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1014: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 -24)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1018:define float @ret_ldexp_f32_neg126(float %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1019:; CHECK-LABEL: define float @ret_ldexp_f32_neg126
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1021:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 noundef -126) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1024: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 -126)
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1028:define float @ret_ldexp_f32_neg127(float %arg0) #0 {
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1029:; CHECK-LABEL: define float @ret_ldexp_f32_neg127
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1031:; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.ldexp.f32.i32(float [[ARG0]], i32 noundef -127) #[[ATTR10]]
llvm/test/Transforms/Attributor/nofpclass-ldexp.ll:1034: %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 -127)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:4:declare { float, i32 } @llvm.frexp.f32.i32(float)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:5:declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:6:declare { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float>)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:8:define { float, i32 } @ret_frexp_f32(float %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:9:; CHECK-LABEL: define { float, i32 } @ret_frexp_f32
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:11:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7:[0-9]+]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:14: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:18:define { float, i32 } @ret_frexp_f32_nonan(float nofpclass(nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:19:; CHECK-LABEL: define { float, i32 } @ret_frexp_f32_nonan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:21:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(nan) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:24: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:28:define float @ret_frexp_f32_0_nonan(float nofpclass(nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:29:; CHECK-LABEL: define nofpclass(nan sub) float @ret_frexp_f32_0_nonan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:31:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(nan) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:35: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:40:define float @ret_frexp_f32_0_nosnan(float nofpclass(snan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:41:; CHECK-LABEL: define nofpclass(snan sub) float @ret_frexp_f32_0_nosnan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:43:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(snan) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:47: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:52:define float @ret_frexp_f32_0_noqnan(float nofpclass(qnan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:53:; CHECK-LABEL: define nofpclass(sub) float @ret_frexp_f32_0_noqnan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:55:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(qnan) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:59: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:64:define i32 @ret_frexp_f32_1_nonan(float nofpclass(nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:65:; CHECK-LABEL: define i32 @ret_frexp_f32_1_nonan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:67:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(nan) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:71: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:76:define <2 x float> @ret_frexp_v2f32_0_nonan(<2 x float> nofpclass(nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:77:; CHECK-LABEL: define nofpclass(nan sub) <2 x float> @ret_frexp_v2f32_0_nonan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:79:; CHECK-NEXT: [[CALL:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> nofpclass(nan) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:83: %call = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:88:define <2 x i32> @ret_frexp_v2f32_1_nonan(<2 x float> nofpclass(nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:89:; CHECK-LABEL: define <2 x i32> @ret_frexp_v2f32_1_nonan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:91:; CHECK-NEXT: [[CALL:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> nofpclass(nan) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:95: %call = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:100:define float @ret_frexp_v4f32_0_nonan_elt1(<4 x float> nofpclass(nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:101:; CHECK-LABEL: define nofpclass(nan sub) float @ret_frexp_v4f32_0_nonan_elt1
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:103:; CHECK-NEXT: [[CALL:%.*]] = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> nofpclass(nan) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:108: %call = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:114:define float @ret_frexp_f32_0_nopos_nopzero(float nofpclass(pinf psub pnorm pzero) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:115:; CHECK-LABEL: define nofpclass(pinf pzero sub pnorm) float @ret_frexp_f32_0_nopos_nopzero
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:117:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(pinf pzero psub pnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:121: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:126:define float @ret_frexp_f32_0_nopos_nopzero_nonan(float nofpclass(pinf psub pnorm pzero nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:127:; CHECK-LABEL: define nofpclass(nan pinf pzero sub pnorm) float @ret_frexp_f32_0_nopos_nopzero_nonan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:129:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(nan pinf pzero psub pnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:133: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:138:define float @ret_frexp_f32_0_nopos(float nofpclass(pinf psub pnorm) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:139:; CHECK-LABEL: define nofpclass(pinf sub) float @ret_frexp_f32_0_nopos
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:141:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(pinf psub pnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:145: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:150:define float @ret_frexp_f32_0_nopos_nonan(float nofpclass(pinf psub pnorm nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:151:; CHECK-LABEL: define nofpclass(nan pinf sub) float @ret_frexp_f32_0_nopos_nonan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:153:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(nan pinf psub pnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:157: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:162:define float @ret_frexp_f32_0_nopos_nozero(float nofpclass(pinf psub pnorm zero) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:163:; CHECK-LABEL: define nofpclass(pinf zero sub pnorm) float @ret_frexp_f32_0_nopos_nozero
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:165:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(pinf zero psub pnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:169: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:174:define float @ret_frexp_f32_0_noneg_nonzero(float nofpclass(ninf nsub nnorm nzero) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:175:; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_frexp_f32_0_noneg_nonzero
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:177:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(ninf nzero nsub nnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:181: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:186:define float @ret_frexp_f32_0_noneg_nonzero_nonan(float nofpclass(ninf nsub nnorm nzero nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:187:; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) float @ret_frexp_f32_0_noneg_nonzero_nonan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:189:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(nan ninf nzero nsub nnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:193: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:198:define float @ret_frexp_f32_0_noneg(float nofpclass(ninf nsub nnorm) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:199:; CHECK-LABEL: define nofpclass(ninf sub) float @ret_frexp_f32_0_noneg
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:201:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(ninf nsub nnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:205: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:210:define float @ret_frexp_f32_0_noneg_nonan(float nofpclass(ninf nsub nnorm nan) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:211:; CHECK-LABEL: define nofpclass(nan ninf sub) float @ret_frexp_f32_0_noneg_nonan
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:213:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(nan ninf nsub nnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:217: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:222:define float @ret_frexp_f32_0_noneg_nozero(float nofpclass(ninf nsub nnorm nzero) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:223:; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_frexp_f32_0_noneg_nozero
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:225:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(ninf nzero nsub nnorm) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:229: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:234:define float @ret_frexp_f32_0_nopzero(float nofpclass(pzero) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:235:; CHECK-LABEL: define nofpclass(pzero sub) float @ret_frexp_f32_0_nopzero
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:237:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(pzero) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:241: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:246:define float @ret_frexp_f32_0_nonzero(float nofpclass(nzero) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:247:; CHECK-LABEL: define nofpclass(nzero sub) float @ret_frexp_f32_0_nonzero
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:249:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(nzero) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:253: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:258:define float @ret_frexp_f32_0_nozero(float nofpclass(zero) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:259:; CHECK-LABEL: define nofpclass(zero sub) float @ret_frexp_f32_0_nozero
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:261:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(zero) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:265: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:270:define float @ret_frexp_f32_0_nopinf(float nofpclass(pinf) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:271:; CHECK-LABEL: define nofpclass(pinf sub) float @ret_frexp_f32_0_nopinf
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:273:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(pinf) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:277: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:282:define float @ret_frexp_f32_0_noninf(float nofpclass(ninf) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:283:; CHECK-LABEL: define nofpclass(ninf sub) float @ret_frexp_f32_0_noninf
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:285:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(ninf) [[ARG0]]) #[[ATTR7]]
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:289: %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0)
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:294:define float @ret_frexp_f32_0_noinf(float nofpclass(inf) %arg0) {
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:295:; CHECK-LABEL: define nofpclass(inf sub) float @ret_frexp_f32_0_noinf
llvm/test/Transforms/Attributor/nofpclass-frexp.ll:297:; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float nofpclass(inf) [[ARG0]]) #[[ATTR7]]
... (truncated, total 29012 lines){"inst":"llvm.frexp"}.. _int_frexp:
'``llvm.frexp.*``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
This is an overloaded intrinsic. You can use ``llvm.frexp`` on any
floating point or vector of floating point type. Not all targets support
all types however.
::
declare { float, i32 } @llvm.frexp.f32.i32(float %Val)
declare { double, i32 } @llvm.frexp.f64.i32(double %Val)
declare { x86_fp80, i32 } @llvm.frexp.f80.i32(x86_fp80 %Val)
declare { fp128, i32 } @llvm.frexp.f128.i32(fp128 %Val)
declare { ppc_fp128, i32 } @llvm.frexp.ppcf128.i32(ppc_fp128 %Val)
declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %Val)
Overview:
"""""""""
The '``llvm.frexp.*``' intrinsics perform the frexp function.
Arguments:
""""""""""
The argument is a :ref:`floating-point <t_floating>` or
:ref:`vector <t_vector>` of floating-point values. Returns two values
in a struct. The first struct field matches the argument type, and the
second field is an integer or a vector of integer values with the same
number of elements as the argument.
Semantics:
""""""""""
This intrinsic splits a floating point value into a normalized
fractional component and integral exponent.
For a non-zero argument, returns the argument multiplied by some power
of two such that the absolute value of the returned value is in the
range [0.5, 1.0), with the same sign as the argument. The second
result is an integer such that the first result raised to the power of
the second result is the input argument.
If the argument is a zero, returns a zero with the same sign and a 0
exponent.
If the argument is a NaN, a NaN is returned and the returned exponent
is unspecified.
If the argument is an infinity, returns an infinity with the same sign
and an unspecified exponent.{"inst":"llvm.ldexp"}.. _int_exp10:
'``llvm.exp10.*``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
This is an overloaded intrinsic. You can use ``llvm.exp10`` on any
floating-point or vector of floating-point type. Not all targets support
all types however.
::
declare float @llvm.exp10.f32(float %Val)
declare double @llvm.exp10.f64(double %Val)
declare x86_fp80 @llvm.exp10.f80(x86_fp80 %Val)
declare fp128 @llvm.exp10.f128(fp128 %Val)
declare ppc_fp128 @llvm.exp10.ppcf128(ppc_fp128 %Val)
Overview:
"""""""""
The '``llvm.exp10.*``' intrinsics compute the base-10 exponential of the
specified value.
Arguments:
""""""""""
The argument and return value are floating-point numbers of the same type.
Semantics:
""""""""""
Return the same value as a corresponding libm '``exp10``' function but without
trapping or setting ``errno``.
When specified with the fast-math-flag 'afn', the result may be approximated
using a less accurate calculation.
'``llvm.ldexp.*``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
This is an overloaded intrinsic. You can use ``llvm.ldexp`` on any
floating point or vector of floating point type. Not all targets support
all types however.
::
declare float @llvm.ldexp.f32.i32(float %Val, i32 %Exp)
declare double @llvm.ldexp.f64.i32(double %Val, i32 %Exp)
declare x86_fp80 @llvm.ldexp.f80.i32(x86_fp80 %Val, i32 %Exp)
declare fp128 @llvm.ldexp.f128.i32(fp128 %Val, i32 %Exp)
declare ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 %Val, i32 %Exp)
declare <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %Val, <2 x i32> %Exp)
Overview:
"""""""""
The '``llvm.ldexp.*``' intrinsics perform the ldexp function.
Arguments:
""""""""""
The first argument and the return value are :ref:`floating-point
<t_floating>` or :ref:`vector <t_vector>` of floating-point values of
the same type. The second argument is an integer with the same number
of elements.
Semantics:
""""""""""
This function multiplies the first argument by 2 raised to the second
argument's power. If the first argument is NaN or infinite, the same
value is returned. If the result underflows a zero with the same sign
is returned. If the result overflows, the result is an infinity with
the same sign.{"file":"llvm/lib/Analysis/ValueTracking.cpp","position":1020}file: llvm/lib/Analysis/ValueTracking.cpp:1020-1270
---------------------------------------------------
1020 if (cast<TruncInst>(Cond)->hasNoUnsignedWrap()) {
1021 Known = Known.unionWith(DstKnown.zext(Known.getBitWidth()));
1022 return;
1023 }
1024 Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth()));
1025 return;
1026 }
1027
1028 if (Depth < MaxAnalysisRecursionDepth && match(Cond, m_Not(m_Value(A))))
1029 computeKnownBitsFromCond(V, A, Known, SQ, !Invert, Depth + 1);
1030 }
1031
1032 void llvm::computeKnownBitsFromContext(const Value *V, KnownBits &Known,
1033 const SimplifyQuery &Q, unsigned Depth) {
1034 // Handle injected condition.
1035 if (Q.CC && Q.CC->AffectedValues.contains(V))
1036 computeKnownBitsFromCond(V, Q.CC->Cond, Known, Q, Q.CC->Invert, Depth);
1037
1038 if (!Q.CxtI)
1039 return;
1040
1041 if (Q.DC && Q.DT) {
1042 // Handle dominating conditions.
1043 for (CondBrInst *BI : Q.DC->conditionsFor(V)) {
1044 BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
1045 if (Q.DT->dominates(Edge0, Q.CxtI->getParent()))
1046 computeKnownBitsFromCond(V, BI->getCondition(), Known, Q,
1047 /*Invert*/ false, Depth);
1048
1049 BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
1050 if (Q.DT->dominates(Edge1, Q.CxtI->getParent()))
1051 computeKnownBitsFromCond(V, BI->getCondition(), Known, Q,
1052 /*Invert*/ true, Depth);
1053 }
1054
1055 if (Known.hasConflict())
1056 Known.resetAll();
1057 }
1058
1059 if (!Q.AC)
1060 return;
1061
1062 unsigned BitWidth = Known.getBitWidth();
1063
1064 // Note that the patterns below need to be kept in sync with the code
1065 // in AssumptionCache::updateAffectedValues.
1066
1067 for (AssumptionCache::ResultElem &Elem : Q.AC->assumptionsFor(V)) {
1068 if (!Elem.Assume)
1069 continue;
1070
1071 AssumeInst *I = cast<AssumeInst>(Elem.Assume);
1072 assert(I->getParent()->getParent() == Q.CxtI->getParent()->getParent() &&
1073 "Got assumption for the wrong function!");
1074
1075 if (Elem.Index != AssumptionCache::ExprResultIdx) {
1076 if (auto OBU = I->getOperandBundleAt(Elem.Index);
1077 getBundleAttrFromOBU(OBU) == BundleAttr::Align) {
1078 auto [Ptr, _, _2, Alignment, Offset] = getAssumeAlignInfo(OBU);
1079 if (Ptr == V && Alignment && Offset && isPowerOf2_64(*Alignment) &&
1080 isValidAssumeForContext(I, Q)) {
1081 Known.Zero |= (*Alignment - 1) & ~*Offset;
1082 Known.One |= (*Alignment - 1) & *Offset;
1083 }
1084 }
1085 continue;
1086 }
1087
1088 // Warning: This loop can end up being somewhat performance sensitive.
1089 // We're running this loop for once for each value queried resulting in a
1090 // runtime of ~O(#assumes * #values).
1091
1092 Value *Arg = I->getArgOperand(0);
1093
1094 if (Arg == V && isValidAssumeForContext(I, Q)) {
1095 assert(BitWidth == 1 && "assume operand is not i1?");
1096 (void)BitWidth;
1097 Known.setAllOnes();
1098 return;
1099 }
1100 if (match(Arg, m_Not(m_Specific(V))) &&
1101 isValidAssumeForContext(I, Q)) {
1102 assert(BitWidth == 1 && "assume operand is not i1?");
1103 (void)BitWidth;
1104 Known.setAllZero();
1105 return;
1106 }
1107 auto *Trunc = dyn_cast<TruncInst>(Arg);
1108 if (Trunc && Trunc->getOperand(0) == V &&
1109 isValidAssumeForContext(I, Q)) {
1110 if (Trunc->hasNoUnsignedWrap()) {
1111 Known = KnownBits::makeConstant(APInt(BitWidth, 1));
1112 return;
1113 }
1114 Known.One.setBit(0);
1115 return;
1116 }
1117
1118 // The remaining tests are all recursive, so bail out if we hit the limit.
1119 if (Depth == MaxAnalysisRecursionDepth)
1120 continue;
1121
1122 ICmpInst *Cmp = dyn_cast<ICmpInst>(Arg);
1123 if (!Cmp)
1124 continue;
1125
1126 if (!isValidAssumeForContext(I, Q))
1127 continue;
1128
1129 computeKnownBitsFromICmpCond(V, Cmp, Known, Q, /*Invert=*/false);
1130 }
1131
1132 // Conflicting assumption: Undefined behavior will occur on this execution
1133 // path.
1134 if (Known.hasConflict())
1135 Known.resetAll();
1136 }
1137
1138 /// Compute known bits from a shift operator, including those with a
1139 /// non-constant shift amount. Known is the output of this function. Known2 is a
1140 /// pre-allocated temporary with the same bit width as Known and on return
1141 /// contains the known bit of the shift value source. KF is an
1142 /// operator-specific function that, given the known-bits and a shift amount,
1143 /// compute the implied known-bits of the shift operator's result respectively
1144 /// for that shift amount. The results from calling KF are conservatively
1145 /// combined for all permitted shift amounts.
1146 static void computeKnownBitsFromShiftOperator(
1147 const Operator *I, const APInt &DemandedElts, KnownBits &Known,
1148 KnownBits &Known2, const SimplifyQuery &Q, unsigned Depth,
1149 function_ref<KnownBits(const KnownBits &, const KnownBits &, bool)> KF) {
1150 computeKnownBits(I->getOperand(0), DemandedElts, Known2, Q, Depth + 1);
1151 computeKnownBits(I->getOperand(1), DemandedElts, Known, Q, Depth + 1);
1152 // To limit compile-time impact, only query isKnownNonZero() if we know at
1153 // least something about the shift amount.
1154 bool ShAmtNonZero =
1155 Known.isNonZero() ||
1156 (Known.getMaxValue().ult(Known.getBitWidth()) &&
1157 isKnownNonZero(I->getOperand(1), DemandedElts, Q, Depth + 1));
1158 Known = KF(Known2, Known, ShAmtNonZero);
1159 }
1160
1161 static KnownBits
1162 getKnownBitsFromAndXorOr(const Operator *I, const APInt &DemandedElts,
1163 const KnownBits &KnownLHS, const KnownBits &KnownRHS,
1164 const SimplifyQuery &Q, unsigned Depth) {
1165 unsigned BitWidth = KnownLHS.getBitWidth();
1166 KnownBits KnownOut(BitWidth);
1167 bool IsAnd = false;
1168 bool HasKnownOne = !KnownLHS.One.isZero() || !KnownRHS.One.isZero();
1169 Value *X = nullptr, *Y = nullptr;
1170
1171 switch (I->getOpcode()) {
1172 case Instruction::And:
1173 KnownOut = KnownLHS & KnownRHS;
1174 IsAnd = true;
1175 // and(x, -x) is common idioms that will clear all but lowest set
1176 // bit. If we have a single known bit in x, we can clear all bits
1177 // above it.
1178 // TODO: instcombine often reassociates independent `and` which can hide
1179 // this pattern. Try to match and(x, and(-x, y)) / and(and(x, y), -x).
1180 if (HasKnownOne && match(I, m_c_And(m_Value(X), m_Neg(m_Deferred(X))))) {
1181 // -(-x) == x so using whichever (LHS/RHS) gets us a better result.
1182 if (KnownLHS.countMaxTrailingZeros() <= KnownRHS.countMaxTrailingZeros())
1183 KnownOut = KnownLHS.blsi();
1184 else
1185 KnownOut = KnownRHS.blsi();
1186 }
1187 break;
1188 case Instruction::Or:
1189 KnownOut = KnownLHS | KnownRHS;
1190 break;
1191 case Instruction::Xor:
1192 KnownOut = KnownLHS ^ KnownRHS;
1193 // xor(x, x-1) is common idioms that will clear all but lowest set
1194 // bit. If we have a single known bit in x, we can clear all bits
1195 // above it.
1196 // TODO: xor(x, x-1) is often rewritting as xor(x, x-C) where C !=
1197 // -1 but for the purpose of demanded bits (xor(x, x-C) &
1198 // Demanded) == (xor(x, x-1) & Demanded). Extend the xor pattern
1199 // to use arbitrary C if xor(x, x-C) as the same as xor(x, x-1).
1200 if (HasKnownOne &&
1201 match(I, m_c_Xor(m_Value(X), m_Add(m_Deferred(X), m_AllOnes())))) {
1202 const KnownBits &XBits = I->getOperand(0) == X ? KnownLHS : KnownRHS;
1203 KnownOut = XBits.blsmsk();
1204 }
1205 break;
1206 default:
1207 llvm_unreachable("Invalid Op used in 'analyzeKnownBitsFromAndXorOr'");
1208 }
1209
1210 // and(x, add (x, -1)) is a common idiom that always clears the low bit;
1211 // xor/or(x, add (x, -1)) is an idiom that will always set the low bit.
1212 // here we handle the more general case of adding any odd number by
1213 // matching the form and/xor/or(x, add(x, y)) where y is odd.
1214 // TODO: This could be generalized to clearing any bit set in y where the
1215 // following bit is known to be unset in y.
1216 if (!KnownOut.Zero[0] && !KnownOut.One[0] &&
1217 (match(I, m_c_BinOp(m_Value(X), m_c_Add(m_Deferred(X), m_Value(Y)))) ||
1218 match(I, m_c_BinOp(m_Value(X), m_Sub(m_Deferred(X), m_Value(Y)))) ||
1219 match(I, m_c_BinOp(m_Value(X), m_Sub(m_Value(Y), m_Deferred(X)))))) {
1220 KnownBits KnownY(BitWidth);
1221 computeKnownBits(Y, DemandedElts, KnownY, Q, Depth + 1);
1222 if (KnownY.countMinTrailingOnes() > 0) {
1223 if (IsAnd)
1224 KnownOut.Zero.setBit(0);
1225 else
1226 KnownOut.One.setBit(0);
1227 }
1228 }
1229 return KnownOut;
1230 }
1231
1232 static KnownBits computeKnownBitsForHorizontalOperation(
1233 const Operator *I, const APInt &DemandedElts, const SimplifyQuery &Q,
1234 unsigned Depth,
1235 const function_ref<KnownBits(const KnownBits &, const KnownBits &)>
1236 KnownBitsFunc) {
1237 APInt DemandedEltsLHS, DemandedEltsRHS;
1238 getHorizDemandedEltsForFirstOperand(Q.DL.getTypeSizeInBits(I->getType()),
1239 DemandedElts, DemandedEltsLHS,
1240 DemandedEltsRHS);
1241
1242 const auto ComputeForSingleOpFunc =
1243 [Depth, &Q, KnownBitsFunc](const Value *Op, APInt &DemandedEltsOp) {
1244 return KnownBitsFunc(
1245 computeKnownBits(Op, DemandedEltsOp, Q, Depth + 1),
1246 computeKnownBits(Op, DemandedEltsOp << 1, Q, Depth + 1));
1247 };
1248
1249 if (DemandedEltsRHS.isZero())
1250 return ComputeForSingleOpFunc(I->getOperand(0), DemandedEltsLHS);
1251 if (DemandedEltsLHS.isZero())
1252 return ComputeForSingleOpFunc(I->getOperand(1), DemandedEltsRHS);
1253
1254 return ComputeForSingleOpFunc(I->getOperand(0), DemandedEltsLHS)
1255 .intersectWith(ComputeForSingleOpFunc(I->getOperand(1), DemandedEltsRHS));
1256 }
1257
1258 // Public so this can be used in `SimplifyDemandedUseBits`.
1259 KnownBits llvm::analyzeKnownBitsFromAndXorOr(const Operator *I,
1260 const KnownBits &KnownLHS,
1261 const KnownBits &KnownRHS,
1262 const SimplifyQuery &SQ,
1263 unsigned Depth) {
1264 auto *FVTy = dyn_cast<FixedVectorType>(I->getType());
1265 APInt DemandedElts =
1266 FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
1267
1268 return getKnownBitsFromAndXorOr(I, DemandedElts, KnownLHS, KnownRHS, SQ,
1269 Depth);
---------------------------------------------------{"file":"llvm/lib/Analysis/ValueTracking.cpp","position":4840}file: llvm/lib/Analysis/ValueTracking.cpp:4840-5090
---------------------------------------------------
4840 Depth + 1);
4841 return;
4842 }
4843 CmpPredicate Pred;
4844 Value *LHS;
4845 uint64_t ClassVal = 0;
4846 const APFloat *CRHS;
4847 const APInt *RHS;
4848 if (match(Cond, m_FCmp(Pred, m_Value(LHS), m_APFloat(CRHS)))) {
4849 auto [CmpVal, MaskIfTrue, MaskIfFalse] = fcmpImpliesClass(
4850 Pred, *cast<Instruction>(Cond)->getParent()->getParent(), LHS, *CRHS,
4851 LHS != V);
4852 if (CmpVal == V)
4853 KnownFromContext.knownNot(~(CondIsTrue ? MaskIfTrue : MaskIfFalse));
4854 } else if (match(Cond, m_Intrinsic<Intrinsic::is_fpclass>(
4855 m_Specific(V), m_ConstantInt(ClassVal)))) {
4856 FPClassTest Mask = static_cast<FPClassTest>(ClassVal);
4857 KnownFromContext.knownNot(CondIsTrue ? ~Mask : Mask);
4858 } else if (match(Cond, m_ICmp(Pred, m_ElementWiseBitCast(m_Specific(V)),
4859 m_APInt(RHS)))) {
4860 bool TrueIfSigned;
4861 if (!isSignBitCheck(Pred, *RHS, TrueIfSigned))
4862 return;
4863 if (TrueIfSigned == CondIsTrue)
4864 KnownFromContext.signBitMustBeOne();
4865 else
4866 KnownFromContext.signBitMustBeZero();
4867 }
4868 }
4869
4870 /// Compute the minimum and maximum values (inclusive) for the exponent of \p V,
4871 /// assuming it is not nan.
4872 static std::pair<int, int>
4873 computeKnownExponentRangeFromContext(const Value *V, const SimplifyQuery &Q) {
4874 if (!Q.CxtI || !Q.DC || !Q.DT)
4875 return {APFloat::IEK_NaN, APFloat::IEK_Inf};
4876
4877 for (CondBrInst *BI : Q.DC->conditionsFor(V)) {
4878 CmpPredicate Pred;
4879 const APFloat *LimitC;
4880 if (!match(BI->getCondition(),
4881 m_FCmp(Pred, m_FAbs(m_Specific(V)), m_Finite(LimitC))))
4882 continue;
4883
4884 if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO ||
4885 Pred == FCmpInst::FCMP_TRUE || Pred == FCmpInst::FCMP_FALSE)
4886 continue;
4887
4888 APFloat::cmpResult CmpOne =
4889 LimitC->compare(APFloat::getOne(LimitC->getSemantics()));
4890 if (CmpOne > APFloat::cmpEqual)
4891 continue;
4892
4893 // If fabs(x) <= K, K <= 1.0 => exponent min exp range
4894 // if fabs(x) >= K, K <= 1.0 swap the successor
4895 bool IsLessEqual =
4896 Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE ||
4897 Pred == FCmpInst::FCMP_ULT || Pred == FCmpInst::FCMP_ULE ||
4898 Pred == FCmpInst::FCMP_OEQ || Pred == FCmpInst::FCMP_UEQ;
4899
4900 BasicBlockEdge Edge1(BI->getParent(),
4901 BI->getSuccessor(IsLessEqual ? 0 : 1));
4902 if (Q.DT->dominates(Edge1, Q.CxtI->getParent())) {
4903 int Exp = ilogb(*LimitC);
4904
4905 // TODO: Figure out lower bound to detect no-underflow.
4906 return {APFloat::IEK_NaN, Exp};
4907 }
4908 }
4909
4910 return {APFloat::IEK_NaN, APFloat::IEK_Inf};
4911 }
4912
4913 static KnownFPClass computeKnownFPClassFromContext(const Value *V,
4914 const SimplifyQuery &Q) {
4915 KnownFPClass KnownFromContext;
4916
4917 if (Q.CC && Q.CC->AffectedValues.contains(V))
4918 computeKnownFPClassFromCond(V, Q.CC->Cond, !Q.CC->Invert, Q.CxtI,
4919 KnownFromContext);
4920
4921 if (!Q.CxtI)
4922 return KnownFromContext;
4923
4924 if (Q.DC && Q.DT) {
4925 // Handle dominating conditions.
4926 for (CondBrInst *BI : Q.DC->conditionsFor(V)) {
4927 Value *Cond = BI->getCondition();
4928
4929 BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
4930 if (Q.DT->dominates(Edge0, Q.CxtI->getParent()))
4931 computeKnownFPClassFromCond(V, Cond, /*CondIsTrue=*/true, Q.CxtI,
4932 KnownFromContext);
4933
4934 BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
4935 if (Q.DT->dominates(Edge1, Q.CxtI->getParent()))
4936 computeKnownFPClassFromCond(V, Cond, /*CondIsTrue=*/false, Q.CxtI,
4937 KnownFromContext);
4938 }
4939 }
4940
4941 if (!Q.AC)
4942 return KnownFromContext;
4943
4944 // Try to restrict the floating-point classes based on information from
4945 // assumptions.
4946 for (auto &AssumeVH : Q.AC->assumptionsFor(V)) {
4947 if (!AssumeVH)
4948 continue;
4949 CallInst *I = cast<CallInst>(AssumeVH);
4950
4951 assert(I->getFunction() == Q.CxtI->getParent()->getParent() &&
4952 "Got assumption for the wrong function!");
4953 assert(I->getIntrinsicID() == Intrinsic::assume &&
4954 "must be an assume intrinsic");
4955
4956 if (!isValidAssumeForContext(I, Q))
4957 continue;
4958
4959 computeKnownFPClassFromCond(V, I->getArgOperand(0),
4960 /*CondIsTrue=*/true, Q.CxtI, KnownFromContext);
4961 }
4962
4963 return KnownFromContext;
4964 }
4965
4966 void llvm::adjustKnownFPClassForSelectArm(KnownFPClass &Known, Value *Cond,
4967 Value *Arm, bool Invert,
4968 const SimplifyQuery &SQ,
4969 unsigned Depth) {
4970
4971 KnownFPClass KnownSrc;
4972 computeKnownFPClassFromCond(Arm, Cond,
4973 /*CondIsTrue=*/!Invert, SQ.CxtI, KnownSrc,
4974 Depth + 1);
4975 KnownSrc = KnownSrc.unionWith(Known);
4976 if (KnownSrc.isUnknown())
4977 return;
4978
4979 if (isGuaranteedNotToBeUndef(Arm, SQ.AC, SQ.CxtI, SQ.DT, Depth + 1))
4980 Known = KnownSrc;
4981 }
4982
4983 void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
4984 FPClassTest InterestedClasses, KnownFPClass &Known,
4985 const SimplifyQuery &Q, unsigned Depth);
4986
4987 static void computeKnownFPClass(const Value *V, KnownFPClass &Known,
4988 FPClassTest InterestedClasses,
4989 const SimplifyQuery &Q, unsigned Depth) {
4990 auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
4991 APInt DemandedElts =
4992 FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
4993 computeKnownFPClass(V, DemandedElts, InterestedClasses, Known, Q, Depth);
4994 }
4995
4996 static void computeKnownFPClassForFPTrunc(const Operator *Op,
4997 const APInt &DemandedElts,
4998 FPClassTest InterestedClasses,
4999 KnownFPClass &Known,
5000 const SimplifyQuery &Q,
5001 unsigned Depth) {
5002 if ((InterestedClasses &
5003 (KnownFPClass::OrderedLessThanZeroMask | fcNan)) == fcNone)
5004 return;
5005
5006 KnownFPClass KnownSrc;
5007 computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedClasses,
5008 KnownSrc, Q, Depth + 1);
5009 Known = KnownFPClass::fptrunc(KnownSrc);
5010 }
5011
5012 static constexpr KnownFPClass::MinMaxKind getMinMaxKind(Intrinsic::ID IID) {
5013 switch (IID) {
5014 case Intrinsic::minimum:
5015 return KnownFPClass::MinMaxKind::minimum;
5016 case Intrinsic::maximum:
5017 return KnownFPClass::MinMaxKind::maximum;
5018 case Intrinsic::minimumnum:
5019 return KnownFPClass::MinMaxKind::minimumnum;
5020 case Intrinsic::maximumnum:
5021 return KnownFPClass::MinMaxKind::maximumnum;
5022 case Intrinsic::minnum:
5023 return KnownFPClass::MinMaxKind::minnum;
5024 case Intrinsic::maxnum:
5025 return KnownFPClass::MinMaxKind::maxnum;
5026 default:
5027 llvm_unreachable("not a floating-point min-max intrinsic");
5028 }
5029 }
5030
5031 /// \return true if this is a floating point value that is known to have a
5032 /// magnitude smaller than 1. i.e., fabs(X) <= 1.0 or is nan.
5033 static bool isAbsoluteValueULEOne(const Value *V) {
5034 // TODO: Handle frexp
5035 // TODO: Other rounding intrinsics?
5036 // TODO: Try computeKnownExponentRangeFromContext
5037
5038 // fabs(x - floor(x)) <= 1
5039 const Value *SubFloorX;
5040 if (match(V, m_FSub(m_Value(SubFloorX),
5041 m_Intrinsic<Intrinsic::floor>(m_Deferred(SubFloorX)))))
5042 return true;
5043
5044 return match(V, m_Intrinsic<Intrinsic::amdgcn_trig_preop>(m_Value())) ||
5045 match(V, m_Intrinsic<Intrinsic::amdgcn_fract>(m_Value()));
5046 }
5047
5048 void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
5049 FPClassTest InterestedClasses, KnownFPClass &Known,
5050 const SimplifyQuery &Q, unsigned Depth) {
5051 assert(Known.isUnknown() && "should not be called with known information");
5052
5053 if (!DemandedElts) {
5054 // No demanded elts, better to assume we don't know anything.
5055 Known.resetAll();
5056 return;
5057 }
5058
5059 assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
5060
5061 if (auto *CFP = dyn_cast<ConstantFP>(V)) {
5062 Known = KnownFPClass(CFP->getValueAPF());
5063 return;
5064 }
5065
5066 if (isa<ConstantAggregateZero>(V)) {
5067 Known.KnownFPClasses = fcPosZero;
5068 Known.SignBit = false;
5069 return;
5070 }
5071
5072 if (isa<PoisonValue>(V)) {
5073 Known.KnownFPClasses = fcNone;
5074 Known.SignBit = false;
5075 return;
5076 }
5077
5078 // Try to handle fixed width vector constants
5079 auto *VFVTy = dyn_cast<FixedVectorType>(V->getType());
5080 const Constant *CV = dyn_cast<Constant>(V);
5081 if (VFVTy && CV) {
5082 Known.KnownFPClasses = fcNone;
5083 bool SignBitAllZero = true;
5084 bool SignBitAllOne = true;
5085
5086 // For vectors, verify that each element is not NaN.
5087 unsigned NumElts = VFVTy->getNumElements();
5088 for (unsigned i = 0; i != NumElts; ++i) {
5089 if (!DemandedElts[i])
---------------------------------------------------{"file":"llvm/lib/Analysis/ValueTracking.cpp","position":10470}file: llvm/lib/Analysis/ValueTracking.cpp:10470-10720
-----------------------------------------------------
10470 setLimitsForBinOp(*BO, Lower, Upper, SQ.IIQ, ForSigned);
10471 CR = ConstantRange::getNonEmpty(Lower, Upper);
10472 } else if (auto *II = dyn_cast<IntrinsicInst>(V))
10473 CR = getRangeForIntrinsic(*II, SQ.IIQ.UseInstrInfo);
10474 else if (auto *SI = dyn_cast<SelectInst>(V)) {
10475 ConstantRange CRTrue =
10476 computeConstantRange(SI->getTrueValue(), ForSigned, SQ, Depth + 1);
10477 ConstantRange CRFalse =
10478 computeConstantRange(SI->getFalseValue(), ForSigned, SQ, Depth + 1);
10479 CR = CRTrue.unionWith(CRFalse);
10480 CR = CR.intersectWith(getRangeForSelectPattern(*SI, SQ.IIQ));
10481 } else if (auto *TI = dyn_cast<TruncInst>(V)) {
10482 ConstantRange SrcCR =
10483 computeConstantRange(TI->getOperand(0), ForSigned, SQ, Depth + 1);
10484 CR = SrcCR.truncate(BitWidth);
10485 } else if (isa<FPToUIInst>(V) || isa<FPToSIInst>(V)) {
10486 APInt Lower = APInt(BitWidth, 0);
10487 APInt Upper = APInt(BitWidth, 0);
10488 // TODO: Return ConstantRange.
10489 setLimitForFPToI(cast<Instruction>(V), Lower, Upper);
10490 CR = ConstantRange::getNonEmpty(Lower, Upper);
10491 } else if (const auto *A = dyn_cast<Argument>(V))
10492 if (std::optional<ConstantRange> Range = A->getRange())
10493 CR = *Range;
10494
10495 if (auto *I = dyn_cast<Instruction>(V)) {
10496 if (auto *Range = SQ.IIQ.getMetadata(I, LLVMContext::MD_range))
10497 CR = CR.intersectWith(getConstantRangeFromMetadata(*Range));
10498
10499 Value *FrexpSrc;
10500 if (const auto *CB = dyn_cast<CallBase>(V)) {
10501 if (std::optional<ConstantRange> Range = CB->getRange())
10502 CR = CR.intersectWith(*Range);
10503 } else if (match(I, m_ExtractValue<1>(m_Intrinsic<Intrinsic::frexp>(
10504 m_Value(FrexpSrc))))) {
10505 const fltSemantics &FltSem =
10506 FrexpSrc->getType()->getScalarType()->getFltSemantics();
10507 // It should be possible to implement this for any type, but this logic
10508 // only computes the range assuming standard subnormal handling.
10509 if (APFloat::isIEEELikeFP(FltSem)) {
10510 KnownFPClass KnownSrc = computeKnownFPClass(
10511 FrexpSrc, fcSubnormal | fcNan | fcInf, SQ, Depth + 1);
10512
10513 // The exponent of frexp(NaN) and frexp(Inf) is unspecified. Only
10514 // constrain its range when the source can be neither.
10515 if (KnownSrc.isKnownNeverInfOrNaN()) {
10516 int MinExp = APFloat::semanticsMinExponent(FltSem) + 1;
10517
10518 // Offset to find the true minimum exponent value for a denormal.
10519 if (!KnownSrc.isKnownNeverSubnormal())
10520 MinExp -= (APFloat::semanticsPrecision(FltSem) - 1);
10521
10522 int MaxExp = APFloat::semanticsMaxExponent(FltSem) + 1;
10523
10524 auto [AdjustedMin, AdjustedMax] =
10525 computeKnownExponentRangeFromContext(FrexpSrc, SQ);
10526
10527 MinExp = std::max(AdjustedMin, MinExp);
10528 MaxExp = std::min(AdjustedMax, MaxExp);
10529
10530 CR = ConstantRange::getNonEmpty(
10531 APInt(BitWidth, static_cast<int64_t>(MinExp), /*isSigned=*/true),
10532 APInt(BitWidth, static_cast<int64_t>(MaxExp) + 1,
10533 /*isSigned=*/true));
10534 }
10535 }
10536 }
10537 }
10538
10539 if (SQ.CxtI && SQ.AC) {
10540 // Try to restrict the range based on information from assumptions.
10541 for (auto &AssumeVH : SQ.AC->assumptionsFor(V)) {
10542 if (!AssumeVH)
10543 continue;
10544 CallInst *I = cast<CallInst>(AssumeVH);
10545 assert(I->getParent()->getParent() == SQ.CxtI->getParent()->getParent() &&
10546 "Got assumption for the wrong function!");
10547 assert(I->getIntrinsicID() == Intrinsic::assume &&
10548 "must be an assume intrinsic");
10549
10550 if (!isValidAssumeForContext(I, SQ))
10551 continue;
10552 Value *Arg = I->getArgOperand(0);
10553 ICmpInst *Cmp = dyn_cast<ICmpInst>(Arg);
10554 // Currently we just use information from comparisons.
10555 if (!Cmp || Cmp->getOperand(0) != V)
10556 continue;
10557 // TODO: Set "ForSigned" parameter via Cmp->isSigned()?
10558 ConstantRange RHS =
10559 computeConstantRange(Cmp->getOperand(1), /*ForSigned=*/false,
10560 SQ.getWithInstruction(I), Depth + 1);
10561 CR = CR.intersectWith(
10562 ConstantRange::makeAllowedICmpRegion(Cmp->getCmpPredicate(), RHS));
10563 }
10564 }
10565
10566 return CR;
10567 }
10568
10569 static void
10570 addValueAffectedByCondition(Value *V,
10571 function_ref<void(Value *)> InsertAffected) {
10572 assert(V != nullptr);
10573 if (isa<Argument>(V) || isa<GlobalValue>(V)) {
10574 InsertAffected(V);
10575 } else if (auto *I = dyn_cast<Instruction>(V)) {
10576 InsertAffected(V);
10577
10578 // Peek through unary operators to find the source of the condition.
10579 Value *Op;
10580 if (match(I, m_CombineOr(m_PtrToIntOrAddr(m_Value(Op)),
10581 m_Trunc(m_Value(Op))))) {
10582 if (isa<Instruction>(Op) || isa<Argument>(Op))
10583 InsertAffected(Op);
10584 }
10585 }
10586 }
10587
10588 void llvm::findValuesAffectedByCondition(
10589 Value *Cond, bool IsAssume, function_ref<void(Value *)> InsertAffected) {
10590 auto AddAffected = [&InsertAffected](Value *V) {
10591 addValueAffectedByCondition(V, InsertAffected);
10592 };
10593
10594 auto AddCmpOperands = [&AddAffected, IsAssume](Value *LHS, Value *RHS) {
10595 if (IsAssume) {
10596 AddAffected(LHS);
10597 AddAffected(RHS);
10598 } else if (match(RHS, m_Constant()))
10599 AddAffected(LHS);
10600 };
10601
10602 SmallVector<Value *, 8> Worklist;
10603 SmallPtrSet<Value *, 8> Visited;
10604 Worklist.push_back(Cond);
10605 while (!Worklist.empty()) {
10606 Value *V = Worklist.pop_back_val();
10607 if (!Visited.insert(V).second)
10608 continue;
10609
10610 CmpPredicate Pred;
10611 Value *A, *B, *X;
10612
10613 if (IsAssume) {
10614 AddAffected(V);
10615 if (match(V, m_Not(m_Value(X))))
10616 AddAffected(X);
10617 }
10618
10619 if (match(V, m_LogicalOp(m_Value(A), m_Value(B)))) {
10620 // assume(A && B) is split to -> assume(A); assume(B);
10621 // assume(!(A || B)) is split to -> assume(!A); assume(!B);
10622 // Finally, assume(A || B) / assume(!(A && B)) generally don't provide
10623 // enough information to be worth handling (intersection of information as
10624 // opposed to union).
10625 if (!IsAssume) {
10626 Worklist.push_back(A);
10627 Worklist.push_back(B);
10628 }
10629 } else if (match(V, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
10630 bool HasRHSC = match(B, m_ConstantInt());
10631 if (ICmpInst::isEquality(Pred)) {
10632 AddAffected(A);
10633 if (IsAssume)
10634 AddAffected(B);
10635 if (HasRHSC) {
10636 Value *Y;
10637 // (X << C) or (X >>_s C) or (X >>_u C).
10638 if (match(A, m_Shift(m_Value(X), m_ConstantInt())))
10639 AddAffected(X);
10640 // (X & C) or (X | C).
10641 else if (match(A, m_And(m_Value(X), m_Value(Y))) ||
10642 match(A, m_Or(m_Value(X), m_Value(Y)))) {
10643 AddAffected(X);
10644 AddAffected(Y);
10645 }
10646 // X - Y
10647 else if (match(A, m_Sub(m_Value(X), m_Value(Y)))) {
10648 AddAffected(X);
10649 AddAffected(Y);
10650 }
10651 }
10652 } else {
10653 AddCmpOperands(A, B);
10654 if (HasRHSC) {
10655 // Handle (A + C1) u< C2, which is the canonical form of
10656 // A > C3 && A < C4.
10657 if (match(A, m_AddLike(m_Value(X), m_ConstantInt())))
10658 AddAffected(X);
10659
10660 if (ICmpInst::isUnsigned(Pred)) {
10661 Value *Y;
10662 // X & Y u> C -> X >u C && Y >u C
10663 // X | Y u< C -> X u< C && Y u< C
10664 // X nuw+ Y u< C -> X u< C && Y u< C
10665 if (match(A, m_And(m_Value(X), m_Value(Y))) ||
10666 match(A, m_Or(m_Value(X), m_Value(Y))) ||
10667 match(A, m_NUWAdd(m_Value(X), m_Value(Y)))) {
10668 AddAffected(X);
10669 AddAffected(Y);
10670 }
10671 // X nuw- Y u> C -> X u> C
10672 if (match(A, m_NUWSub(m_Value(X), m_Value())))
10673 AddAffected(X);
10674 }
10675 }
10676
10677 // Handle icmp slt/sgt (bitcast X to int), 0/-1, which is supported
10678 // by computeKnownFPClass().
10679 if (match(A, m_ElementWiseBitCast(m_Value(X)))) {
10680 if (Pred == ICmpInst::ICMP_SLT && match(B, m_Zero()))
10681 InsertAffected(X);
10682 else if (Pred == ICmpInst::ICMP_SGT && match(B, m_AllOnes()))
10683 InsertAffected(X);
10684 }
10685 }
10686
10687 if (HasRHSC && match(A, m_Ctpop(m_Value(X))))
10688 AddAffected(X);
10689 } else if (match(V, m_FCmp(Pred, m_Value(A), m_Value(B)))) {
10690 AddCmpOperands(A, B);
10691
10692 // fcmp fneg(x), y
10693 // fcmp fabs(x), y
10694 // fcmp fneg(fabs(x)), y
10695 if (match(A, m_FNeg(m_Value(A))))
10696 AddAffected(A);
10697 if (match(A, m_FAbs(m_Value(A))))
10698 AddAffected(A);
10699
10700 } else if (match(V, m_Intrinsic<Intrinsic::is_fpclass>(m_Value(A),
10701 m_Value()))) {
10702 // Handle patterns that computeKnownFPClass() support.
10703 AddAffected(A);
10704 } else if (!IsAssume && match(V, m_Trunc(m_Value(X)))) {
10705 // Assume is checked here as X is already added above for assumes in
10706 // addValueAffectedByCondition
10707 AddAffected(X);
10708 } else if (!IsAssume && match(V, m_Not(m_Value(X)))) {
10709 // Assume is checked here to avoid issues with ephemeral values
10710 Worklist.push_back(X);
10711 }
10712 }
10713 }
10714
10715 const Value *llvm::stripNullTest(const Value *V) {
10716 // (X >> C) or/add (X & mask(C) != 0)
10717 if (const auto *BO = dyn_cast<BinaryOperator>(V)) {
10718 if (BO->getOpcode() == Instruction::Add ||
10719 BO->getOpcode() == Instruction::Or) {
-----------------------------------------------------{"file":"llvm/lib/Support/KnownFPClass.cpp","position":760}file: llvm/lib/Support/KnownFPClass.cpp:760-915
-----------------------------------------------
760
761 return Known;
762 }
763
764 KnownFPClass KnownFPClass::frexp_mant(const KnownFPClass &KnownSrc,
765 DenormalMode Mode) {
766 KnownFPClass Known;
767 Known.knownNot(fcSubnormal);
768
769 if (KnownSrc.isKnownNever(fcNegative))
770 Known.knownNot(fcNegative);
771 else {
772 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
773 Known.knownNot(fcNegZero);
774 if (KnownSrc.isKnownNever(fcNegInf))
775 Known.knownNot(fcNegInf);
776 }
777
778 if (KnownSrc.isKnownNever(fcPositive))
779 Known.knownNot(fcPositive);
780 else {
781 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
782 Known.knownNot(fcPosZero);
783 if (KnownSrc.isKnownNever(fcPosInf))
784 Known.knownNot(fcPosInf);
785 }
786
787 Known.propagateNaN(KnownSrc);
788 return Known;
789 }
790
791 KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
792 const APInt &ConstantRangeExpMin,
793 const APInt &ConstantRangeExpMax,
794 const fltSemantics &Flt, DenormalMode Mode) {
795 KnownFPClass Known;
796 Known.propagateNaN(KnownSrc, /*PropagateSign=*/true);
797
798 // Sign is preserved, but underflows may produce zeroes.
799 if (KnownSrc.isKnownNever(fcNegative))
800 Known.knownNot(fcNegative);
801 else if (KnownSrc.cannotBeOrderedLessThanZero())
802 Known.knownNot(OrderedLessThanZeroMask);
803
804 if (KnownSrc.isKnownNever(fcPositive))
805 Known.knownNot(fcPositive);
806 else if (KnownSrc.cannotBeOrderedGreaterThanZero())
807 Known.knownNot(OrderedGreaterThanZeroMask);
808
809 unsigned Precision = APFloat::semanticsPrecision(Flt);
810 const int MantissaBits = Precision - 1;
811 if (ConstantRangeExpMin.sge(MantissaBits))
812 Known.knownNot(fcSubnormal);
813
814 if (ConstantRangeExpMin.isZero() && ConstantRangeExpMax.isZero()) {
815 // ldexp(x, 0) -> x, so propagate everything.
816 Known.propagateCanonicalizingSrc(KnownSrc, Mode);
817 } else if (ConstantRangeExpMax.isNonPositive()) {
818 // If we know the power is <= 0, can't introduce inf
819 if (KnownSrc.isKnownNeverPosInfinity())
820 Known.knownNot(fcPosInf);
821 if (KnownSrc.isKnownNeverNegInfinity())
822 Known.knownNot(fcNegInf);
823 } else if (ConstantRangeExpMin.isNonNegative()) {
824 // If we know the power is >= 0, can't introduce subnormal or zero
825 if (KnownSrc.isKnownNeverPosSubnormal())
826 Known.knownNot(fcPosSubnormal);
827 if (KnownSrc.isKnownNeverNegSubnormal())
828 Known.knownNot(fcNegSubnormal);
829 if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
830 Known.knownNot(fcPosZero);
831 if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
832 Known.knownNot(fcNegZero);
833 }
834
835 return Known;
836 }
837
838 KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
839 const KnownBits &ExpBits,
840 const fltSemantics &Flt, DenormalMode Mode) {
841 return ldexp(KnownSrc, ExpBits.getSignedMinValue(),
842 ExpBits.getSignedMaxValue(), Flt, Mode);
843 }
844
845 KnownFPClass KnownFPClass::powi(const KnownFPClass &KnownSrc,
846 const KnownBits &ExponentKnownBits) {
847 KnownFPClass Known;
848 Known.propagateNaN(KnownSrc);
849
850 if (ExponentKnownBits.isZero()) {
851 // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
852 // return 1.0 or a NaN.
853 if (KnownSrc.isKnownNever(fcSNan)) {
854 Known.knownNot(~fcPosNormal);
855 return Known;
856 }
857
858 Known.knownNot(~(fcPosNormal | fcNan));
859 return Known;
860 }
861
862 // powi(x, exp) --> inf
863 // when:
864 // * powi(inf, exp), exp > 0
865 // * powi(+/-0, exp), exp < 0
866 // * powi(finite, exp), |exp| > 1
867 // * powi(subnormal, -1)
868 // TODO:
869 // 1. This simple all or nothing approach. We can do better
870 // and cover sign/parity and exp > 1 vs exp < -1 separately.
871 // 2. powi(0/nan, exp), exp > 0 can be refinable
872 // to fcNan | fcZero | fcPosNormal.
873 {
874 APInt MinExp = ExponentKnownBits.getSignedMinValue();
875 APInt MaxExp = ExponentKnownBits.getSignedMaxValue();
876
877 // powi(inf, exp), exp > 0
878 bool MayInfSrc =
879 !KnownSrc.isKnownNever(fcInf) && MaxExp.isStrictlyPositive();
880
881 // powi(+/-0, exp), exp < 0
882 bool MayDivByZero = !KnownSrc.isKnownNever(fcZero) && MinExp.isNegative();
883
884 // powi(finite, exp), |exp| > 1
885 bool MayFinite = !KnownSrc.isKnownNever(fcNormal | fcSubnormal);
886 bool MayAbsExpGT1 = MinExp.slt(-1) || MaxExp.sgt(1);
887 bool MayFiniteOverflow = MayFinite && MayAbsExpGT1;
888
889 // powi(subnormal, -1)
890 bool MayBeNegOne = ExponentKnownBits.Zero.isZero();
891 bool MaySubnormInv = !KnownSrc.isKnownNever(fcSubnormal) && MayBeNegOne;
892
893 if (!MayInfSrc && !MayDivByZero && !MayFiniteOverflow && !MaySubnormInv)
894 Known.knownNot(fcInf);
895 }
896
897 if (ExponentKnownBits.isEven()) {
898 Known.knownNot(fcNegative);
899 return Known;
900 }
901
902 // Given that exp is an integer, here are the
903 // ways that pow can return a negative value:
904 //
905 // pow(-x, exp) --> negative if exp is odd and x is negative.
906 // pow(-0, exp) --> -inf if exp is negative odd.
907 // pow(-0, exp) --> -0 if exp is positive odd.
908 // pow(-inf, exp) --> -0 if exp is negative odd.
909 // pow(-inf, exp) --> -inf if exp is positive odd.
910 if (KnownSrc.isKnownNever(fcNegative))
911 Known.knownNot(fcNegative);
912
913 return Known;
914 }
-----------------------------------------------{"args":"-nRI 'IEK_Zero\\|enum.*IEK' llvm/include/llvm llvm/lib/Support","k":1}llvm/include/llvm/ADT/APFloat.h:1665:/// 0 -> \c IEK_Zero
llvm/include/llvm/ADT/APFloat.h:385: IEK_Zero = INT_MIN + 1,
llvm/lib/Support/APFloat.cpp:4599: return APFloat::IEK_Zero;
llvm/lib/Support/APFloat.cpp:4649: Exp = Exp == APFloat::IEK_Zero ? 0 : Exp + 1;
llvm/lib/Support/APFloat.cpp:5731: if (Exp == APFloat::IEK_Zero) {{"file":"llvm/include/llvm/ADT/APFloat.h","position":360}file: llvm/include/llvm/ADT/APFloat.h:360-610
---------------------------------------------
360 /// shall be a quiet NaN."
361 enum opStatus {
362 opOK = 0x00,
363 opInvalidOp = 0x01,
364 opDivByZero = 0x02,
365 opOverflow = 0x04,
366 opUnderflow = 0x08,
367 opInexact = 0x10
368 };
369
370 /// Category of internally-represented number.
371 enum fltCategory {
372 fcInfinity,
373 fcNaN,
374 fcNormal,
375 fcZero
376 };
377
378 /// Convenience enum used to construct an uninitialized APFloat.
379 enum uninitializedTag {
380 uninitialized
381 };
382
383 /// Enumeration of \c ilogb error results.
384 enum IlogbErrorKinds {
385 IEK_Zero = INT_MIN + 1,
386 IEK_NaN = INT_MIN,
387 IEK_Inf = INT_MAX
388 };
389
390 LLVM_ABI static unsigned int semanticsPrecision(const fltSemantics &);
391 LLVM_ABI static ExponentType semanticsMinExponent(const fltSemantics &);
392 LLVM_ABI static ExponentType semanticsMaxExponent(const fltSemantics &);
393 LLVM_ABI static unsigned int semanticsSizeInBits(const fltSemantics &);
394 LLVM_ABI static unsigned int semanticsIntSizeInBits(const fltSemantics &,
395 bool);
396 LLVM_ABI static bool semanticsHasZero(const fltSemantics &);
397 LLVM_ABI static bool semanticsHasSignedRepr(const fltSemantics &);
398 LLVM_ABI static bool semanticsHasInf(const fltSemantics &);
399 LLVM_ABI static bool semanticsHasNaN(const fltSemantics &);
400 LLVM_ABI static bool isIEEELikeFP(const fltSemantics &);
401 LLVM_ABI static bool hasSignBitInMSB(const fltSemantics &);
402
403 // Returns true if any number described by \p Src can be precisely represented
404 // by a normal (not subnormal) value in \p Dst.
405 LLVM_ABI static bool isRepresentableAsNormalIn(const fltSemantics &Src,
406 const fltSemantics &Dst);
407
408 /// Returns the size of the floating point number (in bits) in the given
409 /// semantics.
410 LLVM_ABI static unsigned getSizeInBits(const fltSemantics &Sem);
411
412 /// Returns true if the given string is a valid arbitrary floating-point
413 /// format interpretation for llvm.convert.to.arbitrary.fp and
414 /// llvm.convert.from.arbitrary.fp intrinsics.
415 LLVM_ABI static bool isValidArbitraryFPFormat(StringRef Format);
416
417 /// Returns the fltSemantics for a given arbitrary FP format string,
418 /// or nullptr if invalid.
419 LLVM_ABI static const fltSemantics *getArbitraryFPSemantics(StringRef Format);
420 };
421
422 namespace detail {
423
424 using integerPart = APFloatBase::integerPart;
425 using uninitializedTag = APFloatBase::uninitializedTag;
426 using roundingMode = APFloatBase::roundingMode;
427 using opStatus = APFloatBase::opStatus;
428 using cmpResult = APFloatBase::cmpResult;
429 using fltCategory = APFloatBase::fltCategory;
430 using ExponentType = APFloatBase::ExponentType;
431 static constexpr uninitializedTag uninitialized = APFloatBase::uninitialized;
432 static constexpr roundingMode rmNearestTiesToEven =
433 APFloatBase::rmNearestTiesToEven;
434 static constexpr roundingMode rmNearestTiesToAway =
435 APFloatBase::rmNearestTiesToAway;
436 static constexpr roundingMode rmTowardNegative = APFloatBase::rmTowardNegative;
437 static constexpr roundingMode rmTowardPositive = APFloatBase::rmTowardPositive;
438 static constexpr roundingMode rmTowardZero = APFloatBase::rmTowardZero;
439 static constexpr unsigned integerPartWidth = APFloatBase::integerPartWidth;
440 static constexpr cmpResult cmpEqual = APFloatBase::cmpEqual;
441 static constexpr cmpResult cmpLessThan = APFloatBase::cmpLessThan;
442 static constexpr cmpResult cmpGreaterThan = APFloatBase::cmpGreaterThan;
443 static constexpr cmpResult cmpUnordered = APFloatBase::cmpUnordered;
444 static constexpr opStatus opOK = APFloatBase::opOK;
445 static constexpr opStatus opInvalidOp = APFloatBase::opInvalidOp;
446 static constexpr opStatus opDivByZero = APFloatBase::opDivByZero;
447 static constexpr opStatus opOverflow = APFloatBase::opOverflow;
448 static constexpr opStatus opUnderflow = APFloatBase::opUnderflow;
449 static constexpr opStatus opInexact = APFloatBase::opInexact;
450 static constexpr fltCategory fcInfinity = APFloatBase::fcInfinity;
451 static constexpr fltCategory fcNaN = APFloatBase::fcNaN;
452 static constexpr fltCategory fcNormal = APFloatBase::fcNormal;
453 static constexpr fltCategory fcZero = APFloatBase::fcZero;
454
455 class IEEEFloat final {
456 public:
457 /// \name Constructors
458 /// @{
459
460 LLVM_ABI IEEEFloat(const fltSemantics &); // Default construct to +0.0
461 LLVM_ABI IEEEFloat(const fltSemantics &, integerPart);
462 LLVM_ABI IEEEFloat(const fltSemantics &, uninitializedTag);
463 LLVM_ABI IEEEFloat(const fltSemantics &, const APInt &);
464 LLVM_ABI explicit IEEEFloat(double d);
465 LLVM_ABI explicit IEEEFloat(float f);
466 LLVM_ABI IEEEFloat(const IEEEFloat &);
467 LLVM_ABI IEEEFloat(IEEEFloat &&);
468 LLVM_ABI ~IEEEFloat();
469
470 /// @}
471
472 /// Returns whether this instance allocated memory.
473 bool needsCleanup() const { return partCount() > 1; }
474
475 /// \name Convenience "constructors"
476 /// @{
477
478 /// @}
479
480 /// \name Arithmetic
481 /// @{
482
483 LLVM_ABI opStatus add(const IEEEFloat &, roundingMode);
484 LLVM_ABI opStatus subtract(const IEEEFloat &, roundingMode);
485 LLVM_ABI opStatus multiply(const IEEEFloat &, roundingMode);
486 LLVM_ABI opStatus divide(const IEEEFloat &, roundingMode);
487 /// IEEE remainder.
488 LLVM_ABI opStatus remainder(const IEEEFloat &);
489 /// C fmod, or llvm frem.
490 LLVM_ABI opStatus mod(const IEEEFloat &);
491 LLVM_ABI opStatus fusedMultiplyAdd(const IEEEFloat &, const IEEEFloat &,
492 roundingMode);
493 LLVM_ABI opStatus roundToIntegral(roundingMode);
494 /// IEEE-754R 5.3.1: nextUp/nextDown.
495 LLVM_ABI opStatus next(bool nextDown);
496
497 /// @}
498
499 /// \name Sign operations.
500 /// @{
501
502 LLVM_ABI void changeSign();
503
504 /// @}
505
506 /// \name Conversions
507 /// @{
508
509 LLVM_ABI opStatus convert(const fltSemantics &, roundingMode, bool *);
510 LLVM_ABI opStatus convertToInteger(MutableArrayRef<integerPart>, unsigned int,
511 bool, roundingMode, bool *) const;
512 LLVM_ABI opStatus convertFromAPInt(const APInt &, bool, roundingMode);
513 LLVM_ABI Expected<opStatus> convertFromString(StringRef, roundingMode);
514 LLVM_ABI APInt bitcastToAPInt() const;
515 LLVM_ABI double convertToDouble() const;
516 #ifdef HAS_IEE754_FLOAT128
517 LLVM_ABI float128 convertToQuad() const;
518 #endif
519 LLVM_ABI float convertToFloat() const;
520
521 /// @}
522
523 /// The definition of equality is not straightforward for floating point, so
524 /// we won't use operator==. Use one of the following, or write whatever it
525 /// is you really mean.
526 bool operator==(const IEEEFloat &) const = delete;
527
528 /// IEEE comparison with another floating point number (NaNs compare
529 /// unordered, 0==-0).
530 LLVM_ABI cmpResult compare(const IEEEFloat &) const;
531
532 /// Bitwise comparison for equality (QNaNs compare equal, 0!=-0).
533 LLVM_ABI bool bitwiseIsEqual(const IEEEFloat &) const;
534
535 /// Write out a hexadecimal representation of the floating point value to DST,
536 /// which must be of sufficient size, in the C99 form [-]0xh.hhhhp[+-]d.
537 /// Return the number of characters written, excluding the terminating NUL.
538 LLVM_ABI unsigned int convertToHexString(char *dst, unsigned int hexDigits,
539 bool upperCase, roundingMode) const;
540
541 /// \name IEEE-754R 5.7.2 General operations.
542 /// @{
543
544 /// IEEE-754R isSignMinus: Returns true if and only if the current value is
545 /// negative.
546 ///
547 /// This applies to zeros and NaNs as well.
548 bool isNegative() const { return sign; }
549
550 /// IEEE-754R isNormal: Returns true if and only if the current value is normal.
551 ///
552 /// This implies that the current value of the float is not zero, subnormal,
553 /// infinite, or NaN following the definition of normality from IEEE-754R.
554 bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
555
556 /// Returns true if and only if the current value is zero, subnormal, or
557 /// normal.
558 ///
559 /// This means that the value is not infinite or NaN.
560 bool isFinite() const { return !isNaN() && !isInfinity(); }
561
562 /// Returns true if and only if the float is plus or minus zero.
563 bool isZero() const { return category == fltCategory::fcZero; }
564
565 /// IEEE-754R isSubnormal(): Returns true if and only if the float is a
566 /// denormal.
567 LLVM_ABI bool isDenormal() const;
568
569 /// IEEE-754R isInfinite(): Returns true if and only if the float is infinity.
570 bool isInfinity() const { return category == fcInfinity; }
571
572 /// Returns true if and only if the float is a quiet or signaling NaN.
573 bool isNaN() const { return category == fcNaN; }
574
575 /// Returns true if and only if the float is a signaling NaN.
576 LLVM_ABI bool isSignaling() const;
577
578 /// @}
579
580 /// \name Simple Queries
581 /// @{
582
583 fltCategory getCategory() const { return category; }
584 const fltSemantics &getSemantics() const { return *semantics; }
585 bool isNonZero() const { return category != fltCategory::fcZero; }
586 bool isFiniteNonZero() const { return isFinite() && !isZero(); }
587 bool isPosZero() const { return isZero() && !isNegative(); }
588 bool isNegZero() const { return isZero() && isNegative(); }
589
590 /// Returns true if and only if the number has the smallest possible non-zero
591 /// magnitude in the current semantics.
592 LLVM_ABI bool isSmallest() const;
593
594 /// Returns true if this is the smallest (by magnitude) normalized finite
595 /// number in the given semantics.
596 LLVM_ABI bool isSmallestNormalized() const;
597
598 /// Returns true if and only if the number has the largest possible finite
599 /// magnitude in the current semantics.
600 LLVM_ABI bool isLargest() const;
601
602 /// Returns true if and only if the number is an exact integer.
603 LLVM_ABI bool isInteger() const;
604
605 /// @}
606
607 LLVM_ABI IEEEFloat &operator=(const IEEEFloat &);
608 LLVM_ABI IEEEFloat &operator=(IEEEFloat &&);
609
---------------------------------------------{"file":"llvm/lib/Support/APFloat.cpp","position":4580}file: llvm/lib/Support/APFloat.cpp:4580-4830
--------------------------------------------
4580 sign = Negative;
4581 if (semantics->nanEncoding == fltNanEncoding::NegativeZero) {
4582 // Merge negative zero to positive because 0b10000...000 is used for NaN
4583 sign = false;
4584 }
4585 exponent = exponentZero();
4586 APInt::tcSet(significandParts(), 0, partCount());
4587 }
4588
4589 void IEEEFloat::makeQuiet() {
4590 assert(isNaN());
4591 if (semantics->nonFiniteBehavior != fltNonfiniteBehavior::NanOnly)
4592 APInt::tcSetBit(significandParts(), semantics->precision - 2);
4593 }
4594
4595 int ilogb(const IEEEFloat &Arg) {
4596 if (Arg.isNaN())
4597 return APFloat::IEK_NaN;
4598 if (Arg.isZero())
4599 return APFloat::IEK_Zero;
4600 if (Arg.isInfinity())
4601 return APFloat::IEK_Inf;
4602 if (!Arg.isDenormal())
4603 return Arg.exponent;
4604
4605 IEEEFloat Normalized(Arg);
4606 int SignificandBits = Arg.getSemantics().precision - 1;
4607
4608 Normalized.exponent += SignificandBits;
4609 Normalized.normalize(APFloat::rmNearestTiesToEven, lfExactlyZero);
4610 return Normalized.exponent - SignificandBits;
4611 }
4612
4613 IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode RoundingMode) {
4614 auto MaxExp = X.getSemantics().maxExponent;
4615 auto MinExp = X.getSemantics().minExponent;
4616
4617 // If Exp is wildly out-of-scale, simply adding it to X.exponent will
4618 // overflow; clamp it to a safe range before adding, but ensure that the range
4619 // is large enough that the clamp does not change the result. The range we
4620 // need to support is the difference between the largest possible exponent and
4621 // the normalized exponent of half the smallest denormal.
4622
4623 int SignificandBits = X.getSemantics().precision - 1;
4624 int MaxIncrement = MaxExp - (MinExp - SignificandBits) + 1;
4625
4626 // Clamp to one past the range ends to let normalize handle overlflow.
4627 X.exponent += std::clamp(Exp, -MaxIncrement - 1, MaxIncrement);
4628 X.normalize(RoundingMode, lfExactlyZero);
4629 if (X.isNaN())
4630 X.makeQuiet();
4631 return X;
4632 }
4633
4634 IEEEFloat frexp(const IEEEFloat &Val, int &Exp, roundingMode RM) {
4635 Exp = ilogb(Val);
4636
4637 // Quiet signalling nans.
4638 if (Exp == APFloat::IEK_NaN) {
4639 IEEEFloat Quiet(Val);
4640 Quiet.makeQuiet();
4641 return Quiet;
4642 }
4643
4644 if (Exp == APFloat::IEK_Inf)
4645 return Val;
4646
4647 // 1 is added because frexp is defined to return a normalized fraction in
4648 // +/-[0.5, 1.0), rather than the usual +/-[1.0, 2.0).
4649 Exp = Exp == APFloat::IEK_Zero ? 0 : Exp + 1;
4650 return scalbn(Val, -Exp, RM);
4651 }
4652
4653 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S)
4654 : Semantics(&S),
4655 Floats(new APFloat[2]{APFloat(APFloatBase::semIEEEdouble),
4656 APFloat(APFloatBase::semIEEEdouble)}) {
4657 assert(Semantics == &APFloatBase::semPPCDoubleDouble);
4658 }
4659
4660 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, uninitializedTag)
4661 : Semantics(&S), Floats(new APFloat[2]{
4662 APFloat(APFloatBase::semIEEEdouble, uninitialized),
4663 APFloat(APFloatBase::semIEEEdouble, uninitialized)}) {
4664 assert(Semantics == &APFloatBase::semPPCDoubleDouble);
4665 }
4666
4667 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, integerPart I)
4668 : Semantics(&S),
4669 Floats(new APFloat[2]{APFloat(APFloatBase::semIEEEdouble, I),
4670 APFloat(APFloatBase::semIEEEdouble)}) {
4671 assert(Semantics == &APFloatBase::semPPCDoubleDouble);
4672 }
4673
4674 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, const APInt &I)
4675 : Semantics(&S),
4676 Floats(new APFloat[2]{
4677 APFloat(APFloatBase::semIEEEdouble, APInt(64, I.getRawData()[0])),
4678 APFloat(APFloatBase::semIEEEdouble, APInt(64, I.getRawData()[1]))}) {
4679 assert(Semantics == &APFloatBase::semPPCDoubleDouble);
4680 }
4681
4682 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, APFloat &&First,
4683 APFloat &&Second)
4684 : Semantics(&S),
4685 Floats(new APFloat[2]{std::move(First), std::move(Second)}) {
4686 assert(Semantics == &APFloatBase::semPPCDoubleDouble);
4687 assert(&Floats[0].getSemantics() == &APFloatBase::semIEEEdouble);
4688 assert(&Floats[1].getSemantics() == &APFloatBase::semIEEEdouble);
4689 }
4690
4691 DoubleAPFloat::DoubleAPFloat(const DoubleAPFloat &RHS)
4692 : Semantics(RHS.Semantics),
4693 Floats(RHS.Floats ? new APFloat[2]{APFloat(RHS.Floats[0]),
4694 APFloat(RHS.Floats[1])}
4695 : nullptr) {
4696 assert(Semantics == &APFloatBase::semPPCDoubleDouble);
4697 }
4698
4699 DoubleAPFloat::DoubleAPFloat(DoubleAPFloat &&RHS)
4700 : Semantics(RHS.Semantics), Floats(RHS.Floats) {
4701 RHS.Semantics = &APFloatBase::semBogus;
4702 RHS.Floats = nullptr;
4703 assert(Semantics == &APFloatBase::semPPCDoubleDouble);
4704 }
4705
4706 DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) {
4707 if (Semantics == RHS.Semantics && RHS.Floats) {
4708 Floats[0] = RHS.Floats[0];
4709 Floats[1] = RHS.Floats[1];
4710 } else if (this != &RHS) {
4711 this->~DoubleAPFloat();
4712 new (this) DoubleAPFloat(RHS);
4713 }
4714 return *this;
4715 }
4716
4717 // Returns a result such that:
4718 // 1. abs(Lo) <= ulp(Hi)/2
4719 // 2. Hi == RTNE(Hi + Lo)
4720 // 3. Hi + Lo == X + Y
4721 //
4722 // Requires that log2(X) >= log2(Y).
4723 static std::pair<APFloat, APFloat> fastTwoSum(APFloat X, APFloat Y) {
4724 if (!X.isFinite())
4725 return {X, APFloat::getZero(X.getSemantics(), /*Negative=*/false)};
4726 APFloat Hi = X + Y;
4727 APFloat Delta = Hi - X;
4728 APFloat Lo = Y - Delta;
4729 return {Hi, Lo};
4730 }
4731
4732 // Implement addition, subtraction, multiplication and division based on:
4733 // "Software for Doubled-Precision Floating-Point Computations",
4734 // by Seppo Linnainmaa, ACM TOMS vol 7 no 3, September 1981, pages 272-283.
4735 APFloat::opStatus DoubleAPFloat::addImpl(const APFloat &a, const APFloat &aa,
4736 const APFloat &c, const APFloat &cc,
4737 roundingMode RM) {
4738 int Status = opOK;
4739 APFloat z = a;
4740 Status |= z.add(c, RM);
4741 if (!z.isFinite()) {
4742 if (!z.isInfinity()) {
4743 Floats[0] = std::move(z);
4744 Floats[1].makeZero(/* Neg = */ false);
4745 return (opStatus)Status;
4746 }
4747 Status = opOK;
4748 auto AComparedToC = a.compareAbsoluteValue(c);
4749 z = cc;
4750 Status |= z.add(aa, RM);
4751 if (AComparedToC == APFloat::cmpGreaterThan) {
4752 // z = cc + aa + c + a;
4753 Status |= z.add(c, RM);
4754 Status |= z.add(a, RM);
4755 } else {
4756 // z = cc + aa + a + c;
4757 Status |= z.add(a, RM);
4758 Status |= z.add(c, RM);
4759 }
4760 if (!z.isFinite()) {
4761 Floats[0] = std::move(z);
4762 Floats[1].makeZero(/* Neg = */ false);
4763 return (opStatus)Status;
4764 }
4765 Floats[0] = z;
4766 APFloat zz = aa;
4767 Status |= zz.add(cc, RM);
4768 if (AComparedToC == APFloat::cmpGreaterThan) {
4769 // Floats[1] = a - z + c + zz;
4770 Floats[1] = a;
4771 Status |= Floats[1].subtract(z, RM);
4772 Status |= Floats[1].add(c, RM);
4773 Status |= Floats[1].add(zz, RM);
4774 } else {
4775 // Floats[1] = c - z + a + zz;
4776 Floats[1] = c;
4777 Status |= Floats[1].subtract(z, RM);
4778 Status |= Floats[1].add(a, RM);
4779 Status |= Floats[1].add(zz, RM);
4780 }
4781 } else {
4782 // q = a - z;
4783 APFloat q = a;
4784 Status |= q.subtract(z, RM);
4785
4786 // zz = q + c + (a - (q + z)) + aa + cc;
4787 // Compute a - (q + z) as -((q + z) - a) to avoid temporary copies.
4788 auto zz = q;
4789 Status |= zz.add(c, RM);
4790 Status |= q.add(z, RM);
4791 Status |= q.subtract(a, RM);
4792 q.changeSign();
4793 Status |= zz.add(q, RM);
4794 Status |= zz.add(aa, RM);
4795 Status |= zz.add(cc, RM);
4796 if (zz.isZero() && !zz.isNegative()) {
4797 Floats[0] = std::move(z);
4798 Floats[1].makeZero(/* Neg = */ false);
4799 return opOK;
4800 }
4801 Floats[0] = z;
4802 Status |= Floats[0].add(zz, RM);
4803 if (!Floats[0].isFinite()) {
4804 Floats[1].makeZero(/* Neg = */ false);
4805 return (opStatus)Status;
4806 }
4807 Floats[1] = std::move(z);
4808 Status |= Floats[1].subtract(Floats[0], RM);
4809 Status |= Floats[1].add(zz, RM);
4810 }
4811 return (opStatus)Status;
4812 }
4813
4814 APFloat::opStatus DoubleAPFloat::addWithSpecial(const DoubleAPFloat &LHS,
4815 const DoubleAPFloat &RHS,
4816 DoubleAPFloat &Out,
4817 roundingMode RM) {
4818 if (LHS.getCategory() == fcNaN) {
4819 Out = LHS;
4820 return opOK;
4821 }
4822 if (RHS.getCategory() == fcNaN) {
4823 Out = RHS;
4824 return opOK;
4825 }
4826 if (LHS.getCategory() == fcZero) {
4827 Out = RHS;
4828 return opOK;
4829 }
--------------------------------------------{"args":"-nRI 'frexp.*fabs\\|fabs.*frexp\\|ldexp.*frexp\\|extractvalue.*frexp' llvm/test/Transforms llvm/test/Analysis","k":1}llvm/test/Transforms/Inline/simplify-instruction-computeKnownFPClass-context.ll:200: %frexp.0 = extractvalue { double, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1004: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1044: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1085: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1125: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1163: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1203: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1236: %exp = extractvalue { float, i128 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1247:define float @frexp_fcmp_ogt_1_fabs_wrong_value(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1248:; CHECK-LABEL: define float @frexp_fcmp_ogt_1_fabs_wrong_value(
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1268: %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x.fabs)
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1269: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:128: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:160: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:192: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:225: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:257: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:289: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:321: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:32: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:353: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:385: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:417: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:449: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:481: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:513: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:545: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:577: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:609: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:641: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:64: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:673: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:705: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:735: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:760: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:790: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:815: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:848: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:881: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:914: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:947: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:96: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:978: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/frexp.ll:19: %frexp0.0 = extractvalue { float, i32 } %frexp0, 0
llvm/test/Transforms/InstCombine/frexp.ll:309: %frexp0.0 = extractvalue { double, i64 } %frexp0, 0llvm/test/Transforms/InstCombine/frexp.ll:32: %frexp0.0 = extractvalue { <2 x float>, <2 x i32> } %frexp0, 0
llvm/test/Transforms/InstCombine/frexp.ll:43: %frexp0.0 = extractvalue { float, i32 } %frexp0, 0
llvm/test/Transforms/InstCombine/frexp.ll:56: %frexp0.0 = extractvalue { <vscale x 2 x float>, <vscale x 2 x i32> } %frexp0, 0
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:111: %exp = extractvalue { <2 x float>, <2 x i32> } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:126: %exp = extractvalue { double, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:13: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:140: %exp = extractvalue { double, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:154: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:27: %exp = extractvalue { float, i16 } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:41: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:55: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:69: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:83: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/known-range-frexp-exp.ll:97: %exp = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/select_frexp.ll:110: %frexp.0 = extractvalue { float, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:125: %frexp.1 = extractvalue { float, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/select_frexp.ll:140: %frexp.0 = extractvalue { float, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:156: %frexp.0 = extractvalue { <2 x float>, <2 x i32> } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:171: %frexp.0 = extractvalue { <vscale x 2 x float>, <vscale x 2 x i32> } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:186: %frexp.0 = extractvalue { <vscale x 2 x float>, <vscale x 2 x i32> } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:18: %frexp.0 = extractvalue { float, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:33: %frexp.0 = extractvalue { float, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:50: %frexp.0 = extractvalue { float, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:65: %frexp.0 = extractvalue { <2 x float>, <2 x i32> } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:80: %frexp.0 = extractvalue { <2 x float>, <2 x i32> } %frexp, 0
llvm/test/Transforms/InstCombine/select_frexp.ll:95: %frexp.0 = extractvalue { <2 x float>, <2 x i32> } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:101: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:111: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:121: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:131: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:141: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:153: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:163: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:173: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:183: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:193: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:208: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:226: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:227: %frexp.exp = extractvalue { half, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:245: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:263: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:264: %frexp.exp = extractvalue { half, i32 } %frexp, 1
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:280: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:295: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:311: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:327: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:342: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:357: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:372: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:388: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:402: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:416: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:430: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:444: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:458: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:472: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:486: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:501: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:516: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:529: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:540: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:54:define nofpclass(nan) half @extractvalue_not_frexp() {
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:553: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:55:; CHECK-LABEL: define nofpclass(nan) half @extractvalue_not_frexp() {
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:566: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:579: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:590: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:608: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:609: %frexp.mant2 = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:624: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:71: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:81: %frexp.mant = extractvalue { half, i32 } %frexp, 0
llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-frexp.ll:91: %frexp.mant = extractvalue { half, i32 } %frexp, 0{"file":"llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll","position":1}file: llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:1-251
--------------------------------------------------------------------------------------------------
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4 ; Test that nofpclass(inf) can be propagated based on the contextual
5 ; knowledge that the exponent of a frexp must be negative
6 ;
7 ; We can infer from a not-inf source, plus the compare that the clamp
8 ; of infinity inside small can be deleted.
9
10 define float @frexp_fcmp_ogt_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
11 ; CHECK-LABEL: define float @frexp_fcmp_ogt_1(
12 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
13 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
14 ; CHECK-NEXT: [[IS_LARGE:%.*]] = fcmp ogt float [[X_FABS]], 1.000000e+00
15 ; CHECK-NEXT: br i1 [[IS_LARGE]], label %[[LARGE:.*]], label %[[SMALL:.*]]
16 ; CHECK: [[SMALL]]:
17 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
18 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
19 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
20 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
21 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
22 ; CHECK-NEXT: ret float [[SELECT]]
23 ; CHECK: [[LARGE]]:
24 ; CHECK-NEXT: ret float 0.000000e+00
25 ;
26 %x.fabs = call float @llvm.fabs.f32(float %x)
27 %is.large = fcmp ogt float %x.fabs, 1.0
28 br i1 %is.large, label %large, label %small
29
30 small:
31 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
32 %exp = extractvalue { float, i32 } %frexp, 1
33 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
34 %is.inf = fcmp oeq float %scaled, +inf
35 %select = select i1 %is.inf, float 0.0, float %scaled
36 ret float %select
37
38 large:
39 ret float 0.0
40 }
41
42 define float @frexp_fcmp_oge_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
43 ; CHECK-LABEL: define float @frexp_fcmp_oge_1(
44 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
45 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
46 ; CHECK-NEXT: [[IS_LARGE:%.*]] = fcmp ult float [[X_FABS]], 1.000000e+00
47 ; CHECK-NEXT: br i1 [[IS_LARGE]], label %[[SMALL:.*]], label %[[LARGE:.*]]
48 ; CHECK: [[SMALL]]:
49 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
50 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
51 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
52 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
53 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
54 ; CHECK-NEXT: ret float [[SELECT]]
55 ; CHECK: [[LARGE]]:
56 ; CHECK-NEXT: ret float 0.000000e+00
57 ;
58 %x.fabs = call float @llvm.fabs.f32(float %x)
59 %is.large = fcmp oge float %x.fabs, 1.0
60 br i1 %is.large, label %large, label %small
61
62 small:
63 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
64 %exp = extractvalue { float, i32 } %frexp, 1
65 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
66 %is.inf = fcmp oeq float %scaled, +inf
67 %select = select i1 %is.inf, float 0.0, float %scaled
68 ret float %select
69
70 large:
71 ret float 0.0
72 }
73
74 define float @frexp_fcmp_ugt_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
75 ; CHECK-LABEL: define float @frexp_fcmp_ugt_1(
76 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
77 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
78 ; CHECK-NEXT: [[IS_LARGE:%.*]] = fcmp ugt float [[X_FABS]], 1.000000e+00
79 ; CHECK-NEXT: br i1 [[IS_LARGE]], label %[[LARGE:.*]], label %[[SMALL:.*]]
80 ; CHECK: [[SMALL]]:
81 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
82 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
83 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
84 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
85 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
86 ; CHECK-NEXT: ret float [[SELECT]]
87 ; CHECK: [[LARGE]]:
88 ; CHECK-NEXT: ret float 0.000000e+00
89 ;
90 %x.fabs = call float @llvm.fabs.f32(float %x)
91 %is.large = fcmp ugt float %x.fabs, 1.0
92 br i1 %is.large, label %large, label %small
93
94 small:
95 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
96 %exp = extractvalue { float, i32 } %frexp, 1
97 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
98 %is.inf = fcmp oeq float %scaled, +inf
99 %select = select i1 %is.inf, float 0.0, float %scaled
100 ret float %select
101
102 large:
103 ret float 0.0
104 }
105
106 define float @frexp_fcmp_uge_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
107 ; CHECK-LABEL: define float @frexp_fcmp_uge_1(
108 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
109 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
110 ; CHECK-NEXT: [[IS_LARGE:%.*]] = fcmp uge float [[X_FABS]], 1.000000e+00
111 ; CHECK-NEXT: br i1 [[IS_LARGE]], label %[[LARGE:.*]], label %[[SMALL:.*]]
112 ; CHECK: [[SMALL]]:
113 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
114 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
115 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
116 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
117 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
118 ; CHECK-NEXT: ret float [[SELECT]]
119 ; CHECK: [[LARGE]]:
120 ; CHECK-NEXT: ret float 0.000000e+00
121 ;
122 %x.fabs = call float @llvm.fabs.f32(float %x)
123 %is.large = fcmp uge float %x.fabs, 1.0
124 br i1 %is.large, label %large, label %small
125
126 small:
127 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
128 %exp = extractvalue { float, i32 } %frexp, 1
129 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
130 %is.inf = fcmp oeq float %scaled, +inf
131 %select = select i1 %is.inf, float 0.0, float %scaled
132 ret float %select
133
134 large:
135 ret float 0.0
136 }
137
138 define float @frexp_fcmp_olt_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
139 ; CHECK-LABEL: define float @frexp_fcmp_olt_1(
140 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
141 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
142 ; CHECK-NEXT: [[IS_SMALL:%.*]] = fcmp olt float [[X_FABS]], 1.000000e+00
143 ; CHECK-NEXT: br i1 [[IS_SMALL]], label %[[SMALL:.*]], label %[[LARGE:.*]]
144 ; CHECK: [[SMALL]]:
145 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
146 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
147 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
148 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
149 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
150 ; CHECK-NEXT: ret float [[SELECT]]
151 ; CHECK: [[LARGE]]:
152 ; CHECK-NEXT: ret float 0.000000e+00
153 ;
154 %x.fabs = call float @llvm.fabs.f32(float %x)
155 %is.small = fcmp olt float %x.fabs, 1.0
156 br i1 %is.small, label %small, label %large
157
158 small:
159 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
160 %exp = extractvalue { float, i32 } %frexp, 1
161 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
162 %is.inf = fcmp oeq float %scaled, +inf
163 %select = select i1 %is.inf, float 0.0, float %scaled
164 ret float %select
165
166 large:
167 ret float 0.0
168 }
169
170 define float @frexp_fcmp_ole_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
171 ; CHECK-LABEL: define float @frexp_fcmp_ole_1(
172 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
173 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
174 ; CHECK-NEXT: [[IS_SMALL:%.*]] = fcmp ugt float [[X_FABS]], 1.000000e+00
175 ; CHECK-NEXT: br i1 [[IS_SMALL]], label %[[LARGE:.*]], label %[[SMALL:.*]]
176 ; CHECK: [[SMALL]]:
177 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
178 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
179 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
180 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
181 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
182 ; CHECK-NEXT: ret float [[SELECT]]
183 ; CHECK: [[LARGE]]:
184 ; CHECK-NEXT: ret float 0.000000e+00
185 ;
186 %x.fabs = call float @llvm.fabs.f32(float %x)
187 %is.small = fcmp ole float %x.fabs, 1.0
188 br i1 %is.small, label %small, label %large
189
190 small:
191 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
192 %exp = extractvalue { float, i32 } %frexp, 1
193 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
194 %is.inf = fcmp oeq float %scaled, +inf
195 %select = select i1 %is.inf, float 0.0, float %scaled
196 ret float %select
197
198 large:
199 ret float 0.0
200 }
201
202
203 define float @frexp_fcmp_ult_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
204 ; CHECK-LABEL: define float @frexp_fcmp_ult_1(
205 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
206 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
207 ; CHECK-NEXT: [[IS_SMALL:%.*]] = fcmp ult float [[X_FABS]], 1.000000e+00
208 ; CHECK-NEXT: br i1 [[IS_SMALL]], label %[[SMALL:.*]], label %[[LARGE:.*]]
209 ; CHECK: [[SMALL]]:
210 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
211 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
212 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
213 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
214 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
215 ; CHECK-NEXT: ret float [[SELECT]]
216 ; CHECK: [[LARGE]]:
217 ; CHECK-NEXT: ret float 0.000000e+00
218 ;
219 %x.fabs = call float @llvm.fabs.f32(float %x)
220 %is.small = fcmp ult float %x.fabs, 1.0
221 br i1 %is.small, label %small, label %large
222
223 small:
224 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
225 %exp = extractvalue { float, i32 } %frexp, 1
226 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
227 %is.inf = fcmp oeq float %scaled, +inf
228 %select = select i1 %is.inf, float 0.0, float %scaled
229 ret float %select
230
231 large:
232 ret float 0.0
233 }
234
235 define float @frexp_fcmp_ule_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
236 ; CHECK-LABEL: define float @frexp_fcmp_ule_1(
237 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
238 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
239 ; CHECK-NEXT: [[IS_SMALL:%.*]] = fcmp ule float [[X_FABS]], 1.000000e+00
240 ; CHECK-NEXT: br i1 [[IS_SMALL]], label %[[SMALL:.*]], label %[[LARGE:.*]]
241 ; CHECK: [[SMALL]]:
242 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
243 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
244 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
245 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
246 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
247 ; CHECK-NEXT: ret float [[SELECT]]
248 ; CHECK: [[LARGE]]:
249 ; CHECK-NEXT: ret float 0.000000e+00
250 ;
--------------------------------------------------------------------------------------------------{"file":"llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll","position":735}file: llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:735-985
----------------------------------------------------------------------------------------------------
735 %exp = extractvalue { float, i32 } %frexp, 1
736 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
737 %is.inf = fcmp oeq float %scaled, +inf
738 %select = select i1 %is.inf, float 0.0, float %scaled
739 ret float %select
740
741 large:
742 ret float 0.0
743 }
744
745 define float @frexp_fcmp_false_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
746 ; CHECK-LABEL: define float @frexp_fcmp_false_1(
747 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
748 ; CHECK-NEXT: br i1 false, label %[[SMALL:.*]], label %[[LARGE:.*]]
749 ; CHECK: [[SMALL]]:
750 ; CHECK-NEXT: ret float poison
751 ; CHECK: [[LARGE]]:
752 ; CHECK-NEXT: ret float 0.000000e+00
753 ;
754 %x.fabs = call float @llvm.fabs.f32(float %x)
755 %is.false = fcmp false float %x.fabs, 1.0
756 br i1 %is.false, label %small, label %large
757
758 small:
759 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
760 %exp = extractvalue { float, i32 } %frexp, 1
761 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
762 %is.inf = fcmp oeq float %scaled, +inf
763 %select = select i1 %is.inf, float 0.0, float %scaled
764 ret float %select
765
766 large:
767 ret float 0.0
768 }
769
770 define float @frexp_fcmp_ord_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
771 ; CHECK-LABEL: define float @frexp_fcmp_ord_1(
772 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
773 ; CHECK-NEXT: br i1 true, label %[[SMALL:.*]], label %[[LARGE:.*]]
774 ; CHECK: [[SMALL]]:
775 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
776 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
777 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
778 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
779 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
780 ; CHECK-NEXT: ret float [[SELECT]]
781 ; CHECK: [[LARGE]]:
782 ; CHECK-NEXT: ret float 0.000000e+00
783 ;
784 %x.fabs = call float @llvm.fabs.f32(float %x)
785 %is.ord = fcmp ord float %x.fabs, 1.0
786 br i1 %is.ord, label %small, label %large
787
788 small:
789 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
790 %exp = extractvalue { float, i32 } %frexp, 1
791 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
792 %is.inf = fcmp oeq float %scaled, +inf
793 %select = select i1 %is.inf, float 0.0, float %scaled
794 ret float %select
795
796 large:
797 ret float 0.0
798 }
799
800 define float @frexp_fcmp_uno_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
801 ; CHECK-LABEL: define float @frexp_fcmp_uno_1(
802 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
803 ; CHECK-NEXT: br i1 false, label %[[SMALL:.*]], label %[[LARGE:.*]]
804 ; CHECK: [[SMALL]]:
805 ; CHECK-NEXT: ret float poison
806 ; CHECK: [[LARGE]]:
807 ; CHECK-NEXT: ret float 0.000000e+00
808 ;
809 %x.fabs = call float @llvm.fabs.f32(float %x)
810 %is.uno = fcmp uno float %x.fabs, 1.0
811 br i1 %is.uno, label %small, label %large
812
813 small:
814 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
815 %exp = extractvalue { float, i32 } %frexp, 1
816 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
817 %is.inf = fcmp oeq float %scaled, +inf
818 %select = select i1 %is.inf, float 0.0, float %scaled
819 ret float %select
820
821 large:
822 ret float 0.0
823 }
824
825 ; Negative test
826 define float @frexp_fcmp_ogt_nextafter1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
827 ; CHECK-LABEL: define float @frexp_fcmp_ogt_nextafter1(
828 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
829 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
830 ; CHECK-NEXT: [[IS_LARGE:%.*]] = fcmp ogt float [[X_FABS]], f0x3F800001
831 ; CHECK-NEXT: br i1 [[IS_LARGE]], label %[[LARGE:.*]], label %[[SMALL:.*]]
832 ; CHECK: [[SMALL]]:
833 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
834 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
835 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
836 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
837 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
838 ; CHECK-NEXT: ret float [[SELECT]]
839 ; CHECK: [[LARGE]]:
840 ; CHECK-NEXT: ret float 0.000000e+00
841 ;
842 %x.fabs = call float @llvm.fabs.f32(float %x)
843 %is.large = fcmp ogt float %x.fabs, f0x3f800001
844 br i1 %is.large, label %large, label %small
845
846 small:
847 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
848 %exp = extractvalue { float, i32 } %frexp, 1
849 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
850 %is.inf = fcmp oeq float %scaled, +inf
851 %select = select i1 %is.inf, float 0.0, float %scaled
852 ret float %select
853
854 large:
855 ret float 0.0
856 }
857
858 ; Negative test
859 define float @frexp_fcmp_ole_nextafter1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
860 ; CHECK-LABEL: define float @frexp_fcmp_ole_nextafter1(
861 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
862 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
863 ; CHECK-NEXT: [[IS_SMALL:%.*]] = fcmp ugt float [[X_FABS]], f0x3F800001
864 ; CHECK-NEXT: br i1 [[IS_SMALL]], label %[[LARGE:.*]], label %[[SMALL:.*]]
865 ; CHECK: [[SMALL]]:
866 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
867 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
868 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
869 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
870 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
871 ; CHECK-NEXT: ret float [[SELECT]]
872 ; CHECK: [[LARGE]]:
873 ; CHECK-NEXT: ret float 0.000000e+00
874 ;
875 %x.fabs = call float @llvm.fabs.f32(float %x)
876 %is.small = fcmp ole float %x.fabs, f0x3f800001
877 br i1 %is.small, label %small, label %large
878
879 small:
880 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
881 %exp = extractvalue { float, i32 } %frexp, 1
882 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
883 %is.inf = fcmp oeq float %scaled, +inf
884 %select = select i1 %is.inf, float 0.0, float %scaled
885 ret float %select
886
887 large:
888 ret float 0.0
889 }
890
891 ; Negative test
892 define float @frexp_fcmp_ogt_nextdown1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
893 ; CHECK-LABEL: define float @frexp_fcmp_ogt_nextdown1(
894 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
895 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
896 ; CHECK-NEXT: [[IS_LARGE:%.*]] = fcmp ogt float [[X_FABS]], f0x3F7FFFFF
897 ; CHECK-NEXT: br i1 [[IS_LARGE]], label %[[LARGE:.*]], label %[[SMALL:.*]]
898 ; CHECK: [[SMALL]]:
899 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
900 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
901 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
902 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
903 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
904 ; CHECK-NEXT: ret float [[SELECT]]
905 ; CHECK: [[LARGE]]:
906 ; CHECK-NEXT: ret float 0.000000e+00
907 ;
908 %x.fabs = call float @llvm.fabs.f32(float %x)
909 %is.large = fcmp ogt float %x.fabs, f0x3f7fffff
910 br i1 %is.large, label %large, label %small
911
912 small:
913 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
914 %exp = extractvalue { float, i32 } %frexp, 1
915 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
916 %is.inf = fcmp oeq float %scaled, +inf
917 %select = select i1 %is.inf, float 0.0, float %scaled
918 ret float %select
919
920 large:
921 ret float 0.0
922 }
923
924 ; Negative test
925 define float @frexp_fcmp_ole_nextdown1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
926 ; CHECK-LABEL: define float @frexp_fcmp_ole_nextdown1(
927 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
928 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
929 ; CHECK-NEXT: [[IS_SMALL:%.*]] = fcmp ugt float [[X_FABS]], f0x3F7FFFFF
930 ; CHECK-NEXT: br i1 [[IS_SMALL]], label %[[LARGE:.*]], label %[[SMALL:.*]]
931 ; CHECK: [[SMALL]]:
932 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
933 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
934 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
935 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
936 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
937 ; CHECK-NEXT: ret float [[SELECT]]
938 ; CHECK: [[LARGE]]:
939 ; CHECK-NEXT: ret float 0.000000e+00
940 ;
941 %x.fabs = call float @llvm.fabs.f32(float %x)
942 %is.small = fcmp ole float %x.fabs, f0x3f7fffff
943 br i1 %is.small, label %small, label %large
944
945 small:
946 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
947 %exp = extractvalue { float, i32 } %frexp, 1
948 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
949 %is.inf = fcmp oeq float %scaled, +inf
950 %select = select i1 %is.inf, float 0.0, float %scaled
951 ret float %select
952
953 large:
954 ret float 0.0
955 }
956
957 ; Negative test
958 define float @frexp_fcmp_ole_inf(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
959 ; CHECK-LABEL: define float @frexp_fcmp_ole_inf(
960 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
961 ; CHECK-NEXT: br i1 true, label %[[SMALL:.*]], label %[[LARGE:.*]]
962 ; CHECK: [[SMALL]]:
963 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
964 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
965 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
966 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
967 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
968 ; CHECK-NEXT: ret float [[SELECT]]
969 ; CHECK: [[LARGE]]:
970 ; CHECK-NEXT: ret float 0.000000e+00
971 ;
972 %x.fabs = call float @llvm.fabs.f32(float %x)
973 %is.small = fcmp ole float %x.fabs, +inf
974 br i1 %is.small, label %small, label %large
975
976 small:
977 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
978 %exp = extractvalue { float, i32 } %frexp, 1
979 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
980 %is.inf = fcmp oeq float %scaled, +inf
981 %select = select i1 %is.inf, float 0.0, float %scaled
982 ret float %select
983
984 large:
----------------------------------------------------------------------------------------------------{"file":"llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll","position":985}file: llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll:985-1235
-----------------------------------------------------------------------------------------------------
985 ret float 0.0
986 }
987
988 ; Negative test
989 define float @frexp_fcmp_ole_nan(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
990 ; CHECK-LABEL: define float @frexp_fcmp_ole_nan(
991 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
992 ; CHECK-NEXT: br i1 false, label %[[SMALL:.*]], label %[[LARGE:.*]]
993 ; CHECK: [[SMALL]]:
994 ; CHECK-NEXT: ret float poison
995 ; CHECK: [[LARGE]]:
996 ; CHECK-NEXT: ret float 0.000000e+00
997 ;
998 %x.fabs = call float @llvm.fabs.f32(float %x)
999 %is.small = fcmp ole float %x.fabs, +qnan
1000 br i1 %is.small, label %small, label %large
1001
1002 small:
1003 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
1004 %exp = extractvalue { float, i32 } %frexp, 1
1005 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
1006 %is.inf = fcmp oeq float %scaled, +inf
1007 %select = select i1 %is.inf, float 0.0, float %scaled
1008 ret float %select
1009
1010 large:
1011 ret float 0.0
1012 }
1013
1014 ; Negative test
1015 define float @frexp_fcmp_olt_1_not_dominated(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf, i1 %arg) {
1016 ; CHECK-LABEL: define float @frexp_fcmp_olt_1_not_dominated(
1017 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]], i1 [[ARG:%.*]]) {
1018 ; CHECK-NEXT: [[ENTRY:.*:]]
1019 ; CHECK-NEXT: br i1 [[ARG]], label %[[GUARD:.*]], label %[[SMALL:.*]]
1020 ; CHECK: [[GUARD]]:
1021 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
1022 ; CHECK-NEXT: [[IS_SMALL:%.*]] = fcmp olt float [[X_FABS]], 1.000000e+00
1023 ; CHECK-NEXT: br i1 [[IS_SMALL]], label %[[SMALL]], label %[[EXIT:.*]]
1024 ; CHECK: [[SMALL]]:
1025 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
1026 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
1027 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
1028 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
1029 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
1030 ; CHECK-NEXT: ret float [[SELECT]]
1031 ; CHECK: [[EXIT]]:
1032 ; CHECK-NEXT: ret float 0.000000e+00
1033 ;
1034 entry:
1035 br i1 %arg, label %guard, label %small
1036
1037 guard:
1038 %x.fabs = call float @llvm.fabs.f32(float %x)
1039 %is.small = fcmp olt float %x.fabs, 1.0
1040 br i1 %is.small, label %small, label %exit
1041
1042 small:
1043 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
1044 %exp = extractvalue { float, i32 } %frexp, 1
1045 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
1046 %is.inf = fcmp oeq float %scaled, +inf
1047 %select = select i1 %is.inf, float 0.0, float %scaled
1048 ret float %select
1049
1050 exit:
1051 ret float 0.0
1052 }
1053
1054 ; Make sure the inner compare against 1 is recognized and doesn't
1055 ; abort the search after seeing the outer compare.
1056 define float @frexp_fcmp_olt_1_multiple_conditions_wrong_constant(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
1057 ; CHECK-LABEL: define float @frexp_fcmp_olt_1_multiple_conditions_wrong_constant(
1058 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
1059 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
1060 ; CHECK-NEXT: [[IS_SMALL:%.*]] = fcmp olt float [[X_FABS]], 2.000000e+00
1061 ; CHECK-NEXT: br i1 [[IS_SMALL]], label %[[SMALL:.*]], label %[[EXIT:.*]]
1062 ; CHECK: [[SMALL]]:
1063 ; CHECK-NEXT: [[OTHER_COND:%.*]] = fcmp olt float [[X_FABS]], 1.000000e+00
1064 ; CHECK-NEXT: br i1 [[OTHER_COND]], label %[[BODY:.*]], label %[[EXIT]]
1065 ; CHECK: [[BODY]]:
1066 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
1067 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
1068 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
1069 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
1070 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
1071 ; CHECK-NEXT: ret float [[SELECT]]
1072 ; CHECK: [[EXIT]]:
1073 ; CHECK-NEXT: ret float 0.000000e+00
1074 ;
1075 %x.fabs = call float @llvm.fabs.f32(float %x)
1076 %is.small = fcmp olt float %x.fabs, 2.0
1077 br i1 %is.small, label %small, label %exit
1078
1079 small:
1080 %other.cond = fcmp olt float %x.fabs, 1.0
1081 br i1 %other.cond, label %body, label %exit
1082
1083 body:
1084 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
1085 %exp = extractvalue { float, i32 } %frexp, 1
1086 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
1087 %is.inf = fcmp oeq float %scaled, +inf
1088 %select = select i1 %is.inf, float 0.0, float %scaled
1089 ret float %select
1090
1091 exit:
1092 ret float 0.0
1093 }
1094
1095 ; Make sure the inner compare against 1 is recognized and doesn't
1096 ; abort the search after seeing the outer compare.
1097 define float @frexp_fcmp_olt_1_multiple_conditions_nonfinite_constant(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
1098 ; CHECK-LABEL: define float @frexp_fcmp_olt_1_multiple_conditions_nonfinite_constant(
1099 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
1100 ; CHECK-NEXT: br i1 true, label %[[SMALL:.*]], label %[[EXIT:.*]]
1101 ; CHECK: [[SMALL]]:
1102 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
1103 ; CHECK-NEXT: [[OTHER_COND:%.*]] = fcmp olt float [[X_FABS]], 1.000000e+00
1104 ; CHECK-NEXT: br i1 [[OTHER_COND]], label %[[BODY:.*]], label %[[EXIT]]
1105 ; CHECK: [[BODY]]:
1106 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
1107 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
1108 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
1109 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
1110 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
1111 ; CHECK-NEXT: ret float [[SELECT]]
1112 ; CHECK: [[EXIT]]:
1113 ; CHECK-NEXT: ret float 0.000000e+00
1114 ;
1115 %x.fabs = call float @llvm.fabs.f32(float %x)
1116 %is.small = fcmp olt float %x.fabs, +inf
1117 br i1 %is.small, label %small, label %exit
1118
1119 small:
1120 %other.cond = fcmp olt float %x.fabs, 1.0
1121 br i1 %other.cond, label %body, label %exit
1122
1123 body:
1124 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
1125 %exp = extractvalue { float, i32 } %frexp, 1
1126 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
1127 %is.inf = fcmp oeq float %scaled, +inf
1128 %select = select i1 %is.inf, float 0.0, float %scaled
1129 ret float %select
1130
1131 exit:
1132 ret float 0.0
1133 }
1134
1135 define float @frexp_fcmp_olt_1_multiple_conditions_edge_case_compare(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
1136 ; CHECK-LABEL: define float @frexp_fcmp_olt_1_multiple_conditions_edge_case_compare(
1137 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
1138 ; CHECK-NEXT: br i1 true, label %[[SMALL:.*]], label %[[EXIT:.*]]
1139 ; CHECK: [[SMALL]]:
1140 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
1141 ; CHECK-NEXT: [[OTHER_COND:%.*]] = fcmp olt float [[X_FABS]], 1.000000e+00
1142 ; CHECK-NEXT: br i1 [[OTHER_COND]], label %[[BODY:.*]], label %[[EXIT]]
1143 ; CHECK: [[BODY]]:
1144 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
1145 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
1146 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
1147 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
1148 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
1149 ; CHECK-NEXT: ret float [[SELECT]]
1150 ; CHECK: [[EXIT]]:
1151 ; CHECK-NEXT: ret float 0.000000e+00
1152 ;
1153 %x.fabs = call float @llvm.fabs.f32(float %x)
1154 %is.small = fcmp ord float %x.fabs, 0.0
1155 br i1 %is.small, label %small, label %exit
1156
1157 small:
1158 %other.cond = fcmp olt float %x.fabs, 1.0
1159 br i1 %other.cond, label %body, label %exit
1160
1161 body:
1162 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
1163 %exp = extractvalue { float, i32 } %frexp, 1
1164 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
1165 %is.inf = fcmp oeq float %scaled, +inf
1166 %select = select i1 %is.inf, float 0.0, float %scaled
1167 ret float %select
1168
1169 exit:
1170 ret float 0.0
1171 }
1172
1173
1174 define float @frexp_fcmp_olt_1_multiple_conditions_other(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
1175 ; CHECK-LABEL: define float @frexp_fcmp_olt_1_multiple_conditions_other(
1176 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
1177 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
1178 ; CHECK-NEXT: [[IS_SMALL:%.*]] = fcmp olt float [[X_FABS]], 1.000000e+00
1179 ; CHECK-NEXT: br i1 [[IS_SMALL]], label %[[SMALL:.*]], label %[[EXIT:.*]]
1180 ; CHECK: [[SMALL]]:
1181 ; CHECK-NEXT: [[OTHER_COND:%.*]] = fcmp ueq float [[X]], 5.000000e-01
1182 ; CHECK-NEXT: br i1 [[OTHER_COND]], label %[[EXIT]], label %[[BODY:.*]]
1183 ; CHECK: [[BODY]]:
1184 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
1185 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
1186 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]])
1187 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
1188 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
1189 ; CHECK-NEXT: ret float [[SELECT]]
1190 ; CHECK: [[EXIT]]:
1191 ; CHECK-NEXT: ret float 0.000000e+00
1192 ;
1193 %x.fabs = call float @llvm.fabs.f32(float %x)
1194 %is.small = fcmp olt float %x.fabs, 1.0
1195 br i1 %is.small, label %small, label %exit
1196
1197 small:
1198 %other.cond = fcmp one float %x, 0.5
1199 br i1 %other.cond, label %body, label %exit
1200
1201 body:
1202 %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)
1203 %exp = extractvalue { float, i32 } %frexp, 1
1204 %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)
1205 %is.inf = fcmp oeq float %scaled, +inf
1206 %select = select i1 %is.inf, float 0.0, float %scaled
1207 ret float %select
1208
1209 exit:
1210 ret float 0.0
1211 }
1212
1213 ; Test no assertion on exponent type > 64
1214 define float @frexp_fcmp_ogt_1_large_int(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {
1215 ; CHECK-LABEL: define float @frexp_fcmp_ogt_1_large_int(
1216 ; CHECK-SAME: float nofpclass(nan inf) [[X:%.*]], float nofpclass(inf) [[NOT_INF:%.*]]) {
1217 ; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
1218 ; CHECK-NEXT: [[IS_LARGE:%.*]] = fcmp ogt float [[X_FABS]], 1.000000e+00
1219 ; CHECK-NEXT: br i1 [[IS_LARGE]], label %[[LARGE:.*]], label %[[SMALL:.*]]
1220 ; CHECK: [[SMALL]]:
1221 ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i128 } @llvm.frexp.f32.i128(float [[X]])
1222 ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i128 } [[FREXP]], 1
1223 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i128(float [[NOT_INF]], i128 [[EXP]])
1224 ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf
1225 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]]
1226 ; CHECK-NEXT: ret float [[SELECT]]
1227 ; CHECK: [[LARGE]]:
1228 ; CHECK-NEXT: ret float 0.000000e+00
1229 ;
1230 %x.fabs = call float @llvm.fabs.f32(float %x)
1231 %is.large = fcmp ogt float %x.fabs, 1.0
1232 br i1 %is.large, label %large, label %small
1233
1234 small:
-----------------------------------------------------------------------------------------------------{"strategies":[{"expected_issue":"The optimizer may prove the frexp exponent is <= 0 and remove an ldexp overflow check, but at x = 1.0 frexp returns exponent 1, so ldexp(max_finite, 1) can overflow to +inf and the removed check was semantically observable.","name":"Inclusive one off-by-one overflow guard","rationale":"The new context range uses ilogb(K) as the inclusive maximum frexp exponent for fabs(x) <= K. For nonzero finite x, frexp exponent is ilogb(x)+1. Thus fabs(x) <= 1.0 permits x=1.0 with exponent 1, but the analysis records max 0.","target":"Mutate an existing frexp_fcmp_ole_1 / frexp_fcmp_ogt_1 false-edge test so the ldexp source can be the largest finite float/double and the result is guarded by `fcmp oeq +inf` or an `is_fpclass(inf)` path."},{"expected_issue":"Integer users of the exponent may be folded incorrectly, e.g. `icmp sle i32 %exp, -1` or `icmp slt i32 %exp, 0` may become true under a dominating `fabs(x) <= 0.75`, although x=0.75 gives frexp exponent 0.","name":"Non-power-of-two bound off-by-one","rationale":"For a non-power-of-two K in (0.5, 1), ilogb(K) is -1, but values in [0.5,K] have frexp exponent 0. The patch accepts any finite K <= 1.0, not just strict comparisons against powers of two where ilogb(K) is a valid upper bound.","target":"Mutate the dominating compare constant from 1.0 to 0.75 (or hex f0x3F400000) and add an integer comparison/select on the extracted frexp exponent, such as `select (icmp slt %exp, 0) ...`."},{"expected_issue":"The analysis may create a nonsensical or wrapped ConstantRange for the exponent, possibly leading to wrong folds of comparisons against very negative values, or assertions in debug builds around ConstantRange construction/use.","name":"Zero limit pathological range","rationale":"`ilogb(0.0)` returns APFloat::IEK_Zero (INT_MIN+1), but frexp(0.0) returns exponent 0. Under `fabs(x) <= 0.0` or `fabs(x) == 0.0`, the patch sets the adjusted max to IEK_Zero rather than 0, making max less than the normal minimum exponent and potentially wrapping when converted to ConstantRange.","target":"Mutate the compare limit to `0.0` with a no-NaN/non-inf source and use the extracted exponent in an `icmp` (for example `icmp slt %exp, -1000000`) or downstream ldexp classification."},{"expected_issue":"Equality cases may be optimized as if the exponent is <= ilogb(K), but when fabs(x) == K and K is nonzero, the exponent is ilogb(K)+1; this can miscompile both integer exponent tests and ldexp overflow pruning.","name":"OEQ/UEQ exact-bound exponent","rationale":"The patch groups `oeq`/`ueq` with less-or-equal predicates. Equality to a finite nonzero magnitude gives a precise frexp exponent of ilogb(K)+1, not ilogb(K). With `nofpclass(nan inf)` on the source, unordered complications are removed and the off-by-one becomes directly observable.","target":"Mutate an existing `fcmp ole/ule` case to `fcmp oeq float fabs(x), 1.0` (and separately `0.5` or `0.75`) on the true edge, then test either `ldexp(max_finite, %exp)` overflow or an `icmp sle %exp, 0` fold."},{"expected_issue":"For small integer exponent result types, min/max APInt construction may truncate the real float exponent bounds, producing wrapped or overly precise ConstantRanges and incorrect signed comparisons or known-fp-class deductions.","name":"Narrow frexp exponent type wrapping","rationale":"The frexp exponent range for float is roughly [-149,128], which does not fit in i8 and certainly not in i1/i2. The patch constructs `APInt(BitWidth, MinExp, isSigned=true)` and `APInt(BitWidth, MaxExp+1, isSigned=true)`, so narrow result types can wrap the mathematical bounds. Existing tests cover i16/i128 but not too-narrow types.","target":"Mutate `known-range-frexp-exp.ll` or the dominating-condition test to declare/use `@llvm.frexp.f32.i8` (and possibly i1/i2), extract the exponent, and feed it to signed `icmp` or `llvm.ldexp.f32.i8` under a dominating `fabs(x) < 1.0` condition."}],"thoughts":"### 1. Fix Understanding\nThe patch improves ValueTracking by deriving a signed ConstantRange for the exponent result of `llvm.frexp` from dominating control-flow conditions of the form `fcmp Pred (fabs V), finite_constant`. That exponent range is then used by `computeConstantRange`, and `computeKnownFPClass` for `llvm.ldexp` is changed from `KnownBits`-based exponent reasoning to ConstantRange min/max reasoning. The intended optimization is to recognize that, in a block dominated by a condition like `fabs(x) < 1.0`, `frexp(x)` has a non-positive exponent, so a following `ldexp(finite, exp)` cannot overflow to infinity.\n\nKey changed pieces:\n* `computeKnownExponentRangeFromContext(V,Q)` scans dominating conditional branches involving `fabs(V)` and a finite constant <= 1.0.\n* For a matching dominated edge, it returns `{IEK_NaN, ilogb(LimitC)}` as adjusted exponent min/max.\n* `computeConstantRange` for `extractvalue 1 (llvm.frexp(src))` intersects the normal IEEE exponent bounds with that contextual bound.\n* `KnownFPClass::ldexp` now accepts exponent signed min/max APInts, with a KnownBits wrapper preserving old API users.\n\n### 2. Formal Semantic Modeling\nBefore the fix, for a non-NaN/non-inf IEEE-like source `x`, ValueTracking modeled the frexp exponent result with a type-wide-ish floating format range:\n* normal/subnormal float: approximately `[-149, 128]` for f32, because frexp returns 0 for zero and `ilogb(x)+1` for finite nonzero x.\n* no dominating `fabs` condition affected this range.\n\nAfter the fix, under a dominating branch condition matching `fabs(x) Pred K` with finite `K <= 1.0`, the range is further adjusted to max exponent `ilogb(K)` for the edge interpreted as proving `fabs(x) <= K` (or the false edge of a greater-than predicate).\n\nThe semantic contract the patch appears to claim is:\n* If the current block is dominated by a condition implying `fabs(x) <= K`, with finite `K <= 1.0`, and `x` is known not NaN/Inf, then `frexp(x).exp <= ilogb(K)`.\n\nHowever, the mathematical frexp semantics are:\n* `frexp(0).exp = 0`.\n* For finite nonzero `x`, `frexp(x).exp = ilogb(x) + 1`.\n\nConcrete instantiation:\n* Let `x = 1.0f`; `fabs(x) <= 1.0` is true.\n* `ilogb(1.0) = 0`.\n* `frexp(1.0).exp = 1`, because mantissa is 0.5 and exponent is 1.\n* The patch would infer max exponent 0 on inclusive/equality paths, which excludes the real value 1.\n\nAnother instantiation:\n* Let `x = 0.75f`; `fabs(x) <= 0.75` is true.\n* `ilogb(0.75) = -1`.\n* `frexp(0.75).exp = 0`, excluding the inferred max -1.\n\n### 3. Assumptions and Preconditions Identified\nThe fix relies on these assumptions:\n1. `ilogb(K)` is a sound upper bound for the frexp exponent whenever the branch implies `fabs(x) <= K`.\n2. Inclusive comparisons (`ole`, `ule`) and equality comparisons (`oeq`, `ueq`) can be treated the same as strict less-than for exponent upper-bound purposes.\n3. The zero limit can be handled by the same `ilogb` path as nonzero finite constants.\n4. The extracted frexp exponent integer type is wide enough to represent the APFloat exponent bounds and adjusted bounds without harmful APInt truncation.\n5. Passing only ConstantRange signed min/max to `KnownFPClass::ldexp` is conservative enough for all ranges produced by computeConstantRange.\n6. Unordered predicates are safe provided `KnownSrc.isKnownNeverInfOrNaN()` is checked before constraining the frexp range.\n\n### 4. Potential Cases to Break Assumptions\n* Inclusive bound at exactly 1.0: `fabs(x) <= 1.0` allows `x = +/-1.0`, where frexp exponent is 1, not 0.\n* Equality bound: `fabs(x) == 1.0` or `fabs(x) == 0.5` gives exponent 1 or 0 respectively, but the patch uses ilogb(K), one less for nonzero K.\n* Non-power-of-two bound: `fabs(x) <= 0.75` allows exponents up to 0, while `ilogb(0.75)` is -1.\n* Zero bound: `fabs(x) <= 0.0` implies x is zero (modulo NaN handling), whose frexp exponent is 0; `ilogb(0.0)` is an error sentinel `IEK_Zero`, not a valid upper bound.\n* Narrow exponent result types: the mathematical f32 exponent range does not fit in i8/i1, and APInt construction may wrap values, producing invalid-looking ConstantRanges.\n* Downstream observable effects: integer comparisons on the exponent may fold incorrectly; ldexp known-fp-class may remove infinity checks when the real exponent can still be positive.\n\n### 5. Test Strategies\nThe proposed strategies focus on mutating existing frexp/ldexp InstCombine and known-range tests to make the inferred exponent bound observable through either removed overflow checks or folded integer comparisons. The highest-risk strategies are the inclusive/equality off-by-one cases and zero-limit case because they are direct semantic mismatches with LangRef frexp semantics."}{
"strategies": [
[
"Inclusive one off-by-one overflow guard",
"Mutate an existing frexp_fcmp_ole_1 / frexp_fcmp_ogt_1 false-edge test so the ldexp source can be the largest finite float/double and the result is guarded by `fcmp oeq +inf` or an `is_fpclass(inf)` path.",
"The new context range uses ilogb(K) as the inclusive maximum frexp exponent for fabs(x) <= K. For nonzero finite x, frexp exponent is ilogb(x)+1. Thus fabs(x) <= 1.0 permits x=1.0 with exponent 1, but the analysis records max 0.",
"The optimizer may prove the frexp exponent is <= 0 and remove an ldexp overflow check, but at x = 1.0 frexp returns exponent 1, so ldexp(max_finite, 1) can overflow to +inf and the removed check was semantically observable."
],
[
"Non-power-of-two bound off-by-one",
"Mutate the dominating compare constant from 1.0 to 0.75 (or hex f0x3F400000) and add an integer comparison/select on the extracted frexp exponent, such as `select (icmp slt %exp, 0) ...`.",
"For a non-power-of-two K in (0.5, 1), ilogb(K) is -1, but values in [0.5,K] have frexp exponent 0. The patch accepts any finite K <= 1.0, not just strict comparisons against powers of two where ilogb(K) is a valid upper bound.",
"Integer users of the exponent may be folded incorrectly, e.g. `icmp sle i32 %exp, -1` or `icmp slt i32 %exp, 0` may become true under a dominating `fabs(x) <= 0.75`, although x=0.75 gives frexp exponent 0."
],
[
"Zero limit pathological range",
"Mutate the compare limit to `0.0` with a no-NaN/non-inf source and use the extracted exponent in an `icmp` (for example `icmp slt %exp, -1000000`) or downstream ldexp classification.",
"`ilogb(0.0)` returns APFloat::IEK_Zero (INT_MIN+1), but frexp(0.0) returns exponent 0. Under `fabs(x) <= 0.0` or `fabs(x) == 0.0`, the patch sets the adjusted max to IEK_Zero rather than 0, making max less than the normal minimum exponent and potentially wrapping when converted to ConstantRange.",
"The analysis may create a nonsensical or wrapped ConstantRange for the exponent, possibly leading to wrong folds of comparisons against very negative values, or assertions in debug builds around ConstantRange construction/use."
],
[
"OEQ/UEQ exact-bound exponent",
"Mutate an existing `fcmp ole/ule` case to `fcmp oeq float fabs(x), 1.0` (and separately `0.5` or `0.75`) on the true edge, then test either `ldexp(max_finite, %exp)` overflow or an `icmp sle %exp, 0` fold.",
"The patch groups `oeq`/`ueq` with less-or-equal predicates. Equality to a finite nonzero magnitude gives a precise frexp exponent of ilogb(K)+1, not ilogb(K). With `nofpclass(nan inf)` on the source, unordered complications are removed and the off-by-one becomes directly observable.",
"Equality cases may be optimized as if the exponent is <= ilogb(K), but when fabs(x) == K and K is nonzero, the exponent is ilogb(K)+1; this can miscompile both integer exponent tests and ldexp overflow pruning."
],
[
"Narrow frexp exponent type wrapping",
"Mutate `known-range-frexp-exp.ll` or the dominating-condition test to declare/use `@llvm.frexp.f32.i8` (and possibly i1/i2), extract the exponent, and feed it to signed `icmp` or `llvm.ldexp.f32.i8` under a dominating `fabs(x) < 1.0` condition.",
"The frexp exponent range for float is roughly [-149,128], which does not fit in i8 and certainly not in i1/i2. The patch constructs `APInt(BitWidth, MinExp, isSigned=true)` and `APInt(BitWidth, MaxExp+1, isSigned=true)`, so narrow result types can wrap the mathematical bounds. Existing tests cover i16/i128 but not too-narrow types.",
"For small integer exponent result types, min/max APInt construction may truncate the real float exponent bounds, producing wrapped or overly precise ConstantRanges and incorrect signed comparisons or known-fp-class deductions."
]
],
"thoughts": "### 1. Fix Understanding\nThe patch improves ValueTracking by deriving a signed ConstantRange for the exponent result of `llvm.frexp` from dominating control-flow conditions of the form `fcmp Pred (fabs V), finite_constant`. That exponent range is then used by `computeConstantRange`, and `computeKnownFPClass` for `llvm.ldexp` is changed from `KnownBits`-based exponent reasoning to ConstantRange min/max reasoning. The intended optimization is to recognize that, in a block dominated by a condition like `fabs(x) < 1.0`, `frexp(x)` has a non-positive exponent, so a following `ldexp(finite, exp)` cannot overflow to infinity.\n\nKey changed pieces:\n* `computeKnownExponentRangeFromContext(V,Q)` scans dominating conditional branches involving `fabs(V)` and a finite constant <= 1.0.\n* For a matching dominated edge, it returns `{IEK_NaN, ilogb(LimitC)}` as adjusted exponent min/max.\n* `computeConstantRange` for `extractvalue 1 (llvm.frexp(src))` intersects the normal IEEE exponent bounds with that contextual bound.\n* `KnownFPClass::ldexp` now accepts exponent signed min/max APInts, with a KnownBits wrapper preserving old API users.\n\n### 2. Formal Semantic Modeling\nBefore the fix, for a non-NaN/non-inf IEEE-like source `x`, ValueTracking modeled the frexp exponent result with a type-wide-ish floating format range:\n* normal/subnormal float: approximately `[-149, 128]` for f32, because frexp returns 0 for zero and `ilogb(x)+1` for finite nonzero x.\n* no dominating `fabs` condition affected this range.\n\nAfter the fix, under a dominating branch condition matching `fabs(x) Pred K` with finite `K <= 1.0`, the range is further adjusted to max exponent `ilogb(K)` for the edge interpreted as proving `fabs(x) <= K` (or the false edge of a greater-than predicate).\n\nThe semantic contract the patch appears to claim is:\n* If the current block is dominated by a condition implying `fabs(x) <= K`, with finite `K <= 1.0`, and `x` is known not NaN/Inf, then `frexp(x).exp <= ilogb(K)`.\n\nHowever, the mathematical frexp semantics are:\n* `frexp(0).exp = 0`.\n* For finite nonzero `x`, `frexp(x).exp = ilogb(x) + 1`.\n\nConcrete instantiation:\n* Let `x = 1.0f`; `fabs(x) <= 1.0` is true.\n* `ilogb(1.0) = 0`.\n* `frexp(1.0).exp = 1`, because mantissa is 0.5 and exponent is 1.\n* The patch would infer max exponent 0 on inclusive/equality paths, which excludes the real value 1.\n\nAnother instantiation:\n* Let `x = 0.75f`; `fabs(x) <= 0.75` is true.\n* `ilogb(0.75) = -1`.\n* `frexp(0.75).exp = 0`, excluding the inferred max -1.\n\n### 3. Assumptions and Preconditions Identified\nThe fix relies on these assumptions:\n1. `ilogb(K)` is a sound upper bound for the frexp exponent whenever the branch implies `fabs(x) <= K`.\n2. Inclusive comparisons (`ole`, `ule`) and equality comparisons (`oeq`, `ueq`) can be treated the same as strict less-than for exponent upper-bound purposes.\n3. The zero limit can be handled by the same `ilogb` path as nonzero finite constants.\n4. The extracted frexp exponent integer type is wide enough to represent the APFloat exponent bounds and adjusted bounds without harmful APInt truncation.\n5. Passing only ConstantRange signed min/max to `KnownFPClass::ldexp` is conservative enough for all ranges produced by computeConstantRange.\n6. Unordered predicates are safe provided `KnownSrc.isKnownNeverInfOrNaN()` is checked before constraining the frexp range.\n\n### 4. Potential Cases to Break Assumptions\n* Inclusive bound at exactly 1.0: `fabs(x) <= 1.0` allows `x = +/-1.0`, where frexp exponent is 1, not 0.\n* Equality bound: `fabs(x) == 1.0` or `fabs(x) == 0.5` gives exponent 1 or 0 respectively, but the patch uses ilogb(K), one less for nonzero K.\n* Non-power-of-two bound: `fabs(x) <= 0.75` allows exponents up to 0, while `ilogb(0.75)` is -1.\n* Zero bound: `fabs(x) <= 0.0` implies x is zero (modulo NaN handling), whose frexp exponent is 0; `ilogb(0.0)` is an error sentinel `IEK_Zero`, not a valid upper bound.\n* Narrow exponent result types: the mathematical f32 exponent range does not fit in i8/i1, and APInt construction may wrap values, producing invalid-looking ConstantRanges.\n* Downstream observable effects: integer comparisons on the exponent may fold incorrectly; ldexp known-fp-class may remove infinity checks when the real exponent can still be positive.\n\n### 5. Test Strategies\nThe proposed strategies focus on mutating existing frexp/ldexp InstCombine and known-range tests to make the inferred exponent bound observable through either removed overflow checks or folded integer comparisons. The highest-risk strategies are the inclusive/equality off-by-one cases and zero-limit case because they are direct semantic mismatches with LangRef frexp semantics."
}# Phase 2: Generate Verified Test Cases
You have proposed the following test strategies in Phase 1:
[{'name': 'Inclusive one off-by-one overflow guard', 'target': 'Mutate an existing frexp_fcmp_ole_1 / frexp_fcmp_ogt_1 false-edge test so the ldexp source can be the largest finite float/double and the result is guarded by `fcmp oeq +inf` or an `is_fpclass(inf)` path.', 'rationale': 'The new context range uses ilogb(K) as the inclusive maximum frexp exponent for fabs(x) <= K. For nonzero finite x, frexp exponent is ilogb(x)+1. Thus fabs(x) <= 1.0 permits x=1.0 with exponent 1, but the analysis records max 0.', 'expected_issue': 'The optimizer may prove the frexp exponent is <= 0 and remove an ldexp overflow check, but at x = 1.0 frexp returns exponent 1, so ldexp(max_finite, 1) can overflow to +inf and the removed check was semantically observable.'}, {'name': 'Non-power-of-two bound off-by-one', 'target': 'Mutate the dominating compare constant from 1.0 to 0.75 (or hex f0x3F400000) and add an integer comparison/select on the extracted frexp exponent, such as `select (icmp slt %exp, 0) ...`.', 'rationale': 'For a non-power-of-two K in (0.5, 1), ilogb(K) is -1, but values in [0.5,K] have frexp exponent 0. The patch accepts any finite K <= 1.0, not just strict comparisons against powers of two where ilogb(K) is a valid upper bound.', 'expected_issue': 'Integer users of the exponent may be folded incorrectly, e.g. `icmp sle i32 %exp, -1` or `icmp slt i32 %exp, 0` may become true under a dominating `fabs(x) <= 0.75`, although x=0.75 gives frexp exponent 0.'}, {'name': 'Zero limit pathological range', 'target': 'Mutate the compare limit to `0.0` with a no-NaN/non-inf source and use the extracted exponent in an `icmp` (for example `icmp slt %exp, -1000000`) or downstream ldexp classification.', 'rationale': '`ilogb(0.0)` returns APFloat::IEK_Zero (INT_MIN+1), but frexp(0.0) returns exponent 0. Under `fabs(x) <= 0.0` or `fabs(x) == 0.0`, the patch sets the adjusted max to IEK_Zero rather than 0, making max less than the normal minimum exponent and potentially wrapping when converted to ConstantRange.', 'expected_issue': 'The analysis may create a nonsensical or wrapped ConstantRange for the exponent, possibly leading to wrong folds of comparisons against very negative values, or assertions in debug builds around ConstantRange construction/use.'}, {'name': 'OEQ/UEQ exact-bound exponent', 'target': 'Mutate an existing `fcmp ole/ule` case to `fcmp oeq float fabs(x), 1.0` (and separately `0.5` or `0.75`) on the true edge, then test either `ldexp(max_finite, %exp)` overflow or an `icmp sle %exp, 0` fold.', 'rationale': 'The patch groups `oeq`/`ueq` with less-or-equal predicates. Equality to a finite nonzero magnitude gives a precise frexp exponent of ilogb(K)+1, not ilogb(K). With `nofpclass(nan inf)` on the source, unordered complications are removed and the off-by-one becomes directly observable.', 'expected_issue': 'Equality cases may be optimized as if the exponent is <= ilogb(K), but when fabs(x) == K and K is nonzero, the exponent is ilogb(K)+1; this can miscompile both integer exponent tests and ldexp overflow pruning.'}, {'name': 'Narrow frexp exponent type wrapping', 'target': 'Mutate `known-range-frexp-exp.ll` or the dominating-condition test to declare/use `@llvm.frexp.f32.i8` (and possibly i1/i2), extract the exponent, and feed it to signed `icmp` or `llvm.ldexp.f32.i8` under a dominating `fabs(x) < 1.0` condition.', 'rationale': 'The frexp exponent range for float is roughly [-149,128], which does not fit in i8 and certainly not in i1/i2. The patch constructs `APInt(BitWidth, MinExp, isSigned=true)` and `APInt(BitWidth, MaxExp+1, isSigned=true)`, so narrow result types can wrap the mathematical bounds. Existing tests cover i16/i128 but not too-narrow types.', 'expected_issue': 'For small integer exponent result types, min/max APInt construction may truncate the real float exponent bounds, producing wrapped or overly precise ConstantRanges and incorrect signed comparisons or known-fp-class deductions.'}]
## Your Task for Phase 2
In this phase, you will use the `tests_manager` tool to retrieve existing test cases, apply your proposed mutations, and verify them. You must ensure that **every test case** managed by the `tests_manager` is processed and marked as tested.
Follow this structured workflow:
### Step 1: Retrieve and Prioritize Test Cases
- Use the `tests_manager` tool with the `list` action to see all available test cases and their current status.
- Use the `tests_manager` tool with the `get` action to retrieve the full details of an untested test case.
- Due to context length and round limit, you should prioritize test cases that are more relevant to the identified issues.
### Step 2: Understand the Test Case
- Analyze the selected test case to understand its structure, input characteristics, and what it is testing.
- Call the `verify` tool to see how the LLVM IR code in the test case is transformed by the optimization pass. This can help you understand the semantics of the test case and how it relates to the fix.
### Step 3: Apply Mutations
For the selected test case, apply mutations according to your proposed test strategies:
- **Focus**: Ensure the mutations focus on exposing the potential issues identified in Phase 1.
- **Format**: Provide each mutated test case in a separate ```llvm ... ``` code block.
- **Coverage**: **CRITICAL**: You must cover all the proposed test strategies across different test cases to ensure comprehensive testing of potential issues.
### Step 4: Verify and Test
- **Verify Tool**: Use the `verify` tool to submit the generated test cases along with your reasoning. This uses `alive2` to check if the test cases expose any issues with the fix.
- **Difftest Tool**: Use the `difftest` tool to execute the original and optimized LLVM IR (transformed by `opt`) with specific input values to check for execution differences.
### Step 5: Analyze Results and Refine
- If the `verify` or `difftest` fails to find issues, refine the test case only if you believe unexplored potential issues remain. Otherwise, move on to other strategies or test cases. Check **Guidelines for Refining Test Cases** below for suggestions on how to refine test cases based on verification results.
### Step 6: Mark as Tested
- Once you have fully explored and verified a test case, use the `tests_manager` tool with the `mark_tested` action to mark it as completed.
- **CRITICAL**: You must repeat this process until the `tests_manager` confirms that **all** test cases have been tested.
Repeat the above steps for each test case until all test cases in the `tests_manager` are marked as tested.
You are also allowed to generate tests from scratch or find more related tests from the LLVM test suite by using `find` or `list` tools and reading them with `read` or `grep` tools if you think the provided test cases have limited coverage of potential issues. Make sure you call `verify` and `difftest` tools to check the validity of these test cases and confirm whether the issues can be exposed by actual execution.
---
## Guidelines for Refining Test Cases
### Important Rule
You can always keep mutating the test case and verifying it until you find an issue or are confident that no issues can be found. However, make sure it is aligned with the potential issues you identified in Phase 1. Meanwhile, avoid stucking on a test case for too long. If you have tried multiple mutations and still cannot find any issues, move on to other test cases or strategies.
### Handling Verification Results
- **Failed-to-prove**:
1. Try to reduce the test case to a smaller example that still fails. This can help isolate the specific conditions that cause the issue.
2. Try to call `difftest` to run the test case with specific input value that you think can trigger the issue based on your analysis. This can help check if the issue can be exposed by actual execution even if it cannot be proved by alive2.
- **Alive2 errors**: Try to call `trans` to run opt with the same command arguments and adjust the test case or command arguments to fix.
- **Correct transformation**: Try to first analyze if the test strategy is correct and then decide to refine the test case or continue to generate other test cases.
### Additional Notes
- **Coverage**: If you think the provided test cases have limited coverage of potential issues, you can also find more related tests from the LLVM test suite by using `find` or `list` tools and reading them with `read` or `grep` tools.
- **Completeness**: Make sure you have at least explored all the test strategies you proposed in Phase 1, and generated multiple test cases if possible.
- **Completion**: You cannot finish Phase 2 until all tests in the `tests_manager` are marked as tested.
---
## Tools that you can use
- `findN`: Search for files in the LLVM codebase related to the component or optimization pass to understand the context of the fix and find relevant tests.
- `listN`: List files in the LLVM codebase to find relevant tests or code regions.
- `readN`: Read the content of a file in the LLVM codebase to understand existing tests or the fix.
- `grepN`: Search for specific patterns in the codebase to find relevant tests or code regions.
- `langref`: Query the LLVM Language Reference Manual for specific instructions, semantics, or optimization details relevant to the fix.
- `tests_manager`: Manage the list of test cases. You can list all tests to see their status, get the details of a specific test, or mark a test as tested. Your goal is to ensure all tests are tested.
- `trans`: Run the `opt` tool with specific arguments to see how the LLVM IR code is transformed by the optimization pass.
- `verify`: Use alive2 to verify if the transformation from original LLVM IR code to optimized LLVM IR code is correct, which can help check the validity of generated test cases in Phase 2.
- `difftest`: Use llubi to perform differential testing on the original and transformed LLVM IR code, which can help check if the generated test cases cannot be proved by alive2.
- `report`: End Phase 2 by submitting the generated test cases and their verification results.{"action":"list"}{
"tests": [
{
"index": 0,
"name": "ret_ldexp_f32_neg127",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 1,
"name": "ret_ldexp_f32_noinf_exp_known_neg_or_0",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 2,
"name": "ret_ldexp_v2f32_known_neg_exp_noinf_nonsplat",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 3,
"name": "ret_ldexp_v2f32_known_pos_exp_noinf",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 4,
"name": "ret_ldexp_v2f32_known_neg_exp_noinf_splat",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 5,
"name": "frexp_fcmp_ule_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 6,
"name": "frexp_fcmp_une_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 7,
"name": "frexp_fcmp_oeq_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 8,
"name": "frexp_fcmp_ogt_nextdown1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 9,
"name": "frexp_fcmp_one_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 10,
"name": "frexp_fcmp_olt_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 11,
"name": "frexp_cmp_uge_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 12,
"name": "frexp_fcmp_ogt_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 13,
"name": "frexp_fcmp_ugt_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 14,
"name": "frexp_fcmp_one_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 15,
"name": "frexp_fcmp_olt_1_multiple_conditions_wrong_constant",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 16,
"name": "frexp_cmp_ugt_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 17,
"name": "frexp_fcmp_ole_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 18,
"name": "frexp_fcmp_ueq_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 19,
"name": "frexp_fcmp_oeq_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 20,
"name": "frexp_fcmp_ogt_1_large_int",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 21,
"name": "frexp_fcmp_ult_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 22,
"name": "frexp_fcmp_une_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 23,
"name": "frexp_fcmp_olt_1_multiple_conditions_nonfinite_constant",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 24,
"name": "frexp_fcmp_ole_nextdown1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 25,
"name": "frexp_fcmp_olt_1_multiple_conditions_other",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 26,
"name": "frexp_fcmp_ueq_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 27,
"name": "frexp_fcmp_ule_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 28,
"name": "frexp_fcmp_olt_1_multiple_conditions_edge_case_compare",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 29,
"name": "frexp_fcmp_uge_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 30,
"name": "frexp_fcmp_oge_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 31,
"name": "frexp_fcmp_uge_0.5",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 32,
"name": "frexp_fcmp_ugt_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 33,
"name": "frexp_fcmp_ult_1",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 34,
"name": "ldexp_v2f32_v2i32_fmul_crash",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
},
{
"index": 35,
"name": "qnan_result_demands_snan_src",
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
}
],
"all_tested": false,
"message": "Some tests have not covered all Phase 1 strategies yet."
}{"action":"get","index":17}{
"test_name": "frexp_fcmp_ole_1",
"test_body": "define float @frexp_fcmp_ole_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {\n %x.fabs = call float @llvm.fabs.f32(float %x)\n %is.small = fcmp ole float %x.fabs, 1.000000e+00\n br i1 %is.small, label %small, label %large\n\nsmall: ; preds = %0\n %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %exp = extractvalue { float, i32 } %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)\n %is.inf = fcmp oeq float %scaled, +inf\n %select = select i1 %is.inf, float 0.000000e+00, float %scaled\n ret float %select\n\nlarge: ; preds = %0\n ret float 0.000000e+00\n}\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare float @llvm.fabs.f32(float) #0\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare float @llvm.ldexp.f32.i32(float, i32) #0\n\nattributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }\n",
"commands": [
"opt -S -passes=instcombine < %s"
],
"tested": false,
"uncovered_strategies": [
"Narrow frexp exponent type wrapping",
"OEQ/UEQ exact-bound exponent",
"Zero limit pathological range",
"Non-power-of-two bound off-by-one",
"Inclusive one off-by-one overflow guard"
]
}{"args":"-passes=instcombine","orig_ir":"```llvm\ndefine float @frexp_fcmp_ole_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {\n %x.fabs = call float @llvm.fabs.f32(float %x)\n %is.small = fcmp ole float %x.fabs, 1.000000e+00\n br i1 %is.small, label %small, label %large\n\nsmall:\n %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %exp = extractvalue { float, i32 } %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)\n %is.inf = fcmp oeq float %scaled, +inf\n %select = select i1 %is.inf, float 0.000000e+00, float %scaled\n ret float %select\n\nlarge:\n ret float 0.000000e+00\n}\n\ndeclare float @llvm.fabs.f32(float) #0\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\ndeclare float @llvm.ldexp.f32.i32(float, i32) #0\nattributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }\n```"}{"found": false, "tool": "verify", "args": "-passes=instcombine", "original_ir": "define float @frexp_fcmp_ole_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {\n %x.fabs = call float @llvm.fabs.f32(float %x)\n %is.small = fcmp ole float %x.fabs, 1.000000e+00\n br i1 %is.small, label %small, label %large\n\nsmall:\n %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %exp = extractvalue { float, i32 } %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)\n %is.inf = fcmp oeq float %scaled, +inf\n %select = select i1 %is.inf, float 0.000000e+00, float %scaled\n ret float %select\n\nlarge:\n ret float 0.000000e+00\n}\n\ndeclare float @llvm.fabs.f32(float) #0\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\ndeclare float @llvm.ldexp.f32.i32(float, i32) #0\nattributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }", "transformed_ir": "; ModuleID = '/data/tmp/tmp28icunly/orig.ll'\nsource_filename = \"/data/tmp/tmp28icunly/orig.ll\"\n\ndefine float @frexp_fcmp_ole_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {\n %x.fabs = call float @llvm.fabs.f32(float %x)\n %is.small = fcmp ugt float %x.fabs, 1.000000e+00\n br i1 %is.small, label %large, label %small\n\nsmall: ; preds = %0\n %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %exp = extractvalue { float, i32 } %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)\n ret float %scaled\n\nlarge: ; preds = %0\n ret float 0.000000e+00\n}\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare float @llvm.fabs.f32(float) #0\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare float @llvm.ldexp.f32.i32(float, i32) #0\n\nattributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }\n", "log": "----------------------------------------\ndeclare float @llvm.ldexp.f32.i32(float, i32) nofree willreturn memory(none)\n\ndefine float @frexp_fcmp_ole_1(float nofpclass(519) %x, float nofpclass(516) %not.inf) {\n#0:\n %x.fabs = fabs float nofpclass(519) %x\n %is.small = fcmp ole float %x.fabs, 1e+00\n br i1 %is.small, label %small, label %large\n\nlarge:\n ret float 0e+00\n\nsmall:\n %frexp = frexp float nofpclass(519) %x\n %exp = extractvalue {float, i32} %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float nofpclass(516) %not.inf, i32 %exp) nofree willreturn memory(none)\n %is.inf = fcmp oeq float %scaled, inf\n %select = select i1 %is.inf, float 0e+00, float %scaled\n ret float %select\n}\n=>\ndeclare float @llvm.ldexp.f32.i32(float, i32) nofree willreturn memory(none)\n\ndefine float @frexp_fcmp_ole_1(float nofpclass(519) %x, float nofpclass(516) %not.inf) {\n#0:\n %x.fabs = fabs float nofpclass(519) %x\n %is.small = fcmp ugt float %x.fabs, 1e+00\n br i1 %is.small, label %large, label %small\n\nsmall:\n %frexp = frexp float nofpclass(519) %x\n %exp = extractvalue {float, i32} %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float nofpclass(516) %not.inf, i32 %exp) nofree willreturn memory(none)\n ret float %scaled\n\nlarge:\n ret float 0e+00\n}\nERROR: Couldn't prove the correctness of the transformation\nAlive2 approximated the semantics of the programs and therefore we\ncannot conclude whether the bug found is valid or not.\n\nApproximations done:\n - Unknown libcall: @llvm.ldexp.f32.i32\n\n\nSummary:\n 0 correct transformations\n 0 incorrect transformations\n 1 failed-to-prove transformations\n 0 Alive2 errors"}{"action":"test","args":"-S -passes=instcombine","call_instr":"call float @frexp_fcmp_ole_1(float 1.000000e+00, float 0x47EFFFFFE0000000)","covered_strategy":"Inclusive one off-by-one overflow guard","is_bug":false,"orig_ir":"```llvm\ndefine float @frexp_fcmp_ole_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {\n %x.fabs = call float @llvm.fabs.f32(float %x)\n %is.small = fcmp ole float %x.fabs, 1.000000e+00\n br i1 %is.small, label %small, label %large\n\nsmall:\n %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %exp = extractvalue { float, i32 } %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)\n %is.inf = fcmp oeq float %scaled, +inf\n %select = select i1 %is.inf, float 0.000000e+00, float %scaled\n ret float %select\n\nlarge:\n ret float 0.000000e+00\n}\n\ndeclare float @llvm.fabs.f32(float) #0\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\ndeclare float @llvm.ldexp.f32.i32(float, i32) #0\nattributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }\n```","test_index":17,"thoughts":"Testing inclusive <= 1 off-by-one: x=1 gives frexp exp 1, and max finite ldexp by 1 overflows to +inf. Original selects 0 on inf; optimized removed guard and returns inf if patch is unsound.","use_lli":true}Error: [Errno 2] No such file or directory: 'bin/lli'
{"action":"test","args":"-S -passes=instcombine","call_instr":"call float @frexp_fcmp_ole_1(float 1.000000e+00, float 0x47EFFFFFE0000000)","covered_strategy":"Inclusive one off-by-one overflow guard","orig_ir":"```llvm\ndefine float @frexp_fcmp_ole_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {\n %x.fabs = call float @llvm.fabs.f32(float %x)\n %is.small = fcmp ole float %x.fabs, 1.000000e+00\n br i1 %is.small, label %small, label %large\n\nsmall:\n %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %exp = extractvalue { float, i32 } %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)\n %is.inf = fcmp oeq float %scaled, +inf\n %select = select i1 %is.inf, float 0.000000e+00, float %scaled\n ret float %select\n\nlarge:\n ret float 0.000000e+00\n}\n\ndeclare float @llvm.fabs.f32(float) #0\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\ndeclare float @llvm.ldexp.f32.i32(float, i32) #0\nattributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }\n```","test_index":17,"thoughts":"Testing inclusive <= 1 off-by-one: x=1 gives frexp exp 1, and max finite ldexp by 1 overflows to +inf. Original selects 0 on inf; optimized removed guard and returns inf if patch is unsound."}{"found": false, "tool": "difftest", "action": "test", "args": "-S -passes=instcombine", "original_ir": "\ndefine float @frexp_fcmp_ole_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {\n %x.fabs = call float @llvm.fabs.f32(float %x)\n %is.small = fcmp ole float %x.fabs, 1.000000e+00\n br i1 %is.small, label %small, label %large\n\nsmall:\n %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %exp = extractvalue { float, i32 } %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)\n %is.inf = fcmp oeq float %scaled, +inf\n %select = select i1 %is.inf, float 0.000000e+00, float %scaled\n ret float %select\n\nlarge:\n ret float 0.000000e+00\n}\n\ndeclare float @llvm.fabs.f32(float) #0\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\ndeclare float @llvm.ldexp.f32.i32(float, i32) #0\nattributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }\n\ndefine float @main(i32 %argc, ptr %argv) {\nentry:\n %r = call float @frexp_fcmp_ole_1(float 1.000000e+00, float 0x47EFFFFFE0000000)\n ret float %r\n}\n", "transformed_ir": "\n; ModuleID = '/data/tmp/tmp4jdpnvss/orig.ll'\nsource_filename = \"/data/tmp/tmp4jdpnvss/orig.ll\"\n\ndefine float @frexp_fcmp_ole_1(float nofpclass(nan inf) %x, float nofpclass(inf) %not.inf) {\n %x.fabs = call float @llvm.fabs.f32(float %x)\n %is.small = fcmp ugt float %x.fabs, 1.000000e+00\n br i1 %is.small, label %large, label %small\n\nsmall: ; preds = %0\n %frexp = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %exp = extractvalue { float, i32 } %frexp, 1\n %scaled = call float @llvm.ldexp.f32.i32(float %not.inf, i32 %exp)\n ret float %scaled\n\nlarge: ; preds = %0\n ret float 0.000000e+00\n}\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare float @llvm.fabs.f32(float) #0\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare float @llvm.ldexp.f32.i32(float, i32) #0\n\nattributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }\n\ndefine float @main(i32 %argc, ptr %argv) {\nentry:\n %r = call float @frexp_fcmp_ole_1(float 1.000000e+00, float 0x47EFFFFFE0000000)\n ret float %r\n}\n", "log": {"original_test_output": {"timed_out": false, "return_code": 1, "stdout": "", "stderr": "/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy: /data/tmp/tmpuj6dmvhu/orig.ll:11:37: error: expected value token\n %is.inf = fcmp oeq float %scaled, +inf\n ^", "executor": "llubi"}, "transformed_test_output": {"timed_out": false, "return_code": -6, "stdout": "", "stderr": "Unsupported intrinsic: llvm.frexp.f32.i32\nPLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.\nStack dump:\n0.\tProgram arguments: /data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy /data/tmp/tmpuj6dmvhu/transformed.ll\n #0 0x000071b0db868a68 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/data/yunboni/utils/compilers/llvm_latest_llubi/lib/libLLVM.so.23.0git+0x868a68)\n #1 0x000071b0db8658e5 llvm::sys::RunSignalHandlers() (/data/yunboni/utils/compilers/llvm_latest_llubi/lib/libLLVM.so.23.0git+0x8658e5)\n #2 0x000071b0db8698c1 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0\n #3 0x000071b0da845330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)\n #4 0x000071b0da89eb2c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76\n #5 0x000071b0da89eb2c __pthread_kill_internal ./nptl/pthread_kill.c:78:10\n #6 0x000071b0da89eb2c pthread_kill ./nptl/pthread_kill.c:89:10\n #7 0x000071b0da84527e raise ./signal/../sysdeps/posix/raise.c:27:6\n #8 0x000071b0da8288ff abort ./stdlib/abort.c:81:7\n #9 0x00005d4c1637770c UBAwareInterpreter::callIntrinsic(llvm::IntrinsicInst&, llvm::SmallVectorImpl<AnyValue>&) (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x3b70c)\n#10 0x00005d4c1637e488 UBAwareInterpreter::call(llvm::Function*, llvm::CallBase*, llvm::SmallVectorImpl<AnyValue>&) (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x42488)\n#11 0x00005d4c1638154c UBAwareInterpreter::handleCall(llvm::CallBase&) (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x4554c)\n#12 0x00005d4c16381a2f UBAwareInterpreter::visitCallInst(llvm::CallInst&) (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x45a2f)\n#13 0x00005d4c1637ea64 UBAwareInterpreter::call(llvm::Function*, llvm::CallBase*, llvm::SmallVectorImpl<AnyValue>&) (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x42a64)\n#14 0x00005d4c1638154c UBAwareInterpreter::handleCall(llvm::CallBase&) (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x4554c)\n#15 0x00005d4c16381a2f UBAwareInterpreter::visitCallInst(llvm::CallInst&) (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x45a2f)\n#16 0x00005d4c1637ea64 UBAwareInterpreter::call(llvm::Function*, llvm::CallBase*, llvm::SmallVectorImpl<AnyValue>&) (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x42a64)\n#17 0x00005d4c163821b7 UBAwareInterpreter::runMain() (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x461b7)\n#18 0x00005d4c1634beab main (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0xfeab)\n#19 0x000071b0da82a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3\n#20 0x000071b0da82a28b call_init ./csu/../csu/libc-start.c:128:20\n#21 0x000071b0da82a28b __libc_start_main ./csu/../csu/libc-start.c:347:5\n#22 0x00005d4c1634c155 _start (/data/yunboni/projects/Archer/deps/llvm-ub-aware-interpreter/build/llubi_legacy+0x10155)", "executor": "llubi"}}, "thoughts": "Testing inclusive <= 1 off-by-one: x=1 gives frexp exp 1, and max finite ldexp by 1 overflows to +inf. Original selects 0 on inf; optimized removed guard and returns inf if patch is unsound.", "test_index": 17, "covered_strategy": "Inclusive one off-by-one overflow guard"}{"args":"-passes=instcombine","orig_ir":"```llvm\ndefine i1 @bug_ole_one_exp_le0(float nofpclass(nan inf) %x) {\nentry:\n %abs = call float @llvm.fabs.f32(float %x)\n %c = fcmp ole float %abs, 1.0\n br i1 %c, label %small, label %large\nsmall:\n %fx = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %e = extractvalue { float, i32 } %fx, 1\n %r = icmp sle i32 %e, 0\n ret i1 %r\nlarge:\n ret i1 false\n}\ndeclare float @llvm.fabs.f32(float) #0\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\nattributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }\n```"}{"found": true, "tool": "verify", "args": "-passes=instcombine", "original_ir": "define i1 @bug_ole_one_exp_le0(float nofpclass(nan inf) %x) {\nentry:\n %abs = call float @llvm.fabs.f32(float %x)\n %c = fcmp ole float %abs, 1.0\n br i1 %c, label %small, label %large\nsmall:\n %fx = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %e = extractvalue { float, i32 } %fx, 1\n %r = icmp sle i32 %e, 0\n ret i1 %r\nlarge:\n ret i1 false\n}\ndeclare float @llvm.fabs.f32(float) #0\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\nattributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }", "transformed_ir": "; ModuleID = '/data/tmp/tmp0upfw8ci/orig.ll'\nsource_filename = \"/data/tmp/tmp0upfw8ci/orig.ll\"\n\ndefine i1 @bug_ole_one_exp_le0(float nofpclass(nan inf) %x) {\nentry:\n %abs = call float @llvm.fabs.f32(float %x)\n %c = fcmp ugt float %abs, 1.000000e+00\n br i1 %c, label %large, label %small\n\nsmall: ; preds = %entry\n ret i1 true\n\nlarge: ; preds = %entry\n ret i1 false\n}\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare float @llvm.fabs.f32(float) #0\n\n; Function Attrs: nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none)\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\n\nattributes #0 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }\n", "log": "----------------------------------------\ndefine i1 @bug_ole_one_exp_le0(float nofpclass(519) %x) {\nentry:\n %abs = fabs float nofpclass(519) %x\n %c = fcmp ole float %abs, 1e+00\n br i1 %c, label %small, label %large\n\nlarge:\n ret i1 0\n\nsmall:\n %fx = frexp float nofpclass(519) %x\n %e = extractvalue {float, i32} %fx, 1\n %r = icmp sle i32 %e, 0\n ret i1 %r\n}\n=>\ndefine i1 @bug_ole_one_exp_le0(float nofpclass(519) %x) {\nentry:\n %abs = fabs float nofpclass(519) %x\n %c = fcmp ugt float %abs, 1e+00\n br i1 %c, label %large, label %small\n\nsmall:\n ret i1 1\n\nlarge:\n ret i1 0\n}\nTransformation doesn't verify!\n\nERROR: Value mismatch\n\nExample:\nfloat nofpclass(519) %x = #x3f800000 (1e+00)\n\nSource:\nfloat %abs = #x3f800000 (1e+00)\ni1 %c = #x1 (1)\n >> Jump to %small\n{float, i32} %fx = { #x3f000000 (5e-01), #x00000001 (1) }\ni32 %e = #x00000001 (1)\ni1 %r = #x0 (0)\n\nTarget:\nfloat %abs = #x3f800000 (1e+00)\ni1 %c = #x0 (0)\n >> Jump to %small\nSource value: #x0 (0)\nTarget value: #x1 (1)\n\nSummary:\n 0 correct transformations\n 1 incorrect transformations\n 0 failed-to-prove transformations\n 0 Alive2 errors"}{"force":true,"test":["```llvm\ndefine i1 @bug_ole_one_exp_le0(float nofpclass(nan inf) %x) {\nentry:\n %abs = call float @llvm.fabs.f32(float %x)\n %c = fcmp ole float %abs, 1.0\n br i1 %c, label %small, label %large\n\nsmall:\n %fx = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %e = extractvalue { float, i32 } %fx, 1\n %r = icmp sle i32 %e, 0\n ret i1 %r\n\nlarge:\n ret i1 false\n}\n\ndeclare float @llvm.fabs.f32(float) #0\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\nattributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }\n```","opt -S -passes=instcombine repro.ll"],"thoughts":"## Bug Triggering Analysis\nThe patch infers the exponent range of `llvm.frexp` from a dominating `fabs(x) <= 1.0` condition by using `ilogb(1.0) == 0` as the maximum exponent. This is off by one for nonzero finite inputs: `frexp(1.0)` returns mantissa `0.5` and exponent `1`. The reduced test makes this observable with `icmp sle i32 %e, 0`. InstCombine transforms the guarded block to `ret i1 true`, but Alive2 produces the counterexample `x = 1.0`, where the original returns false.\n\nAlive2 verification result:\n- Command: `alive-tv -passes=instcombine`\n- Result: incorrect transformation\n- Counterexample: `%x = 1.0f`\n- Source: `%e = 1`, `%r = false`\n- Target: `true`\n\n## Fix Weakness Analysis\nThe weakness is in `computeKnownExponentRangeFromContext`: it treats `ilogb(K)` as an inclusive upper bound for the frexp exponent when the path implies `fabs(x) <= K`. For finite nonzero values, frexp's exponent is `ilogb(x) + 1`, so inclusive/equality predicates at the boundary are unsound. The same issue likely affects `oeq/ueq` and non-power-of-two constants such as `0.75`, and zero requires special handling because `ilogb(0.0)` returns an error sentinel while `frexp(0.0)` returns exponent `0`."}{
"test": [
"```llvm\ndefine i1 @bug_ole_one_exp_le0(float nofpclass(nan inf) %x) {\nentry:\n %abs = call float @llvm.fabs.f32(float %x)\n %c = fcmp ole float %abs, 1.0\n br i1 %c, label %small, label %large\n\nsmall:\n %fx = call { float, i32 } @llvm.frexp.f32.i32(float %x)\n %e = extractvalue { float, i32 } %fx, 1\n %r = icmp sle i32 %e, 0\n ret i1 %r\n\nlarge:\n ret i1 false\n}\n\ndeclare float @llvm.fabs.f32(float) #0\ndeclare { float, i32 } @llvm.frexp.f32.i32(float) #0\nattributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }\n```",
"opt -S -passes=instcombine repro.ll"
],
"thoughts": "## Bug Triggering Analysis\nThe patch infers the exponent range of `llvm.frexp` from a dominating `fabs(x) <= 1.0` condition by using `ilogb(1.0) == 0` as the maximum exponent. This is off by one for nonzero finite inputs: `frexp(1.0)` returns mantissa `0.5` and exponent `1`. The reduced test makes this observable with `icmp sle i32 %e, 0`. InstCombine transforms the guarded block to `ret i1 true`, but Alive2 produces the counterexample `x = 1.0`, where the original returns false.\n\nAlive2 verification result:\n- Command: `alive-tv -passes=instcombine`\n- Result: incorrect transformation\n- Counterexample: `%x = 1.0f`\n- Source: `%e = 1`, `%r = false`\n- Target: `true`\n\n## Fix Weakness Analysis\nThe weakness is in `computeKnownExponentRangeFromContext`: it treats `ilogb(K)` as an inclusive upper bound for the frexp exponent when the path implies `fabs(x) <= K`. For finite nonzero values, frexp's exponent is `ilogb(x) + 1`, so inclusive/equality predicates at the boundary are unsound. The same issue likely affects `oeq/ueq` and non-power-of-two constants such as `0.75`, and zero requires special handling because `ilogb(0.0)` returns an error sentinel while `frexp(0.0)` returns exponent `0`.",
"force": true
}