jyu2 created this revision.
jyu2 added reviewers: hfinkel, erichkeane, rjmccall, cfe-commits.
Herald added a subscriber: jfb.

When using __sync_nand_and_fetch with __int128, a problem is found that
the wrong value for the 'invert' value gets emitted to the xor in case
where the int size is greater than 64 bits.

This is because uses of llvm::ConstantInt::get which zero extends the
greater than 64 bits, so instead -1 that we require, it end up
getting 18446744073709551615

This patch replaces the call to llvm::ConstantInt::get with the call
to llvm::Constant::getAllOnesValue which works for all integer types.


Repository:
  rC Clang

https://reviews.llvm.org/D82832

Files:
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/Atomics.c


Index: clang/test/CodeGen/Atomics.c
===================================================================
--- clang/test/CodeGen/Atomics.c
+++ clang/test/CodeGen/Atomics.c
@@ -10,6 +10,8 @@
 unsigned int ui;
 signed long long sll;
 unsigned long long ull;
+__int128 s128;
+unsigned  __int128 u128;
 
 void test_op_ignore (void) // CHECK-LABEL: define void @test_op_ignore
 {
@@ -48,6 +50,8 @@
   (void) __sync_fetch_and_xor (&ui, 1); // CHECK: atomicrmw xor i32
   (void) __sync_fetch_and_xor (&sll, 1); // CHECK: atomicrmw xor i64
   (void) __sync_fetch_and_xor (&ull, 1); // CHECK: atomicrmw xor i64
+  (void) __sync_fetch_and_xor (&u128, 1); // CHECK: atomicrmw xor i128
+  (void) __sync_fetch_and_xor (&s128, 1); // CHECK: atomicrmw xor i128
 
   (void) __sync_fetch_and_nand (&sc, 1); // CHECK: atomicrmw nand i8
   (void) __sync_fetch_and_nand (&uc, 1); // CHECK: atomicrmw nand i8
@@ -168,27 +172,43 @@
   sc = __sync_nand_and_fetch (&sc, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   uc = __sync_nand_and_fetch (&uc, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   ss = __sync_nand_and_fetch (&ss, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   us = __sync_nand_and_fetch (&us, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   si = __sync_nand_and_fetch (&si, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   ui = __sync_nand_and_fetch (&ui, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   sll = __sync_nand_and_fetch (&sll, uc); // CHECK: atomicrmw nand
                                           // CHECK: and
                                           // CHECK: xor
+                                          // CHECK: -1
   ull = __sync_nand_and_fetch (&ull, uc); // CHECK: atomicrmw nand
                                           // CHECK: and
                                           // CHECK: xor
+                                          // CHECK: -1
+  u128 = __sync_nand_and_fetch (&u128, uc); // CHECK: atomicrmw nand
+                                          // CHECK: and
+                                          // CHECK: xor
+                                          // CHECK: -1
+  s128 = __sync_nand_and_fetch (&s128, uc); // CHECK: atomicrmw nand
+                                          // CHECK: and
+                                          // CHECK: xor
+                                          // CHECK: -1
 
   sc = __sync_and_and_fetch (&sc, uc); // CHECK: atomicrmw and
   uc = __sync_and_and_fetch (&uc, uc); // CHECK: atomicrmw and
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -219,8 +219,9 @@
       Kind, Args[0], Args[1], llvm::AtomicOrdering::SequentiallyConsistent);
   Result = CGF.Builder.CreateBinOp(Op, Result, Args[1]);
   if (Invert)
-    Result = CGF.Builder.CreateBinOp(llvm::Instruction::Xor, Result,
-                                     llvm::ConstantInt::get(IntType, -1));
+    Result =
+        CGF.Builder.CreateBinOp(llvm::Instruction::Xor, Result,
+                                llvm::ConstantInt::getAllOnesValue(IntType));
   Result = EmitFromInt(CGF, Result, T, ValueType);
   return RValue::get(Result);
 }


Index: clang/test/CodeGen/Atomics.c
===================================================================
--- clang/test/CodeGen/Atomics.c
+++ clang/test/CodeGen/Atomics.c
@@ -10,6 +10,8 @@
 unsigned int ui;
 signed long long sll;
 unsigned long long ull;
+__int128 s128;
+unsigned  __int128 u128;
 
 void test_op_ignore (void) // CHECK-LABEL: define void @test_op_ignore
 {
@@ -48,6 +50,8 @@
   (void) __sync_fetch_and_xor (&ui, 1); // CHECK: atomicrmw xor i32
   (void) __sync_fetch_and_xor (&sll, 1); // CHECK: atomicrmw xor i64
   (void) __sync_fetch_and_xor (&ull, 1); // CHECK: atomicrmw xor i64
+  (void) __sync_fetch_and_xor (&u128, 1); // CHECK: atomicrmw xor i128
+  (void) __sync_fetch_and_xor (&s128, 1); // CHECK: atomicrmw xor i128
 
   (void) __sync_fetch_and_nand (&sc, 1); // CHECK: atomicrmw nand i8
   (void) __sync_fetch_and_nand (&uc, 1); // CHECK: atomicrmw nand i8
@@ -168,27 +172,43 @@
   sc = __sync_nand_and_fetch (&sc, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   uc = __sync_nand_and_fetch (&uc, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   ss = __sync_nand_and_fetch (&ss, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   us = __sync_nand_and_fetch (&us, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   si = __sync_nand_and_fetch (&si, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   ui = __sync_nand_and_fetch (&ui, uc); // CHECK: atomicrmw nand
                                         // CHECK: and
                                         // CHECK: xor
+                                        // CHECK: -1
   sll = __sync_nand_and_fetch (&sll, uc); // CHECK: atomicrmw nand
                                           // CHECK: and
                                           // CHECK: xor
+                                          // CHECK: -1
   ull = __sync_nand_and_fetch (&ull, uc); // CHECK: atomicrmw nand
                                           // CHECK: and
                                           // CHECK: xor
+                                          // CHECK: -1
+  u128 = __sync_nand_and_fetch (&u128, uc); // CHECK: atomicrmw nand
+                                          // CHECK: and
+                                          // CHECK: xor
+                                          // CHECK: -1
+  s128 = __sync_nand_and_fetch (&s128, uc); // CHECK: atomicrmw nand
+                                          // CHECK: and
+                                          // CHECK: xor
+                                          // CHECK: -1
 
   sc = __sync_and_and_fetch (&sc, uc); // CHECK: atomicrmw and
   uc = __sync_and_and_fetch (&uc, uc); // CHECK: atomicrmw and
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -219,8 +219,9 @@
       Kind, Args[0], Args[1], llvm::AtomicOrdering::SequentiallyConsistent);
   Result = CGF.Builder.CreateBinOp(Op, Result, Args[1]);
   if (Invert)
-    Result = CGF.Builder.CreateBinOp(llvm::Instruction::Xor, Result,
-                                     llvm::ConstantInt::get(IntType, -1));
+    Result =
+        CGF.Builder.CreateBinOp(llvm::Instruction::Xor, Result,
+                                llvm::ConstantInt::getAllOnesValue(IntType));
   Result = EmitFromInt(CGF, Result, T, ValueType);
   return RValue::get(Result);
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to