[clang] fda0e63 - [clang] handle fp options in __builtin_convertvector (#125522)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 19 09:03:23 PST 2025
Author: Jakub Ficek
Date: 2025-02-19T09:03:18-08:00
New Revision: fda0e63e7331debacf9f36a64dad76339ad86482
URL: https://github.com/llvm/llvm-project/commit/fda0e63e7331debacf9f36a64dad76339ad86482
DIFF: https://github.com/llvm/llvm-project/commit/fda0e63e7331debacf9f36a64dad76339ad86482.diff
LOG: [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
Added:
Modified:
clang/include/clang/AST/Expr.h
clang/include/clang/AST/Stmt.h
clang/include/clang/AST/TextNodeDumper.h
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/Expr.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/CodeGen/CGExprScalar.cpp
clang/lib/Sema/SemaChecking.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/test/AST/ast-dump-fpfeatures.cpp
clang/test/AST/const-fpfeatures.c
clang/test/CodeGen/pragma-fenv_access.c
Removed:
################################################################################
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index ff4f236c1fa88..0f98d237dcbcd 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4579,25 +4579,97 @@ class ShuffleVectorExpr : public Expr {
/// ConvertVectorExpr - Clang builtin function __builtin_convertvector
/// This AST node provides support for converting a vector type to another
/// vector type of the same arity.
-class ConvertVectorExpr : public Expr {
+class ConvertVectorExpr final
+ : public Expr,
+ private llvm::TrailingObjects<ConvertVectorExpr, FPOptionsOverride> {
private:
Stmt *SrcExpr;
TypeSourceInfo *TInfo;
SourceLocation BuiltinLoc, RParenLoc;
+ friend TrailingObjects;
friend class ASTReader;
friend class ASTStmtReader;
- explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {}
+ explicit ConvertVectorExpr(bool HasFPFeatures, EmptyShell Empty)
+ : Expr(ConvertVectorExprClass, Empty) {
+ ConvertVectorExprBits.HasFPFeatures = HasFPFeatures;
+ }
-public:
ConvertVectorExpr(Expr *SrcExpr, TypeSourceInfo *TI, QualType DstType,
ExprValueKind VK, ExprObjectKind OK,
- SourceLocation BuiltinLoc, SourceLocation RParenLoc)
+ SourceLocation BuiltinLoc, SourceLocation RParenLoc,
+ FPOptionsOverride FPFeatures)
: Expr(ConvertVectorExprClass, DstType, VK, OK), SrcExpr(SrcExpr),
TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {
+ ConvertVectorExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ if (hasStoredFPFeatures())
+ setStoredFPFeatures(FPFeatures);
setDependence(computeDependence(this));
}
+ size_t numTrailingObjects(OverloadToken<FPOptionsOverride>) const {
+ return ConvertVectorExprBits.HasFPFeatures ? 1 : 0;
+ }
+
+ FPOptionsOverride &getTrailingFPFeatures() {
+ assert(ConvertVectorExprBits.HasFPFeatures);
+ return *getTrailingObjects<FPOptionsOverride>();
+ }
+
+ const FPOptionsOverride &getTrailingFPFeatures() const {
+ assert(ConvertVectorExprBits.HasFPFeatures);
+ return *getTrailingObjects<FPOptionsOverride>();
+ }
+
+public:
+ static ConvertVectorExpr *CreateEmpty(const ASTContext &C,
+ bool hasFPFeatures);
+
+ static ConvertVectorExpr *Create(const ASTContext &C, Expr *SrcExpr,
+ TypeSourceInfo *TI, QualType DstType,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc,
+ FPOptionsOverride FPFeatures);
+
+ /// Get the FP contractibility status of this operator. Only meaningful for
+ /// operations on floating point types.
+ bool isFPContractableWithinStatement(const LangOptions &LO) const {
+ return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
+ }
+
+ /// Is FPFeatures in Trailing Storage?
+ bool hasStoredFPFeatures() const {
+ return ConvertVectorExprBits.HasFPFeatures;
+ }
+
+ /// Get FPFeatures from trailing storage.
+ FPOptionsOverride getStoredFPFeatures() const {
+ return getTrailingFPFeatures();
+ }
+
+ /// Get the store FPOptionsOverride or default if not stored.
+ FPOptionsOverride getStoredFPFeaturesOrDefault() const {
+ return hasStoredFPFeatures() ? getStoredFPFeatures() : FPOptionsOverride();
+ }
+
+ /// Set FPFeatures in trailing storage, used by Serialization & ASTImporter.
+ void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; }
+
+ /// Get the FP features status of this operator. Only meaningful for
+ /// operations on floating point types.
+ FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
+ if (ConvertVectorExprBits.HasFPFeatures)
+ return getStoredFPFeatures().applyOverrides(LO);
+ return FPOptions::defaultWithoutTrailingStorage(LO);
+ }
+
+ FPOptionsOverride getFPOptionsOverride() const {
+ if (ConvertVectorExprBits.HasFPFeatures)
+ return getStoredFPFeatures();
+ return FPOptionsOverride();
+ }
+
/// getSrcExpr - Return the Expr to be converted.
Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); }
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 405c6166adb15..604ac51d478cf 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -1215,6 +1215,20 @@ class alignas(void *) Stmt {
SourceLocation Loc;
};
+ class ConvertVectorExprBitfields {
+ friend class ConvertVectorExpr;
+
+ LLVM_PREFERRED_TYPE(ExprBitfields)
+ unsigned : NumExprBits;
+
+ //
+ /// This is only meaningful for operations on floating point
+ /// types when additional values need to be in trailing storage.
+ /// It is 0 otherwise.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned HasFPFeatures : 1;
+ };
+
union {
// Same order as in StmtNodes.td.
// Statements
@@ -1293,6 +1307,7 @@ class alignas(void *) Stmt {
// Clang Extensions
OpaqueValueExprBitfields OpaqueValueExprBits;
+ ConvertVectorExprBitfields ConvertVectorExprBits;
};
public:
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index 4b5ad2b5fa74c..81844db2c77fa 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -425,6 +425,7 @@ class TextNodeDumper
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S);
void VisitEmbedExpr(const EmbedExpr *S);
void VisitAtomicExpr(const AtomicExpr *AE);
+ void VisitConvertVectorExpr(const ConvertVectorExpr *S);
};
} // namespace clang
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index c27ebbf838ad1..43da76e14d0a3 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -7386,9 +7386,10 @@ ExpectedStmt ASTNodeImporter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
if (Err)
return std::move(Err);
- return new (Importer.getToContext())
- ConvertVectorExpr(ToSrcExpr, ToTSI, ToType, E->getValueKind(),
- E->getObjectKind(), ToBuiltinLoc, ToRParenLoc);
+ return ConvertVectorExpr::Create(
+ Importer.getToContext(), ToSrcExpr, ToTSI, ToType, E->getValueKind(),
+ E->getObjectKind(), ToBuiltinLoc, ToRParenLoc,
+ E->getStoredFPFeaturesOrDefault());
}
ExpectedStmt ASTNodeImporter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 1f949d495f343..b747aa8df807d 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -3911,6 +3911,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 ConvertVector = dyn_cast<ConvertVectorExpr>(this))
+ return ConvertVector->getFPFeaturesInEffect(LO);
return FPOptions::defaultWithoutTrailingStorage(LO);
}
@@ -5451,3 +5453,21 @@ OpenACCAsteriskSizeExpr *
OpenACCAsteriskSizeExpr::CreateEmpty(const ASTContext &C) {
return new (C) OpenACCAsteriskSizeExpr({}, C.IntTy);
}
+
+ConvertVectorExpr *ConvertVectorExpr::CreateEmpty(const ASTContext &C,
+ bool hasFPFeatures) {
+ void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(hasFPFeatures),
+ alignof(ConvertVectorExpr));
+ return new (Mem) ConvertVectorExpr(hasFPFeatures, EmptyShell());
+}
+
+ConvertVectorExpr *ConvertVectorExpr::Create(
+ const ASTContext &C, Expr *SrcExpr, TypeSourceInfo *TI, QualType DstType,
+ ExprValueKind VK, ExprObjectKind OK, SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc, FPOptionsOverride FPFeatures) {
+ bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ unsigned Size = totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures);
+ void *Mem = C.Allocate(Size, alignof(ConvertVectorExpr));
+ return new (Mem) ConvertVectorExpr(SrcExpr, TI, DstType, VK, OK, BuiltinLoc,
+ RParenLoc, FPFeatures);
+}
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 26493caa5d06a..fd1eaab9621dd 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -3069,3 +3069,9 @@ void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) {
void TextNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) {
OS << ' ' << AE->getOpAsString();
}
+
+void TextNodeDumper::VisitConvertVectorExpr(const ConvertVectorExpr *S) {
+ VisitStmt(S);
+ if (S->hasStoredFPFeatures())
+ printFPOptions(S->getStoredFPFeatures());
+}
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 30f01496ba221..5ee8a1bfa8175 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1949,6 +1949,7 @@ Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
llvm::Value *Zero = llvm::Constant::getNullValue(SrcTy);
if (SrcEltTy->isFloatingPointTy()) {
+ CodeGenFunction::CGFPOptionsRAII FPOptions(CGF, E);
return Builder.CreateFCmpUNE(Src, Zero, "tobool");
} else {
return Builder.CreateICmpNE(Src, Zero, "tobool");
@@ -1975,6 +1976,7 @@ Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
} else {
assert(SrcEltTy->isFloatingPointTy() && DstEltTy->isFloatingPointTy() &&
"Unknown real conversion");
+ CodeGenFunction::CGFPOptionsRAII FPOptions(CGF, E);
if (DstEltTy->getTypeID() < SrcEltTy->getTypeID())
Res = Builder.CreateFPTrunc(Src, DstTy, "conv");
else
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index aae61f612a4bc..74f425d32648f 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5262,8 +5262,8 @@ ExprResult Sema::ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
<< E->getSourceRange());
}
- return new (Context) class ConvertVectorExpr(E, TInfo, DstTy, VK, OK,
- BuiltinLoc, RParenLoc);
+ return ConvertVectorExpr::Create(Context, E, TInfo, DstTy, VK, OK, BuiltinLoc,
+ RParenLoc, CurFPFeatureOverrides());
}
bool Sema::BuiltinPrefetch(CallExpr *TheCall) {
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index fba54023a6bb2..835ad4a658944 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1387,10 +1387,15 @@ void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
void ASTStmtReader::VisitConvertVectorExpr(ConvertVectorExpr *E) {
VisitExpr(E);
+ bool HasFPFeatures = CurrentUnpackingBits->getNextBit();
+ assert(HasFPFeatures == E->hasStoredFPFeatures());
E->BuiltinLoc = readSourceLocation();
E->RParenLoc = readSourceLocation();
E->TInfo = readTypeSourceInfo();
E->SrcExpr = Record.readSubExpr();
+ if (HasFPFeatures)
+ E->setStoredFPFeatures(
+ FPOptionsOverride::getFromOpaqueInt(Record.readInt()));
}
void ASTStmtReader::VisitBlockExpr(BlockExpr *E) {
@@ -3385,9 +3390,13 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = new (Context) ShuffleVectorExpr(Empty);
break;
- case EXPR_CONVERT_VECTOR:
- S = new (Context) ConvertVectorExpr(Empty);
+ case EXPR_CONVERT_VECTOR: {
+ BitsUnpacker ConvertVectorExprBits(Record[ASTStmtReader::NumStmtFields]);
+ ConvertVectorExprBits.advance(ASTStmtReader::NumExprBits);
+ bool HasFPFeatures = ConvertVectorExprBits.getNextBit();
+ S = ConvertVectorExpr::CreateEmpty(Context, HasFPFeatures);
break;
+ }
case EXPR_BLOCK:
S = new (Context) BlockExpr(Empty);
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 2687231d7820f..82738d3a8c88a 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1335,11 +1335,15 @@ void ASTStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
void ASTStmtWriter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
VisitExpr(E);
+ bool HasFPFeatures = E->hasStoredFPFeatures();
+ CurrentPackingBits.addBit(HasFPFeatures);
Record.AddSourceLocation(E->getBuiltinLoc());
Record.AddSourceLocation(E->getRParenLoc());
Record.AddTypeSourceInfo(E->getTypeSourceInfo());
Record.AddStmt(E->getSrcExpr());
Code = serialization::EXPR_CONVERT_VECTOR;
+ if (HasFPFeatures)
+ Record.push_back(E->getStoredFPFeatures().getAsOpaqueInt());
}
void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) {
diff --git a/clang/test/AST/ast-dump-fpfeatures.cpp b/clang/test/AST/ast-dump-fpfeatures.cpp
index cd00650db55cc..eeead3462c0ec 100644
--- a/clang/test/AST/ast-dump-fpfeatures.cpp
+++ b/clang/test/AST/ast-dump-fpfeatures.cpp
@@ -8,6 +8,17 @@
// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
// RUN: | FileCheck --strict-whitespace %s
+// CHECK-LABEL: FunctionDecl {{.*}} no_fpfeatures_func_01 'vector2float (vector2double)'
+// CHECK: CompoundStmt {{.*\>$}}
+// CHECK: ReturnStmt
+// CHECK: ConvertVectorExpr {{.*}} 'vector2float':'__attribute__((__vector_size__(2 * sizeof(float)))) float'{{$}}
+
+typedef double vector2double __attribute__((__vector_size__(16)));
+typedef float vector2float __attribute__((__vector_size__(8)));
+vector2float no_fpfeatures_func_01(vector2double x) {
+ return __builtin_convertvector(x, vector2float);
+}
+
float func_01(float x);
template <typename T>
@@ -248,4 +259,14 @@ __attribute__((optnone)) T func_22(T x, T y) {
float func_23(float x, float y) {
return func_22(x, y);
-}
\ No newline at end of file
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} func_24 'vector2float (vector2double)'
+// CHECK: CompoundStmt {{.*}} FPContractMode=2 ConstRoundingMode=towardzero
+// CHECK: ReturnStmt
+// CHECK: ConvertVectorExpr {{.*}} FPContractMode=2 ConstRoundingMode=towardzero
+
+#pragma STDC FENV_ROUND FE_TOWARDZERO
+vector2float func_24(vector2double x) {
+ return __builtin_convertvector(x, vector2float);
+}
diff --git a/clang/test/AST/const-fpfeatures.c b/clang/test/AST/const-fpfeatures.c
index 8dc3221b0638a..787bb989dd4a2 100644
--- a/clang/test/AST/const-fpfeatures.c
+++ b/clang/test/AST/const-fpfeatures.c
@@ -22,6 +22,12 @@ float _Complex C1u = C0;
float FLu = 0.1F;
// CHECK: @FLu = {{.*}} float 0x3FB99999A0000000
+typedef float vector2float __attribute__((__vector_size__(8)));
+typedef double vector2double __attribute__((__vector_size__(16)));
+const vector2float V2Fu = {1.0F + 0x0.000001p0F, 1.0F + 0x0.000002p0F};
+vector2double V2Du = __builtin_convertvector(V2Fu, vector2double);
+// CHECK: @V2Fu = {{.*}} <2 x float> splat (float 0x3FF0000020000000)
+// CHECK: @V2Du = {{.*}} <2 x double> splat (double 0x3FF0000020000000)
#pragma STDC FENV_ROUND FE_DOWNWARD
@@ -41,3 +47,8 @@ float _Complex C1d = C0;
float FLd = 0.1F;
// CHECK: @FLd = {{.*}} float 0x3FB9999980000000
+
+const vector2float V2Fd = {1.0F + 0x0.000001p0F, 1.0F + 0x0.000002p0F};
+vector2double V2Dd = __builtin_convertvector(V2Fd, vector2double);
+// CHECK: @V2Fd = {{.*}} <2 x float> <float 1.000000e+00, float 0x3FF0000020000000>
+// CHECK: @V2Dd = {{.*}} <2 x double> <double 1.000000e+00, double 0x3FF0000020000000>
diff --git a/clang/test/CodeGen/pragma-fenv_access.c b/clang/test/CodeGen/pragma-fenv_access.c
index afca115ed08d1..347e9670c4742 100644
--- a/clang/test/CodeGen/pragma-fenv_access.c
+++ b/clang/test/CodeGen/pragma-fenv_access.c
@@ -242,3 +242,12 @@ float func_20(float x, float y) {
// CHECK-LABEL: @func_20
// STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
// DEFAULT: fadd float
+
+typedef double vector4double __attribute__((__vector_size__(32)));
+typedef float vector4float __attribute__((__vector_size__(16)));
+vector4float func_21(vector4double x) {
+ #pragma STDC FENV_ROUND FE_UPWARD
+ return __builtin_convertvector(x, vector4float);
+}
+// CHECK-LABEL: @func_21
+// STRICT: call <4 x float> @llvm.experimental.constrained.fptrunc.v4f32.v4f64(<4 x double> {{.*}}, metadata !"round.upward", metadata !"fpexcept.strict")
More information about the cfe-commits
mailing list