diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -5466,6 +5466,15 @@ if (!In->isNaN()) return ConstantFP::getNaN(Ty); + // If we known this is a NaN, and it's scalable vector, we must have a splat + // on our hands. Grab that before splatting a QNaN constant. + if (isa(Ty)) { + auto *Splat = In->getSplatValue(); + assert(Splat && Splat->isNaN() && + "Found a scalable-vector NaN but not a splat"); + In = Splat; + } + // Propagate an existing QNaN constant. If it is an SNaN, make it quiet, but // preserve the sign/payload. return ConstantFP::get(Ty, cast(In)->getValue().makeQuiet()); diff --git a/llvm/test/Transforms/InstSimplify/fp-nan.ll b/llvm/test/Transforms/InstSimplify/fp-nan.ll --- a/llvm/test/Transforms/InstSimplify/fp-nan.ll +++ b/llvm/test/Transforms/InstSimplify/fp-nan.ll @@ -49,6 +49,22 @@ ret <2 x float> %r } +define @fsub_nan_op1_scalable_vec_0( %x) { +; CHECK-LABEL: @fsub_nan_op1_scalable_vec_0( +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, float 0x7FF9000000000000, i64 0), poison, zeroinitializer) +; + %r = fsub %x, shufflevector ( insertelement ( poison, float 0x7FF1000000000000, i64 0), poison, zeroinitializer) + ret %r +} + +define @fsub_nan_op1_scalable_vec_1( %x) { +; CHECK-LABEL: @fsub_nan_op1_scalable_vec_1( +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, float 0xFFF9000000000000, i64 0), poison, zeroinitializer) +; + %r = fsub %x, shufflevector ( insertelement ( poison, float 0xFFF1000000000000, i64 0), poison, zeroinitializer) + ret %r +} + ; Signaling and signed - make quiet and preserve the payload and signbit define double @fmul_nan_op0(double %x) { @@ -67,6 +83,22 @@ ret <2 x double> %r } +define @fmul_nan_op0_scalable_vec_0( %x) { +; CHECK-LABEL: @fmul_nan_op0_scalable_vec_0( +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, double 0xFFF8000000000001, i64 0), poison, zeroinitializer) +; + %r = fmul shufflevector ( insertelement ( poison, double 0xFFF0000000000001, i64 0), poison, zeroinitializer), %x + ret %r +} + +define @fmul_nan_op0_scalable_vec_1( %x) { +; CHECK-LABEL: @fmul_nan_op0_scalable_vec_1( +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, double 0xFFF8DEADDEADDEAD, i64 0), poison, zeroinitializer) +; + %r = fmul shufflevector ( insertelement ( poison, double 0xFFF0DEADDEADDEAD, i64 0), poison, zeroinitializer), %x + ret %r +} + ; Vector type define <2 x float> @fmul_nan_op1(<2 x float> %x) { @@ -77,6 +109,14 @@ ret <2 x float> %r } +define @fmul_nan_op1_scalable_vec( %x) { +; CHECK-LABEL: @fmul_nan_op1_scalable_vec( +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, double 0x7FF8000000000000, i64 0), poison, zeroinitializer) +; + %r = fmul %x, shufflevector ( insertelement ( poison, double 0x7FF8000000000000, i64 0), poison, zeroinitializer) + ret %r +} + ; Vector signed and non-zero payload define <2 x double> @fdiv_nan_op0(<2 x double> %x) { @@ -87,6 +127,14 @@ ret <2 x double> %r } +define @fdivl_nan_op0_scalable_vec( %x) { +; CHECK-LABEL: @fdivl_nan_op0_scalable_vec( +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, double 0xFFF800000000000F, i64 0), poison, zeroinitializer) +; + %r = fdiv shufflevector ( insertelement ( poison, double 0xFFF800000000000F, i64 0), poison, zeroinitializer), %x + ret %r +} + ; Vector with different NaN constant elements define <2 x half> @fdiv_nan_op1(<2 x half> %x) { @@ -97,6 +145,14 @@ ret <2 x half> %r } +define @fdiv_nan_op1_scalable_vec( %x) { +; CHECK-LABEL: @fdiv_nan_op1_scalable_vec( +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, half 0xH7FFF, i64 0), poison, zeroinitializer) +; + %r = fdiv %x, shufflevector ( insertelement ( poison, half 0xH7FFF, i64 0), poison, zeroinitializer) + ret %r +} + ; Vector with poison element define <2 x double> @fsub_nan_poison_op1(<2 x double> %x) { @@ -161,6 +217,14 @@ ret <2 x double> %r } +define @fneg_nan_2_scalable_vec() { +; CHECK-LABEL: @fneg_nan_2_scalable_vec( +; CHECK-NEXT: ret shufflevector ( insertelement ( poison, double 0xFFF9234567890ABC, i64 0), poison, zeroinitializer) +; + %r = fsub shufflevector ( insertelement ( poison, double -0.0, i64 0), poison, zeroinitializer), shufflevector ( insertelement ( poison, double 0xFFF1234567890ABC, i64 0), poison, zeroinitializer) + ret %r +} + define <2 x double> @unary_fneg_nan_2(<2 x double> %x) { ; CHECK-LABEL: @unary_fneg_nan_2( ; CHECK-NEXT: ret <2 x double> @@ -169,6 +233,26 @@ ret <2 x double> %r } +; FIXME: This doesn't behave the same way as the fixed-length vectors above +define @unary_fneg_nan_2_scalable_vec_0() { +; CHECK-LABEL: @unary_fneg_nan_2_scalable_vec_0( +; CHECK-NEXT: [[R:%.*]] = fneg shufflevector ( insertelement ( poison, double 0xFFF1234567890ABC, i64 0), poison, zeroinitializer) +; CHECK-NEXT: ret [[R]] +; + %r = fneg shufflevector ( insertelement ( poison, double 0xFFF1234567890ABC, i64 0), poison, zeroinitializer) + ret %r +} + +; FIXME: This doesn't behave the same way as the fixed-length vectors above +define @unary_fneg_nan_2_scalable_vec_1() { +; CHECK-LABEL: @unary_fneg_nan_2_scalable_vec_1( +; CHECK-NEXT: [[R:%.*]] = fneg shufflevector ( insertelement ( poison, double 0x7FF0000000000001, i64 0), poison, zeroinitializer) +; CHECK-NEXT: ret [[R]] +; + %r = fneg shufflevector ( insertelement ( poison, double 0x7FF0000000000001, i64 0), poison, zeroinitializer) + ret %r +} + ; Repeat all tests with fast-math-flags. Alternate 'nnan' and 'fast' for more coverage. define float @fadd_nan_op0_nnan(float %x) {