// If the input denormal mode could be PreserveSign, a negative
// subnormal input could produce a negative zero output.
- if (KnownSrc.isKnownNeverLogicalNegZero(*II->getFunction(),
- II->getType())) {
+ const Function *F = II->getFunction();
+ if (F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType())) {
Known.knownNot(fcNegZero);
if (KnownSrc.isKnownNeverNaN())
Known.SignBit = false;
// Canonicalize is guaranteed to quiet signaling nans.
Known.knownNot(fcSNan);
+ const Function *F = II->getFunction();
+ if (!F)
+ break;
+
// If the parent function flushes denormals, the canonical output cannot
// be a denormal.
const fltSemantics &FPType =
II->getType()->getScalarType()->getFltSemantics();
- DenormalMode DenormMode = II->getFunction()->getDenormalMode(FPType);
+ DenormalMode DenormMode = F->getDenormalMode(FPType);
if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero())
Known.knownNot(fcSubnormal);
KnownSrc.cannotBeOrderedLessThanZero())
Known.knownNot(fcNan);
- if (KnownSrc.isKnownNeverLogicalZero(*II->getFunction(), II->getType()))
+ const Function *F = II->getFunction();
+ if (F && KnownSrc.isKnownNeverLogicalZero(*F, II->getType()))
Known.knownNot(fcNegInf);
break;
(KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()))
Known.knownNot(fcNan);
+ // FIXME: Context function should always be passed in separately
const Function *F = cast<Instruction>(Op)->getFunction();
+ if (!F)
+ break;
+
if (Op->getOpcode() == Instruction::FAdd) {
// (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
if ((KnownLHS.isKnownNeverLogicalNegZero(*F, Op->getType()) ||
// TODO: Check operand combinations.
// e.g. fmul nofpclass(inf nan zero), nofpclass(nan) -> nofpclass(nan)
if ((KnownLHS.isKnownNeverInfinity() ||
- KnownLHS.isKnownNeverLogicalZero(*F, Op->getType())) &&
+ (F && KnownLHS.isKnownNeverLogicalZero(*F, Op->getType()))) &&
(KnownRHS.isKnownNeverInfinity() ||
- KnownRHS.isKnownNeverLogicalZero(*F, Op->getType())))
+ (F && KnownRHS.isKnownNeverLogicalZero(*F, Op->getType()))))
Known.knownNot(fcNan);
}
if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
(KnownLHS.isKnownNeverInfinity() ||
KnownRHS.isKnownNeverInfinity()) &&
- (KnownLHS.isKnownNeverLogicalZero(*F, Op->getType()) ||
- KnownRHS.isKnownNeverLogicalZero(*F, Op->getType()))) {
+ ((F && KnownLHS.isKnownNeverLogicalZero(*F, Op->getType())) ||
+ (F && KnownRHS.isKnownNeverLogicalZero(*F, Op->getType())))) {
Known.knownNot(fcNan);
}
} else {
// Inf REM x and x REM 0 produce NaN.
if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
- KnownLHS.isKnownNeverInfinity() &&
+ KnownLHS.isKnownNeverInfinity() && F &&
KnownRHS.isKnownNeverLogicalZero(*F, Op->getType())) {
Known.knownNot(fcNan);
}
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt < %s -passes=inline -inline-threshold=20 -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=20 -S | FileCheck %s
+
+; Make sure there are no crashes when calling computeKnownFPClass with
+; un-inserted cloned instructions.
+
+; Hit computeKnownFPClass in a context where the denormal mode is
+; queried for the function for an operand not in a parent function.
+
+define i1 @simplify_fcmp_ord_fsub_caller(double nofpclass(zero nan) %i0, double nofpclass(zero nan) %i1) {
+; CHECK-LABEL: define i1 @simplify_fcmp_ord_fsub_caller
+; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]], double nofpclass(nan zero) [[I1:%.*]]) {
+; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = fsub double [[I0]], [[I1]]
+; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[CMP_I]]
+;
+ %call = call i1 @simplify_fcmp_ord_fsub_callee(double %i0, double %i1)
+ ret i1 %call
+}
+
+; Make sure we hit the denormal query in isKnownNeverLogicalZero
+define internal i1 @simplify_fcmp_ord_fsub_callee(double %a, double %b) {
+ %sub.double.sub = fsub double %a, %b
+ %cmp = fcmp ord double %sub.double.sub, 0.0
+ ret i1 %cmp
+}
+
+define i1 @simplify_fcmp_ord_fdiv_caller(double nofpclass(zero nan inf) %i0, double nofpclass(zero nan inf) %i1) {
+; CHECK-LABEL: define i1 @simplify_fcmp_ord_fdiv_caller
+; CHECK-SAME: (double nofpclass(nan inf zero) [[I0:%.*]], double nofpclass(nan inf zero) [[I1:%.*]]) {
+; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = fdiv double [[I0]], [[I1]]
+; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[CMP_I]]
+;
+ %call = call i1 @simplify_fcmp_ord_fdiv_callee(double %i0, double %i1)
+ ret i1 %call
+}
+
+; Make sure we hit the denormal query in isKnownNeverLogicalZero
+define internal i1 @simplify_fcmp_ord_fdiv_callee(double %a, double %b) {
+ %sub.double.sub = fdiv double %a, %b
+ %cmp = fcmp ord double %sub.double.sub, 0.0
+ ret i1 %cmp
+}
+
+define i1 @simplify_fcmp_ord_frem_caller(double nofpclass(zero nan inf) %i0, double nofpclass(zero nan inf) %i1) {
+; CHECK-LABEL: define i1 @simplify_fcmp_ord_frem_caller
+; CHECK-SAME: (double nofpclass(nan inf zero) [[I0:%.*]], double nofpclass(nan inf zero) [[I1:%.*]]) {
+; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = frem double [[I0]], [[I1]]
+; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[CMP_I]]
+;
+ %call = call i1 @simplify_fcmp_ord_frem_callee(double %i0, double %i1)
+ ret i1 %call
+}
+
+; Make sure we hit the denormal query in isKnownNeverLogicalZero
+define internal i1 @simplify_fcmp_ord_frem_callee(double %a, double %b) {
+ %sub.double.sub = frem double %a, %b
+ %cmp = fcmp ord double %sub.double.sub, 0.0
+ ret i1 %cmp
+}
+
+define i1 @simplify_fcmp_ord_fmul_caller(double nofpclass(zero nan) %i0, double nofpclass(zero nan) %i1) {
+; CHECK-LABEL: define i1 @simplify_fcmp_ord_fmul_caller
+; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]], double nofpclass(nan zero) [[I1:%.*]]) {
+; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = fmul double [[I0]], [[I1]]
+; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[CMP_I]]
+;
+ %call = call i1 @simplify_fcmp_ord_fmul_callee(double %i0, double %i1)
+ ret i1 %call
+}
+
+; Make sure we hit the denormal query in isKnownNeverLogicalZero
+define internal i1 @simplify_fcmp_ord_fmul_callee(double %a, double %b) {
+ %sub.double.sub = fmul double %a, %b
+ %cmp = fcmp ord double %sub.double.sub, 0.0
+ ret i1 %cmp
+}
+
+define i1 @simplify_fcmp_ord_sqrt_caller(double nofpclass(zero nan) %i0) {
+; CHECK-LABEL: define i1 @simplify_fcmp_ord_sqrt_caller
+; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]]) {
+; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = call double @llvm.sqrt.f64(double [[I0]])
+; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[CMP_I]]
+;
+ %call = call i1 @simplify_fcmp_ord_sqrt_callee(double %i0)
+ ret i1 %call
+}
+
+; Make sure we hit the denormal query in isKnownNeverLogicalZero
+define internal i1 @simplify_fcmp_ord_sqrt_callee(double %a) {
+ %sub.double.sub = call double @llvm.sqrt.f64(double %a)
+ %cmp = fcmp ord double %sub.double.sub, 0.0
+ ret i1 %cmp
+}
+
+declare double @llvm.sqrt.f64(double)
+
+define i1 @simplify_fcmp_ord_canonicalize_caller(double nofpclass(zero nan) %i0) {
+; CHECK-LABEL: define i1 @simplify_fcmp_ord_canonicalize_caller
+; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]]) {
+; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = call double @llvm.canonicalize.f64(double [[I0]])
+; CHECK-NEXT: ret i1 true
+;
+ %call = call i1 @simplify_fcmp_ord_canonicalize_callee(double %i0)
+ ret i1 %call
+}
+
+; Make sure we hit the denormal query in isKnownNeverLogicalZero
+define internal i1 @simplify_fcmp_ord_canonicalize_callee(double %a) {
+ %sub.double.sub = call double @llvm.canonicalize.f64(double %a)
+ %cmp = fcmp ord double %sub.double.sub, 0.0
+ ret i1 %cmp
+}
+
+declare double @llvm.canonicalize.f64(double)
+
+define i1 @simplify_fcmp_ord_log_caller(double nofpclass(zero nan) %i0) {
+; CHECK-LABEL: define i1 @simplify_fcmp_ord_log_caller
+; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]]) {
+; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = call double @llvm.log.f64(double [[I0]])
+; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[CMP_I]]
+;
+ %call = call i1 @simplify_fcmp_ord_log_callee(double %i0)
+ ret i1 %call
+}
+
+; Make sure we hit the denormal query in isKnownNeverLogicalZero
+define internal i1 @simplify_fcmp_ord_log_callee(double %a) {
+ %sub.double.sub = call double @llvm.log.f64(double %a)
+ %cmp = fcmp ord double %sub.double.sub, 0.0
+ ret i1 %cmp
+}
+
+declare double @llvm.log.f64(double)