Author: petarj Date: Fri Nov 6 08:52:46 2015 New Revision: 252307 URL: http://llvm.org/viewvc/llvm-project?rev=252307&view=rev Log: Fix __builtin_signbit for ppcf128 type
Function__builtin_signbit returns wrong value for type ppcf128 on big endian machines. This patch fixes how value is generated in that case. Patch by Aleksandar Beserminji. Differential Revision: http://reviews.llvm.org/D14149 Added: cfe/trunk/test/Analysis/builtin_signbit.cpp Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=252307&r1=252306&r2=252307&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Fri Nov 6 08:52:46 2015 @@ -238,10 +238,20 @@ static Value *EmitSignBit(CodeGenFunctio llvm::Type *IntTy = llvm::IntegerType::get(C, Width); V = CGF.Builder.CreateBitCast(V, IntTy); if (Ty->isPPC_FP128Ty()) { - // The higher-order double comes first, and so we need to truncate the - // pair to extract the overall sign. The order of the pair is the same - // in both little- and big-Endian modes. + // We want the sign bit of the higher-order double. The bitcast we just + // did works as if the double-double was stored to memory and then + // read as an i128. The "store" will put the higher-order double in the + // lower address in both little- and big-Endian modes, but the "load" + // will treat those bits as a different part of the i128: the low bits in + // little-Endian, the high bits in big-Endian. Therefore, on big-Endian + // we need to shift the high bits down to the low before truncating. Width >>= 1; + if (CGF.getTarget().isBigEndian()) { + Value *ShiftCst = llvm::ConstantInt::get(IntTy, Width); + V = CGF.Builder.CreateLShr(V, ShiftCst); + } + // We are truncating value in order to extract the higher-order + // double, which we will be using to extract the sign from. IntTy = llvm::IntegerType::get(C, Width); V = CGF.Builder.CreateTrunc(V, IntTy); } Added: cfe/trunk/test/Analysis/builtin_signbit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/builtin_signbit.cpp?rev=252307&view=auto ============================================================================== --- cfe/trunk/test/Analysis/builtin_signbit.cpp (added) +++ cfe/trunk/test/Analysis/builtin_signbit.cpp Fri Nov 6 08:52:46 2015 @@ -0,0 +1,43 @@ +// RUN: %clang -target powerpc-linux-gnu -emit-llvm -S -O0 %s -o - | FileCheck %s --check-prefix=CHECK-BE --check-prefix=CHECK +// RUN: %clang -target powerpc64-linux-gnu -emit-llvm -S -O0 %s -o - | FileCheck %s --check-prefix=CHECK-BE --check-prefix=CHECK +// RUN: %clang -target powerpc64le-linux-gnu -emit-llvm -S -O0 %s -o - | FileCheck %s --check-prefix=CHECK-LE --check-prefix=CHECK + +bool b; +double d = -1.0; +long double ld = -1.0L; +void test_signbit() +{ + b = __builtin_signbit(1.0L); + // CHECK: i128 + // CHECK-LE-NOT: lshr + // CHECK-BE: lshr + // CHECK: bitcast + // CHECK: ppc_fp128 + + b = __builtin_signbit(ld); + // CHECK: bitcast + // CHECK: ppc_fp128 + // CHECK-LE-NOT: lshr + // CHECK-BE: lshr + + b = __builtin_signbitf(1.0); + // CHECK: store i8 0 + + b = __builtin_signbitf(d); + // CHECK: bitcast + // CHECK-LE-NOT: lshr + // CHECK-BE-NOT: lshr + + b = __builtin_signbitl(1.0L); + // CHECK: i128 + // CHECK-LE-NOT: lshr + // CHECK-BE: lshr + // CHECK: bitcast + // CHECK: ppc_fp128 + + b = __builtin_signbitl(ld); + // CHECK: bitcast + // CHECK: ppc_fp128 + // CHECK-LE-NOT: lshr + // CHECK-BE: lshr +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits