From 8ec71585719d63223e1f796056b9ddee05b8263d Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 12 Mar 2020 09:10:26 -0400 Subject: [PATCH] [InstSimplify] simplify FP ops harder with FMF This is part of the IR sibling for: D75576 (I'm splitting part of the transform as a separate commit to reduce risk. I don't know of any bugs that might be exposed by this improved folding, but it's hard to see those in advance...) --- llvm/lib/Analysis/InstructionSimplify.cpp | 27 ++++++++++++++++++++------- llvm/test/Transforms/InstSimplify/fp-nan.ll | 20 ++++++++++---------- llvm/test/Transforms/InstSimplify/fp-undef.ll | 10 ++-------- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 073ddb4..6144618 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4603,9 +4603,22 @@ static Constant *propagateNaN(Constant *In) { /// Perform folds that are common to any floating-point operation. This implies /// transforms based on undef/NaN because the operation itself makes no /// difference to the result. -static Constant *simplifyFPOp(ArrayRef Ops) { +static Constant *simplifyFPOp(ArrayRef Ops, + FastMathFlags FMF = FastMathFlags()) { for (Value *V : Ops) { - if (match(V, m_Undef()) || match(V, m_NaN())) + bool IsNan = match(V, m_NaN()); + bool IsInf = match(V, m_Inf()); + bool IsUndef = match(V, m_Undef()); + + // If this operation has 'nnan' or 'ninf' and at least 1 disallowed operand + // (TODO: an undef operand can be chosen to be Nan/Inf), then the result of + // this operation is poison. That result can be relaxed to undef. + if (FMF.noNaNs() && IsNan) + return UndefValue::get(V->getType()); + if (FMF.noInfs() && IsInf) + return UndefValue::get(V->getType()); + + if (IsUndef || IsNan) return propagateNaN(cast(V)); } return nullptr; @@ -4618,7 +4631,7 @@ static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, if (Constant *C = foldOrCommuteConstant(Instruction::FAdd, Op0, Op1, Q)) return C; - if (Constant *C = simplifyFPOp({Op0, Op1})) + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF)) return C; // fadd X, -0 ==> X @@ -4665,7 +4678,7 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF, if (Constant *C = foldOrCommuteConstant(Instruction::FSub, Op0, Op1, Q)) return C; - if (Constant *C = simplifyFPOp({Op0, Op1})) + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF)) return C; // fsub X, +0 ==> X @@ -4707,7 +4720,7 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF, static Value *SimplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF, const SimplifyQuery &Q, unsigned MaxRecurse) { - if (Constant *C = simplifyFPOp({Op0, Op1})) + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF)) return C; // fmul X, 1.0 ==> X @@ -4774,7 +4787,7 @@ static Value *SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF, if (Constant *C = foldOrCommuteConstant(Instruction::FDiv, Op0, Op1, Q)) return C; - if (Constant *C = simplifyFPOp({Op0, Op1})) + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF)) return C; // X / 1.0 -> X @@ -4819,7 +4832,7 @@ static Value *SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF, if (Constant *C = foldOrCommuteConstant(Instruction::FRem, Op0, Op1, Q)) return C; - if (Constant *C = simplifyFPOp({Op0, Op1})) + if (Constant *C = simplifyFPOp({Op0, Op1}, FMF)) return C; // Unlike fdiv, the result of frem always matches the sign of the dividend. diff --git a/llvm/test/Transforms/InstSimplify/fp-nan.ll b/llvm/test/Transforms/InstSimplify/fp-nan.ll index 4dd2523..7382fdf 100644 --- a/llvm/test/Transforms/InstSimplify/fp-nan.ll +++ b/llvm/test/Transforms/InstSimplify/fp-nan.ll @@ -137,7 +137,7 @@ define <2 x double> @unary_fneg_nan_2(<2 x double> %x) { define float @fadd_nan_op0_nnan(float %x) { ; CHECK-LABEL: @fadd_nan_op0_nnan( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fadd nnan float 0x7FF8000000000000, %x ret float %r @@ -145,7 +145,7 @@ define float @fadd_nan_op0_nnan(float %x) { define float @fadd_nan_op1_fast(float %x) { ; CHECK-LABEL: @fadd_nan_op1_fast( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fadd fast float %x, 0x7FF8000000000000 ret float %r @@ -153,7 +153,7 @@ define float @fadd_nan_op1_fast(float %x) { define float @fsub_nan_op0_fast(float %x) { ; CHECK-LABEL: @fsub_nan_op0_fast( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fsub fast float 0x7FF8000000000000, %x ret float %r @@ -161,7 +161,7 @@ define float @fsub_nan_op0_fast(float %x) { define float @fsub_nan_op1_nnan(float %x) { ; CHECK-LABEL: @fsub_nan_op1_nnan( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fsub nnan float %x, 0x7FF8000000000000 ret float %r @@ -169,7 +169,7 @@ define float @fsub_nan_op1_nnan(float %x) { define float @fmul_nan_op0_nnan(float %x) { ; CHECK-LABEL: @fmul_nan_op0_nnan( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fmul nnan float 0x7FF8000000000000, %x ret float %r @@ -177,7 +177,7 @@ define float @fmul_nan_op0_nnan(float %x) { define float @fmul_nan_op1_fast(float %x) { ; CHECK-LABEL: @fmul_nan_op1_fast( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fmul fast float %x, 0x7FF8000000000000 ret float %r @@ -185,7 +185,7 @@ define float @fmul_nan_op1_fast(float %x) { define float @fdiv_nan_op0_fast(float %x) { ; CHECK-LABEL: @fdiv_nan_op0_fast( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fdiv fast float 0x7FF8000000000000, %x ret float %r @@ -193,7 +193,7 @@ define float @fdiv_nan_op0_fast(float %x) { define float @fdiv_nan_op1_nnan(float %x) { ; CHECK-LABEL: @fdiv_nan_op1_nnan( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fdiv nnan float %x, 0x7FF8000000000000 ret float %r @@ -201,7 +201,7 @@ define float @fdiv_nan_op1_nnan(float %x) { define float @frem_nan_op0_nnan(float %x) { ; CHECK-LABEL: @frem_nan_op0_nnan( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = frem nnan float 0x7FF8000000000000, %x ret float %r @@ -209,7 +209,7 @@ define float @frem_nan_op0_nnan(float %x) { define float @frem_nan_op1_fast(float %x) { ; CHECK-LABEL: @frem_nan_op1_fast( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = frem fast float %x, 0x7FF8000000000000 ret float %r diff --git a/llvm/test/Transforms/InstSimplify/fp-undef.ll b/llvm/test/Transforms/InstSimplify/fp-undef.ll index 1319c2e..cdf887f 100644 --- a/llvm/test/Transforms/InstSimplify/fp-undef.ll +++ b/llvm/test/Transforms/InstSimplify/fp-undef.ll @@ -179,23 +179,17 @@ define double @fadd_ninf_nan_op1(double %x) { ret double %r } -; TODO: Should simplify to undef. - define double @fdiv_ninf_inf_op0(double %x) { ; CHECK-LABEL: @fdiv_ninf_inf_op0( -; CHECK-NEXT: [[R:%.*]] = fdiv ninf double 0x7FF0000000000000, [[X:%.*]] -; CHECK-NEXT: ret double [[R]] +; CHECK-NEXT: ret double undef ; %r = fdiv ninf double 0x7ff0000000000000, %x ret double %r } -; TODO: Should simplify to undef. - define double @fadd_ninf_inf_op1(double %x) { ; CHECK-LABEL: @fadd_ninf_inf_op1( -; CHECK-NEXT: [[R:%.*]] = fadd ninf double [[X:%.*]], 0xFFF0000000000000 -; CHECK-NEXT: ret double [[R]] +; CHECK-NEXT: ret double undef ; %r = fadd ninf double %x, 0xfff0000000000000 ret double %r -- 2.7.4