aboutsummaryrefslogtreecommitdiffstats
path: root/meta-xilinx-bsp/recipes-microblaze/gcc/gcc-7/0003-microblaze-sync.md-Correct-behaviour-and-define-side.patch
blob: 9336291ba37a520c84fedb4560e49a3d6e83777f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
From 6c7a10a9e077d0221cc9a6c5f5a6365815c1dca4 Mon Sep 17 00:00:00 2001
From: Nathan Rossi <nathan@nathanrossi.com>
Date: Mon, 12 Jun 2017 00:28:42 +1000
Subject: [PATCH 3/4] microblaze/sync.md: Correct behaviour and define
 side-effects

This change corrects the behaviour with regards to the bool output.
Previously the definition would set the bool operand to true (non-zero)
on failure, specifically at the 'cmp' against the expected operand which
would be set non-zero when the memory != expected value. Instead of
using the bool operand as the compare result use the clobbered %8
operand for temporary comparison result and set the bool operand at the
end of the definition to true (in this case the immediate value of 1).
Also to ensure that the bool operand is 0 in all other cases the first
instruction which is intended as a clear of the carry bit is reused to
set the bool operand to 0 at the same time as clearing the carry bit.
And finally the jump offsets were updated

Additional to the behaviour change this change defines the side-effects
of the atomic_compare_and_swap. Specifically the side effects where the
bool and val operands are modified/set based on the value of the memory
content. This prevents certain optimization behaviour from incorrectly
optimizing away code. An example of this is the snippet below, where in
certain cases the comparison is optimized away entirely.

  mem = 2;
  if (atomic_compare_and_swap(&mem, ...) == 2)
    ...

Signed-off-by: Nathan Rossi <nathan@nathanrossi.com>
Upstream-Status: Unsubmitted
---
 gcc/config/microblaze/sync.md | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/gcc/config/microblaze/sync.md b/gcc/config/microblaze/sync.md
index 8125bd8d63..605a9a969e 100644
--- a/gcc/config/microblaze/sync.md
+++ b/gcc/config/microblaze/sync.md
@@ -18,9 +18,10 @@
 ;; <http://www.gnu.org/licenses/>.
 
 (define_insn "atomic_compare_and_swapsi"
-  [(match_operand:SI 0 "register_operand" "=&d")	;; bool output
-   (match_operand:SI 1 "register_operand" "=&d")	;; val output
-   (match_operand:SI 2 "nonimmediate_operand" "+Q")	;; memory
+  [(set (match_operand:SI 0 "register_operand" "=&d")	;; bool output
+     (match_operand:SI 2 "nonimmediate_operand" "+Q"))	;; memory
+   (set (match_operand:SI 1 "register_operand" "=&d")	;; val output
+     (match_dup 2))
    (match_operand:SI 3 "register_operand" "d")		;; expected value
    (match_operand:SI 4 "register_operand" "d")		;; desired value
    (match_operand:SI 5 "const_int_operand" "")		;; is_weak
@@ -29,15 +30,16 @@
    (clobber (match_scratch:SI 8 "=&d"))]
   ""
   {
-    output_asm_insn ("addc \tr0,r0,r0", operands);
+    output_asm_insn ("add  \t%0,r0,r0", operands);
     output_asm_insn ("lwx  \t%1,%y2,r0", operands);
     output_asm_insn ("addic\t%8,r0,0", operands);
     output_asm_insn ("bnei \t%8,.-8", operands);
-    output_asm_insn ("cmp  \t%0,%1,%3", operands);
-    output_asm_insn ("bnei \t%0,.+16", operands);
+    output_asm_insn ("cmp  \t%8,%1,%3", operands);
+    output_asm_insn ("bnei \t%8,.+20", operands);
     output_asm_insn ("swx  \t%4,%y2,r0", operands);
     output_asm_insn ("addic\t%8,r0,0", operands);
     output_asm_insn ("bnei \t%8,.-28", operands);
+    output_asm_insn ("addi \t%0,r0,1", operands);
     return "";
   }
 )
-- 
2.11.0