I submitted a new patch into r244502. Please let me know if there is any other error. Thanks.
On Mon, Aug 10, 2015 at 12:46 PM, David Blaikie <dblai...@gmail.com> wrote: > > > On Mon, Aug 10, 2015 at 10:33 AM, Chih-Hung Hsieh via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> Author: chh >> Date: Mon Aug 10 12:33:31 2015 >> New Revision: 244468 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=244468&view=rev >> Log: >> Correct x86_64 fp128 calling convention >> >> These changes are for Android x86_64 targets to be compatible >> with current Android g++ and conform to AMD64 ABI. >> >> https://llvm.org/bugs/show_bug.cgi?id=23897 >> * Return type of long double (fp128) should be fp128, not x86_fp80. >> * Vararg of long double (fp128) could be in register and overflowed to >> memory. >> >> https://llvm.org/bugs/show_bug.cgi?id=24111 >> * Return value of long double (fp128) _Complex should be in memory like >> a structure of {fp128,fp128}. >> >> Differential Revision: http://reviews.llvm.org/D11437 >> >> >> Added: >> cfe/trunk/test/CodeGen/x86_64-fp128.c >> Modified: >> cfe/trunk/lib/CodeGen/TargetInfo.cpp >> >> Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=244468&r1=244467&r2=244468&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original) >> +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Mon Aug 10 12:33:31 2015 >> @@ -1862,13 +1862,20 @@ void X86_64ABIInfo::classify(QualType Ty >> Hi = Integer; >> } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) { >> Current = Integer; >> - } else if ((k == BuiltinType::Float || k == BuiltinType::Double) || >> - (k == BuiltinType::LongDouble && >> - getTarget().getTriple().isOSNaCl())) { >> + } else if (k == BuiltinType::Float || k == BuiltinType::Double) { >> Current = SSE; >> } else if (k == BuiltinType::LongDouble) { >> - Lo = X87; >> - Hi = X87Up; >> + const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat(); >> + if (LDF == &llvm::APFloat::IEEEquad) { >> + Lo = SSE; >> + Hi = SSEUp; >> + } else if (LDF == &llvm::APFloat::x87DoubleExtended) { >> + Lo = X87; >> + Hi = X87Up; >> + } else if (LDF == &llvm::APFloat::IEEEdouble) { >> + Current = SSE; >> + } else >> + llvm_unreachable("unexpected long double representation!"); >> } >> // FIXME: _Decimal32 and _Decimal64 are SSE. >> // FIXME: _float128 and _Decimal128 are (SSE, SSEUp). >> @@ -1973,14 +1980,21 @@ void X86_64ABIInfo::classify(QualType Ty >> Current = Integer; >> else if (Size <= 128) >> Lo = Hi = Integer; >> - } else if (ET == getContext().FloatTy) >> + } else if (ET == getContext().FloatTy) { >> Current = SSE; >> - else if (ET == getContext().DoubleTy || >> - (ET == getContext().LongDoubleTy && >> - getTarget().getTriple().isOSNaCl())) >> + } else if (ET == getContext().DoubleTy) { >> Lo = Hi = SSE; >> - else if (ET == getContext().LongDoubleTy) >> - Current = ComplexX87; >> + } else if (ET == getContext().LongDoubleTy) { >> + const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat(); >> + if (LDF == &llvm::APFloat::IEEEquad) >> + Current = Memory; >> + else if (LDF == &llvm::APFloat::x87DoubleExtended) >> + Current = ComplexX87; >> + else if (LDF == &llvm::APFloat::IEEEdouble) >> + Lo = Hi = SSE; >> + else >> + llvm_unreachable("unexpected long double representation!"); >> + } >> >> // If this complex type crosses an eightbyte boundary then it >> // should be split. >> @@ -2249,7 +2263,8 @@ llvm::Type *X86_64ABIInfo::GetByteVector >> Ty = QualType(InnerTy, 0); >> >> llvm::Type *IRType = CGT.ConvertType(Ty); >> - if(isa<llvm::VectorType>(IRType)) >> + if (isa<llvm::VectorType>(IRType) || >> + IRType->getTypeID() == llvm::Type::FP128TyID) >> return IRType; >> >> // We couldn't find the preferred IR vector type for 'Ty'. >> >> Added: cfe/trunk/test/CodeGen/x86_64-fp128.c >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/x86_64-fp128.c?rev=244468&view=auto >> >> ============================================================================== >> --- cfe/trunk/test/CodeGen/x86_64-fp128.c (added) >> +++ cfe/trunk/test/CodeGen/x86_64-fp128.c Mon Aug 10 12:33:31 2015 >> @@ -0,0 +1,116 @@ >> +// RUN: %clang_cc1 -triple x86_64-linux-android -emit-llvm -O -o - %s \ >> +// RUN: | FileCheck %s --check-prefix=ANDROID --check-prefix=CHECK >> +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -O -o - %s \ >> +// RUN: | FileCheck %s --check-prefix=GNU --check-prefix=CHECK >> +// RUN: %clang_cc1 -triple x86_64 -emit-llvm -O -o - %s \ >> +// RUN: | FileCheck %s --check-prefix=GNU --check-prefix=CHECK >> + >> +// Android uses fp128 for long double but other x86_64 targets use >> x86_fp80. >> + >> +long double dataLD = 1.0L; >> +// ANDROID: @dataLD = global fp128 0xL00000000000000003FFF000000000000, >> align 16 >> +// GNU: @dataLD = global x86_fp80 0xK3FFF8000000000000000, align 16 >> + >> +long double _Complex dataLDC = {1.0L, 1.0L}; >> +// ANDROID: @dataLDC = global { fp128, fp128 } { fp128 >> 0xL00000000000000003FFF000000000000, fp128 >> 0xL00000000000000003FFF000000000000 }, align 16 >> +// GNU: @dataLDC = global { x86_fp80, x86_fp80 } { x86_fp80 >> 0xK3FFF8000000000000000, x86_fp80 0xK3FFF8000000000000000 }, align 16 >> + >> +long double TestLD(long double x) { >> + return x * x; >> +// ANDROID: define fp128 @TestLD(fp128 %x) >> +// GNU: define x86_fp80 @TestLD(x86_fp80 %x) >> +} >> + >> +long double _Complex TestLDC(long double _Complex x) { >> + return x * x; >> +// ANDROID: define void @TestLDC({ fp128, fp128 }* {{.*}}, { fp128, >> fp128 }* {{.*}} %x) >> +// GNU: define { x86_fp80, x86_fp80 } @TestLDC({ x86_fp80, x86_fp80 }* >> {{.*}} %x) >> +} >> + >> +typedef __builtin_va_list va_list; >> + >> +int TestGetVarInt(va_list ap) { >> + return __builtin_va_arg(ap, int); >> +// Since int can be passed in memory or in register there is a branch >> and a phi. >> +// CHECK: define i32 @TestGetVarInt( >> +// CHECK: br >> +// CHECK: load {{.*}} %overflow_arg_area_p >> > > Checks like this are not resilient to -Asserts builds. When Clang is built > without assertions, it does not create names for IR values (so that > %overflow_arg_area_p will be %47 instead). Please update the test to be > usable on a -Asserts build. > > - David > > >> +// CHECK: = phi >> +// CHECK: ret i32 >> +} >> + >> +double TestGetVarDouble(va_list ap) { >> + return __builtin_va_arg(ap, double); >> +// Since double can be passed in memory or in register there is a branch >> and a phi. >> +// CHECK: define double @TestGetVarDouble( >> +// CHECK: br >> +// CHECK: load {{.*}} %overflow_arg_area_p >> +// CHECK: = phi >> +// CHECK: ret double >> +} >> + >> +long double TestGetVarLD(va_list ap) { >> + return __builtin_va_arg(ap, long double); >> +// fp128 can be passed in memory or in register, but x86_fp80 is in >> memory. >> +// ANDROID: define fp128 @TestGetVarLD( >> +// GNU: define x86_fp80 @TestGetVarLD( >> +// ANDROID: br >> +// GNU-NOT: br >> +// CHECK: load {{.*}} %overflow_arg_area_p >> +// ANDROID: = phi >> +// GNU-NOT: = phi >> +// ANDROID: ret fp128 >> +// GNU: ret x86_fp80 >> +} >> + >> +long double _Complex TestGetVarLDC(va_list ap) { >> + return __builtin_va_arg(ap, long double _Complex); >> +// Pair of fp128 or x86_fp80 are passed as struct in memory. >> +// ANDROID: define void @TestGetVarLDC({ fp128, fp128 }* {{.*}}, >> %struct.__va_list_tag* >> +// GNU: define { x86_fp80, x86_fp80 } @TestGetVarLDC( >> +// CHECK-NOT: br >> +// CHECK: load {{.*}} %overflow_arg_area_p >> +// CHECK-NOT: phi >> +// ANDROID: ret void >> +// GNU: ret { x86_fp80, x86_fp80 } >> +} >> + >> +void TestVarArg(const char *s, ...); >> + >> +void TestPassVarInt(int x) { >> + TestVarArg("A", x); >> +// CHECK: define void @TestPassVarInt(i32 %x) >> +// CHECK: call {{.*}} @TestVarArg(i8* {{.*}}, i32 %x) >> +} >> + >> +void TestPassVarFloat(float x) { >> + TestVarArg("A", x); >> +// CHECK: define void @TestPassVarFloat(float %x) >> +// CHECK: call {{.*}} @TestVarArg(i8* {{.*}}, double % >> +} >> + >> +void TestPassVarDouble(double x) { >> + TestVarArg("A", x); >> +// CHECK: define void @TestPassVarDouble(double %x) >> +// CHECK: call {{.*}} @TestVarArg(i8* {{.*}}, double %x >> +} >> + >> +void TestPassVarLD(long double x) { >> + TestVarArg("A", x); >> +// ANDROID: define void @TestPassVarLD(fp128 %x) >> +// ANDROID: call {{.*}} @TestVarArg(i8* {{.*}}, fp128 %x >> +// GNU: define void @TestPassVarLD(x86_fp80 %x) >> +// GNU: call {{.*}} @TestVarArg(i8* {{.*}}, x86_fp80 %x >> +} >> + >> +void TestPassVarLDC(long double _Complex x) { >> + TestVarArg("A", x); >> +// ANDROID: define void @TestPassVarLDC({ fp128, fp128 }* {{.*}} %x) >> +// ANDROID: store fp128 %x.{{.*}}, fp128* % >> +// ANDROID-NEXT: store fp128 %x.{{.*}}, fp128* % >> +// ANDROID-NEXT: call {{.*}} @TestVarArg(i8* {{.*}}, { fp128, fp128 }* >> {{.*}} % >> +// GNU: define void @TestPassVarLDC({ x86_fp80, x86_fp80 }* >> {{.*}} %x) >> +// GNU: store x86_fp80 %x.{{.*}}, x86_fp80* % >> +// GNU-NEXT: store x86_fp80 %x.{{.*}}, x86_fp80* % >> +// GNGNU-NEXT: call {{.*}} @TestVarArg(i8* {{.*}}, { x86_fp80, >> x86_fp80 }* {{.*}} % >> +} >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> > >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits