Hi

The bug reported a particular test di-longlong64-sync-1.c failing when run on arm-linux-gnueabi with options -mthumb -march=armv5t -O[g,1,2,3] and -mthumb -march=armv6 -O[g,1,2,3].

According to what I could see, the crash was caused because of the explicit VOIDmode argument that was sent to emit_store_flag_force (). Since the comparing argument was a long long, it was being forced into a VOID type register before the comparison (in prepare_cmp_insn()) is done.

As pointed out by Kyrill, there is a comment on emit_store_flag() which says "MODE is the mode to use for OP0 and OP1 should they be CONST_INTs. If it is VOIDmode, they cannot both be CONST_INT". This condition is not true in this case and thus I think it is suitable to change the argument.

Testing done: Checked for regressions on bootstrapped arm-none-linux-gnueabi and arm-none-linux-gnueabihf and added new test cases.

Sudi

ChangeLog entries:

*** gcc/ChangeLog ***

2017-01-04  Sudakshina Das  <sudi....@arm.com>

        PR target/82096
        * optabs.c (expand_atomic_compare_and_swap): Change argument
        to emit_store_flag_force.

*** gcc/testsuite/ChangeLog ***

2017-01-04  Sudakshina Das  <sudi....@arm.com>

        PR target/82096
        * gcc.c-torture/compile/pr82096-1.c: New test.
        * gcc.c-torture/compile/pr82096-2.c: Likwise.
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 225e955..45b018e 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -6295,7 +6295,7 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
       if (cc_reg)
 	{
 	  target_bool = emit_store_flag_force (target_bool, EQ, cc_reg,
-					       const0_rtx, VOIDmode, 0, 1);
+					       const0_rtx, mode, 0, 1);
 	  goto success;
 	}
       goto success_bool_from_val;
@@ -6323,7 +6323,7 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
 
  success_bool_from_val:
    target_bool = emit_store_flag_force (target_bool, EQ, target_oval,
-					expected, VOIDmode, 1, 1);
+					expected, mode, 1, 1);
  success:
   /* Make sure that the oval output winds up where the caller asked.  */
   if (ptarget_oval)
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr82096-1.c b/gcc/testsuite/gcc.c-torture/compile/pr82096-1.c
new file mode 100644
index 0000000..07eb5f6
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr82096-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { arm*-*-* } } } */
+/* { dg-options "-march=armv5t -mthumb -mfloat-abi=soft" } */
+
+static long long AL[24];
+
+int
+check_ok (void)
+{
+  return (__sync_bool_compare_and_swap (AL+1, 0x200000003ll, 0x1234567890ll));
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr82096-2.c b/gcc/testsuite/gcc.c-torture/compile/pr82096-2.c
new file mode 100644
index 0000000..2570b16
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr82096-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { arm*-*-* } } } */
+/* { dg-options "-march=armv6 -mthumb -mfloat-abi=soft" } */
+
+static long long AL[24];
+
+int
+check_ok (void)
+{
+  return (__sync_bool_compare_and_swap (AL+1, 0x200000003ll, 0x1234567890ll));
+}

Reply via email to