I tested that locally, but forgot to add a test case to Clang. I'll add that in soon.<div><br></div><div>Thanks for catching this!<br><div><br></div><div>- Lang.<br><br><div class="gmail_quote">On Tue, Oct 2, 2012 at 12:06 PM, David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">On Mon, Oct 1, 2012 at 9:45 PM, Lang Hames <<a href="mailto:lhames@gmail.com">lhames@gmail.com</a>> wrote:<br>

> Author: lhames<br>
> Date: Mon Oct  1 23:45:10 2012<br>
> New Revision: 164989<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=164989&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=164989&view=rev</a><br>
> Log:<br>
> Add FP_CONTRACT support for clang.<br>
><br>
> Clang will now honor the FP_CONTRACT pragma and emit LLVM<br>
> fmuladd intrinsics for expressions of the form A * B + C (when they occur in a<br>
> single statement).<br>
<br>
</div>Hooray \o/<br>
<br>
I think you were telling me that the pragma can be applied at the file<br>
scope. Is that tested somewhere?<br>
<span class="HOEnZb"><font color="#888888"><br>
- David<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
><br>
><br>
> Added:<br>
>     cfe/trunk/test/CodeGen/ffp-contract-option.c<br>
>       - copied unchanged from r164952, cfe/trunk/test/CodeGen/fp-contract.c<br>
>     cfe/trunk/test/CodeGen/fp-contract-pragma.cpp<br>
> Removed:<br>
>     cfe/trunk/test/CodeGen/fp-contract.c<br>
> Modified:<br>
>     cfe/trunk/include/clang/AST/Expr.h<br>
>     cfe/trunk/include/clang/AST/ExprCXX.h<br>
>     cfe/trunk/include/clang/Sema/Sema.h<br>
>     cfe/trunk/lib/AST/ASTImporter.cpp<br>
>     cfe/trunk/lib/Analysis/BodyFarm.cpp<br>
>     cfe/trunk/lib/CodeGen/CGExprScalar.cpp<br>
>     cfe/trunk/lib/CodeGen/CGObjC.cpp<br>
>     cfe/trunk/lib/Parse/ParseStmt.cpp<br>
>     cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp<br>
>     cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp<br>
>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
>     cfe/trunk/lib/Sema/SemaExpr.cpp<br>
>     cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
>     cfe/trunk/lib/Sema/SemaOverload.cpp<br>
>     cfe/trunk/lib/Sema/SemaPseudoObject.cpp<br>
>     cfe/trunk/lib/Sema/TreeTransform.h<br>
>     cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
>     cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
>     cfe/trunk/test/CodeGenOpenCL/<a href="http://single-precision-constant.cl" target="_blank">single-precision-constant.cl</a><br>
><br>
> Modified: cfe/trunk/include/clang/AST/Expr.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/Expr.h (original)<br>
> +++ cfe/trunk/include/clang/AST/Expr.h Mon Oct  1 23:45:10 2012<br>
> @@ -2785,6 +2785,12 @@<br>
><br>
>  private:<br>
>    unsigned Opc : 6;<br>
> +<br>
> +  // Records the FP_CONTRACT pragma status at the point that this binary<br>
> +  // operator was parsed. This bit is only meaningful for operations on<br>
> +  // floating point types. For all other types it should default to<br>
> +  // false.<br>
> +  unsigned FPContractable : 1;<br>
>    SourceLocation OpLoc;<br>
><br>
>    enum { LHS, RHS, END_EXPR };<br>
> @@ -2793,7 +2799,7 @@<br>
><br>
>    BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,<br>
>                   ExprValueKind VK, ExprObjectKind OK,<br>
> -                 SourceLocation opLoc)<br>
> +                 SourceLocation opLoc, bool fpContractable)<br>
>      : Expr(BinaryOperatorClass, ResTy, VK, OK,<br>
>             lhs->isTypeDependent() || rhs->isTypeDependent(),<br>
>             lhs->isValueDependent() || rhs->isValueDependent(),<br>
> @@ -2801,7 +2807,7 @@<br>
>              rhs->isInstantiationDependent()),<br>
>             (lhs->containsUnexpandedParameterPack() ||<br>
>              rhs->containsUnexpandedParameterPack())),<br>
> -      Opc(opc), OpLoc(opLoc) {<br>
> +      Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {<br>
>      SubExprs[LHS] = lhs;<br>
>      SubExprs[RHS] = rhs;<br>
>      assert(!isCompoundAssignmentOp() &&<br>
> @@ -2902,10 +2908,18 @@<br>
>      return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);<br>
>    }<br>
><br>
> +  // Set the FP contractability status of this operator. Only meaningful for<br>
> +  // operations on floating point types.<br>
> +  void setFPContractable(bool FPC) { FPContractable = FPC; }<br>
> +<br>
> +  // Get the FP contractability status of this operator. Only meaningful for<br>
> +  // operations on floating point types.<br>
> +  bool isFPContractable() const { return FPContractable; }<br>
> +<br>
>  protected:<br>
>    BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,<br>
>                   ExprValueKind VK, ExprObjectKind OK,<br>
> -                 SourceLocation opLoc, bool dead)<br>
> +                 SourceLocation opLoc, bool fpContractable, bool dead2)<br>
>      : Expr(CompoundAssignOperatorClass, ResTy, VK, OK,<br>
>             lhs->isTypeDependent() || rhs->isTypeDependent(),<br>
>             lhs->isValueDependent() || rhs->isValueDependent(),<br>
> @@ -2913,7 +2927,7 @@<br>
>              rhs->isInstantiationDependent()),<br>
>             (lhs->containsUnexpandedParameterPack() ||<br>
>              rhs->containsUnexpandedParameterPack())),<br>
> -      Opc(opc), OpLoc(opLoc) {<br>
> +      Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {<br>
>      SubExprs[LHS] = lhs;<br>
>      SubExprs[RHS] = rhs;<br>
>    }<br>
> @@ -2935,8 +2949,9 @@<br>
>    CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,<br>
>                           ExprValueKind VK, ExprObjectKind OK,<br>
>                           QualType CompLHSType, QualType CompResultType,<br>
> -                         SourceLocation OpLoc)<br>
> -    : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, true),<br>
> +                         SourceLocation OpLoc, bool fpContractable)<br>
> +    : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable,<br>
> +                     true),<br>
>        ComputationLHSType(CompLHSType),<br>
>        ComputationResultType(CompResultType) {<br>
>      assert(isCompoundAssignmentOp() &&<br>
><br>
> Modified: cfe/trunk/include/clang/AST/ExprCXX.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/ExprCXX.h (original)<br>
> +++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Oct  1 23:45:10 2012<br>
> @@ -53,14 +53,19 @@<br>
>    OverloadedOperatorKind Operator;<br>
>    SourceRange Range;<br>
><br>
> +  // Record the FP_CONTRACT state that applies to this operator call. Only<br>
> +  // meaningful for floating point types. For other types this value can be<br>
> +  // set to false.<br>
> +  unsigned FPContractable : 1;<br>
> +<br>
>    SourceRange getSourceRangeImpl() const LLVM_READONLY;<br>
>  public:<br>
>    CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,<br>
>                        ArrayRef<Expr*> args, QualType t, ExprValueKind VK,<br>
> -                      SourceLocation operatorloc)<br>
> +                      SourceLocation operatorloc, bool fpContractable)<br>
>      : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, t, VK,<br>
>                 operatorloc),<br>
> -      Operator(Op) {<br>
> +      Operator(Op), FPContractable(fpContractable) {<br>
>      Range = getSourceRangeImpl();<br>
>    }<br>
>    explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :<br>
> @@ -85,6 +90,14 @@<br>
>    }<br>
>    static bool classof(const CXXOperatorCallExpr *) { return true; }<br>
><br>
> +  // Set the FP contractability status of this operator. Only meaningful for<br>
> +  // operations on floating point types.<br>
> +  void setFPContractable(bool FPC) { FPContractable = FPC; }<br>
> +<br>
> +  // Get the FP contractability status of this operator. Only meaningful for<br>
> +  // operations on floating point types.<br>
> +  bool isFPContractable() const { return FPContractable; }<br>
> +<br>
>    friend class ASTStmtReader;<br>
>    friend class ASTStmtWriter;<br>
>  };<br>
><br>
> Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct  1 23:45:10 2012<br>
> @@ -735,6 +735,20 @@<br>
>    /// should not be used elsewhere.<br>
>    void EmitCurrentDiagnostic(unsigned DiagID);<br>
><br>
> +  /// Records and restores the FP_CONTRACT state on entry/exit of compound<br>
> +  /// statements.<br>
> +  class FPContractStateRAII {<br>
> +  public:<br>
> +    FPContractStateRAII(Sema& S)<br>
> +      : S(S), OldFPContractState(S.FPFeatures.fp_contract) {}<br>
> +    ~FPContractStateRAII() {<br>
> +      S.FPFeatures.fp_contract = OldFPContractState;<br>
> +    }<br>
> +  private:<br>
> +    Sema& S;<br>
> +    bool OldFPContractState : 1;<br>
> +  };<br>
> +<br>
>  public:<br>
>    Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,<br>
>         TranslationUnitKind TUKind = TU_Complete,<br>
><br>
> Modified: cfe/trunk/lib/AST/ASTImporter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)<br>
> +++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -4082,7 +4082,8 @@<br>
>    return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(),<br>
>                                                        T, E->getValueKind(),<br>
>                                                        E->getObjectKind(),<br>
> -                                          Importer.Import(E->getOperatorLoc()));<br>
> +                                           Importer.Import(E->getOperatorLoc()),<br>
> +                                                      E->isFPContractable());<br>
>  }<br>
><br>
>  Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {<br>
> @@ -4111,7 +4112,8 @@<br>
>                                                 T, E->getValueKind(),<br>
>                                                 E->getObjectKind(),<br>
>                                                 CompLHSType, CompResultType,<br>
> -                                          Importer.Import(E->getOperatorLoc()));<br>
> +                                           Importer.Import(E->getOperatorLoc()),<br>
> +                                               E->isFPContractable());<br>
>  }<br>
><br>
>  static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {<br>
><br>
> Modified: cfe/trunk/lib/Analysis/BodyFarm.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Analysis/BodyFarm.cpp (original)<br>
> +++ cfe/trunk/lib/Analysis/BodyFarm.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -70,7 +70,7 @@<br>
>                                           QualType Ty) {<br>
>   return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS),<br>
>                                 BO_Assign, Ty, VK_RValue,<br>
> -                               OK_Ordinary, SourceLocation());<br>
> +                               OK_Ordinary, SourceLocation(), false);<br>
>  }<br>
><br>
>  DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) {<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -45,6 +45,7 @@<br>
>    Value *RHS;<br>
>    QualType Ty;  // Computation Type.<br>
>    BinaryOperator::Opcode Opcode; // Opcode of BinOp to perform<br>
> +  bool FPContractable;<br>
>    const Expr *E;      // Entire expr, for error unsupported.  May not be binop.<br>
>  };<br>
><br>
> @@ -1654,6 +1655,7 @@<br>
>    Result.RHS = Visit(E->getRHS());<br>
>    Result.Ty  = E->getType();<br>
>    Result.Opcode = E->getOpcode();<br>
> +  Result.FPContractable = E->isFPContractable();<br>
>    Result.E = E;<br>
>    return Result;<br>
>  }<br>
> @@ -1982,6 +1984,77 @@<br>
>    return CGF.Builder.CreateInBoundsGEP(pointer, index, "add.ptr");<br>
>  }<br>
><br>
> +// Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and<br>
> +// Addend. Use negMul and negAdd to negate the first operand of the Mul or<br>
> +// the add operand respectively. This allows fmuladd to represent a*b-c, or<br>
> +// c-a*b. Patterns in LLVM should catch the negated forms and translate them to<br>
> +// efficient operations.<br>
> +static Value* buildFMulAdd(llvm::BinaryOperator *MulOp, Value *Addend,<br>
> +                           const CodeGenFunction &CGF, CGBuilderTy &Builder,<br>
> +                           bool negMul, bool negAdd) {<br>
> +  assert(!(negMul && negAdd) && "Only one of negMul and negAdd should be set.");<br>
> +<br>
> +  Value *MulOp0 = MulOp->getOperand(0);<br>
> +  Value *MulOp1 = MulOp->getOperand(1);<br>
> +  if (negMul) {<br>
> +    MulOp0 =<br>
> +      Builder.CreateFSub(<br>
> +        llvm::ConstantFP::getZeroValueForNegation(MulOp0->getType()), MulOp0,<br>
> +        "neg");<br>
> +  } else if (negAdd) {<br>
> +    Addend =<br>
> +      Builder.CreateFSub(<br>
> +        llvm::ConstantFP::getZeroValueForNegation(Addend->getType()), Addend,<br>
> +        "neg");<br>
> +  }<br>
> +<br>
> +  Value *FMulAdd =<br>
> +    Builder.CreateCall3(<br>
> +      CGF.CGM.getIntrinsic(llvm::Intrinsic::fmuladd, Addend->getType()),<br>
> +                           MulOp0, MulOp1, Addend);<br>
> +   MulOp->eraseFromParent();<br>
> +<br>
> +   return FMulAdd;<br>
> +}<br>
> +<br>
> +// Check whether it would be legal to emit an fmuladd intrinsic call to<br>
> +// represent op and if so, build the fmuladd.<br>
> +//<br>
> +// Checks that (a) the operation is fusable, and (b) -ffp-contract=on.<br>
> +// Does NOT check the type of the operation - it's assumed that this function<br>
> +// will be called from contexts where it's known that the type is contractable.<br>
> +static Value* tryEmitFMulAdd(const BinOpInfo &op,<br>
> +                         const CodeGenFunction &CGF, CGBuilderTy &Builder,<br>
> +                         bool isSub=false) {<br>
> +<br>
> +  assert((op.Opcode == BO_Add || op.Opcode == BO_AddAssign ||<br>
> +          op.Opcode == BO_Sub || op.Opcode == BO_SubAssign) &&<br>
> +         "Only fadd/fsub can be the root of an fmuladd.");<br>
> +<br>
> +  // Check whether this op is marked as fusable.<br>
> +  if (!op.FPContractable)<br>
> +    return 0;<br>
> +<br>
> +  // Check whether -ffp-contract=on. (If -ffp-contract=off/fast, fusing is<br>
> +  // either disabled, or handled entirely by the LLVM backend).<br>
> +  if (CGF.getContext().getLangOpts().getFPContractMode() != LangOptions::FPC_On)<br>
> +    return 0;<br>
> +<br>
> +  // We have a potentially fusable op. Look for a mul on one of the operands.<br>
> +  if (llvm::BinaryOperator* LHSBinOp = dyn_cast<llvm::BinaryOperator>(op.LHS)) {<br>
> +    if (LHSBinOp->getOpcode() == llvm::Instruction::FMul) {<br>
> +      return buildFMulAdd(LHSBinOp, op.RHS, CGF, Builder, false, isSub);<br>
> +    }<br>
> +  } else if (llvm::BinaryOperator* RHSBinOp =<br>
> +               dyn_cast<llvm::BinaryOperator>(op.RHS)) {<br>
> +    if (RHSBinOp->getOpcode() == llvm::Instruction::FMul) {<br>
> +      return buildFMulAdd(RHSBinOp, op.LHS, CGF, Builder, isSub, false);<br>
> +    }<br>
> +  }<br>
> +<br>
> +  return 0;<br>
> +}<br>
> +<br>
>  Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {<br>
>    if (op.LHS->getType()->isPointerTy() ||<br>
>        op.RHS->getType()->isPointerTy())<br>
> @@ -2000,8 +2073,13 @@<br>
>      }<br>
>    }<br>
><br>
> -  if (op.LHS->getType()->isFPOrFPVectorTy())<br>
> +  if (op.LHS->getType()->isFPOrFPVectorTy()) {<br>
> +    // Try to form an fmuladd.<br>
> +    if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder))<br>
> +      return FMulAdd;<br>
> +<br>
>      return Builder.CreateFAdd(op.LHS, op.RHS, "add");<br>
> +  }<br>
><br>
>    return Builder.CreateAdd(op.LHS, op.RHS, "add");<br>
>  }<br>
> @@ -2022,8 +2100,12 @@<br>
>        }<br>
>      }<br>
><br>
> -    if (op.LHS->getType()->isFPOrFPVectorTy())<br>
> +    if (op.LHS->getType()->isFPOrFPVectorTy()) {<br>
> +      // Try to form an fmuladd.<br>
> +      if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder, true))<br>
> +        return FMulAdd;<br>
>        return Builder.CreateFSub(op.LHS, op.RHS, "sub");<br>
> +    }<br>
><br>
>      return Builder.CreateSub(op.LHS, op.RHS, "sub");<br>
>    }<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -1213,7 +1213,7 @@<br>
><br>
>    BinaryOperator assign(&ivarRef, finalArg, BO_Assign,<br>
>                          ivarRef.getType(), VK_RValue, OK_Ordinary,<br>
> -                        SourceLocation());<br>
> +                        SourceLocation(), false);<br>
>    EmitStmt(&assign);<br>
>  }<br>
><br>
> @@ -2850,7 +2850,7 @@<br>
>    CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());<br>
>    CXXOperatorCallExpr TheCall(C, OO_Equal, CalleeExp->getCallee(),<br>
>                                Args, DestTy->getPointeeType(),<br>
> -                              VK_LValue, SourceLocation());<br>
> +                              VK_LValue, SourceLocation(), false);<br>
><br>
>    EmitStmt(&TheCall);<br>
><br>
><br>
> Modified: cfe/trunk/lib/Parse/ParseStmt.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/ParseStmt.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/ParseStmt.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -679,6 +679,11 @@<br>
>    PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),<br>
>                                  Tok.getLocation(),<br>
>                                  "in compound statement ('{}')");<br>
> +<br>
> +  // Record the state of the FP_CONTRACT pragma, restore on leaving the<br>
> +  // compound statement.<br>
> +  Sema::FPContractStateRAII SaveFPContractState(Actions);<br>
> +<br>
>    InMessageExpressionRAIIObject InMessage(*this, false);<br>
>    BalancedDelimiterTracker T(*this, tok::l_brace);<br>
>    if (T.consumeOpen())<br>
><br>
> Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp (original)<br>
> +++ cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -3576,7 +3576,8 @@<br>
>                                                     SourceLocation());<br>
>      BinaryOperator *lessThanExpr =<br>
>        new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy,<br>
> -                                   VK_RValue, OK_Ordinary, SourceLocation());<br>
> +                                   VK_RValue, OK_Ordinary, SourceLocation(),<br>
> +                                   false);<br>
>      // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))<br>
>      ConditionalOperator *CondExpr =<br>
>        new (Context) ConditionalOperator(lessThanExpr,<br>
> @@ -7473,7 +7474,7 @@<br>
>        BinaryOperator *addExpr =<br>
>          new (Context) BinaryOperator(castExpr, DRE, BO_Add,<br>
>                                       Context->getPointerType(Context->CharTy),<br>
> -                                     VK_RValue, OK_Ordinary, SourceLocation());<br>
> +                                     VK_RValue, OK_Ordinary, SourceLocation(), false);<br>
>        // Don't forget the parens to enforce the proper binding.<br>
>        ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),<br>
>                                                SourceLocation(),<br>
><br>
> Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp (original)<br>
> +++ cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -3078,7 +3078,8 @@<br>
>                                                     SourceLocation());<br>
>      BinaryOperator *lessThanExpr =<br>
>        new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy,<br>
> -                                   VK_RValue, OK_Ordinary, SourceLocation());<br>
> +                                   VK_RValue, OK_Ordinary, SourceLocation(),<br>
> +                                   false);<br>
>      // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))<br>
>      ConditionalOperator *CondExpr =<br>
>        new (Context) ConditionalOperator(lessThanExpr,<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -7504,7 +7504,7 @@<br>
>      = new (S.Context) BinaryOperator(IterationVarRefRVal,<br>
>                       IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),<br>
>                                       BO_NE, S.Context.BoolTy,<br>
> -                                     VK_RValue, OK_Ordinary, Loc);<br>
> +                                     VK_RValue, OK_Ordinary, Loc, false);<br>
><br>
>    // Create the pre-increment of the iteration variable.<br>
>    Expr *Increment<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -8416,7 +8416,8 @@<br>
><br>
>    if (CompResultTy.isNull())<br>
>      return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc,<br>
> -                                              ResultTy, VK, OK, OpLoc));<br>
> +                                              ResultTy, VK, OK, OpLoc,<br>
> +                                              FPFeatures.fp_contract));<br>
>    if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() !=<br>
>        OK_ObjCProperty) {<br>
>      VK = VK_LValue;<br>
> @@ -8424,7 +8425,8 @@<br>
>    }<br>
>    return Owned(new (Context) CompoundAssignOperator(LHS.take(), RHS.take(), Opc,<br>
>                                                      ResultTy, VK, OK, CompLHSTy,<br>
> -                                                    CompResultTy, OpLoc));<br>
> +                                                    CompResultTy, OpLoc,<br>
> +                                                    FPFeatures.fp_contract));<br>
>  }<br>
><br>
>  /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -4833,7 +4833,8 @@<br>
>                                                  BO_Comma, BO->getType(),<br>
>                                                  BO->getValueKind(),<br>
>                                                  BO->getObjectKind(),<br>
> -                                                BO->getOperatorLoc()));<br>
> +                                                BO->getOperatorLoc(),<br>
> +                                                BO->isFPContractable()));<br>
>      }<br>
>    }<br>
><br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -9981,7 +9981,7 @@<br>
>                                                llvm::makeArrayRef(Args, NumArgs),<br>
>                                                     Context.DependentTy,<br>
>                                                     VK_RValue,<br>
> -                                                   OpLoc));<br>
> +                                                   OpLoc, false));<br>
>    }<br>
><br>
>    // Build an empty overload set.<br>
> @@ -10058,7 +10058,7 @@<br>
>        CallExpr *TheCall =<br>
>          new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),<br>
>                                            llvm::makeArrayRef(Args, NumArgs),<br>
> -                                          ResultTy, VK, OpLoc);<br>
> +                                          ResultTy, VK, OpLoc, false);<br>
><br>
>        if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,<br>
>                                FnDecl))<br>
> @@ -10159,7 +10159,8 @@<br>
>          return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,<br>
>                                                    Context.DependentTy,<br>
>                                                    VK_RValue, OK_Ordinary,<br>
> -                                                  OpLoc));<br>
> +                                                  OpLoc,<br>
> +                                                  FPFeatures.fp_contract));<br>
><br>
>        return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,<br>
>                                                          Context.DependentTy,<br>
> @@ -10167,7 +10168,8 @@<br>
>                                                          OK_Ordinary,<br>
>                                                          Context.DependentTy,<br>
>                                                          Context.DependentTy,<br>
> -                                                        OpLoc));<br>
> +                                                        OpLoc,<br>
> +                                                        FPFeatures.fp_contract));<br>
>      }<br>
><br>
>      // FIXME: save results of ADL from here?<br>
> @@ -10179,11 +10181,9 @@<br>
>                                       NestedNameSpecifierLoc(), OpNameInfo,<br>
>                                       /*ADL*/ true, IsOverloaded(Fns),<br>
>                                       Fns.begin(), Fns.end());<br>
> -    return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,<br>
> -                                                   Args,<br>
> -                                                   Context.DependentTy,<br>
> -                                                   VK_RValue,<br>
> -                                                   OpLoc));<br>
> +    return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args,<br>
> +                                                Context.DependentTy, VK_RValue,<br>
> +                                                OpLoc, FPFeatures.fp_contract));<br>
>    }<br>
><br>
>    // Always do placeholder-like conversions on the RHS.<br>
> @@ -10298,7 +10298,8 @@<br>
><br>
>          CXXOperatorCallExpr *TheCall =<br>
>            new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),<br>
> -                                            Args, ResultTy, VK, OpLoc);<br>
> +                                            Args, ResultTy, VK, OpLoc,<br>
> +                                            FPFeatures.fp_contract);<br>
><br>
>          if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,<br>
>                                  FnDecl))<br>
> @@ -10430,7 +10431,7 @@<br>
>                                                     Args,<br>
>                                                     Context.DependentTy,<br>
>                                                     VK_RValue,<br>
> -                                                   RLoc));<br>
> +                                                   RLoc, false));<br>
>    }<br>
><br>
>    // Handle placeholders on both operands.<br>
> @@ -10507,7 +10508,8 @@<br>
>          CXXOperatorCallExpr *TheCall =<br>
>            new (Context) CXXOperatorCallExpr(Context, OO_Subscript,<br>
>                                              FnExpr.take(), Args,<br>
> -                                            ResultTy, VK, RLoc);<br>
> +                                            ResultTy, VK, RLoc,<br>
> +                                            false);<br>
><br>
>          if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,<br>
>                                  FnDecl))<br>
> @@ -11035,7 +11037,7 @@<br>
>    CXXOperatorCallExpr *TheCall =<br>
>      new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(),<br>
>                                        llvm::makeArrayRef(MethodArgs, NumArgs+1),<br>
> -                                      ResultTy, VK, RParenLoc);<br>
> +                                      ResultTy, VK, RParenLoc, false);<br>
>    delete [] MethodArgs;<br>
><br>
>    if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,<br>
> @@ -11208,7 +11210,7 @@<br>
>    ResultTy = ResultTy.getNonLValueExprType(Context);<br>
>    CXXOperatorCallExpr *TheCall =<br>
>      new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(),<br>
> -                                      Base, ResultTy, VK, OpLoc);<br>
> +                                      Base, ResultTy, VK, OpLoc, false);<br>
><br>
>    if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,<br>
>                            Method))<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -356,7 +356,7 @@<br>
>      syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,<br>
>                                                 opcode, capturedRHS->getType(),<br>
>                                                 capturedRHS->getValueKind(),<br>
> -                                               OK_Ordinary, opcLoc);<br>
> +                                               OK_Ordinary, opcLoc, false);<br>
>    } else {<br>
>      ExprResult opLHS = buildGet();<br>
>      if (opLHS.isInvalid()) return ExprError();<br>
> @@ -375,7 +375,7 @@<br>
>                                               OK_Ordinary,<br>
>                                               opLHS.get()->getType(),<br>
>                                               result.get()->getType(),<br>
> -                                             opcLoc);<br>
> +                                             opcLoc, false);<br>
>    }<br>
><br>
>    // The result of the assignment, if not void, is the value set into<br>
> @@ -1366,7 +1366,7 @@<br>
>    // Do nothing if either argument is dependent.<br>
>    if (LHS->isTypeDependent() || RHS->isTypeDependent())<br>
>      return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,<br>
> -                                        VK_RValue, OK_Ordinary, opcLoc);<br>
> +                                        VK_RValue, OK_Ordinary, opcLoc, false);<br>
><br>
>    // Filter out non-overload placeholder types in the RHS.<br>
>    if (RHS->getType()->isNonOverloadPlaceholderType()) {<br>
> @@ -1437,14 +1437,14 @@<br>
>                                                  cop->getObjectKind(),<br>
>                                                  cop->getComputationLHSType(),<br>
>                                                  cop->getComputationResultType(),<br>
> -                                                cop->getOperatorLoc());<br>
> +                                                cop->getOperatorLoc(), false);<br>
>    } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {<br>
>      Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());<br>
>      Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();<br>
>      return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),<br>
>                                          bop->getType(), bop->getValueKind(),<br>
>                                          bop->getObjectKind(),<br>
> -                                        bop->getOperatorLoc());<br>
> +                                        bop->getOperatorLoc(), false);<br>
>    } else {<br>
>      assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));<br>
>      return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);<br>
><br>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
> +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Oct  1 23:45:10 2012<br>
> @@ -6429,6 +6429,9 @@<br>
>        RHS.get() == E->getRHS())<br>
>      return SemaRef.Owned(E);<br>
><br>
> +  Sema::FPContractStateRAII FPContractState(getSema());<br>
> +  getSema().FPFeatures.fp_contract = E->isFPContractable();<br>
> +<br>
>    return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),<br>
>                                              LHS.get(), RHS.get());<br>
>  }<br>
> @@ -6852,6 +6855,9 @@<br>
>        (E->getNumArgs() != 2 || Second.get() == E->getArg(1)))<br>
>      return SemaRef.MaybeBindToTemporary(E);<br>
><br>
> +  Sema::FPContractStateRAII FPContractState(getSema());<br>
> +  getSema().FPFeatures.fp_contract = E->isFPContractable();<br>
> +<br>
>    return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),<br>
>                                                   E->getOperatorLoc(),<br>
>                                                   Callee.get(),<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -565,6 +565,7 @@<br>
>    E->setRHS(Reader.ReadSubExpr());<br>
>    E->setOpcode((BinaryOperator::Opcode)Record[Idx++]);<br>
>    E->setOperatorLoc(ReadSourceLocation(Record, Idx));<br>
> +  E->setFPContractable((bool)Record[Idx++]);<br>
>  }<br>
><br>
>  void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {<br>
> @@ -1086,6 +1087,7 @@<br>
>    VisitCallExpr(E);<br>
>    E->Operator = (OverloadedOperatorKind)Record[Idx++];<br>
>    E->Range = Reader.ReadSourceRange(F, Record, Idx);<br>
> +  E->setFPContractable((bool)Record[Idx++]);<br>
>  }<br>
><br>
>  void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -536,6 +536,7 @@<br>
>    Writer.AddStmt(E->getRHS());<br>
>    Record.push_back(E->getOpcode()); // FIXME: stable encoding<br>
>    Writer.AddSourceLocation(E->getOperatorLoc(), Record);<br>
> +  Record.push_back(E->isFPContractable());<br>
>    Code = serialization::EXPR_BINARY_OPERATOR;<br>
>  }<br>
><br>
> @@ -1055,6 +1056,7 @@<br>
>    VisitCallExpr(E);<br>
>    Record.push_back(E->getOperator());<br>
>    Writer.AddSourceRange(E->Range, Record);<br>
> +  Record.push_back(E->isFPContractable());<br>
>    Code = serialization::EXPR_CXX_OPERATOR_CALL;<br>
>  }<br>
><br>
><br>
> Added: cfe/trunk/test/CodeGen/fp-contract-pragma.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/fp-contract-pragma.cpp?rev=164989&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/fp-contract-pragma.cpp?rev=164989&view=auto</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGen/fp-contract-pragma.cpp (added)<br>
> +++ cfe/trunk/test/CodeGen/fp-contract-pragma.cpp Mon Oct  1 23:45:10 2012<br>
> @@ -0,0 +1,39 @@<br>
> +// RUN: %clang_cc1 -O3 -emit-llvm -o - %s | FileCheck %s<br>
> +<br>
> +// Is FP_CONTRACT is honored in a simple case?<br>
> +float fp_contract_1(float a, float b, float c) {<br>
> +// CHECK: _Z13fp_contract_1fff<br>
> +// CHECK-NEXT: entry<br>
> +// CHECK-NEXT: %0 = tail call float @llvm.fmuladd<br>
> +  #pragma STDC FP_CONTRACT ON<br>
> +  return a * b + c;<br>
> +}<br>
> +<br>
> +// Is FP_CONTRACT state cleared on exiting compound statements?<br>
> +float fp_contract_2(float a, float b, float c) {<br>
> +// CHECK: _Z13fp_contract_2fff<br>
> +// CHECK-NEXT: entry<br>
> +// CHECK-NEXT: %mul = fmul float %a, %b<br>
> +// CHECK-NEXT: %add = fadd float %mul, %c<br>
> +  {<br>
> +    #pragma STDC FP_CONTRACT ON<br>
> +  }<br>
> +  return a * b + c;<br>
> +}<br>
> +<br>
> +// Does FP_CONTRACT survive template instatiation?<br>
> +class Foo {};<br>
> +Foo operator+(Foo, Foo);<br>
> +<br>
> +template <typename T><br>
> +T template_muladd(T a, T b, T c) {<br>
> +  #pragma STDC FP_CONTRACT ON<br>
> +  return a * b + c;<br>
> +}<br>
> +<br>
> +float fp_contract_3(float a, float b, float c) {<br>
> +// CHECK: _Z13fp_contract_3fff<br>
> +// CHECK-NEXT: entry<br>
> +// CHECK-NEXT: %0 = tail call float @llvm.fmuladd<br>
> +  return template_muladd<float>(a, b, c);<br>
> +}<br>
><br>
> Removed: cfe/trunk/test/CodeGen/fp-contract.c<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/fp-contract.c?rev=164988&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/fp-contract.c?rev=164988&view=auto</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGen/fp-contract.c (original)<br>
> +++ cfe/trunk/test/CodeGen/fp-contract.c (removed)<br>
> @@ -1,9 +0,0 @@<br>
> -// RUN: %clang_cc1 -O3 -ffp-contract=fast -triple=powerpc-apple-darwin10 -S -o - %s | FileCheck %s<br>
> -// REQUIRES: ppc32-registered-target<br>
> -<br>
> -float fma_test1(float a, float b, float c) {<br>
> -// CHECK: fmadds<br>
> -  float x = a * b;<br>
> -  float y = x + c;<br>
> -  return y;<br>
> -}<br>
><br>
> Modified: cfe/trunk/test/CodeGenOpenCL/<a href="http://single-precision-constant.cl" target="_blank">single-precision-constant.cl</a><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl?rev=164989&r1=164988&r2=164989&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl?rev=164989&r1=164988&r2=164989&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CodeGenOpenCL/<a href="http://single-precision-constant.cl" target="_blank">single-precision-constant.cl</a> (original)<br>
> +++ cfe/trunk/test/CodeGenOpenCL/<a href="http://single-precision-constant.cl" target="_blank">single-precision-constant.cl</a> Mon Oct  1 23:45:10 2012<br>
> @@ -1,7 +1,6 @@<br>
>  // RUN: %clang_cc1 %s -cl-single-precision-constant -emit-llvm -o - | FileCheck %s<br>
><br>
>  float fn(float f) {<br>
> -  // CHECK: fmul float<br>
> -  // CHECK: fadd float<br>
> +  // CHECK: %0 = tail call float @llvm.fmuladd.f32(float %f, float 2.000000e+00, float 1.000000e+00)<br>
>    return f*2. + 1.;<br>
>  }<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</div></div></blockquote></div><br></div></div>