Skip to content

Commit 1231a56

Browse files
committed
[clang] Allow ConditionalOperator fast-math flags to be overridden by pragma float_control
Currently, the fast-math flags set on `select` or `phi` instruction emitted by CodeGen when visiting `ConditionalOperator` take into account only global `FPOptions` and ignore `pragma float_control`. This involves storing `FPOptionsOverride` in trailing storage of `ConditionalOperator` and storing `CurFPOptionsOverride` when creating an AST node. Fixes #84648
1 parent 6e78aef commit 1231a56

File tree

15 files changed

+193
-27
lines changed

15 files changed

+193
-27
lines changed

clang/include/clang/AST/Expr.h

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4210,26 +4210,45 @@ class AbstractConditionalOperator : public Expr {
42104210

42114211
/// ConditionalOperator - The ?: ternary operator. The GNU "missing
42124212
/// middle" extension is a BinaryConditionalOperator.
4213-
class ConditionalOperator : public AbstractConditionalOperator {
4213+
class ConditionalOperator final
4214+
: public AbstractConditionalOperator,
4215+
private llvm::TrailingObjects<ConditionalOperator, FPOptionsOverride> {
42144216
enum { COND, LHS, RHS, END_EXPR };
42154217
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
42164218

42174219
friend class ASTStmtReader;
4218-
public:
4220+
42194221
ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
42204222
SourceLocation CLoc, Expr *rhs, QualType t,
4221-
ExprValueKind VK, ExprObjectKind OK)
4223+
ExprValueKind VK, ExprObjectKind OK,
4224+
FPOptionsOverride FPFeatures)
42224225
: AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK, QLoc,
42234226
CLoc) {
42244227
SubExprs[COND] = cond;
42254228
SubExprs[LHS] = lhs;
42264229
SubExprs[RHS] = rhs;
4230+
ConditionalOperatorBits.HasFPFeatures =
4231+
FPFeatures.requiresTrailingStorage();
4232+
if (hasStoredFPFeatures())
4233+
setStoredFPFeatures(FPFeatures);
42274234
setDependence(computeDependence(this));
42284235
}
42294236

42304237
/// Build an empty conditional operator.
4231-
explicit ConditionalOperator(EmptyShell Empty)
4232-
: AbstractConditionalOperator(ConditionalOperatorClass, Empty) { }
4238+
ConditionalOperator(EmptyShell Empty, bool HasFPFeatures)
4239+
: AbstractConditionalOperator(ConditionalOperatorClass, Empty) {
4240+
ConditionalOperatorBits.HasFPFeatures = HasFPFeatures;
4241+
}
4242+
4243+
public:
4244+
static ConditionalOperator *CreateEmpty(const ASTContext &C, EmptyShell Empty,
4245+
bool HasFPFeatures);
4246+
4247+
static ConditionalOperator *Create(const ASTContext &C, Expr *cond,
4248+
SourceLocation QLoc, Expr *lhs,
4249+
SourceLocation CLoc, Expr *rhs, QualType t,
4250+
ExprValueKind VK, ExprObjectKind OK,
4251+
FPOptionsOverride FPFeatures);
42334252

