+template<typename LHS_t>
+struct fneg_match {
+ LHS_t L;
+
+ fneg_match(const LHS_t &LHS) : L(LHS) {}
+
+ template<typename OpTy>
+ bool match(OpTy *V) {
+ if (Instruction *I = dyn_cast<Instruction>(V))
+ if (I->getOpcode() == Instruction::FSub)
+ return matchIfFNeg(I->getOperand(0), I->getOperand(1));
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+ if (CE->getOpcode() == Instruction::FSub)
+ return matchIfFNeg(CE->getOperand(0), CE->getOperand(1));
+ if (ConstantFP *CF = dyn_cast<ConstantFP>(V))
+ return L.match(ConstantExpr::getFNeg(CF));
+ return false;
+ }
+private:
+ bool matchIfFNeg(Value *LHS, Value *RHS) {
+ return LHS == ConstantExpr::getZeroValueForNegationExpr(LHS->getType()) &&
+ L.match(RHS);
+ }
+};
+
+template<typename LHS>
+inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; }
+
+