Index: ChangeLog
authorGeoffrey Keating <geoffk@gcc.gnu.org>
Wed, 1 Jun 2005 00:45:24 +0000 (00:45 +0000)
committerGeoffrey Keating <geoffk@gcc.gnu.org>
Wed, 1 Jun 2005 00:45:24 +0000 (00:45 +0000)
2005-05-31  Geoffrey Keating  <geoffk@geoffk.org>

* config/rs6000/rs6000.md (sync_boolcshort_internal): New.
* config/rs6000/rs6000.c (rs6000_emit_sync): Shift count must
be complemented for big-endian.  Mask for AND must be rotated,
not shifted.  Handle short operands with NOT on the memory
operation.

Index: testsuite/ChangeLog
2005-05-31  Geoffrey Keating  <geoffk@geoffk.org>

* lib/target-supports.exp
(check_effective_target_sync_char_short): New.
* gcc.dg/sync-2.c: New.

From-SVN: r100418

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/sync-2.c [new file with mode: 0644]

index 7b6f3ff..ec8ed23 100644 (file)
@@ -1,3 +1,11 @@
+2005-05-31  Geoffrey Keating  <geoffk@geoffk.org>
+
+       * config/rs6000/rs6000.md (sync_boolcshort_internal): New.
+       * config/rs6000/rs6000.c (rs6000_emit_sync): Shift count must
+       be complemented for big-endian.  Mask for AND must be rotated,
+       not shifted.  Handle short operands with NOT on the memory
+       operation.
+
 2005-05-30  Daniel Berlin  <dberlin@dberlin.org>
 
        * c-objc-common.c (c_tree_printer): Check flag before hashtable.
index 265a9ef..9f8bbd7 100644 (file)
@@ -11409,13 +11409,15 @@ rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
       else
        {
          rtx addrSI, aligned_addr;
+         int shift_mask = mode == QImode ? 0x18 : 0x10;
          
          addrSI = force_reg (SImode, gen_lowpart_common (SImode,
                                                          XEXP (used_m, 0)));
          shift = gen_reg_rtx (SImode);
 
          emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
-                                GEN_INT (0x18)));
+                                GEN_INT (shift_mask)));
+         emit_insn (gen_xorsi3 (shift, shift, GEN_INT (shift_mask)));
 
          aligned_addr = expand_binop (Pmode, and_optab,
                                       XEXP (used_m, 0),
@@ -11453,7 +11455,7 @@ rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
          newop = expand_binop (SImode, ior_optab,
                                oldop, GEN_INT (~imask), NULL_RTX,
                                1, OPTAB_LIB_WIDEN);
-         emit_insn (gen_ashlsi3 (newop, newop, shift));
+         emit_insn (gen_rotlsi3 (newop, newop, shift));
          break;
 
        case PLUS:
@@ -11482,6 +11484,19 @@ rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
          gcc_unreachable ();
        }
 
+      if (GET_CODE (m) == NOT)
+       {
+         rtx mask, xorm;
+
+         mask = gen_reg_rtx (SImode);
+         emit_move_insn (mask, GEN_INT (imask));
+         emit_insn (gen_ashlsi3 (mask, mask, shift));
+
+         xorm = gen_rtx_XOR (SImode, used_m, mask);
+         /* Depending on the value of 'op', the XOR or the operation might
+            be able to be simplified away.  */
+         newop = simplify_gen_binary (code, SImode, xorm, newop);
+       }
       op = newop;
       used_mode = SImode;
       before = gen_reg_rtx (used_mode);
@@ -11499,7 +11514,7 @@ rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
        after = gen_reg_rtx (used_mode);
     }
   
-  if (code == PLUS && used_mode != mode)
+  if ((code == PLUS || GET_CODE (m) == NOT) && used_mode != mode)
     the_op = op;  /* Computed above.  */
   else if (GET_CODE (op) == NOT && GET_CODE (m) != NOT)
     the_op = gen_rtx_fmt_ee (code, used_mode, op, m);
index 02847df..53e4884 100644 (file)
   "<larx> %3,%y0\n\t%q4 %2,%1,%3\n\t<stcx> %2,%y0\n\tbne- $-12"
   [(set_attr "length" "16")])
 
