Skip to content

Commit fda0e63

Browse files
authored
[clang] handle fp options in __builtin_convertvector (#125522)
This patch allows using fpfeatures pragmas with __builtin_convertvector: - added TrailingObjects with FPOptionsOverride and methods for handling it to ConvertVectorExpr - added support for codegen, node dumping, and serialization of fpfeatures contained in ConvertVectorExpr
1 parent e7bf54d commit fda0e63

File tree

13 files changed

+183
-12
lines changed

13 files changed

+183
-12
lines changed

clang/include/clang/AST/Expr.h

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4579,25 +4579,97 @@ class ShuffleVectorExpr : public Expr {
45794579
/// ConvertVectorExpr - Clang builtin function __builtin_convertvector
45804580
/// This AST node provides support for converting a vector type to another
45814581
/// vector type of the same arity.
4582-
class ConvertVectorExpr : public Expr {
4582+
class ConvertVectorExpr final
4583+
: public Expr,
4584+
private llvm::TrailingObjects<ConvertVectorExpr, FPOptionsOverride> {
45834585
private:
45844586
Stmt *SrcExpr;
45854587
TypeSourceInfo *TInfo;
45864588
SourceLocation BuiltinLoc, RParenLoc;
45874589

4590+
friend TrailingObjects;
45884591
friend class ASTReader;
45894592
friend class ASTStmtReader;
4590-
explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {}
4593+
explicit ConvertVectorExpr(bool HasFPFeatures, EmptyShell Empty)
4594+
: Expr(ConvertVectorExprClass, Empty) {
4595+
ConvertVectorExprBits.HasFPFeatures = HasFPFeatures;
4596+
}
45914597

4592-
public:
45934598
ConvertVectorExpr(Expr *SrcExpr, TypeSourceInfo *TI, QualType DstType,
45944599
ExprValueKind VK, ExprObjectKind OK,
4595-
SourceLocation BuiltinLoc, SourceLocation RParenLoc)
4600+
SourceLocation BuiltinLoc, SourceLocation RParenLoc,
4601+
FPOptionsOverride FPFeatures)
45964602
: Expr(ConvertVectorExprClass, DstType, VK, OK), SrcExpr(SrcExpr),
45974603
TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {
4604+
ConvertVectorExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
4605+
if (hasStoredFPFeatures())
4606+
setStoredFPFeatures(FPFeatures);
45984607
setDependence(computeDependence(this));
45994608
}
46004609

4610+
size_t numTrailingObjects(OverloadToken<FPOptionsOverride>) const {
4611+
return ConvertVectorExprBits.HasFPFeatures ? 1 : 0;
4612+
}
4613+
4614+
FPOptionsOverride &getTrailingFPFeatures() {
4615+
assert(ConvertVectorExprBits.HasFPFeatures);
4616+
return *getTrailingObjects<FPOptionsOverride>();
4617+
}
4618+
4619+
const FPOptionsOverride &getTrailingFPFeatures() const {
4620+
assert(ConvertVectorExprBits.HasFPFeatures);
4621+
return *getTrailingObjects<FPOptionsOverride>();
4622+
}
4623+
4624+
public:
4625+
static ConvertVectorExpr *CreateEmpty(const ASTContext &C,
4626+
bool hasFPFeatures);
4627+
4628+
static ConvertVectorExpr *Create(const ASTContext &C, Expr *SrcExpr,
4629+
TypeSourceInfo *TI, QualType DstType,
4630+
ExprValueKind VK, ExprObjectKind OK,
4631+
SourceLocation BuiltinLoc,
4632+
SourceLocation RParenLoc,
4633+
FPOptionsOverride FPFeatures);
4634+
4635+
/// Get the FP contractibility status of this operator. Only meaningful for
4636+
/// operations on floating point types.
4637+
bool isFPContractableWithinStatement(const LangOptions &LO) const {
4638+
return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
4639+
}
4640+
4641+
/// Is FPFeatures in Trailing Storage?
4642+
bool hasStoredFPFeatures() const {
4643+
return ConvertVectorExprBits.HasFPFeatures;
4644+
}
4645+
4646+
/// Get FPFeatures from trailing storage.
4647+
FPOptionsOverride getStoredFPFeatures() const {
4648+
return getTrailingFPFeatures();
4649+
}
4650+
4651+
/// Get the store FPOptionsOverride or default if not stored.
4652+
FPOptionsOverride getStoredFPFeaturesOrDefault() const {
4653+
return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride();
4654+
}
4655+
4656+
/// Set FPFeatures in trailing storage, used by Serialization & ASTImporter.
4657+
void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; }
4658+
4659+
/// Get the FP features status of this operator. Only meaningful for
4660+
/// operations on floating point types.
4661+
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
4662+
if (ConvertVectorExprBits.HasFPFeatures)
4663+
return getStoredFPFeatures().applyOverrides(LO);
4664+
return FPOptions::defaultWithoutTrailingStorage(LO);
4665+
}
4666+
4667+
FPOptionsOverride getFPOptionsOverride() const {
4668+
if (ConvertVectorExprBits.HasFPFeatures)
4669+
return getStoredFPFeatures();
4670+
return FPOptionsOverride();
4671+
}
4672+
46014673
/// getSrcExpr - Return the Expr to be converted.
46024674
Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); }
46034675

