diff options
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 12 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/known-never-nan.ll | 191 | ||||
-rw-r--r-- | llvm/test/Transforms/InstSimplify/known-never-nan.ll | 90 |
3 files changed, 33 insertions, 260 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 35aaf96d15b..290d169df24 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3511,13 +3511,11 @@ static Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, if (Pred == FCmpInst::FCMP_TRUE) return getTrue(RetTy); - // UNO/ORD predicates can be trivially folded if NaNs are ignored. - if (FMF.noNaNs()) { - if (Pred == FCmpInst::FCMP_UNO) - return getFalse(RetTy); - if (Pred == FCmpInst::FCMP_ORD) - return getTrue(RetTy); - } + // Fold (un)ordered comparison if we can determine there are no NaNs. + if (Pred == FCmpInst::FCMP_UNO || Pred == FCmpInst::FCMP_ORD) + if (FMF.noNaNs() || + (isKnownNeverNaN(LHS, Q.TLI) && isKnownNeverNaN(RHS, Q.TLI))) + return ConstantInt::get(RetTy, Pred == FCmpInst::FCMP_ORD); // NaN is unordered; NaN is not ordered. assert((FCmpInst::isOrdered(Pred) || FCmpInst::isUnordered(Pred)) && diff --git a/llvm/test/Transforms/InstCombine/known-never-nan.ll b/llvm/test/Transforms/InstCombine/known-never-nan.ll index 3b0549311be..23a0780fe43 100644 --- a/llvm/test/Transforms/InstCombine/known-never-nan.ll +++ b/llvm/test/Transforms/InstCombine/known-never-nan.ll @@ -1,58 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -instcombine %s | FileCheck %s +; RUN: opt < %s -S -instcombine | FileCheck %s -declare double @func() - -define i1 @nnan_call() { -; CHECK-LABEL: @nnan_call( -; CHECK-NEXT: [[OP:%.*]] = call nnan double @func() -; CHECK-NEXT: ret i1 true -; - %op = call nnan double @func() - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @nnan_fabs_src(double %arg) { -; CHECK-LABEL: @nnan_fabs_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.fabs.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @nnan_canonicalize_src(double %arg) { -; CHECK-LABEL: @nnan_canonicalize_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.canonicalize.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @nnan_copysign_src(double %arg0, double %arg1) { -; CHECK-LABEL: @nnan_copysign_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg0, 1.0 - %op = call double @llvm.copysign.f64(double %nnan, double %arg1) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @fabs_sqrt_src(double %arg0, double %arg1) { -; CHECK-LABEL: @fabs_sqrt_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg0, 1.0 - %fabs = call double @llvm.fabs.f64(double %nnan) - %op = call double @llvm.sqrt.f64(double %fabs) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} +; This file used to contain more tests that folded to true/false, +; but those are all tested identically in InstSimplify now. +; If any remaining tests are made to return true/false, that +; functionality/testing may be better housed in InstSimplify +; rather than InstCombine. define i1 @fabs_sqrt_src_maybe_nan(double %arg0, double %arg1) { ; CHECK-LABEL: @fabs_sqrt_src_maybe_nan( @@ -67,97 +20,6 @@ define i1 @fabs_sqrt_src_maybe_nan(double %arg0, double %arg1) { ret i1 %tmp } -define i1 @exp_nnan_src(double %arg) { -; CHECK-LABEL: @exp_nnan_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.exp.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @exp2_nnan_src(double %arg) { -; CHECK-LABEL: @exp2_nnan_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.exp2.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @floor_nnan_src(double %arg) { -; CHECK-LABEL: @floor_nnan_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.floor.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @ceil_nnan_src(double %arg) { -; CHECK-LABEL: @ceil_nnan_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.ceil.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @trunc_nnan_src(double %arg) { -; CHECK-LABEL: @trunc_nnan_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.trunc.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @rint_nnan_src(double %arg) { -; CHECK-LABEL: @rint_nnan_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.rint.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @nearbyint_nnan_src(double %arg) { -; CHECK-LABEL: @nearbyint_nnan_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.nearbyint.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @round_nnan_src(double %arg) { -; CHECK-LABEL: @round_nnan_src( -; CHECK-NEXT: ret i1 true -; - %nnan = fadd nnan double %arg, 1.0 - %op = call double @llvm.round.f64(double %nnan) - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @known_nan_select(i1 %cond, double %arg0, double %arg1) { -; CHECK-LABEL: @known_nan_select( -; CHECK-NEXT: ret i1 true -; - %lhs = fadd nnan double %arg0, 1.0 - %rhs = fadd nnan double %arg1, 2.0 - %op = select i1 %cond, double %lhs, double %rhs - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - define i1 @select_maybe_nan_lhs(i1 %cond, double %lhs, double %arg1) { ; CHECK-LABEL: @select_maybe_nan_lhs( ; CHECK-NEXT: [[RHS:%.*]] = fadd nnan double [[ARG1:%.*]], 1.000000e+00 @@ -255,6 +117,8 @@ define i1 @nnan_fsub(double %arg0, double %arg1) { ret i1 %tmp } +declare double @func() + define i1 @nnan_fneg() { ; CHECK-LABEL: @nnan_fneg( ; CHECK-NEXT: [[NNAN:%.*]] = call nnan double @func() @@ -266,34 +130,6 @@ define i1 @nnan_fneg() { ret i1 %tmp } -define i1 @sitofp(i32 %arg0) { -; CHECK-LABEL: @sitofp( -; CHECK-NEXT: ret i1 true -; - %op = sitofp i32 %arg0 to double - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @uitofp(i32 %arg0) { -; CHECK-LABEL: @uitofp( -; CHECK-NEXT: ret i1 true -; - %op = uitofp i32 %arg0 to double - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - -define i1 @fpext(float %arg0) { -; CHECK-LABEL: @fpext( -; CHECK-NEXT: ret i1 true -; - %arg0.nnan = fadd nnan float %arg0, 1.0 - %op = fpext float %arg0.nnan to double - %tmp = fcmp ord double %op, %op - ret i1 %tmp -} - define i1 @fpext_maybe_nan(float %arg0) { ; CHECK-LABEL: @fpext_maybe_nan( ; CHECK-NEXT: [[TMP:%.*]] = fcmp ord float [[ARG0:%.*]], 0.000000e+00 @@ -304,16 +140,6 @@ define i1 @fpext_maybe_nan(float %arg0) { ret i1 %tmp } -define i1 @fptrunc(double %arg0) { -; CHECK-LABEL: @fptrunc( -; CHECK-NEXT: ret i1 true -; - %arg0.nnan = fadd nnan double %arg0, 1.0 - %op = fptrunc double %arg0.nnan to float - %tmp = fcmp ord float %op, %op - ret i1 %tmp -} - define i1 @fptrunc_maybe_nan(double %arg0) { ; CHECK-LABEL: @fptrunc_maybe_nan( ; CHECK-NEXT: [[OP:%.*]] = fptrunc double [[ARG0:%.*]] to float @@ -367,3 +193,4 @@ declare double @llvm.trunc.f64(double) declare double @llvm.rint.f64(double) declare double @llvm.nearbyint.f64(double) declare double @llvm.round.f64(double) + diff --git a/llvm/test/Transforms/InstSimplify/known-never-nan.ll b/llvm/test/Transforms/InstSimplify/known-never-nan.ll index abc11264eaf..d7c2fdc1cb1 100644 --- a/llvm/test/Transforms/InstSimplify/known-never-nan.ll +++ b/llvm/test/Transforms/InstSimplify/known-never-nan.ll @@ -1,13 +1,12 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -instsimplify %s | FileCheck %s +; RUN: opt < %s -S -instsimplify | FileCheck %s declare double @func() define i1 @nnan_call() { ; CHECK-LABEL: @nnan_call( ; CHECK-NEXT: [[OP:%.*]] = call nnan double @func() -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %op = call nnan double @func() %tmp = fcmp ord double %op, %op @@ -16,10 +15,7 @@ define i1 @nnan_call() { define i1 @nnan_fabs_src(double %arg) { ; CHECK-LABEL: @nnan_fabs_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.fabs.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 false ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.fabs.f64(double %nnan) @@ -29,10 +25,7 @@ define i1 @nnan_fabs_src(double %arg) { define i1 @nnan_canonicalize_src(double %arg) { ; CHECK-LABEL: @nnan_canonicalize_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.canonicalize.f64(double [[NNAN]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.canonicalize.f64(double %nnan) @@ -42,10 +35,7 @@ define i1 @nnan_canonicalize_src(double %arg) { define i1 @nnan_copysign_src(double %arg0, double %arg1) { ; CHECK-LABEL: @nnan_copysign_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.copysign.f64(double [[NNAN]], double [[ARG1:%.*]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 false ; %nnan = fadd nnan double %arg0, 1.0 %op = call double @llvm.copysign.f64(double %nnan, double %arg1) @@ -55,11 +45,7 @@ define i1 @nnan_copysign_src(double %arg0, double %arg1) { define i1 @fabs_sqrt_src(double %arg0, double %arg1) { ; CHECK-LABEL: @fabs_sqrt_src( -; CHECK-NEXT: [[NNAN:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00 -; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[NNAN]]) -; CHECK-NEXT: [[OP:%.*]] = call double @llvm.sqrt.f64(double [[FABS]]) -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %nnan = fadd nnan double %arg0, 1.0 %fabs = call double @llvm.fabs.f64(double %nnan) @@ -83,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]], [[OP]] -; 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) @@ -96,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 uno double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 false ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.exp2.f64(double %nnan) @@ -109,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]], [[OP]] -; 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) @@ -122,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 uno double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 false ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.ceil.f64(double %nnan) @@ -135,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]], [[OP]] -; 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) @@ -148,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 uno double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 false ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.rint.f64(double %nnan) @@ -161,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]], [[OP]] -; 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) @@ -174,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 uno double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 false ; %nnan = fadd nnan double %arg, 1.0 %op = call double @llvm.round.f64(double %nnan) @@ -187,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]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %lhs = fadd nnan double %arg0, 1.0 %rhs = fadd nnan double %arg1, 2.0 @@ -312,9 +270,7 @@ define i1 @nnan_fneg() { define i1 @sitofp(i32 %arg0) { ; CHECK-LABEL: @sitofp( -; CHECK-NEXT: [[OP:%.*]] = sitofp i32 [[ARG0:%.*]] to double -; CHECK-NEXT: [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 false ; %op = sitofp i32 %arg0 to double %tmp = fcmp uno double %op, %op @@ -323,9 +279,7 @@ define i1 @sitofp(i32 %arg0) { define i1 @uitofp(i32 %arg0) { ; CHECK-LABEL: @uitofp( -; CHECK-NEXT: [[OP:%.*]] = uitofp i32 [[ARG0:%.*]] to double -; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 true ; %op = uitofp i32 %arg0 to double %tmp = fcmp ord double %op, %op @@ -334,10 +288,7 @@ define i1 @uitofp(i32 %arg0) { define i1 @fpext(float %arg0) { ; CHECK-LABEL: @fpext( -; CHECK-NEXT: [[ARG0_NNAN:%.*]] = fadd nnan float [[ARG0:%.*]], 1.000000e+00 -; CHECK-NEXT: [[OP:%.*]] = fpext float [[ARG0_NNAN]] to double -; CHECK-NEXT: [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 false ; %arg0.nnan = fadd nnan float %arg0, 1.0 %op = fpext float %arg0.nnan to double @@ -358,10 +309,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 uno float [[OP]], [[OP]] -; CHECK-NEXT: ret i1 [[TMP]] +; CHECK-NEXT: ret i1 false ; %arg0.nnan = fadd nnan double %arg0, 1.0 %op = fptrunc double %arg0.nnan to float |