Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -5151,6 +5151,25 @@ } return nullptr; } + case Intrinsic::fma: + case Intrinsic::fmuladd: { + // If any operand is NaN, return that NaN value. This arbitrarily + // propagates the first NaN value encountered if there is more than 1. + Value *Op0 = Call->getArgOperand(0); + Value *Op1 = Call->getArgOperand(1); + Value *Op2 = Call->getArgOperand(2); + if (match(Op0, m_NaN())) + return Op0; + if (match(Op1, m_NaN())) + return Op1; + if (match(Op2, m_NaN())) + return Op2; + + // TODO: Handle cases where non-NaN multiplicand operands and/or addend are + // known to produce a NaN. + + return nullptr; + } default: return nullptr; } Index: llvm/test/Transforms/InstSimplify/call.ll =================================================================== --- llvm/test/Transforms/InstSimplify/call.ll +++ llvm/test/Transforms/InstSimplify/call.ll @@ -747,8 +747,7 @@ define double @fma_nan_op0(double %x, double %y) { ; CHECK-LABEL: @fma_nan_op0( -; CHECK-NEXT: [[R:%.*]] = call double @llvm.fma.f64(double 0x7FF8000000000000, double [[X:%.*]], double [[Y:%.*]]) -; CHECK-NEXT: ret double [[R]] +; CHECK-NEXT: ret double 0x7FF8000000000000 ; %r = call double @llvm.fma.f64(double 0x7ff8000000000000, double %x, double %y) ret double %r @@ -756,8 +755,7 @@ define double @fma_nan_op1(double %x, double %y) { ; CHECK-LABEL: @fma_nan_op1( -; CHECK-NEXT: [[R:%.*]] = call double @llvm.fma.f64(double [[X:%.*]], double 0x7FF8000000000001, double [[Y:%.*]]) -; CHECK-NEXT: ret double [[R]] +; CHECK-NEXT: ret double 0x7FF8000000000001 ; %r = call double @llvm.fma.f64(double %x, double 0x7ff8000000000001, double %y) ret double %r @@ -765,8 +763,7 @@ define double @fma_nan_op2(double %x, double %y) { ; CHECK-LABEL: @fma_nan_op2( -; CHECK-NEXT: [[R:%.*]] = call double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double 0x7FF8000000000002) -; CHECK-NEXT: ret double [[R]] +; CHECK-NEXT: ret double 0x7FF8000000000002 ; %r = call double @llvm.fma.f64(double %x, double %y, double 0x7ff8000000000002) ret double %r @@ -774,8 +771,7 @@ define double @fmuladd_nan_op0_op1(double %x) { ; CHECK-LABEL: @fmuladd_nan_op0_op1( -; CHECK-NEXT: [[R:%.*]] = call double @llvm.fmuladd.f64(double 0x7FF8000000001234, double 0x7FF800000000DEAD, double [[X:%.*]]) -; CHECK-NEXT: ret double [[R]] +; CHECK-NEXT: ret double 0x7FF8000000001234 ; %r = call double @llvm.fmuladd.f64(double 0x7ff8000000001234, double 0x7ff800000000dead, double %x) ret double %r @@ -783,8 +779,7 @@ define double @fmuladd_nan_op0_op2(double %x) { ; CHECK-LABEL: @fmuladd_nan_op0_op2( -; CHECK-NEXT: [[R:%.*]] = call double @llvm.fmuladd.f64(double 0x7FF8000000005678, double [[X:%.*]], double 0x7FF800000000DEAD) -; CHECK-NEXT: ret double [[R]] +; CHECK-NEXT: ret double 0x7FF8000000005678 ; %r = call double @llvm.fmuladd.f64(double 0x7ff8000000005678, double %x, double 0x7ff800000000dead) ret double %r @@ -792,8 +787,7 @@ define double @fmuladd_nan_op1_op2(double %x) { ; CHECK-LABEL: @fmuladd_nan_op1_op2( -; CHECK-NEXT: [[R:%.*]] = call double @llvm.fmuladd.f64(double [[X:%.*]], double 0x7FF80000AAAAAAAA, double 0x7FF800000000DEAD) -; CHECK-NEXT: ret double [[R]] +; CHECK-NEXT: ret double 0x7FF80000AAAAAAAA ; %r = call double @llvm.fmuladd.f64(double %x, double 0x7ff80000aaaaaaaa, double 0x7ff800000000dead) ret double %r