42344253
/// getCond - Return the expression representing the condition for
42354254
/// the ?: operator.
@@ -4265,6 +4284,44 @@ class ConditionalOperator : public AbstractConditionalOperator {
42654284
const_child_range children() const {
42664285
return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
42674286
}
4287+
4288+
/// Is FPFeatures in trailing storage?
4289+
bool hasStoredFPFeatures() const {
4290+
return ConditionalOperatorBits.HasFPFeatures;
4291+
}
4292+
/// Get FPFeatures from trailing storage.
4293+
FPOptionsOverride getStoredFPFeatures() const {
4294+
return *getTrailingFPFeatures();
4295+
}
4296+
4297+
// Get the FP features status of this operator. Only meaningful for
4298+
// operations on floating point types.
4299+
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
4300+
if (hasStoredFPFeatures())
4301+
return getStoredFPFeatures().applyOverrides(LO);
4302+
return FPOptions::defaultWithoutTrailingStorage(LO);
4303+
}
4304+
FPOptionsOverride getFPFeatures() const {
4305+
return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride();
4306+
}
4307+
4308+
private:
4309+
/// Set FPFeatures in trailing storage, used only by Serialization.
4310+
void setStoredFPFeatures(FPOptionsOverride F) {
4311+
*getTrailingFPFeatures() = F;
4312+
}
4313+
4314+
FPOptionsOverride *getTrailingFPFeatures() {
4315+
assert(ConditionalOperatorBits.HasFPFeatures);
4316+
return getTrailingObjects<FPOptionsOverride>();
4317+
}
4318+
4319+
const FPOptionsOverride *getTrailingFPFeatures() const {
4320+
assert(ConditionalOperatorBits.HasFPFeatures);
4321+
return getTrailingObjects<FPOptionsOverride>();
4322+
}
4323+
4324+
friend class TrailingObjects;
42684325
};
42694326

42704327
/// BinaryConditionalOperator - The GNU extension to the conditional

clang/include/clang/AST/Stmt.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,16 @@ class alignas(void *) Stmt {
658658
SourceLocation OpLoc;
659659
};
660660

661+
class ConditionalOperatorBitfields {
662+
friend class ConditionalOperator;
663+
664+
unsigned : NumExprBits;
665+
666+
/// This is only meaningful when the second and third operands have floating
667+
/// point types.
668+
unsigned HasFPFeatures : 1;
669+
};
670+
661671
class InitListExprBitfields {
662672
friend class InitListExpr;
663673

@@ -1233,6 +1243,7 @@ class alignas(void *) Stmt {
12331243
MemberExprBitfields MemberExprBits;
12341244
CastExprBitfields CastExprBits;
12351245
BinaryOperatorBitfields BinaryOperatorBits;
1246+
ConditionalOperatorBitfields ConditionalOperatorBits;
12361247
InitListExprBitfields InitListExprBits;
12371248
ParenListExprBitfields ParenListExprBits;
12381249
GenericSelectionExprBitfields GenericSelectionExprBits;

clang/include/clang/AST/TextNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ class TextNodeDumper
286286
void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node);
287287
void VisitBinaryOperator(const BinaryOperator *Node);
288288
void VisitCompoundAssignOperator(const CompoundAssignOperator *Node);
289+
void VisitConditionalOperator(const ConditionalOperator *Node);
289290
void VisitAddrLabelExpr(const AddrLabelExpr *Node);
290291
void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node);
291292
void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node);

clang/lib/AST/ASTImporter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7827,9 +7827,9 @@ ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) {
78277827
if (Err)
78287828
return std::move(Err);
78297829

7830-
return new (Importer.getToContext()) ConditionalOperator(
7831-
ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType,
7832-
E->getValueKind(), E->getObjectKind());
7830+
return ConditionalOperator::Create(
7831+
Importer.getToContext(), ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS,
7832+
ToType, E->getValueKind(), E->getObjectKind(), E->getFPFeatures());
78337833
}
78347834

78357835
ExpectedStmt

clang/lib/AST/Expr.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3870,6 +3870,8 @@ FPOptions Expr::getFPFeaturesInEffect(const LangOptions &LO) const {
38703870
return BO->getFPFeaturesInEffect(LO);
38713871
if (auto Cast = dyn_cast<CastExpr>(this))
38723872
return Cast->getFPFeaturesInEffect(LO);
3873+
if (auto CO = dyn_cast<ConditionalOperator>(this))
3874+
return CO->getFPFeaturesInEffect(LO);
38733875
return FPOptions::defaultWithoutTrailingStorage(LO);
38743876
}
38753877