clang/include/clang/AST/Stmt.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,20 @@ class alignas(void *) Stmt {
12151215
SourceLocation Loc;
12161216
};
12171217

1218+
class ConvertVectorExprBitfields {
1219+
friend class ConvertVectorExpr;
1220+
1221+
LLVM_PREFERRED_TYPE(ExprBitfields)
1222+
unsigned : NumExprBits;
1223+
1224+
//
1225+
/// This is only meaningful for operations on floating point
1226+
/// types when additional values need to be in trailing storage.
1227+
/// It is 0 otherwise.
1228+
LLVM_PREFERRED_TYPE(bool)
1229+
unsigned HasFPFeatures : 1;
1230+
};
1231+
12181232
union {
12191233
// Same order as in StmtNodes.td.
12201234
// Statements
@@ -1293,6 +1307,7 @@ class alignas(void *) Stmt {
12931307

12941308
// Clang Extensions
12951309
OpaqueValueExprBitfields OpaqueValueExprBits;
1310+
ConvertVectorExprBitfields ConvertVectorExprBits;
12961311
};
12971312

12981313
public:

clang/include/clang/AST/TextNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ class TextNodeDumper
425425
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S);
426426
void VisitEmbedExpr(const EmbedExpr *S);
427427
void VisitAtomicExpr(const AtomicExpr *AE);
428+
void VisitConvertVectorExpr(const ConvertVectorExpr *S);
428429
};
429430

430431
} // namespace clang

clang/lib/AST/ASTImporter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7386,9 +7386,10 @@ ExpectedStmt ASTNodeImporter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
73867386
if (Err)
73877387
return std::move(Err);
73887388

7389-
return new (Importer.getToContext())
7390-
ConvertVectorExpr(ToSrcExpr, ToTSI, ToType, E->getValueKind(),
7391-
E->getObjectKind(), ToBuiltinLoc, ToRParenLoc);
7389+
return ConvertVectorExpr::Create(
7390+
Importer.getToContext(), ToSrcExpr, ToTSI, ToType, E->getValueKind(),
7391+
E->getObjectKind(), ToBuiltinLoc, ToRParenLoc,
7392+
E->getStoredFPFeaturesOrDefault());
73927393
}
73937394

73947395
ExpectedStmt ASTNodeImporter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {

clang/lib/AST/Expr.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3911,6 +3911,8 @@ FPOptions Expr::getFPFeaturesInEffect(const LangOptions &LO) const {
39113911
return BO->getFPFeaturesInEffect(LO);
39123912
if (auto Cast = dyn_cast<CastExpr>(this))
39133913
return Cast->getFPFeaturesInEffect(LO);
3914+
if (auto ConvertVector = dyn_cast<ConvertVectorExpr>(this))
3915+
return ConvertVector->getFPFeaturesInEffect(LO);
39143916
return FPOptions::defaultWithoutTrailingStorage(LO);
39153917
}
39163918

@@ -5451,3 +5453,21 @@ OpenACCAsteriskSizeExpr *
54515453
OpenACCAsteriskSizeExpr::CreateEmpty(const ASTContext &C) {
54525454
return new (C) OpenACCAsteriskSizeExpr({}, C.IntTy);
54535455
}
5456+
5457+
ConvertVectorExpr *ConvertVectorExpr::CreateEmpty(const ASTContext &C,
5458+
bool hasFPFeatures) {
5459+
void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(hasFPFeatures),
5460+
alignof(ConvertVectorExpr));
5461+
return new (Mem) ConvertVectorExpr(hasFPFeatures, EmptyShell());
5462+
}
5463+
5464+
ConvertVectorExpr *ConvertVectorExpr::Create(
5465+
const ASTContext &C, Expr *SrcExpr, TypeSourceInfo *TI, QualType DstType,
5466+
ExprValueKind VK, ExprObjectKind OK, SourceLocation BuiltinLoc,
5467+
SourceLocation RParenLoc, FPOptionsOverride FPFeatures) {
5468+
bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
5469+
unsigned Size = totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures);
5470+
void *Mem = C.Allocate(Size, alignof(ConvertVectorExpr));
5471+
return new (Mem) ConvertVectorExpr(SrcExpr, TI, DstType, VK, OK, BuiltinLoc,
5472+
RParenLoc, FPFeatures);
5473+
}

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3069,3 +3069,9 @@ void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) {
30693069
void TextNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) {
30703070
OS << ' ' << AE->getOpAsString();
30713071
}
3072+
3073+
void TextNodeDumper::VisitConvertVectorExpr(const ConvertVectorExpr *S) {
3074+
VisitStmt(S);
3075+
if (S->hasStoredFPFeatures())
3076+
printFPOptions(S->getStoredFPFeatures());
3077+
}

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,6 +1949,7 @@ Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
19491949

19501950
llvm::Value *Zero = llvm::Constant::getNullValue(SrcTy);
19511951
if (SrcEltTy->isFloatingPointTy()) {
1952+
CodeGenFunction::CGFPOptionsRAII FPOptions(CGF, E);
19521953
return Builder.CreateFCmpUNE(Src, Zero, "tobool");
19531954
} else {
19541955
return Builder.CreateICmpNE(Src, Zero, "tobool");
@@ -1975,6 +1976,7 @@ Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
19751976
} else {
19761977
assert(SrcEltTy->isFloatingPointTy() && DstEltTy->isFloatingPointTy() &&
19771978
"Unknown real conversion");
1979+
CodeGenFunction::CGFPOptionsRAII FPOptions(CGF, E);
19781980
if (DstEltTy->getTypeID() < SrcEltTy->getTypeID())
19791981
Res = Builder.CreateFPTrunc(Src, DstTy, "conv");
19801982
else

clang/lib/Sema/SemaChecking.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5262,8 +5262,8 @@ ExprResult Sema::ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
52625262
<< E->getSourceRange());
52635263
}
52645264

5265-
return new (Context) class ConvertVectorExpr(E, TInfo, DstTy, VK, OK,
5266-
BuiltinLoc, RParenLoc);
5265+
return ConvertVectorExpr::Create(Context, E, TInfo, DstTy, VK, OK, BuiltinLoc,
5266+
RParenLoc, CurFPFeatureOverrides());
52675267
}
52685268

