https://github.com/echesakov updated https://github.com/llvm/llvm-project/pull/105912
>From 124a1c4c7c102421b74eaaa1133ea58a9017e07b Mon Sep 17 00:00:00 2001 From: Egor Chesakov <5292656+echesa...@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:44:14 -0700 Subject: [PATCH 1/2] [clang] Allow `pragma float_control(precise, *)` to... ...control `FastMathFlags` during code-generation of `ConditionalOperator`. This involves storing `FPOptionsOverride` in trailing storage of `ConditionalOperator` and storing `CurFPOptionsOverride` when creating an AST node. Fixes #84648 --- clang/include/clang/AST/Expr.h | 67 +++++++++++++++++-- clang/include/clang/AST/Stmt.h | 11 +++ clang/include/clang/AST/TextNodeDumper.h | 1 + clang/lib/AST/ASTImporter.cpp | 6 +- clang/lib/AST/Expr.cpp | 22 ++++++ clang/lib/AST/TextNodeDumper.cpp | 5 ++ clang/lib/CodeGen/CGExprScalar.cpp | 2 + .../Frontend/Rewrite/RewriteModernObjC.cpp | 7 +- clang/lib/Frontend/Rewrite/RewriteObjC.cpp | 13 ++-- clang/lib/Sema/SemaExpr.cpp | 6 +- clang/lib/Sema/SemaOpenMP.cpp | 12 ++-- clang/lib/Serialization/ASTReaderStmt.cpp | 8 ++- clang/lib/Serialization/ASTWriterStmt.cpp | 3 + clang/test/AST/conditional-operator.c | 21 ++++++ clang/test/CodeGen/conditional-operator.c | 36 ++++++++++ 15 files changed, 193 insertions(+), 27 deletions(-) create mode 100644 clang/test/AST/conditional-operator.c create mode 100644 clang/test/CodeGen/conditional-operator.c diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 7bacf028192c65..cc79496e809829 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -4210,26 +4210,45 @@ class AbstractConditionalOperator : public Expr { /// ConditionalOperator - The ?: ternary operator. The GNU "missing /// middle" extension is a BinaryConditionalOperator. -class ConditionalOperator : public AbstractConditionalOperator { +class ConditionalOperator final + : public AbstractConditionalOperator, + llvm::TrailingObjects<ConditionalOperator, FPOptionsOverride> { enum { COND, LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. friend class ASTStmtReader; -public: + ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, SourceLocation CLoc, Expr *rhs, QualType t, - ExprValueKind VK, ExprObjectKind OK) + ExprValueKind VK, ExprObjectKind OK, + FPOptionsOverride FPFeatures) : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK, QLoc, CLoc) { SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; + ConditionalOperatorBits.HasFPFeatures = + FPFeatures.requiresTrailingStorage(); + if (hasStoredFPFeatures()) + setStoredFPFeatures(FPFeatures); setDependence(computeDependence(this)); } /// Build an empty conditional operator. - explicit ConditionalOperator(EmptyShell Empty) - : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { } + ConditionalOperator(EmptyShell Empty, bool HasFPFeatures) + : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { + ConditionalOperatorBits.HasFPFeatures = HasFPFeatures; + } + +public: + static ConditionalOperator *CreateEmpty(const ASTContext &C, EmptyShell Empty, + bool HasFPFeatures); + + static ConditionalOperator *Create(const ASTContext &C, Expr *cond, + SourceLocation QLoc, Expr *lhs, + SourceLocation CLoc, Expr *rhs, QualType t, + ExprValueKind VK, ExprObjectKind OK, + FPOptionsOverride FPFeatures); /// getCond - Return the expression representing the condition for /// the ?: operator. @@ -4265,6 +4284,44 @@ class ConditionalOperator : public AbstractConditionalOperator { const_child_range children() const { return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); } + + /// Is FPFeatures in trailing storage? + bool hasStoredFPFeatures() const { + return ConditionalOperatorBits.HasFPFeatures; + } + /// Get FPFeatures from trailing storage. + FPOptionsOverride getStoredFPFeatures() const { + return *getTrailingFPFeatures(); + } + + // Get the FP features status of this operator. Only meaningful for + // operations on floating point types. + FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { + if (hasStoredFPFeatures()) + return getStoredFPFeatures().applyOverrides(LO); + return FPOptions::defaultWithoutTrailingStorage(LO); + } + FPOptionsOverride getFPFeatures() const { + return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride(); + } + +private: + /// Set FPFeatures in trailing storage, used only by Serialization. + void setStoredFPFeatures(FPOptionsOverride F) { + *getTrailingFPFeatures() = F; + } + + FPOptionsOverride *getTrailingFPFeatures() { + assert(ConditionalOperatorBits.HasFPFeatures); + return getTrailingObjects<FPOptionsOverride>(); + } + + const FPOptionsOverride *getTrailingFPFeatures() const { + assert(ConditionalOperatorBits.HasFPFeatures); + return getTrailingObjects<FPOptionsOverride>(); + } + + friend class TrailingObjects; }; /// BinaryConditionalOperator - The GNU extension to the conditional diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index f1a2aac0a8b2f8..df751a0bbfc450 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -658,6 +658,16 @@ class alignas(void *) Stmt { SourceLocation OpLoc; }; + class ConditionalOperatorBitfields { + friend class ConditionalOperator; + + unsigned : NumExprBits; + + /// This is only meaningful when the second and third operands have floating + /// point types. + unsigned HasFPFeatures : 1; + }; + class InitListExprBitfields { friend class InitListExpr; @@ -1233,6 +1243,7 @@ class alignas(void *) Stmt { MemberExprBitfields MemberExprBits; CastExprBitfields CastExprBits; BinaryOperatorBitfields BinaryOperatorBits; + ConditionalOperatorBitfields ConditionalOperatorBits; InitListExprBitfields InitListExprBits; ParenListExprBitfields ParenListExprBits; GenericSelectionExprBitfields GenericSelectionExprBits; diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index 88d5535829910f..1767972e9a0264 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -286,6 +286,7 @@ class TextNodeDumper void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node); void VisitBinaryOperator(const BinaryOperator *Node); void VisitCompoundAssignOperator(const CompoundAssignOperator *Node); + void VisitConditionalOperator(const ConditionalOperator *Node); void VisitAddrLabelExpr(const AddrLabelExpr *Node); void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node); void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 3bc0a647ebf94f..1e46b1a9ce87e0 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -7827,9 +7827,9 @@ ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { if (Err) return std::move(Err); - return new (Importer.getToContext()) ConditionalOperator( - ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType, - E->getValueKind(), E->getObjectKind()); + return ConditionalOperator::Create( + Importer.getToContext(), ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, + ToType, E->getValueKind(), E->getObjectKind(), E->getFPFeatures()); } ExpectedStmt diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 25ab6f3b2addfb..2b054646e54560 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3870,6 +3870,8 @@ FPOptions Expr::getFPFeaturesInEffect(const LangOptions &LO) const { return BO->getFPFeaturesInEffect(LO); if (auto Cast = dyn_cast<CastExpr>(this)) return Cast->getFPFeaturesInEffect(LO); + if (auto CO = dyn_cast<ConditionalOperator>(this)) + return CO->getFPFeaturesInEffect(LO); return FPOptions::defaultWithoutTrailingStorage(LO); } @@ -4892,6 +4894,26 @@ CompoundAssignOperator::Create(const ASTContext &C, Expr *lhs, Expr *rhs, CompLHSType, CompResultType); } +ConditionalOperator * +ConditionalOperator::Create(const ASTContext &C, Expr *cond, + SourceLocation QLoc, Expr *lhs, SourceLocation CLoc, + Expr *rhs, QualType t, ExprValueKind VK, + ExprObjectKind OK, FPOptionsOverride FPFeatures) { + bool HasFPFeatures = FPFeatures.requiresTrailingStorage(); + void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures), + alignof(ConditionalOperator)); + return new (Mem) + ConditionalOperator(cond, QLoc, lhs, CLoc, rhs, t, VK, OK, FPFeatures); +} + +ConditionalOperator *ConditionalOperator::CreateEmpty(const ASTContext &C, + EmptyShell Empty, + bool HasFPFeatures) { + void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures), + alignof(ConditionalOperator)); + return new (Mem) ConditionalOperator(EmptyShell(), HasFPFeatures); +} + UnaryOperator *UnaryOperator::CreateEmpty(const ASTContext &C, bool hasFPFeatures) { void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(hasFPFeatures), diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 2c962253c8bea4..079fe65a10738d 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1518,6 +1518,11 @@ void TextNodeDumper::VisitCompoundAssignOperator( printFPOptions(Node->getStoredFPFeatures()); } +void TextNodeDumper::VisitConditionalOperator(const ConditionalOperator *Node) { + if (Node->hasStoredFPFeatures()) + printFPOptions(Node->getStoredFPFeatures()); +} + void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) { OS << " " << Node->getLabel()->getName(); dumpPointer(Node->getLabel()); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 2a726bba2dd304..e7ccd3ce661a41 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -5217,6 +5217,8 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { Expr *lhsExpr = E->getTrueExpr(); Expr *rhsExpr = E->getFalseExpr(); + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E); + // If the condition constant folds and can be elided, try to avoid emitting // the condition and the dead arm. bool CondExprBool; diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index f618c536b5f3c6..2871f8a0655839 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -4568,9 +4568,10 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp Expr *RHSExp = CEXPR->getRHS(); Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); Expr *CONDExp = CEXPR->getCond(); - ConditionalOperator *CondExpr = new (Context) ConditionalOperator( - CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(), - cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary); + ConditionalOperator *CondExpr = ConditionalOperator::Create( + *Context, CONDExp, SourceLocation(), cast<Expr>(LHSStmt), + SourceLocation(), cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, + OK_Ordinary, FPOptionsOverride()); return CondExpr; } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { CPT = IRE->getType()->getAs<BlockPointerType>(); diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp index 9db6ddbf0b8908..42d26617fc8bef 100644 --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -2997,9 +2997,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_PRValue, OK_Ordinary, SourceLocation(), FPOptionsOverride()); // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) - ConditionalOperator *CondExpr = new (Context) ConditionalOperator( - lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, returnType, - VK_PRValue, OK_Ordinary); + ConditionalOperator *CondExpr = ConditionalOperator::Create( + *Context, lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, + returnType, VK_PRValue, OK_Ordinary, FPOptionsOverride()); ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), CondExpr); } @@ -3738,9 +3738,10 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { Expr *RHSExp = CEXPR->getRHS(); Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); Expr *CONDExp = CEXPR->getCond(); - ConditionalOperator *CondExpr = new (Context) ConditionalOperator( - CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(), - cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary); + ConditionalOperator *CondExpr = ConditionalOperator::Create( + *Context, CONDExp, SourceLocation(), cast<Expr>(LHSStmt), + SourceLocation(), cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, + OK_Ordinary, FPOptionsOverride()); return CondExpr; } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { CPT = IRE->getType()->getAs<BlockPointerType>(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ea57316ad8014e..b0a0228922e741 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8795,9 +8795,9 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, Context); if (!commonExpr) - return new (Context) - ConditionalOperator(Cond.get(), QuestionLoc, LHS.get(), ColonLoc, - RHS.get(), result, VK, OK); + return ConditionalOperator::Create(Context, Cond.get(), QuestionLoc, + LHS.get(), ColonLoc, RHS.get(), result, + VK, OK, CurFPFeatureOverrides()); return new (Context) BinaryConditionalOperator( commonExpr, opaqueValue, Cond.get(), LHS.get(), RHS.get(), QuestionLoc, diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 74c646f64b42f2..a8e62c102081fb 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -14330,10 +14330,10 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses, Expr *Cond = AssertSuccess(SemaRef.BuildBinOp( CurScope, {}, BO_LE, AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero)); - Expr *MinOne = new (Context) ConditionalOperator( - Cond, {}, One, {}, + Expr *MinOne = ConditionalOperator::Create( + Context, Cond, {}, One, {}, AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy, - VK_PRValue, OK_Ordinary); + VK_PRValue, OK_Ordinary, FPOptionsOverride()); return MinOne; }; @@ -18858,9 +18858,9 @@ static bool actOnOMPReductionKindClause( S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BO_Assign, LHSDRE, ReductionOp.get()); } else { - auto *ConditionalOp = new (Context) - ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc, - RHSDRE, Type, VK_LValue, OK_Ordinary); + auto *ConditionalOp = ConditionalOperator::Create( + Context, ReductionOp.get(), ELoc, LHSDRE, ELoc, RHSDRE, Type, + VK_LValue, OK_Ordinary, FPOptionsOverride()); ReductionOp = S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BO_Assign, LHSDRE, ConditionalOp); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 8ae07907a04aba..c4b809fbf18ccb 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1145,11 +1145,16 @@ void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) { void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) { VisitExpr(E); + bool HasFPFeatures = Record.readInt(); + assert(HasFPFeatures == E->hasStoredFPFeatures()); E->SubExprs[ConditionalOperator::COND] = Record.readSubExpr(); E->SubExprs[ConditionalOperator::LHS] = Record.readSubExpr(); E->SubExprs[ConditionalOperator::RHS] = Record.readSubExpr(); E->QuestionLoc = readSourceLocation(); E->ColonLoc = readSourceLocation(); + if (HasFPFeatures) + E->setStoredFPFeatures( + FPOptionsOverride::getFromOpaqueInt(Record.readInt())); } void @@ -3182,7 +3187,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { } case EXPR_CONDITIONAL_OPERATOR: - S = new (Context) ConditionalOperator(Empty); + S = ConditionalOperator::CreateEmpty( + Context, Empty, Record[ASTStmtReader::NumExprFields]); break; case EXPR_BINARY_CONDITIONAL_OPERATOR: diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index c292d0a789c7cd..8787c376fe873c 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1091,11 +1091,14 @@ void ASTStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { void ASTStmtWriter::VisitConditionalOperator(ConditionalOperator *E) { VisitExpr(E); + Record.push_back(E->hasStoredFPFeatures()); Record.AddStmt(E->getCond()); Record.AddStmt(E->getLHS()); Record.AddStmt(E->getRHS()); Record.AddSourceLocation(E->getQuestionLoc()); Record.AddSourceLocation(E->getColonLoc()); + if (E->hasStoredFPFeatures()) + Record.push_back(E->getStoredFPFeatures().getAsOpaqueInt()); Code = serialization::EXPR_CONDITIONAL_OPERATOR; } diff --git a/clang/test/AST/conditional-operator.c b/clang/test/AST/conditional-operator.c new file mode 100644 index 00000000000000..518703b1fa2c62 --- /dev/null +++ b/clang/test/AST/conditional-operator.c @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -ast-dump -menable-no-infs -fapprox-func -funsafe-math-optimizations \ +// RUN: -fno-signed-zeros -mreassociate -freciprocal-math -ffp-contract=fast -ffast-math %s | FileCheck %s +// RUN: %clang_cc1 -emit-pch -o %t %s +// RUN: %clang_cc1 -x c -include-pch %t -ast-dump-all /dev/null | FileCheck %s + +float test_precise_off(int c, float t, float f) { +#pragma float_control(precise, off) + return c ? t : f; +} + +// CHECK-LABEL: FunctionDecl {{.*}} test_precise_off +// CHECK: ConditionalOperator {{.*}} FPContractMode=2 AllowFPReassociate=1 NoHonorNaNs=1 NoHonorInfs=1 NoSignedZero=1 AllowReciprocal=1 AllowApproxFunc=1 MathErrno=0 + +float test_precise_on(int c, float t, float f) { +#pragma float_control(precise, on) + return c ? t : f; +} + +// CHECK-LABEL: FunctionDecl {{.*}} test_precise_on +// CHECK: ConditionalOperator {{.*}} FPContractMode=1 AllowFPReassociate=0 NoHonorNaNs=0 NoHonorInfs=0 NoSignedZero=0 AllowReciprocal=0 AllowApproxFunc=0 MathErrno=1 diff --git a/clang/test/CodeGen/conditional-operator.c b/clang/test/CodeGen/conditional-operator.c new file mode 100644 index 00000000000000..ebf530a4bb0298 --- /dev/null +++ b/clang/test/CodeGen/conditional-operator.c @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -disable-llvm-passes -emit-llvm -menable-no-infs -fapprox-func\ +// RUN: -funsafe-math-optimizations -fno-signed-zeros -mreassociate -freciprocal-math\ +// RUN: -ffp-contract=fast -ffast-math %s -o - | FileCheck %s + +float test_precise_off_select(int c) { +#pragma float_control(precise, off) + return c ? 0.0f : 1.0f; +} + +// CHECK-LABEL: test_precise_off_select +// CHECK: select fast i1 {{%.+}}, float 0.000000e+00, float 1.000000e+00 + +float test_precise_off_phi(int c, float t, float f) { +#pragma float_control(precise, off) + return c ? t : f; +} + +// CHECK-LABEL: test_precise_off_phi +// CHECK: phi fast float [ {{%.+}}, {{%.+}} ], [ {{%.+}}, {{%.+}} ] + +float test_precise_on_select(int c) { +#pragma float_control(precise, on) + return c ? 0.0f : 1.0f; +} + +// CHECK-LABEL: test_precise_on_select +// CHECK: select i1 {{%.+}}, float 0.000000e+00, float 1.000000e+00 + +float test_precise_on_phi(int c, float t, float f) { +#pragma float_control(precise, on) + return c ? t : f; +} + +// CHECK-LABEL: test_precise_on_phi +// CHECK: phi float [ {{%.+}}, {{%.+}} ], [ {{%.+}}, {{%.+}} ] >From b027866898e62d057ae64fae3ca3e447f44ae594 Mon Sep 17 00:00:00 2001 From: Egor Chesakov <5292656+echesa...@users.noreply.github.com> Date: Sat, 5 Oct 2024 10:19:57 -0700 Subject: [PATCH 2/2] Add private keyword --- clang/include/clang/AST/Expr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index cc79496e809829..848c9676d5f11e 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -4212,7 +4212,7 @@ class AbstractConditionalOperator : public Expr { /// middle" extension is a BinaryConditionalOperator. class ConditionalOperator final : public AbstractConditionalOperator, - llvm::TrailingObjects<ConditionalOperator, FPOptionsOverride> { + private llvm::TrailingObjects<ConditionalOperator, FPOptionsOverride> { enum { COND, LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits