From 3f100e64b429b6468e9a2c5b3e7ef7757a06dc48 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 18 Sep 2020 09:53:06 -0400 Subject: [PATCH] [InstSimplify] fix fmin/fmax miscompile for partial undef vectors (PR47567) It would also be correct to return the variable operand in these cases, but eliminating a variable use is probably better for optimization. --- llvm/lib/Analysis/InstructionSimplify.cpp | 2 +- .../Transforms/InstSimplify/fminmax-folds.ll | 28 +++++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 7d939bb63a6b..7645cc93545c 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -5480,7 +5480,7 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, // minimum(X, nan) -> nan // maximum(X, nan) -> nan if (match(Op1, m_NaN())) - return PropagateNaN ? Op1 : Op0; + return PropagateNaN ? propagateNaN(cast(Op1)) : Op0; // In the following folds, inf can be replaced with the largest finite // float, if the ninf flag is set. diff --git a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll index c62f76c87fae..e87c2f1d1260 100644 --- a/llvm/test/Transforms/InstSimplify/fminmax-folds.ll +++ b/llvm/test/Transforms/InstSimplify/fminmax-folds.ll @@ -806,14 +806,22 @@ define double @minimum_nan_op1(double %x) { ret double %r } -define <2 x double> @maximum_nan_op0_vec(<2 x double> %x) { -; CHECK-LABEL: @maximum_nan_op0_vec( -; CHECK-NEXT: ret <2 x double> +define <2 x double> @maximum_nan_op0_vec_partial_undef(<2 x double> %x) { +; CHECK-LABEL: @maximum_nan_op0_vec_partial_undef( +; CHECK-NEXT: ret <2 x double> ; %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %r } +define <2 x double> @maximum_nan_op1_vec_partial_undef(<2 x double> %x) { +; CHECK-LABEL: @maximum_nan_op1_vec_partial_undef( +; CHECK-NEXT: ret <2 x double> +; + %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> ) + ret <2 x double> %r +} + define <2 x double> @maximum_nan_op1_vec(<2 x double> %x) { ; CHECK-LABEL: @maximum_nan_op1_vec( ; CHECK-NEXT: ret <2 x double> @@ -822,14 +830,22 @@ define <2 x double> @maximum_nan_op1_vec(<2 x double> %x) { ret <2 x double> %r } -define <2 x double> @minimum_nan_op0_vec(<2 x double> %x) { -; CHECK-LABEL: @minimum_nan_op0_vec( -; CHECK-NEXT: ret <2 x double> +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> ; %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> , <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> +; + %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> ) + ret <2 x double> %r +} + define <2 x double> @minimum_nan_op1_vec(<2 x double> %x) { ; CHECK-LABEL: @minimum_nan_op1_vec( ; CHECK-NEXT: ret <2 x double>