diff options
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 36 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/known-never-nan.ll | 51 |
2 files changed, 43 insertions, 44 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index a89c8771234..48d48f275c3 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2930,9 +2930,6 @@ bool llvm::isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI, if (FPMathOp->hasNoNaNs()) return true; - // TODO: Handle instructions and potentially recurse like other 'isKnown' - // functions. For example, the result of sitofp is never NaN. - // Handle scalar constants. if (auto *CFP = dyn_cast<ConstantFP>(V)) return !CFP->isNaN(); @@ -2940,11 +2937,44 @@ bool llvm::isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI, if (Depth == MaxDepth) return false; + if (auto *Inst = dyn_cast<Instruction>(V)) { + switch (Inst->getOpcode()) { + case Instruction::FAdd: + case Instruction::FMul: + case Instruction::FSub: + case Instruction::FDiv: + case Instruction::FRem: { + // TODO: Need isKnownNeverInfinity + return false; + } + case Instruction::Select: { + return isKnownNeverNaN(Inst->getOperand(1), TLI, Depth + 1) && + isKnownNeverNaN(Inst->getOperand(2), TLI, Depth + 1); + } + case Instruction::SIToFP: + case Instruction::UIToFP: + return true; + case Instruction::FPTrunc: + case Instruction::FPExt: + return isKnownNeverNaN(Inst->getOperand(0), TLI, Depth + 1); + default: + break; + } + } + if (const auto *II = dyn_cast<IntrinsicInst>(V)) { switch (II->getIntrinsicID()) { case Intrinsic::canonicalize: case Intrinsic::fabs: case Intrinsic::copysign: + case Intrinsic::exp: + case Intrinsic::exp2: + case Intrinsic::floor: + case Intrinsic::ceil: + case Intrinsic::trunc: + case Intrinsic::rint: + case Intrinsic::nearbyint: + case Intrinsic::round: return isKnownNeverNaN(II->getArgOperand(0), TLI, Depth + 1); case Intrinsic::sqrt: return isKnownNeverNaN(II->getArgOperand(0), TLI, Depth + 1) && diff --git a/llvm/test/Transforms/InstCombine/known-never-nan.ll b/llvm/test/Transforms/InstCombine/known-never-nan.ll index 1d26c203239..3b0549311be 100644 --- a/llvm/test/Transforms/InstCombine/known-never-nan.ll +++ b/llvm/test/Transforms/InstCombine/known-never-nan.ll @@ -69,10 +69,7 @@ define i1 @fabs_sqrt_src_maybe_nan(double %arg0, double %arg1) { define i1 @exp_nnan_src(double %arg) { ; CHECK-LABEL: @exp_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.exp.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.exp.f64(double %nnan) @@ -82,10 +79,7 @@ define i1 @exp_nnan_src(double %arg) { define i1 @exp2_nnan_src(double %arg) { ; CHECK-LABEL: @exp2_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.exp2.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.exp2.f64(double %nnan) @@ -95,10 +89,7 @@ define i1 @exp2_nnan_src(double %arg) { define i1 @floor_nnan_src(double %arg) { ; CHECK-LABEL: @floor_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.floor.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.floor.f64(double %nnan) @@ -108,10 +99,7 @@ define i1 @floor_nnan_src(double %arg) { define i1 @ceil_nnan_src(double %arg) { ; CHECK-LABEL: @ceil_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.ceil.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.ceil.f64(double %nnan) @@ -121,10 +109,7 @@ define i1 @ceil_nnan_src(double %arg) { define i1 @trunc_nnan_src(double %arg) { ; CHECK-LABEL: @trunc_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.trunc.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.trunc.f64(double %nnan) @@ -134,10 +119,7 @@ define i1 @trunc_nnan_src(double %arg) { define i1 @rint_nnan_src(double %arg) { ; CHECK-LABEL: @rint_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.rint.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.rint.f64(double %nnan) @@ -147,10 +129,7 @@ define i1 @rint_nnan_src(double %arg) { define i1 @nearbyint_nnan_src(double %arg) { ; CHECK-LABEL: @nearbyint_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.nearbyint.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.nearbyint.f64(double %nnan) @@ -160,10 +139,7 @@ define i1 @nearbyint_nnan_src(double %arg) { define i1 @round_nnan_src(double %arg) { ; CHECK-LABEL: @round_nnan_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.round.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.round.f64(double %nnan) @@ -173,11 +149,7 @@ define i1 @round_nnan_src(double %arg) { define i1 @known_nan_select(i1 %cond, double %arg0, double %arg1) { ; CHECK-LABEL: @known_nan_select( -; CHECK-NEXT: [[LHS:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00 -; CHECK-NEXT: [[RHS:%.*]] = fadd nnan double [[ARG1:%.*]], 2.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = select i1 [[COND:%.*]], double [[LHS]], double [[RHS]] -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %lhs = fadd nnan double %arg0, 1.0 %rhs = fadd nnan double %arg1, 2.0 @@ -334,10 +306,7 @@ define i1 @fpext_maybe_nan(float %arg0) { define i1 @fptrunc(double %arg0) { ; CHECK-LABEL: @fptrunc( -; CHECK-NEXT: [[ARG0_NNAN:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = fptrunc double [[ARG0_NNAN]] to float -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord float [[OP]], 0.000000e+00 -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %arg0.nnan = fadd nnan double %arg0, 1.0 %op = fptrunc double %arg0.nnan to float |