52695269
bool Sema::BuiltinPrefetch(CallExpr *TheCall) {

clang/lib/Serialization/ASTReaderStmt.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,10 +1387,15 @@ void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
13871387

13881388
void ASTStmtReader::VisitConvertVectorExpr(ConvertVectorExpr *E) {
13891389
VisitExpr(E);
1390+
bool HasFPFeatures = CurrentUnpackingBits->getNextBit();
1391+
assert(HasFPFeatures == E->hasStoredFPFeatures());
13901392
E->BuiltinLoc = readSourceLocation();
13911393
E->RParenLoc = readSourceLocation();
13921394
E->TInfo = readTypeSourceInfo();
13931395
E->SrcExpr = Record.readSubExpr();
1396+
if (HasFPFeatures)
1397+
E->setStoredFPFeatures(
1398+
FPOptionsOverride::getFromOpaqueInt(Record.readInt()));
13941399
}
13951400

13961401
void ASTStmtReader::VisitBlockExpr(BlockExpr *E) {
@@ -3385,9 +3390,13 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
33853390
S = new (Context) ShuffleVectorExpr(Empty);
33863391
break;
33873392

3388-
case EXPR_CONVERT_VECTOR:
3389-
S = new (Context) ConvertVectorExpr(Empty);
3393+
case EXPR_CONVERT_VECTOR: {
3394+
BitsUnpacker ConvertVectorExprBits(Record[ASTStmtReader::NumStmtFields]);
3395+
ConvertVectorExprBits.advance(ASTStmtReader::NumExprBits);
3396+
bool HasFPFeatures = ConvertVectorExprBits.getNextBit();
3397+
S = ConvertVectorExpr::CreateEmpty(Context, HasFPFeatures);
33903398
break;
3399+
}
33913400

33923401
case EXPR_BLOCK:
33933402
S = new (Context) BlockExpr(Empty);

clang/lib/Serialization/ASTWriterStmt.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,11 +1335,15 @@ void ASTStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
13351335

13361336
void ASTStmtWriter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
13371337
VisitExpr(E);
1338+
bool HasFPFeatures = E->hasStoredFPFeatures();
1339+
CurrentPackingBits.addBit(HasFPFeatures);
13381340
Record.AddSourceLocation(E->getBuiltinLoc());
13391341
Record.AddSourceLocation(E->getRParenLoc());
13401342
Record.AddTypeSourceInfo(E->getTypeSourceInfo());
13411343
Record.AddStmt(E->getSrcExpr());
13421344
Code = serialization::EXPR_CONVERT_VECTOR;
1345+
if (HasFPFeatures)
1346+
Record.push_back(E->getStoredFPFeatures().getAsOpaqueInt());
13431347
}
13441348

13451349
void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) {

clang/test/AST/ast-dump-fpfeatures.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@
88
// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
99
// RUN: | FileCheck --strict-whitespace %s
1010

11+
// CHECK-LABEL: FunctionDecl {{.*}} no_fpfeatures_func_01 'vector2float (vector2double)'
12+
// CHECK: CompoundStmt {{.*\>$}}
13+
// CHECK: ReturnStmt
14+
// CHECK: ConvertVectorExpr {{.*}} 'vector2float':'__attribute__((__vector_size__(2 * sizeof(float)))) float'{{$}}
15+
16+
typedef double vector2double __attribute__((__vector_size__(16)));
17+
typedef float vector2float __attribute__((__vector_size__(8)));
18+
vector2float no_fpfeatures_func_01(vector2double x) {
19+
return __builtin_convertvector(x, vector2float);
20+
}
21+
1122
float func_01(float x);
1223

1324
template <typename T>
@@ -248,4 +259,14 @@ __attribute__((optnone)) T func_22(T x, T y) {
248259

249260
float func_23(float x, float y) {
250261
return func_22(x, y);
251-
}
262+
}
263+
264+
// CHECK-LABEL: FunctionDecl {{.*}} func_24 'vector2float (vector2double)'
265+
// CHECK: CompoundStmt {{.*}} FPContractMode=2 ConstRoundingMode=towardzero
266+
// CHECK: ReturnStmt
267+
// CHECK: ConvertVectorExpr {{.*}} FPContractMode=2 ConstRoundingMode=towardzero
268+
269+
#pragma STDC FENV_ROUND FE_TOWARDZERO
270+
vector2float func_24(vector2double x) {
271+
return __builtin_convertvector(x, vector2float);
272+
}

clang/test/AST/const-fpfeatures.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ float _Complex C1u = C0;
2222
float FLu = 0.1F;
2323
// CHECK: @FLu = {{.*}} float 0x3FB99999A0000000
2424

25+
typedef float vector2float __attribute__((__vector_size__(8)));
26+
typedef double vector2double __attribute__((__vector_size__(16)));
27+
const vector2float V2Fu = {1.0F + 0x0.000001p0F, 1.0F + 0x0.000002p0F};
28+
vector2double V2Du = __builtin_convertvector(V2Fu, vector2double);
29+
// CHECK: @V2Fu = {{.*}} <2 x float> splat (float 0x3FF0000020000000)
30+
// CHECK: @V2Du = {{.*}} <2 x double> splat (double 0x3FF0000020000000)
2531

2632
#pragma STDC FENV_ROUND FE_DOWNWARD
2733

@@ -41,3 +47,8 @@ float _Complex C1d = C0;
4147

4248
float FLd = 0.1F;
4349
// CHECK: @FLd = {{.*}} float 0x3FB9999980000000
50+
51+
const vector2float V2Fd = {1.0F + 0x0.000001p0F, 1.0F + 0x0.000002p0F};
52+
vector2double V2Dd = __builtin_convertvector(V2Fd, vector2double);
53+
// CHECK: @V2Fd = {{.*}} <2 x float> <float 1.000000e+00, float 0x3FF0000020000000>
54+
// CHECK: @V2Dd = {{.*}} <2 x double> <double 1.000000e+00, double 0x3FF0000020000000>

clang/test/CodeGen/pragma-fenv_access.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,3 +242,12 @@ float func_20(float x, float y) {
242242
// CHECK-LABEL: @func_20
243243
// STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
244244
// DEFAULT: fadd float
245+
246+
typedef double vector4double __attribute__((__vector_size__(32)));
247+
typedef float vector4float __attribute__((__vector_size__(16)));
248+
vector4float func_21(vector4double x) {
249+
#pragma STDC FENV_ROUND FE_UPWARD
250+
return __builtin_convertvector(x, vector4float);
251+
}
252+
// CHECK-LABEL: @func_21
253+
// STRICT: call <4 x float> @llvm.experimental.constrained.fptrunc.v4f32.v4f64(<4 x double> {{.*}}, metadata !"round.upward", metadata !"fpexcept.strict")

0 commit comments

Comments
 (0)