+; This pattern could also take immediate values of operand 1,
+; since the non-NOT version of the operator is used; but this is not
+; very useful, since in practise operand 1 is a full 32-bit value.
+; Likewise, operand 5 is in practise either <= 2^16 or it is a register.
+(define_insn "*sync_boolcshort_internal"
+  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
+       (match_operator:SI 4 "boolean_operator"
+        [(xor:SI (match_operand:SI 0 "memory_operand" "+Z")
+                 (match_operand:SI 5 "logical_operand" "rK"))
+         (match_operand:SI 1 "gpc_reg_operand" "r")]))
+   (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
+   (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
+   (clobber (match_scratch:CC 6 "=&x"))]
+  "TARGET_POWERPC"
+  "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16"
+  [(set_attr "length" "20")])
+
 (define_insn "*sync_boolc<mode>_internal2"
   [(set (match_operand:GPR 2 "gpc_reg_operand" "=&r")
        (match_operator:GPR 4 "boolean_operator"
index 7e75d30..5b5fce6 100644 (file)
@@ -1,3 +1,9 @@
+2005-05-31  Geoffrey Keating  <geoffk@geoffk.org>
+
+       * lib/target-supports.exp 
+       (check_effective_target_sync_char_short): New.
+       * gcc.dg/sync-2.c: New.
+
 2005-05-31  Zdenek Dvorak  <dvorakz@suse.cz>
 
        PR tree-optimization/21817
@@ -83,6 +89,9 @@
 
 2005-05-29  Geoffrey Keating  <geoffk@apple.com>
 
+       PR c++/17413
+       * g++.dg/template/local5.C: New.
+
        PR target/21761
        * gcc.c-torture/compile/pr21761.c: New.
 
diff --git a/gcc/testsuite/gcc.dg/sync-2.c b/gcc/testsuite/gcc.dg/sync-2.c
new file mode 100644 (file)
index 0000000..41f8ac1
--- /dev/null
@@ -0,0 +1,99 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sync_char_short } */
+
+/* Test functionality of the intrinsics for 'short' and 'char'.  */
+
+extern void abort (void);
+extern void *memcpy (void *, const void *, __SIZE_TYPE__);
+
+static char AI[18];
+static char init_qi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 };
+static char test_qi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 };
+
+static void
+do_qi (void)
+{
+  if (__sync_fetch_and_add(AI+4, 1) != 0)
+    abort ();
+  if (__sync_fetch_and_add(AI+5, 4) != 0)
+    abort ();
+  if (__sync_fetch_and_add(AI+6, 22) != 0)
+    abort ();
+  if (__sync_fetch_and_sub(AI+7, 12) != 0)
+    abort ();
+  if (__sync_fetch_and_and(AI+8, 7) != -1)
+    abort ();
+  if (__sync_fetch_and_or(AI+9, 8) != 0)
+    abort ();
+  if (__sync_fetch_and_xor(AI+10, 9) != 0)
+    abort ();
+  if (__sync_fetch_and_nand(AI+11, 7) != 0)
+    abort ();
+
+  if (__sync_add_and_fetch(AI+12, 1) != 1)
+    abort ();
+  if (__sync_sub_and_fetch(AI+13, 12) != -12)
+    abort ();
+  if (__sync_and_and_fetch(AI+14, 7) != 7)
+    abort ();
+  if (__sync_or_and_fetch(AI+15, 8) != 8)
+    abort ();
+  if (__sync_xor_and_fetch(AI+16, 9) != 9)
+    abort ();
+  if (__sync_nand_and_fetch(AI+17, 7) != 7)
+    abort ();
+}
+
+static short AL[18];
+static short init_hi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 };
+static short test_hi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 };
+
+static void
+do_hi (void)
+{
+  if (__sync_fetch_and_add(AL+4, 1) != 0)
+    abort ();
+  if (__sync_fetch_and_add(AL+5, 4) != 0)
+    abort ();
+  if (__sync_fetch_and_add(AL+6, 22) != 0)
+    abort ();
+  if (__sync_fetch_and_sub(AL+7, 12) != 0)
+    abort ();
+  if (__sync_fetch_and_and(AL+8, 7) != -1)
+    abort ();
+  if (__sync_fetch_and_or(AL+9, 8) != 0)
+    abort ();
+  if (__sync_fetch_and_xor(AL+10, 9) != 0)
+    abort ();
+  if (__sync_fetch_and_nand(AL+11, 7) != 0)
+    abort ();
+
+  if (__sync_add_and_fetch(AL+12, 1) != 1)
+    abort ();
+  if (__sync_sub_and_fetch(AL+13, 12) != -12)
+    abort ();
+  if (__sync_and_and_fetch(AL+14, 7) != 7)
+    abort ();
+  if (__sync_or_and_fetch(AL+15, 8) != 8)
+    abort ();
+  if (__sync_xor_and_fetch(AL+16, 9) != 9)
+    abort ();
+  if (__sync_nand_and_fetch(AL+17, 7) != 7)
+    abort ();
+}
+
+int main()
+{
+  memcpy(AI, init_qi, sizeof(init_qi));
+  memcpy(AL, init_hi, sizeof(init_hi));
+
+  do_qi ();
+  do_hi ();
+
+  if (memcmp (AI, test_qi, sizeof(test_qi)))
+    abort ();
+  if (memcmp (AL, test_hi, sizeof(test_hi)))
+    abort ();
+
+  return 0;
+}