return ::simplifyFNegInst(Op, FMF, Q, RecursionLimit);
}
+/// Try to propagate existing NaN values when possible. If not, replace the
+/// constant or elements in the constant with a canonical NaN.
static Constant *propagateNaN(Constant *In) {
- // If the input is a vector with undef elements, just return a default NaN.
+ if (auto *VecTy = dyn_cast<FixedVectorType>(In->getType())) {
+ unsigned NumElts = VecTy->getNumElements();
+ SmallVector<Constant *, 32> NewC(NumElts);
+ for (unsigned i = 0; i != NumElts; ++i) {
+ Constant *EltC = In->getAggregateElement(i);
+ // Poison and existing NaN elements propagate.
+ // Replace unknown or undef elements with canonical NaN.
+ if (EltC && (isa<PoisonValue>(EltC) || EltC->isNaN()))
+ NewC[i] = EltC;
+ else
+ NewC[i] = (ConstantFP::getNaN(VecTy->getElementType()));
+ }
+ return ConstantVector::get(NewC);
+ }
+
+ // It is not a fixed vector, but not a simple NaN either?
if (!In->isNaN())
return ConstantFP::getNaN(In->getType());
return PoisonValue::get(V->getType());
if (isDefaultFPEnvironment(ExBehavior, Rounding)) {
- if (IsUndef || IsNan)
+ // Undef does not propagate because undef means that all bits can take on
+ // any value. If this is undef * NaN for example, then the result values
+ // (at least the exponent bits) are limited. Assume the undef is a
+ // canonical NaN and propagate that.
+ if (IsUndef)
+ return ConstantFP::getNaN(V->getType());
+ if (IsNan)
return propagateNaN(cast<Constant>(V));
} else if (ExBehavior != fp::ebStrict) {
if (IsNan)
define <2 x double> @minimum_nan_op0_vec_partial_undef(<2 x double> %x) {
; CHECK-LABEL: @minimum_nan_op0_vec_partial_undef(
-; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>
+; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000DEAD00000>
;
%r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x)
ret <2 x double> %r
define <2 x double> @minimum_nan_op1_vec_partial_undef(<2 x double> %x) {
; CHECK-LABEL: @minimum_nan_op1_vec_partial_undef(
-; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>
+; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000DEAD00000>
;
%r = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> <double undef, double 0x7ff8000dead00000>)
ret <2 x double> %r
define <2 x double> @fsub_nan_poison_op1(<2 x double> %x) {
; CHECK-LABEL: @fsub_nan_poison_op1(
-; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>
+; CHECK-NEXT: ret <2 x double> <double 0xFFFF00000000DEAD, double poison>
;
%r = fsub <2 x double> %x, <double 0xFFFF00000000DEAD, double poison>
ret <2 x double> %r
define <2 x double> @frem_nan_undef_op0(<2 x double> %x) {
; CHECK-LABEL: @frem_nan_undef_op0(
-; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>
+; CHECK-NEXT: ret <2 x double> <double 0xFFFF00000000DEAD, double 0x7FF8000000000000>
;
%r = frem <2 x double> <double 0xFFFF00000000DEAD, double undef>, %x
ret <2 x double> %r
define <3 x double> @fadd_nan_poison_undef_op1(<3 x double> %x) {
; CHECK-LABEL: @fadd_nan_poison_undef_op1(
-; CHECK-NEXT: ret <3 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000, double 0x7FF8000000000000>
+; CHECK-NEXT: ret <3 x double> <double 0xFFFF00000000DEAD, double poison, double 0x7FF8000000000000>
;
%r = fadd <3 x double> %x, <double 0xFFFF00000000DEAD, double poison, double undef>
ret <3 x double> %r