qiucf created this revision.
qiucf added reviewers: PowerPC, hubert.reinterpretcast, nemanjai, jsji.
Herald added a subscriber: shchenz.
qiucf requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D109751
Files:
clang/lib/CodeGen/CGExprScalar.cpp
clang/lib/Sema/SemaExpr.cpp
clang/test/CodeGen/ibm128-cast.c
clang/test/Sema/float128-ld-incompatibility.cpp
Index: clang/test/Sema/float128-ld-incompatibility.cpp
===================================================================
--- clang/test/Sema/float128-ld-incompatibility.cpp
+++ clang/test/Sema/float128-ld-incompatibility.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 \
// RUN: -triple powerpc64le-unknown-linux-gnu -target-cpu pwr9 \
-// RUN: -target-feature +float128 %s
+// RUN: -Wno-unused-value -Wno-parentheses -target-feature +float128 %s
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -Wno-parentheses %s
__float128 qf();
@@ -12,12 +12,12 @@
long double ld{qf()}; // expected-error {{cannot initialize a variable of type 'long double' with an rvalue of type '__float128'}}
__float128 q{ldf()}; // expected-error {{cannot initialize a variable of type '__float128' with an rvalue of type 'long double'}}
-auto test1(__float128 q, long double ld) -> decltype(q + ld) { // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}}
- return q + ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}}
+auto test1(__float128 q, long double ld) -> decltype(q + ld) { // expected-no-error {{invalid operands to binary expression ('__float128' and 'long double')}}
+ return q + ld; // expected-no-error {{invalid operands to binary expression ('__float128' and 'long double')}}
}
-auto test2(long double a, __float128 b) -> decltype(a + b) { // expected-error {{invalid operands to binary expression ('long double' and '__float128')}}
- return a + b; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}}
+auto test2(long double a, __float128 b) -> decltype(a + b) { // expected-eno-rror {{invalid operands to binary expression ('long double' and '__float128')}}
+ return a + b; // expected-no-error {{invalid operands to binary expression ('long double' and '__float128')}}
}
#endif
@@ -25,15 +25,15 @@
long double ld;
__float128 q;
- ld + q; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}}
- q + ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}}
- ld - q; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}}
- q - ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}}
- ld * q; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}}
- q * ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}}
- ld / q; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}}
- q / ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}}
+ ld + q; // expected-no-error {{invalid operands to binary expression ('long double' and '__float128')}}
+ q + ld; // expected-no-error {{invalid operands to binary expression ('__float128' and 'long double')}}
+ ld - q; // expected-no-error {{invalid operands to binary expression ('long double' and '__float128')}}
+ q - ld; // expected-no-error {{invalid operands to binary expression ('__float128' and 'long double')}}
+ ld * q; // expected-no-error {{invalid operands to binary expression ('long double' and '__float128')}}
+ q * ld; // expected-no-error {{invalid operands to binary expression ('__float128' and 'long double')}}
+ ld / q; // expected-no-error {{invalid operands to binary expression ('long double' and '__float128')}}
+ q / ld; // expected-no-error {{invalid operands to binary expression ('__float128' and 'long double')}}
ld = q; // expected-error {{assigning to 'long double' from incompatible type '__float128'}}
q = ld; // expected-error {{assigning to '__float128' from incompatible type 'long double'}}
- q + b ? q : ld; // expected-error {{incompatible operand types ('__float128' and 'long double')}}
+ q + b ? q : ld; // expected-no-error {{incompatible operand types ('__float128' and 'long double')}}
}
Index: clang/test/CodeGen/ibm128-cast.c
===================================================================
--- clang/test/CodeGen/ibm128-cast.c
+++ clang/test/CodeGen/ibm128-cast.c
@@ -1,61 +1,115 @@
-// RUN: %clang_cc1 -emit-llvm -triple powerpc64le-unknown-unknown -verify \
-// RUN: -target-feature +float128 -mabi=ieeelongdouble -fsyntax-only -Wno-unused %s
-// RUN: %clang_cc1 -emit-llvm -triple powerpc64le-unknown-unknown -verify \
-// RUN: -target-feature +float128 -fsyntax-only -Wno-unused %s
+// RUN: %clang_cc1 -S -emit-llvm -triple powerpc64le-unknown-unknown \
+// RUN: -target-feature +float128 -mabi=ieeelongdouble -Wno-unused %s \
+// RUN: -o - | FileCheck %s --check-prefix=IEEE
+// RUN: %clang_cc1 -S -emit-llvm -triple powerpc64le-unknown-unknown \
+// RUN: -target-feature +float128 -Wno-unused %s -o - | FileCheck %s
-__float128 cast1(__ibm128 x) { return x; } // expected-error {{returning '__ibm128' from a function with incompatible result type '__float128'}}
+// CHECK: define dso_local fp128 @cast1(ppc_fp128 %{{.+}})
+// CHECK: %{{.+}} = call fp128 @llvm.ppc.convert.ppcf128.to.f128(ppc_fp128 %{{.+}})
+// IEEE: define dso_local fp128 @cast1(ppc_fp128 %{{.+}})
+// IEEE: %{{.+}} = call fp128 @llvm.ppc.convert.ppcf128.to.f128(ppc_fp128 %{{.+}})
+__float128 cast1(__ibm128 x) { return x; }
-__ibm128 cast2(__float128 x) { return x; } // expected-error {{returning '__float128' from a function with incompatible result type '__ibm128'}}
+// CHECK: define dso_local ppc_fp128 @cast2(fp128 %{{.+}})
+// CHECK: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+// IEEE: define dso_local ppc_fp128 @cast2(fp128 %{{.+}})
+// IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+__ibm128 cast2(__float128 x) { return x; }
__ibm128 gf;
+// CHECK: define dso_local void @narrow(double* %{{.+}}, float* %{{.+}})
+// IEEE: define dso_local void @narrow(double* %{{.+}}, float* %{{.+}})
void narrow(double *d, float *f) {
__ibm128 v = gf;
- gf = *d; // expected-no-error {{assigning to '__ibm128' from incompatible type 'double'}}
- *f = v; // expected-no-error {{assigning to 'float' from incompatible type '__ibm128'}}
- *d = gf + *f; // expected-no-error {{invalid operands to binary expression ('__ibm128' and 'float')}}
+ // CHECK: %{{.+}} = fpext double %{{.+}} to ppc_fp128
+ // IEEE: %{{.+}} = fpext double %{{.+}} to ppc_fp128
+ gf = *d;
+ // CHECK: %{{.+}} = fptrunc ppc_fp128 %{{.+}} to float
+ // IEEE: %{{.+}} = fptrunc ppc_fp128 %{{.+}} to float
+ *f = v;
+ // CHECK: %{{.+}} = fpext float %{{.+}} to ppc_fp128
+ // CHECK: %{{.+}} = fadd ppc_fp128 %{{.+}}, %{{.+}}
+ // CHECK: %{{.+}} = fptrunc ppc_fp128 %{{.+}} to double
+ // IEEE: %{{.+}} = fpext float %{{.+}} to ppc_fp128
+ // IEEE: %{{.+}} = fadd ppc_fp128 %{{.+}}, %{{.+}}
+ // IEEE: %{{.+}} = fptrunc ppc_fp128 %{{.+}} to double
+ *d = gf + *f;
}
-#ifdef __LONG_DOUBLE_IEEE128__
-long double cast3(__ibm128 x) { return x; } // expected-error {{returning '__ibm128' from a function with incompatible result type 'long double'}}
+// CHECK: define dso_local ppc_fp128 @cast3(ppc_fp128 %{{.+}})
+// CHECK-NOT: call ppc_fp128
+// IEEE: define dso_local fp128 @cast3(ppc_fp128 %{{.+}})
+// IEEE: %{{.+}} = call fp128 @llvm.ppc.convert.ppcf128.to.f128(ppc_fp128 %{{.+}})
+long double cast3(__ibm128 x) { return x; }
-__ibm128 cast4(long double x) { return x; } // expected-error {{returning 'long double' from a function with incompatible result type '__ibm128'}}
+// CHECK: define dso_local ppc_fp128 @cast4(ppc_fp128 %{{.+}})
+// CHECK-NOT: %{{.+}} = call ppc_fp128
+// IEEE: define dso_local ppc_fp128 @cast4(fp128 %{{.+}})
+// IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+__ibm128 cast4(long double x) { return x; }
+// CHECK: define dso_local void @imp_cast(ppc_fp128 %{{.+}}, fp128 %{{.+}}, ppc_fp128 %{{.+}}, i1 zeroext %{{.+}})
+// IEEE: define dso_local void @imp_cast(ppc_fp128 %{{.+}}, fp128 %{{.+}}, fp128 %{{.+}}, i1 zeroext %{{.+}})
void imp_cast(__ibm128 w, __float128 q, long double l, _Bool b) {
- w + q; // expected-error {{invalid operands to binary expression ('__ibm128' and '__float128')}}
- l + w; // expected-error {{invalid operands to binary expression ('long double' and '__ibm128')}}
- q - w; // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
- w - l; // expected-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
- w *l; // expected-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
- q *w; // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
- q / w; // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
- w / l; // expected-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
- w = q; // expected-error {{assigning to '__ibm128' from incompatible type '__float128'}}
- q = w; // expected-error {{assigning to '__float128' from incompatible type '__ibm128'}}
- l = w; // expected-error {{assigning to 'long double' from incompatible type '__ibm128'}}
- w = l; // expected-error {{assigning to '__ibm128' from incompatible type 'long double'}}
- b ? q : w; // expected-error {{incompatible operand types ('__float128' and '__ibm128')}}
- !b ? w : l; // expected-error {{incompatible operand types ('__ibm128' and 'long double')}}
+ // CHECK: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // CHECK: %{{.+}} = fadd ppc_fp128 %{{.+}}, %{{.+}}
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: %{{.+}} = fadd ppc_fp128 %{{.+}}, %{{.+}}
+ w + q;
+ // CHECK: %{{.+}} = fadd ppc_fp128 %{{.+}}, %{{.+}}
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: %{{.+}} = fadd ppc_fp128 %{{.+}}, %{{.+}}
+ l + w;
+ // CHECK: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // CHECK: %{{.+}} = fsub ppc_fp128 %{{.+}}, %{{.+}}
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: %{{.+}} = fsub ppc_fp128 %{{.+}}, %{{.+}}
+ q - w;
+ // CHECK: %{{.+}} = fsub ppc_fp128 %{{.+}}, %{{.+}}
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: %{{.+}} = fsub ppc_fp128 %{{.+}}, %{{.+}}
+ w - l;
+ // CHECK: %{{.+}} = fmul ppc_fp128 %{{.+}}, %{{.+}}
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: %{{.+}} = fmul ppc_fp128 %{{.+}}, %{{.+}}
+ w *l;
+ // CHECK: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // CHECK: %{{.+}} = fmul ppc_fp128 %{{.+}}, %{{.+}}
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: %{{.+}} = fmul ppc_fp128 %{{.+}}, %{{.+}}
+ q *w;
+ // CHECK: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // CHECK: %{{.+}} = fdiv ppc_fp128 %{{.+}}, %{{.+}}
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: %{{.+}} = fdiv ppc_fp128 %{{.+}}, %{{.+}}
+ q / w;
+ // CHECK: %{{.+}} = fdiv ppc_fp128 %{{.+}}, %{{.+}}
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: %{{.+}} = fdiv ppc_fp128 %{{.+}}, %{{.+}}
+ w / l;
+ // CHECK: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // CHECK: store ppc_fp128 %{{.+}}, ppc_fp128* %{{.+}}, align 16
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: store ppc_fp128 %{{.+}}, ppc_fp128* %{{.+}}, align 16
+ w = q;
+ // CHECK: %{{.+}} = call fp128 @llvm.ppc.convert.ppcf128.to.f128(ppc_fp128 %{{.+}})
+ // CHECK: store fp128 %{{.+}}, fp128* %{{.+}}, align 16
+ // IEEE: %{{.+}} = call fp128 @llvm.ppc.convert.ppcf128.to.f128(ppc_fp128 %{{.+}})
+ // IEEE: store fp128 %{{.+}}, fp128* %{{.+}}, align 16
+ q = w;
+ // CHECK: store ppc_fp128 %{{.+}}, ppc_fp128* %{{.+}}, align 16
+ // IEEE: %{{.+}} = call fp128 @llvm.ppc.convert.ppcf128.to.f128(ppc_fp128 %{{.+}})
+ // IEEE: store fp128 %{{.+}}, fp128* %{{.+}}, align 16
+ l = w;
+ // CHECK: store ppc_fp128 %{{.+}}, ppc_fp128* %{{.+}}, align 16
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: store ppc_fp128 %{{.+}}, ppc_fp128* %{{.+}}, align 16
+ w = l;
+ // CHECK: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ b ? q : w;
+ // CHECK-NOT: call ppc_fp128
+ // IEEE: %{{.+}} = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %{{.+}})
+ !b ? w : l;
}
-#elif __LONG_DOUBLE_IBM128__
-long double cast3(__ibm128 x) { return x; } // expected-no-error {{returning '__ibm128' from a function with incompatible result type 'long double'}}
-
-__ibm128 cast4(long double x) { return x; } // expected-no-error {{returning 'long double' from a function with incompatible result type '__ibm128'}}
-
-void imp_cast(__ibm128 w, __float128 q, long double l, _Bool b) {
- w + q; // expected-error {{invalid operands to binary expression ('__ibm128' and '__float128')}}
- l + w; // expected-no-error {{invalid operands to binary expression ('long double' and '__ibm128')}}
- q - w; // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
- w - l; // expected-no-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
- w *l; // expected-no-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
- q *w; // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
- q / w; // expected-error {{invalid operands to binary expression ('__float128' and '__ibm128')}}
- w / l; // expected-no-error {{invalid operands to binary expression ('__ibm128' and 'long double')}}
- w = q; // expected-error {{assigning to '__ibm128' from incompatible type '__float128'}}
- q = w; // expected-error {{assigning to '__float128' from incompatible type '__ibm128'}}
- l = w; // expected-no-error {{assigning to 'long double' from incompatible type '__ibm128'}}
- w = l; // expected-no-error {{assigning to '__ibm128' from incompatible type 'long double'}}
- b ? q : w; // expected-error {{incompatible operand types ('__float128' and '__ibm128')}}
- !b ? w : l; // expected-no-error {{incompatible operand types ('__ibm128' and 'long double')}}
-}
-#endif
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -1197,34 +1197,6 @@
/*ConvertInt=*/!IsCompAssign);
}
-/// Diagnose attempts to convert between __float128, __ibm128 and
-/// long double if there is no support for such conversion.
-/// Helper function of UsualArithmeticConversions().
-static bool unsupportedTypeConversion(const Sema &S, QualType LHSType,
- QualType RHSType) {
- // No issue if either is not a floating point type.
- if (!LHSType->isFloatingType() || !RHSType->isFloatingType())
- return false;
-
- // No issue if both have the same 128-bit float semantics.
- auto *LHSComplex = LHSType->getAs<ComplexType>();
- auto *RHSComplex = RHSType->getAs<ComplexType>();
-
- QualType LHSElem = LHSComplex ? LHSComplex->getElementType() : LHSType;
- QualType RHSElem = RHSComplex ? RHSComplex->getElementType() : RHSType;
-
- const llvm::fltSemantics &LHSSem = S.Context.getFloatTypeSemantics(LHSElem);
- const llvm::fltSemantics &RHSSem = S.Context.getFloatTypeSemantics(RHSElem);
-
- if ((&LHSSem != &llvm::APFloat::PPCDoubleDouble() ||
- &RHSSem != &llvm::APFloat::IEEEquad()) &&
- (&LHSSem != &llvm::APFloat::IEEEquad() ||
- &RHSSem != &llvm::APFloat::PPCDoubleDouble()))
- return false;
-
- return true;
-}
-
typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType);
namespace {
@@ -1534,11 +1506,6 @@
// At this point, we have two different arithmetic types.
- // Diagnose attempts to convert between __ibm128, __float128 and long double
- // where such conversions currently can't be handled.
- if (unsupportedTypeConversion(*this, LHSType, RHSType))
- return QualType();
-
// Handle complex types first (C99 6.3.1.8p1).
if (LHSType->isComplexType() || RHSType->isComplexType())
return handleComplexFloatConversion(*this, LHS, RHS, LHSType, RHSType,
@@ -8362,15 +8329,6 @@
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
- // Diagnose attempts to convert between __ibm128, __float128 and long double
- // where such conversions currently can't be handled.
- if (unsupportedTypeConversion(*this, LHSTy, RHSTy)) {
- Diag(QuestionLoc,
- diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy
- << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
- return QualType();
- }
-
// OpenCL v2.0 s6.12.5 - Blocks cannot be used as expressions of the ternary
// selection operator (?:).
if (getLangOpts().OpenCL &&
@@ -9297,11 +9255,6 @@
return Incompatible;
}
- // Diagnose attempts to convert between __ibm128, __float128 and long double
- // where such conversions currently can't be handled.
- if (unsupportedTypeConversion(*this, LHSType, RHSType))
- return Incompatible;
-
// Disallow assigning a _Complex to a real type in C++ mode since it simply
// discards the imaginary part.
if (getLangOpts().CPlusPlus && RHSType->getAs<ComplexType>() &&
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -1325,6 +1325,22 @@
}
}
+ if (SrcType->isFloatingType() && DstType->isFloatingType()) {
+ // Handle cast between PPC double-double and IEEE 128-bit float types.
+ const auto *SrcSemantics = &CGF.getContext().getFloatTypeSemantics(SrcType);
+ const auto *DstSemantics = &CGF.getContext().getFloatTypeSemantics(DstType);
+ if (SrcSemantics == &llvm::APFloat::PPCDoubleDouble() &&
+ DstSemantics == &llvm::APFloat::IEEEquad())
+ return Builder.CreateCall(
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::ppc_convert_ppcf128_to_f128),
+ Src);
+ if (SrcSemantics == &llvm::APFloat::IEEEquad() &&
+ DstSemantics == &llvm::APFloat::PPCDoubleDouble())
+ return Builder.CreateCall(
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::ppc_convert_f128_to_ppcf128),
+ Src);
+ }
+
// Ignore conversions like int -> uint.
if (SrcTy == DstTy) {
if (Opts.EmitImplicitIntegerSignChangeChecks)
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits