diff options
Diffstat (limited to 'llvm/include/llvm/IR/PatternMatch.h')
| -rw-r--r-- | llvm/include/llvm/IR/PatternMatch.h | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 7c058342265..dd30072ce57 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -659,11 +659,32 @@ inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L, return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R); } +template <typename Op_t> struct FNeg_match { + Op_t X; + + FNeg_match(const Op_t &Op) : X(Op) {} + template <typename OpTy> bool match(OpTy *V) { + auto *FPMO = dyn_cast<FPMathOperator>(V); + if (!FPMO || FPMO->getOpcode() != Instruction::FSub) + return false; + if (FPMO->hasNoSignedZeros()) { + // With 'nsz', any zero goes. + if (!cstfp_pred_ty<is_any_zero_fp>().match(FPMO->getOperand(0))) + return false; + } else { + // Without 'nsz', we need fsub -0.0, X exactly. + if (!cstfp_pred_ty<is_neg_zero_fp>().match(FPMO->getOperand(0))) + return false; + } + return X.match(FPMO->getOperand(1)); + } +}; + /// Match 'fneg X' as 'fsub -0.0, X'. -template <typename RHS> -inline BinaryOp_match<cstfp_pred_ty<is_neg_zero_fp>, RHS, Instruction::FSub> -m_FNeg(const RHS &X) { - return m_FSub(m_NegZeroFP(), X); +template <typename OpTy> +inline FNeg_match<OpTy> +m_FNeg(const OpTy &X) { + return FNeg_match<OpTy>(X); } /// Match 'fneg X' as 'fsub +-0.0, X'. |

