mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 19:49:36 +00:00
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 llvm-svn: 252307
This commit is contained in:
parent
1aa4d1c56f
commit
73d1044abe
@ -238,10 +238,20 @@ static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) {
|
||||
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);
|
||||
}
|
||||
|
43
clang/test/Analysis/builtin_signbit.cpp
Normal file
43
clang/test/Analysis/builtin_signbit.cpp
Normal file
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user