@@ -4892,6 +4894,26 @@ CompoundAssignOperator::Create(const ASTContext &C, Expr *lhs, Expr *rhs,
48924894
CompLHSType, CompResultType);
48934895
}
48944896

4897+
ConditionalOperator *
4898+
ConditionalOperator::Create(const ASTContext &C, Expr *cond,
4899+
SourceLocation QLoc, Expr *lhs, SourceLocation CLoc,
4900+
Expr *rhs, QualType t, ExprValueKind VK,
4901+
ExprObjectKind OK, FPOptionsOverride FPFeatures) {
4902+
bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
4903+
void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures),
4904+
alignof(ConditionalOperator));
4905+
return new (Mem)
4906+
ConditionalOperator(cond, QLoc, lhs, CLoc, rhs, t, VK, OK, FPFeatures);
4907+
}
4908+
4909+
ConditionalOperator *ConditionalOperator::CreateEmpty(const ASTContext &C,
4910+
EmptyShell Empty,
4911+
bool HasFPFeatures) {
4912+
void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures),
4913+
alignof(ConditionalOperator));
4914+
return new (Mem) ConditionalOperator(EmptyShell(), HasFPFeatures);
4915+
}
4916+
48954917
UnaryOperator *UnaryOperator::CreateEmpty(const ASTContext &C,
48964918
bool hasFPFeatures) {
48974919
void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(hasFPFeatures),

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,11 @@ void TextNodeDumper::VisitCompoundAssignOperator(
15181518
printFPOptions(Node->getStoredFPFeatures());
15191519
}
15201520

1521+
void TextNodeDumper::VisitConditionalOperator(const ConditionalOperator *Node) {
1522+
if (Node->hasStoredFPFeatures())
1523+
printFPOptions(Node->getStoredFPFeatures());
1524+
}
1525+
15211526
void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
15221527
OS << " " << Node->getLabel()->getName();
15231528
dumpPointer(Node->getLabel());

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5217,6 +5217,8 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
52175217
Expr *lhsExpr = E->getTrueExpr();
52185218
Expr *rhsExpr = E->getFalseExpr();
52195219

5220+
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
5221+
52205222
// If the condition constant folds and can be elided, try to avoid emitting
52215223
// the condition and the dead arm.
52225224
bool CondExprBool;

clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4568,9 +4568,10 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp
45684568
Expr *RHSExp = CEXPR->getRHS();
45694569
Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
45704570
Expr *CONDExp = CEXPR->getCond();
4571-
ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
4572-
CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),
4573-
cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);
4571+
ConditionalOperator *CondExpr = ConditionalOperator::Create(
4572+
*Context, CONDExp, SourceLocation(), cast<Expr>(LHSStmt),
4573+
SourceLocation(), cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue,
4574+
OK_Ordinary, FPOptionsOverride());
45744575
return CondExpr;
45754576
} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
45764577
CPT = IRE->getType()->getAs<BlockPointerType>();

clang/lib/Frontend/Rewrite/RewriteObjC.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,9 +2997,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
29972997
*Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_PRValue,
29982998
OK_Ordinary, SourceLocation(), FPOptionsOverride());
29992999
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
3000-
ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
3001-
lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, returnType,
3002-
VK_PRValue, OK_Ordinary);
3000+
ConditionalOperator *CondExpr = ConditionalOperator::Create(
3001+
*Context, lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE,
3002+
returnType, VK_PRValue, OK_Ordinary, FPOptionsOverride());
30033003
ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
30043004
CondExpr);
30053005
}
@@ -3738,9 +3738,10 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
37383738
Expr *RHSExp = CEXPR->getRHS();
37393739
Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
37403740
Expr *CONDExp = CEXPR->getCond();
3741-
ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
3742-
CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),
3743-
cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);
3741+
ConditionalOperator *CondExpr = ConditionalOperator::Create(
3742+
*Context, CONDExp, SourceLocation(), cast<Expr>(LHSStmt),
3743+
SourceLocation(), cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue,
3744+
OK_Ordinary, FPOptionsOverride());
37443745
return CondExpr;
37453746
} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
37463747
CPT = IRE->getType()->getAs<BlockPointerType>();

