abeserminji updated this revision to Diff 39513.
abeserminji marked 2 inline comments as done.
abeserminji added a comment.

Comment modified


Repository:
  rL LLVM

http://reviews.llvm.org/D14149

Files:
  lib/CodeGen/CGBuiltin.cpp
  test/Analysis/builtin_signbit.cpp

Index: test/Analysis/builtin_signbit.cpp
===================================================================
--- test/Analysis/builtin_signbit.cpp
+++ test/Analysis/builtin_signbit.cpp
@@ -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
+}
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -238,10 +238,20 @@
   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);
   }


Index: test/Analysis/builtin_signbit.cpp
===================================================================
--- test/Analysis/builtin_signbit.cpp
+++ test/Analysis/builtin_signbit.cpp
@@ -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
+}
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -238,10 +238,20 @@
   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);
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to