From 348f22eac83d9a3ee946e41be43fe507f04a89b6 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 13 Dec 2019 12:15:41 -0800 Subject: [PATCH] Correct gcc vector splat conversion from float to int-vector In looking into some other code, I came across this issue where a float converted to a gcc integer vector via a splat causes it to miss the float-to-integral cast, which causes some REALLY strange codegen bugs. The AST looked like: `-ImplicitCastExpr 'gcc_int_2':'__attribute__((__vector_size__(2 * sizeof(int)))) int' `-ImplicitCastExpr 'float' `-DeclRefExpr 'float' lvalue ParmVar 0x556f16a5dc90 'f' 'float' Despite the type of the VectorSplat cast as printed, it ended up becoming a vector of float, which caused non-matching instructions. For example, IntVector + a float constant resulted in: add <2 x i32> %8, <2 x float> This patch corrects the conversion so that the float is first converted to an integral, THEN splatted. --- clang/lib/Sema/SemaExpr.cpp | 6 ++++++ clang/test/CodeGenCXX/vector-splat-conversion.cpp | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index a941d524b7f2..620ec30b1285 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8973,6 +8973,12 @@ static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar, return true; ScalarCast = CK_IntegralCast; + } else if (VectorEltTy->isIntegralType(S.Context) && + ScalarTy->isRealFloatingType()) { + if (S.Context.getTypeSize(VectorEltTy) == S.Context.getTypeSize(ScalarTy)) + ScalarCast = CK_FloatingToIntegral; + else + return true; } else if (VectorEltTy->isRealFloatingType()) { if (ScalarTy->isRealFloatingType()) { diff --git a/clang/test/CodeGenCXX/vector-splat-conversion.cpp b/clang/test/CodeGenCXX/vector-splat-conversion.cpp index 805f9f5bab15..618ad76ce691 100644 --- a/clang/test/CodeGenCXX/vector-splat-conversion.cpp +++ b/clang/test/CodeGenCXX/vector-splat-conversion.cpp @@ -49,3 +49,14 @@ void BoolConversion() { // CHECK: store <4 x i128> zeroinitializer constexpr bigint4 cBigintsF = (bigint4)false; } + +typedef __attribute__((vector_size(8))) int gcc_int_2; +gcc_int_2 FloatToIntConversion(gcc_int_2 Int2, float f) { + return Int2 + f; + // CHECK: %[[LOAD_INT:.+]] = load <2 x i32> + // CHECK: %[[LOAD:.+]] = load float, float* + // CHECK: %[[CONV:.+]] = fptosi float %[[LOAD]] to i32 + // CHECK: %[[INSERT:.+]] = insertelement <2 x i32> undef, i32 %[[CONV]], i32 0 + // CHECK: %[[SPLAT:.+]] = shufflevector <2 x i32> %[[INSERT]], <2 x i32> undef, <2 x i32> zeroinitializer + // CHECK: add <2 x i32> %[[LOAD_INT]], %[[SPLAT]] +} -- GitLab