clang/lib/Sema/SemaExpr.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8795,9 +8795,9 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
87958795
Context);
87968796

87978797
if (!commonExpr)
8798-
return new (Context)
8799-
ConditionalOperator(Cond.get(), QuestionLoc, LHS.get(), ColonLoc,
8800-
RHS.get(), result, VK, OK);
8798+
return ConditionalOperator::Create(Context, Cond.get(), QuestionLoc,
8799+
LHS.get(), ColonLoc, RHS.get(), result,
8800+
VK, OK, CurFPFeatureOverrides());
88018801

88028802
return new (Context) BinaryConditionalOperator(
88038803
commonExpr, opaqueValue, Cond.get(), LHS.get(), RHS.get(), QuestionLoc,

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14330,10 +14330,10 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
1433014330
Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
1433114331
CurScope, {}, BO_LE,
1433214332
AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14333-
Expr *MinOne = new (Context) ConditionalOperator(
14334-
Cond, {}, One, {},
14333+
Expr *MinOne = ConditionalOperator::Create(
14334+
Context, Cond, {}, One, {},
1433514335
AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14336-
VK_PRValue, OK_Ordinary);
14336+
VK_PRValue, OK_Ordinary, FPOptionsOverride());
1433714337
return MinOne;
1433814338
};
1433914339

@@ -18858,9 +18858,9 @@ static bool actOnOMPReductionKindClause(
1885818858
S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
1885918859
BO_Assign, LHSDRE, ReductionOp.get());
1886018860
} else {
18861-
auto *ConditionalOp = new (Context)
18862-
ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
18863-
RHSDRE, Type, VK_LValue, OK_Ordinary);
18861+
auto *ConditionalOp = ConditionalOperator::Create(
18862+
Context, ReductionOp.get(), ELoc, LHSDRE, ELoc, RHSDRE, Type,
18863+
VK_LValue, OK_Ordinary, FPOptionsOverride());
1886418864
ReductionOp =
1886518865
S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
1886618866
BO_Assign, LHSDRE, ConditionalOp);

clang/lib/Serialization/ASTReaderStmt.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1145,11 +1145,16 @@ void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
11451145

11461146
void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) {
11471147
VisitExpr(E);
1148+
bool HasFPFeatures = Record.readInt();
1149+
assert(HasFPFeatures == E->hasStoredFPFeatures());
11481150
E->SubExprs[ConditionalOperator::COND] = Record.readSubExpr();
11491151
E->SubExprs[ConditionalOperator::LHS] = Record.readSubExpr();
11501152
E->SubExprs[ConditionalOperator::RHS] = Record.readSubExpr();
11511153
E->QuestionLoc = readSourceLocation();
11521154
E->ColonLoc = readSourceLocation();
1155+
if (HasFPFeatures)
1156+
E->setStoredFPFeatures(
1157+
FPOptionsOverride::getFromOpaqueInt(Record.readInt()));
11531158
}
11541159

11551160
void
@@ -3182,7 +3187,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
31823187
}
31833188

31843189
case EXPR_CONDITIONAL_OPERATOR:
3185-
S = new (Context) ConditionalOperator(Empty);
3190+
S = ConditionalOperator::CreateEmpty(
3191+
Context, Empty, Record[ASTStmtReader::NumExprFields]);
31863192
break;
31873193

31883194
case EXPR_BINARY_CONDITIONAL_OPERATOR:

clang/lib/Serialization/ASTWriterStmt.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,11 +1091,14 @@ void ASTStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
10911091

