[cfe-commits] r164989 - in /cfe/trunk: include/clang/AST/ include/clang/Sema/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Parse/ lib/Rewrite/Frontend/ lib/Sema/ lib/Serialization/ test/CodeGen/ test/CodeGenOpenCL/

David Blaikie dblaikie at gmail.com
Tue Oct 2 12:06:22 PDT 2012


On Mon, Oct 1, 2012 at 9:45 PM, Lang Hames <lhames at gmail.com> wrote:
> Author: lhames
> Date: Mon Oct  1 23:45:10 2012
> New Revision: 164989
>
> URL: http://llvm.org/viewvc/llvm-project?rev=164989&view=rev
> Log:
> Add FP_CONTRACT support for clang.
>
> Clang will now honor the FP_CONTRACT pragma and emit LLVM
> fmuladd intrinsics for expressions of the form A * B + C (when they occur in a
> single statement).

Hooray \o/

I think you were telling me that the pragma can be applied at the file
scope. Is that tested somewhere?

- David

>
>
> Added:
>     cfe/trunk/test/CodeGen/ffp-contract-option.c
>       - copied unchanged from r164952, cfe/trunk/test/CodeGen/fp-contract.c
>     cfe/trunk/test/CodeGen/fp-contract-pragma.cpp
> Removed:
>     cfe/trunk/test/CodeGen/fp-contract.c
> Modified:
>     cfe/trunk/include/clang/AST/Expr.h
>     cfe/trunk/include/clang/AST/ExprCXX.h
>     cfe/trunk/include/clang/Sema/Sema.h
>     cfe/trunk/lib/AST/ASTImporter.cpp
>     cfe/trunk/lib/Analysis/BodyFarm.cpp
>     cfe/trunk/lib/CodeGen/CGExprScalar.cpp
>     cfe/trunk/lib/CodeGen/CGObjC.cpp
>     cfe/trunk/lib/Parse/ParseStmt.cpp
>     cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp
>     cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp
>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>     cfe/trunk/lib/Sema/SemaExpr.cpp
>     cfe/trunk/lib/Sema/SemaExprCXX.cpp
>     cfe/trunk/lib/Sema/SemaOverload.cpp
>     cfe/trunk/lib/Sema/SemaPseudoObject.cpp
>     cfe/trunk/lib/Sema/TreeTransform.h
>     cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
>     cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
>     cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl
>
> Modified: cfe/trunk/include/clang/AST/Expr.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Expr.h (original)
> +++ cfe/trunk/include/clang/AST/Expr.h Mon Oct  1 23:45:10 2012
> @@ -2785,6 +2785,12 @@
>
>  private:
>    unsigned Opc : 6;
> +
> +  // Records the FP_CONTRACT pragma status at the point that this binary
> +  // operator was parsed. This bit is only meaningful for operations on
> +  // floating point types. For all other types it should default to
> +  // false.
> +  unsigned FPContractable : 1;
>    SourceLocation OpLoc;
>
>    enum { LHS, RHS, END_EXPR };
> @@ -2793,7 +2799,7 @@
>
>    BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
>                   ExprValueKind VK, ExprObjectKind OK,
> -                 SourceLocation opLoc)
> +                 SourceLocation opLoc, bool fpContractable)
>      : Expr(BinaryOperatorClass, ResTy, VK, OK,
>             lhs->isTypeDependent() || rhs->isTypeDependent(),
>             lhs->isValueDependent() || rhs->isValueDependent(),
> @@ -2801,7 +2807,7 @@
>              rhs->isInstantiationDependent()),
>             (lhs->containsUnexpandedParameterPack() ||
>              rhs->containsUnexpandedParameterPack())),
> -      Opc(opc), OpLoc(opLoc) {
> +      Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {
>      SubExprs[LHS] = lhs;
>      SubExprs[RHS] = rhs;
>      assert(!isCompoundAssignmentOp() &&
> @@ -2902,10 +2908,18 @@
>      return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
>    }
>
> +  // Set the FP contractability status of this operator. Only meaningful for
> +  // operations on floating point types.
> +  void setFPContractable(bool FPC) { FPContractable = FPC; }
> +
> +  // Get the FP contractability status of this operator. Only meaningful for
> +  // operations on floating point types.
> +  bool isFPContractable() const { return FPContractable; }
> +
>  protected:
>    BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
>                   ExprValueKind VK, ExprObjectKind OK,
> -                 SourceLocation opLoc, bool dead)
> +                 SourceLocation opLoc, bool fpContractable, bool dead2)
>      : Expr(CompoundAssignOperatorClass, ResTy, VK, OK,
>             lhs->isTypeDependent() || rhs->isTypeDependent(),
>             lhs->isValueDependent() || rhs->isValueDependent(),
> @@ -2913,7 +2927,7 @@
>              rhs->isInstantiationDependent()),
>             (lhs->containsUnexpandedParameterPack() ||
>              rhs->containsUnexpandedParameterPack())),
> -      Opc(opc), OpLoc(opLoc) {
> +      Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {
>      SubExprs[LHS] = lhs;
>      SubExprs[RHS] = rhs;
>    }
> @@ -2935,8 +2949,9 @@
>    CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,
>                           ExprValueKind VK, ExprObjectKind OK,
>                           QualType CompLHSType, QualType CompResultType,
> -                         SourceLocation OpLoc)
> -    : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, true),
> +                         SourceLocation OpLoc, bool fpContractable)
> +    : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable,
> +                     true),
>        ComputationLHSType(CompLHSType),
>        ComputationResultType(CompResultType) {
>      assert(isCompoundAssignmentOp() &&
>
> Modified: cfe/trunk/include/clang/AST/ExprCXX.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ExprCXX.h (original)
> +++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Oct  1 23:45:10 2012
> @@ -53,14 +53,19 @@
>    OverloadedOperatorKind Operator;
>    SourceRange Range;
>
> +  // Record the FP_CONTRACT state that applies to this operator call. Only
> +  // meaningful for floating point types. For other types this value can be
> +  // set to false.
> +  unsigned FPContractable : 1;
> +
>    SourceRange getSourceRangeImpl() const LLVM_READONLY;
>  public:
>    CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
>                        ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
> -                      SourceLocation operatorloc)
> +                      SourceLocation operatorloc, bool fpContractable)
>      : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, t, VK,
>                 operatorloc),
> -      Operator(Op) {
> +      Operator(Op), FPContractable(fpContractable) {
>      Range = getSourceRangeImpl();
>    }
>    explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
> @@ -85,6 +90,14 @@
>    }
>    static bool classof(const CXXOperatorCallExpr *) { return true; }
>
> +  // Set the FP contractability status of this operator. Only meaningful for
> +  // operations on floating point types.
> +  void setFPContractable(bool FPC) { FPContractable = FPC; }
> +
> +  // Get the FP contractability status of this operator. Only meaningful for
> +  // operations on floating point types.
> +  bool isFPContractable() const { return FPContractable; }
> +
>    friend class ASTStmtReader;
>    friend class ASTStmtWriter;
>  };
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct  1 23:45:10 2012
> @@ -735,6 +735,20 @@
>    /// should not be used elsewhere.
>    void EmitCurrentDiagnostic(unsigned DiagID);
>
> +  /// Records and restores the FP_CONTRACT state on entry/exit of compound
> +  /// statements.
> +  class FPContractStateRAII {
> +  public:
> +    FPContractStateRAII(Sema& S)
> +      : S(S), OldFPContractState(S.FPFeatures.fp_contract) {}
> +    ~FPContractStateRAII() {
> +      S.FPFeatures.fp_contract = OldFPContractState;
> +    }
> +  private:
> +    Sema& S;
> +    bool OldFPContractState : 1;
> +  };
> +
>  public:
>    Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
>         TranslationUnitKind TUKind = TU_Complete,
>
> Modified: cfe/trunk/lib/AST/ASTImporter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)
> +++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Oct  1 23:45:10 2012
> @@ -4082,7 +4082,8 @@
>    return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(),
>                                                        T, E->getValueKind(),
>                                                        E->getObjectKind(),
> -                                          Importer.Import(E->getOperatorLoc()));
> +                                           Importer.Import(E->getOperatorLoc()),
> +                                                      E->isFPContractable());
>  }
>
>  Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
> @@ -4111,7 +4112,8 @@
>                                                 T, E->getValueKind(),
>                                                 E->getObjectKind(),
>                                                 CompLHSType, CompResultType,
> -                                          Importer.Import(E->getOperatorLoc()));
> +                                           Importer.Import(E->getOperatorLoc()),
> +                                               E->isFPContractable());
>  }
>
>  static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
>
> Modified: cfe/trunk/lib/Analysis/BodyFarm.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Analysis/BodyFarm.cpp (original)
> +++ cfe/trunk/lib/Analysis/BodyFarm.cpp Mon Oct  1 23:45:10 2012
> @@ -70,7 +70,7 @@
>                                           QualType Ty) {
>   return new (C) BinaryOperator(const_cast<Expr*>(LHS), const_cast<Expr*>(RHS),
>                                 BO_Assign, Ty, VK_RValue,
> -                               OK_Ordinary, SourceLocation());
> +                               OK_Ordinary, SourceLocation(), false);
>  }
>
>  DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) {
>
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Oct  1 23:45:10 2012
> @@ -45,6 +45,7 @@
>    Value *RHS;
>    QualType Ty;  // Computation Type.
>    BinaryOperator::Opcode Opcode; // Opcode of BinOp to perform
> +  bool FPContractable;
>    const Expr *E;      // Entire expr, for error unsupported.  May not be binop.
>  };
>
> @@ -1654,6 +1655,7 @@
>    Result.RHS = Visit(E->getRHS());
>    Result.Ty  = E->getType();
>    Result.Opcode = E->getOpcode();
> +  Result.FPContractable = E->isFPContractable();
>    Result.E = E;
>    return Result;
>  }
> @@ -1982,6 +1984,77 @@
>    return CGF.Builder.CreateInBoundsGEP(pointer, index, "add.ptr");
>  }
>
> +// Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and
> +// Addend. Use negMul and negAdd to negate the first operand of the Mul or
> +// the add operand respectively. This allows fmuladd to represent a*b-c, or
> +// c-a*b. Patterns in LLVM should catch the negated forms and translate them to
> +// efficient operations.
> +static Value* buildFMulAdd(llvm::BinaryOperator *MulOp, Value *Addend,
> +                           const CodeGenFunction &CGF, CGBuilderTy &Builder,
> +                           bool negMul, bool negAdd) {
> +  assert(!(negMul && negAdd) && "Only one of negMul and negAdd should be set.");
> +
> +  Value *MulOp0 = MulOp->getOperand(0);
> +  Value *MulOp1 = MulOp->getOperand(1);
> +  if (negMul) {
> +    MulOp0 =
> +      Builder.CreateFSub(
> +        llvm::ConstantFP::getZeroValueForNegation(MulOp0->getType()), MulOp0,
> +        "neg");
> +  } else if (negAdd) {
> +    Addend =
> +      Builder.CreateFSub(
> +        llvm::ConstantFP::getZeroValueForNegation(Addend->getType()), Addend,
> +        "neg");
> +  }
> +
> +  Value *FMulAdd =
> +    Builder.CreateCall3(
> +      CGF.CGM.getIntrinsic(llvm::Intrinsic::fmuladd, Addend->getType()),
> +                           MulOp0, MulOp1, Addend);
> +   MulOp->eraseFromParent();
> +
> +   return FMulAdd;
> +}
> +
> +// Check whether it would be legal to emit an fmuladd intrinsic call to
> +// represent op and if so, build the fmuladd.
> +//
> +// Checks that (a) the operation is fusable, and (b) -ffp-contract=on.
> +// Does NOT check the type of the operation - it's assumed that this function
> +// will be called from contexts where it's known that the type is contractable.
> +static Value* tryEmitFMulAdd(const BinOpInfo &op,
> +                         const CodeGenFunction &CGF, CGBuilderTy &Builder,
> +                         bool isSub=false) {
> +
> +  assert((op.Opcode == BO_Add || op.Opcode == BO_AddAssign ||
> +          op.Opcode == BO_Sub || op.Opcode == BO_SubAssign) &&
> +         "Only fadd/fsub can be the root of an fmuladd.");
> +
> +  // Check whether this op is marked as fusable.
> +  if (!op.FPContractable)
> +    return 0;
> +
> +  // Check whether -ffp-contract=on. (If -ffp-contract=off/fast, fusing is
> +  // either disabled, or handled entirely by the LLVM backend).
> +  if (CGF.getContext().getLangOpts().getFPContractMode() != LangOptions::FPC_On)
> +    return 0;
> +
> +  // We have a potentially fusable op. Look for a mul on one of the operands.
> +  if (llvm::BinaryOperator* LHSBinOp = dyn_cast<llvm::BinaryOperator>(op.LHS)) {
> +    if (LHSBinOp->getOpcode() == llvm::Instruction::FMul) {
> +      return buildFMulAdd(LHSBinOp, op.RHS, CGF, Builder, false, isSub);
> +    }
> +  } else if (llvm::BinaryOperator* RHSBinOp =
> +               dyn_cast<llvm::BinaryOperator>(op.RHS)) {
> +    if (RHSBinOp->getOpcode() == llvm::Instruction::FMul) {
> +      return buildFMulAdd(RHSBinOp, op.LHS, CGF, Builder, isSub, false);
> +    }
> +  }
> +
> +  return 0;
> +}
> +
>  Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
>    if (op.LHS->getType()->isPointerTy() ||
>        op.RHS->getType()->isPointerTy())
> @@ -2000,8 +2073,13 @@
>      }
>    }
>
> -  if (op.LHS->getType()->isFPOrFPVectorTy())
> +  if (op.LHS->getType()->isFPOrFPVectorTy()) {
> +    // Try to form an fmuladd.
> +    if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder))
> +      return FMulAdd;
> +
>      return Builder.CreateFAdd(op.LHS, op.RHS, "add");
> +  }
>
>    return Builder.CreateAdd(op.LHS, op.RHS, "add");
>  }
> @@ -2022,8 +2100,12 @@
>        }
>      }
>
> -    if (op.LHS->getType()->isFPOrFPVectorTy())
> +    if (op.LHS->getType()->isFPOrFPVectorTy()) {
> +      // Try to form an fmuladd.
> +      if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder, true))
> +        return FMulAdd;
>        return Builder.CreateFSub(op.LHS, op.RHS, "sub");
> +    }
>
>      return Builder.CreateSub(op.LHS, op.RHS, "sub");
>    }
>
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Mon Oct  1 23:45:10 2012
> @@ -1213,7 +1213,7 @@
>
>    BinaryOperator assign(&ivarRef, finalArg, BO_Assign,
>                          ivarRef.getType(), VK_RValue, OK_Ordinary,
> -                        SourceLocation());
> +                        SourceLocation(), false);
>    EmitStmt(&assign);
>  }
>
> @@ -2850,7 +2850,7 @@
>    CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());
>    CXXOperatorCallExpr TheCall(C, OO_Equal, CalleeExp->getCallee(),
>                                Args, DestTy->getPointeeType(),
> -                              VK_LValue, SourceLocation());
> +                              VK_LValue, SourceLocation(), false);
>
>    EmitStmt(&TheCall);
>
>
> Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseStmt.cpp Mon Oct  1 23:45:10 2012
> @@ -679,6 +679,11 @@
>    PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
>                                  Tok.getLocation(),
>                                  "in compound statement ('{}')");
> +
> +  // Record the state of the FP_CONTRACT pragma, restore on leaving the
> +  // compound statement.
> +  Sema::FPContractStateRAII SaveFPContractState(Actions);
> +
>    InMessageExpressionRAIIObject InMessage(*this, false);
>    BalancedDelimiterTracker T(*this, tok::l_brace);
>    if (T.consumeOpen())
>
> Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp (original)
> +++ cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp Mon Oct  1 23:45:10 2012
> @@ -3576,7 +3576,8 @@
>                                                     SourceLocation());
>      BinaryOperator *lessThanExpr =
>        new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy,
> -                                   VK_RValue, OK_Ordinary, SourceLocation());
> +                                   VK_RValue, OK_Ordinary, SourceLocation(),
> +                                   false);
>      // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
>      ConditionalOperator *CondExpr =
>        new (Context) ConditionalOperator(lessThanExpr,
> @@ -7473,7 +7474,7 @@
>        BinaryOperator *addExpr =
>          new (Context) BinaryOperator(castExpr, DRE, BO_Add,
>                                       Context->getPointerType(Context->CharTy),
> -                                     VK_RValue, OK_Ordinary, SourceLocation());
> +                                     VK_RValue, OK_Ordinary, SourceLocation(), false);
>        // Don't forget the parens to enforce the proper binding.
>        ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
>                                                SourceLocation(),
>
> Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp (original)
> +++ cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp Mon Oct  1 23:45:10 2012
> @@ -3078,7 +3078,8 @@
>                                                     SourceLocation());
>      BinaryOperator *lessThanExpr =
>        new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy,
> -                                   VK_RValue, OK_Ordinary, SourceLocation());
> +                                   VK_RValue, OK_Ordinary, SourceLocation(),
> +                                   false);
>      // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
>      ConditionalOperator *CondExpr =
>        new (Context) ConditionalOperator(lessThanExpr,
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Oct  1 23:45:10 2012
> @@ -7504,7 +7504,7 @@
>      = new (S.Context) BinaryOperator(IterationVarRefRVal,
>                       IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
>                                       BO_NE, S.Context.BoolTy,
> -                                     VK_RValue, OK_Ordinary, Loc);
> +                                     VK_RValue, OK_Ordinary, Loc, false);
>
>    // Create the pre-increment of the iteration variable.
>    Expr *Increment
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Oct  1 23:45:10 2012
> @@ -8416,7 +8416,8 @@
>
>    if (CompResultTy.isNull())
>      return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc,
> -                                              ResultTy, VK, OK, OpLoc));
> +                                              ResultTy, VK, OK, OpLoc,
> +                                              FPFeatures.fp_contract));
>    if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() !=
>        OK_ObjCProperty) {
>      VK = VK_LValue;
> @@ -8424,7 +8425,8 @@
>    }
>    return Owned(new (Context) CompoundAssignOperator(LHS.take(), RHS.take(), Opc,
>                                                      ResultTy, VK, OK, CompLHSTy,
> -                                                    CompResultTy, OpLoc));
> +                                                    CompResultTy, OpLoc,
> +                                                    FPFeatures.fp_contract));
>  }
>
>  /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Oct  1 23:45:10 2012
> @@ -4833,7 +4833,8 @@
>                                                  BO_Comma, BO->getType(),
>                                                  BO->getValueKind(),
>                                                  BO->getObjectKind(),
> -                                                BO->getOperatorLoc()));
> +                                                BO->getOperatorLoc(),
> +                                                BO->isFPContractable()));
>      }
>    }
>
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Oct  1 23:45:10 2012
> @@ -9981,7 +9981,7 @@
>                                                llvm::makeArrayRef(Args, NumArgs),
>                                                     Context.DependentTy,
>                                                     VK_RValue,
> -                                                   OpLoc));
> +                                                   OpLoc, false));
>    }
>
>    // Build an empty overload set.
> @@ -10058,7 +10058,7 @@
>        CallExpr *TheCall =
>          new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
>                                            llvm::makeArrayRef(Args, NumArgs),
> -                                          ResultTy, VK, OpLoc);
> +                                          ResultTy, VK, OpLoc, false);
>
>        if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
>                                FnDecl))
> @@ -10159,7 +10159,8 @@
>          return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
>                                                    Context.DependentTy,
>                                                    VK_RValue, OK_Ordinary,
> -                                                  OpLoc));
> +                                                  OpLoc,
> +                                                  FPFeatures.fp_contract));
>
>        return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
>                                                          Context.DependentTy,
> @@ -10167,7 +10168,8 @@
>                                                          OK_Ordinary,
>                                                          Context.DependentTy,
>                                                          Context.DependentTy,
> -                                                        OpLoc));
> +                                                        OpLoc,
> +                                                        FPFeatures.fp_contract));
>      }
>
>      // FIXME: save results of ADL from here?
> @@ -10179,11 +10181,9 @@
>                                       NestedNameSpecifierLoc(), OpNameInfo,
>                                       /*ADL*/ true, IsOverloaded(Fns),
>                                       Fns.begin(), Fns.end());
> -    return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
> -                                                   Args,
> -                                                   Context.DependentTy,
> -                                                   VK_RValue,
> -                                                   OpLoc));
> +    return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args,
> +                                                Context.DependentTy, VK_RValue,
> +                                                OpLoc, FPFeatures.fp_contract));
>    }
>
>    // Always do placeholder-like conversions on the RHS.
> @@ -10298,7 +10298,8 @@
>
>          CXXOperatorCallExpr *TheCall =
>            new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
> -                                            Args, ResultTy, VK, OpLoc);
> +                                            Args, ResultTy, VK, OpLoc,
> +                                            FPFeatures.fp_contract);
>
>          if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
>                                  FnDecl))
> @@ -10430,7 +10431,7 @@
>                                                     Args,
>                                                     Context.DependentTy,
>                                                     VK_RValue,
> -                                                   RLoc));
> +                                                   RLoc, false));
>    }
>
>    // Handle placeholders on both operands.
> @@ -10507,7 +10508,8 @@
>          CXXOperatorCallExpr *TheCall =
>            new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
>                                              FnExpr.take(), Args,
> -                                            ResultTy, VK, RLoc);
> +                                            ResultTy, VK, RLoc,
> +                                            false);
>
>          if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
>                                  FnDecl))
> @@ -11035,7 +11037,7 @@
>    CXXOperatorCallExpr *TheCall =
>      new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(),
>                                        llvm::makeArrayRef(MethodArgs, NumArgs+1),
> -                                      ResultTy, VK, RParenLoc);
> +                                      ResultTy, VK, RParenLoc, false);
>    delete [] MethodArgs;
>
>    if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
> @@ -11208,7 +11210,7 @@
>    ResultTy = ResultTy.getNonLValueExprType(Context);
>    CXXOperatorCallExpr *TheCall =
>      new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(),
> -                                      Base, ResultTy, VK, OpLoc);
> +                                      Base, ResultTy, VK, OpLoc, false);
>
>    if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
>                            Method))
>
> Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Mon Oct  1 23:45:10 2012
> @@ -356,7 +356,7 @@
>      syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
>                                                 opcode, capturedRHS->getType(),
>                                                 capturedRHS->getValueKind(),
> -                                               OK_Ordinary, opcLoc);
> +                                               OK_Ordinary, opcLoc, false);
>    } else {
>      ExprResult opLHS = buildGet();
>      if (opLHS.isInvalid()) return ExprError();
> @@ -375,7 +375,7 @@
>                                               OK_Ordinary,
>                                               opLHS.get()->getType(),
>                                               result.get()->getType(),
> -                                             opcLoc);
> +                                             opcLoc, false);
>    }
>
>    // The result of the assignment, if not void, is the value set into
> @@ -1366,7 +1366,7 @@
>    // Do nothing if either argument is dependent.
>    if (LHS->isTypeDependent() || RHS->isTypeDependent())
>      return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
> -                                        VK_RValue, OK_Ordinary, opcLoc);
> +                                        VK_RValue, OK_Ordinary, opcLoc, false);
>
>    // Filter out non-overload placeholder types in the RHS.
>    if (RHS->getType()->isNonOverloadPlaceholderType()) {
> @@ -1437,14 +1437,14 @@
>                                                  cop->getObjectKind(),
>                                                  cop->getComputationLHSType(),
>                                                  cop->getComputationResultType(),
> -                                                cop->getOperatorLoc());
> +                                                cop->getOperatorLoc(), false);
>    } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
>      Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
>      Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
>      return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
>                                          bop->getType(), bop->getValueKind(),
>                                          bop->getObjectKind(),
> -                                        bop->getOperatorLoc());
> +                                        bop->getOperatorLoc(), false);
>    } else {
>      assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
>      return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Oct  1 23:45:10 2012
> @@ -6429,6 +6429,9 @@
>        RHS.get() == E->getRHS())
>      return SemaRef.Owned(E);
>
> +  Sema::FPContractStateRAII FPContractState(getSema());
> +  getSema().FPFeatures.fp_contract = E->isFPContractable();
> +
>    return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
>                                              LHS.get(), RHS.get());
>  }
> @@ -6852,6 +6855,9 @@
>        (E->getNumArgs() != 2 || Second.get() == E->getArg(1)))
>      return SemaRef.MaybeBindToTemporary(E);
>
> +  Sema::FPContractStateRAII FPContractState(getSema());
> +  getSema().FPFeatures.fp_contract = E->isFPContractable();
> +
>    return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
>                                                   E->getOperatorLoc(),
>                                                   Callee.get(),
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon Oct  1 23:45:10 2012
> @@ -565,6 +565,7 @@
>    E->setRHS(Reader.ReadSubExpr());
>    E->setOpcode((BinaryOperator::Opcode)Record[Idx++]);
>    E->setOperatorLoc(ReadSourceLocation(Record, Idx));
> +  E->setFPContractable((bool)Record[Idx++]);
>  }
>
>  void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
> @@ -1086,6 +1087,7 @@
>    VisitCallExpr(E);
>    E->Operator = (OverloadedOperatorKind)Record[Idx++];
>    E->Range = Reader.ReadSourceRange(F, Record, Idx);
> +  E->setFPContractable((bool)Record[Idx++]);
>  }
>
>  void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Mon Oct  1 23:45:10 2012
> @@ -536,6 +536,7 @@
>    Writer.AddStmt(E->getRHS());
>    Record.push_back(E->getOpcode()); // FIXME: stable encoding
>    Writer.AddSourceLocation(E->getOperatorLoc(), Record);
> +  Record.push_back(E->isFPContractable());
>    Code = serialization::EXPR_BINARY_OPERATOR;
>  }
>
> @@ -1055,6 +1056,7 @@
>    VisitCallExpr(E);
>    Record.push_back(E->getOperator());
>    Writer.AddSourceRange(E->Range, Record);
> +  Record.push_back(E->isFPContractable());
>    Code = serialization::EXPR_CXX_OPERATOR_CALL;
>  }
>
>
> Added: cfe/trunk/test/CodeGen/fp-contract-pragma.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/fp-contract-pragma.cpp?rev=164989&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGen/fp-contract-pragma.cpp (added)
> +++ cfe/trunk/test/CodeGen/fp-contract-pragma.cpp Mon Oct  1 23:45:10 2012
> @@ -0,0 +1,39 @@
> +// RUN: %clang_cc1 -O3 -emit-llvm -o - %s | FileCheck %s
> +
> +// Is FP_CONTRACT is honored in a simple case?
> +float fp_contract_1(float a, float b, float c) {
> +// CHECK: _Z13fp_contract_1fff
> +// CHECK-NEXT: entry
> +// CHECK-NEXT: %0 = tail call float @llvm.fmuladd
> +  #pragma STDC FP_CONTRACT ON
> +  return a * b + c;
> +}
> +
> +// Is FP_CONTRACT state cleared on exiting compound statements?
> +float fp_contract_2(float a, float b, float c) {
> +// CHECK: _Z13fp_contract_2fff
> +// CHECK-NEXT: entry
> +// CHECK-NEXT: %mul = fmul float %a, %b
> +// CHECK-NEXT: %add = fadd float %mul, %c
> +  {
> +    #pragma STDC FP_CONTRACT ON
> +  }
> +  return a * b + c;
> +}
> +
> +// Does FP_CONTRACT survive template instatiation?
> +class Foo {};
> +Foo operator+(Foo, Foo);
> +
> +template <typename T>
> +T template_muladd(T a, T b, T c) {
> +  #pragma STDC FP_CONTRACT ON
> +  return a * b + c;
> +}
> +
> +float fp_contract_3(float a, float b, float c) {
> +// CHECK: _Z13fp_contract_3fff
> +// CHECK-NEXT: entry
> +// CHECK-NEXT: %0 = tail call float @llvm.fmuladd
> +  return template_muladd<float>(a, b, c);
> +}
>
> Removed: cfe/trunk/test/CodeGen/fp-contract.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/fp-contract.c?rev=164988&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGen/fp-contract.c (original)
> +++ cfe/trunk/test/CodeGen/fp-contract.c (removed)
> @@ -1,9 +0,0 @@
> -// RUN: %clang_cc1 -O3 -ffp-contract=fast -triple=powerpc-apple-darwin10 -S -o - %s | FileCheck %s
> -// REQUIRES: ppc32-registered-target
> -
> -float fma_test1(float a, float b, float c) {
> -// CHECK: fmadds
> -  float x = a * b;
> -  float y = x + c;
> -  return y;
> -}
>
> Modified: cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl?rev=164989&r1=164988&r2=164989&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl (original)
> +++ cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl Mon Oct  1 23:45:10 2012
> @@ -1,7 +1,6 @@
>  // RUN: %clang_cc1 %s -cl-single-precision-constant -emit-llvm -o - | FileCheck %s
>
>  float fn(float f) {
> -  // CHECK: fmul float
> -  // CHECK: fadd float
> +  // CHECK: %0 = tail call float @llvm.fmuladd.f32(float %f, float 2.000000e+00, float 1.000000e+00)
>    return f*2. + 1.;
>  }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list