10921092
void ASTStmtWriter::VisitConditionalOperator(ConditionalOperator *E) {
10931093
VisitExpr(E);
1094+
Record.push_back(E->hasStoredFPFeatures());
10941095
Record.AddStmt(E->getCond());
10951096
Record.AddStmt(E->getLHS());
10961097
Record.AddStmt(E->getRHS());
10971098
Record.AddSourceLocation(E->getQuestionLoc());
10981099
Record.AddSourceLocation(E->getColonLoc());
1100+
if (E->hasStoredFPFeatures())
1101+
Record.push_back(E->getStoredFPFeatures().getAsOpaqueInt());
10991102
Code = serialization::EXPR_CONDITIONAL_OPERATOR;
11001103
}
11011104

clang/test/AST/conditional-operator.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %clang_cc1 -ast-dump %s | FileCheck %s
2+
// RUN: %clang_cc1 -ast-dump -menable-no-infs -fapprox-func -funsafe-math-optimizations \
3+
// RUN: -fno-signed-zeros -mreassociate -freciprocal-math -ffp-contract=fast -ffast-math %s | FileCheck %s
4+
// RUN: %clang_cc1 -emit-pch -o %t %s
5+
// RUN: %clang_cc1 -x c -include-pch %t -ast-dump-all /dev/null | FileCheck %s
6+
7+
float test_precise_off(int c, float t, float f) {
8+
#pragma float_control(precise, off)
9+
return c ? t : f;
10+
}
11+
12+
// CHECK-LABEL: FunctionDecl {{.*}} test_precise_off
13+
// CHECK: ConditionalOperator {{.*}} FPContractMode=2 AllowFPReassociate=1 NoHonorNaNs=1 NoHonorInfs=1 NoSignedZero=1 AllowReciprocal=1 AllowApproxFunc=1 MathErrno=0
14+
15+
float test_precise_on(int c, float t, float f) {
16+
#pragma float_control(precise, on)
17+
return c ? t : f;
18+
}
19+
20+
// CHECK-LABEL: FunctionDecl {{.*}} test_precise_on
21+
// CHECK: ConditionalOperator {{.*}} FPContractMode=1 AllowFPReassociate=0 NoHonorNaNs=0 NoHonorInfs=0 NoSignedZero=0 AllowReciprocal=0 AllowApproxFunc=0 MathErrno=1
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %clang_cc1 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
2+
// RUN: %clang_cc1 -disable-llvm-passes -emit-llvm -menable-no-infs -fapprox-func\
3+
// RUN: -funsafe-math-optimizations -fno-signed-zeros -mreassociate -freciprocal-math\
4+
// RUN: -ffp-contract=fast -ffast-math %s -o - | FileCheck %s
5+
6+
float test_precise_off_select(int c) {
7+
#pragma float_control(precise, off)
8+
return c ? 0.0f : 1.0f;
9+
}
10+
11+
// CHECK-LABEL: test_precise_off_select
12+
// CHECK: select fast i1 {{%.+}}, float 0.000000e+00, float 1.000000e+00
13+
14+
float test_precise_off_phi(int c, float t, float f) {
15+
#pragma float_control(precise, off)
16+
return c ? t : f;
17+
}
18+
19+
// CHECK-LABEL: test_precise_off_phi
20+
// CHECK: phi fast float [ {{%.+}}, {{%.+}} ], [ {{%.+}}, {{%.+}} ]
21+
22+
float test_precise_on_select(int c) {
23+
#pragma float_control(precise, on)
24+
return c ? 0.0f : 1.0f;
25+
}
26+
27+
// CHECK-LABEL: test_precise_on_select
28+
// CHECK: select i1 {{%.+}}, float 0.000000e+00, float 1.000000e+00
29+
30+
float test_precise_on_phi(int c, float t, float f) {
31+
#pragma float_control(precise, on)
32+
return c ? t : f;
33+
}
34+
35+
// CHECK-LABEL: test_precise_on_phi
36+
// CHECK: phi float [ {{%.+}}, {{%.+}} ], [ {{%.+}}, {{%.+}} ]

0 commit comments

Comments
 (0)