[gen] Limit value checks to communication-adjacent events#1845
[gen] Limit value checks to communication-adjacent events#1845ShaleXIONG wants to merge 7 commits into
Conversation
a64b4fc to
e7aa846
Compare
Only mark read values for final-condition checking when the event is adjacent to a communication edge and the location already requires value checking.
e7aa846 to
b38c444
Compare
| let adjacent_with_communication_edge_or_store m = | ||
| adjacent_with_communication_edge m || E.is_insert_store m.edge.E.edge in | ||
| (* Remove the tail until we reach a write adjacent to a communication | ||
| edge or an inserted store. This `coherence` function works together with `check` in | ||
| `top_gen.ml` to decide coherence/write value check. | ||
| Especially when there are two or more writes, the last value | ||
| will be checked. Here we remove the tail which means a local, | ||
| non-communication write will be ignored. *) | ||
| List.fold_right ( fun (loc,n) (new_list,have_seen_communication) -> | ||
| match have_seen_communication,adjacent_with_communication_edge_or_store n with | ||
| | true,_ | _,true -> (loc,n) :: new_list,true | ||
| | false, false -> new_list,false | ||
| ) (do_rec n) ([],false) | ||
| |> fst |
There was a problem hiding this comment.
| let adjacent_with_communication_edge_or_store m = | |
| adjacent_with_communication_edge m || E.is_insert_store m.edge.E.edge in | |
| (* Remove the tail until we reach a write adjacent to a communication | |
| edge or an inserted store. This `coherence` function works together with `check` in | |
| `top_gen.ml` to decide coherence/write value check. | |
| Especially when there are two or more writes, the last value | |
| will be checked. Here we remove the tail which means a local, | |
| non-communication write will be ignored. *) | |
| List.fold_right ( fun (loc,n) (new_list,have_seen_communication) -> | |
| match have_seen_communication,adjacent_with_communication_edge_or_store n with | |
| | true,_ | _,true -> (loc,n) :: new_list,true | |
| | false, false -> new_list,false | |
| ) (do_rec n) ([],false) | |
| |> fst | |
| do_rec n |
There was a problem hiding this comment.
I have changed back here as you suggested here too.
This means to rule out a particular situation diyone7 -arch AArch64 PosWW PosWW Coi -oneloc -obs oo, which previously generates a test as below:
AArch64 a
Generator=diyone7 (version 7.58+1)
Com=Co
Orig=PosWW PosWW Coi
"PosWW PosWW Coi"
{
0:X1=x;
}
P0 ;
MOV W0,#2 ;
STR W0,[X1] ;
MOV W2,#3 ;
STR W2,[X1] ;
MOV W3,#1 ;
STR W3,[X1] ;
exists ([x]=3) (* <- this should be [x]=2 *)
Yet this is a very uncommon or event uninteresting litmus tests. So maybe we should just leave it for the current check [x]=3. I will need to investigate if there are better way to fix this problem possible another PR?
relokin
left a comment
There was a problem hiding this comment.
I think the case of writes needs more work.
Prior to this PR, I get:
$> diyone7 -metadata false -arch AArch64 PosWW PodWW Rfe PodRR Fre
AArch64 MP+posW-po+po
{
0:X1=x; 0:X4=y;
1:X1=x; 1:X4=y;
}
P0 | P1 ;
MOV W0,#1 | LDR W0,[X4] ;
STR W0,[X1] | LDR W2,[X1] ;
MOV W2,#2 | ;
STR W2,[X1] | ;
MOV W3,#1 | ;
STR W3,[X4] | ;
exists ([x]=2 /\ 1:X0=1 /\ 1:X2=0)
This post-condition is not ideal and I don't think it should check the value of [x], but it is acceptable.
After this PR:
$> diyone7 -metadata false -arch AArch64 PosWW PodWW Rfe PodRR Fre
AArch64 MP+posW-po+po
{
0:X1=x; 0:X4=y;
1:X1=x; 1:X4=y;
}
P0 | P1 ;
MOV W0,#1 | LDR W0,[X4] ;
STR W0,[X1] | LDR W2,[X1] ;
MOV W2,#2 | ;
STR W2,[X1] | ;
MOV W3,#1 | ;
STR W3,[X4] | ;
exists ([x]=1 /\ 1:X0=1 /\ 1:X2=0)
We haven't removed the check on [x]. What is worse is that the new check means the post-condition is focusing of the write after write ordering rather than the whole cycle.
| | _ -> | ||
| C.E.is_com n.C.C.prev.C.C.edge | ||
| || C.E.is_com n.C.C.edge | ||
| || n.C.C.evt.C.C.rmw |
There was a problem hiding this comment.
Why are we adding checks for writes generated by atomics?
There was a problem hiding this comment.
In short, the best fix here is to remove both (1) the write check if it is followed by Rfe event and (2) remove the universal write check in rmw (which is your question here).
let consider diyone7 -arch AArch64 DpAddrdW Rfe Amo.Cas PodWW Rfe
AArch64 LB+addr+amo.cas-po
Generator=diyone7 (version 7.58+1)
Prefetch=0:x=F,0:y=W,1:y=F,1:x=W
Com=Rf Rf
Orig=DpAddrdW Rfe Amo.Cas PodWW Rfe
"DpAddrdW Rfe Amo.Cas PodWW Rfe"
{
0:X0=x; 0:X4=y;
1:X0=x; 1:X4=y;
}
P0 | P1 ;
LDR W1,[X0] | MOV W1,#1 ;
EOR W2,W1,W1 | MOV W2,#2 ;
MOV W3,#1 | CAS W1,W2,[X4] ;
STR W3,[X4,W2,SXTW] | MOV W3,#1 ;
| STR W3,[X0] ;
exists ([y]=2 /\ 0:X1=1 /\ 1:X1=1) (* The current `master`, OR if we keep the universal write check on rmw here *)
exists ([y]=1 /\ 0:X1=1 /\ 1:X1=1) (* If we only remove the universal write check on rmw, which I think is incorrect *)
exists (0:X1=1 /\ 1:X1=1) (* remove write check if it is followed by `Rfe` and remove universal write check in `rmw` *)
I think the best fix here is ignore the write event in |
ea7126f to
3c7342d
Compare
|
Jumping in here as I've spent some time last week familiarising myself with the patch to help with the review process. After the current changes, the problem highlighted above still persists (at least for me, hopefully I haven't done something wrong): To me it seems like the issue is more to do with this write that is checked being on the receiving end of that final Have I missed anything @ShaleXIONG ? If not, then perhaps another check on top of what you're already doing, to verify the checked write can be last in coherence order for that location, might be enough? I'm also wondering if it's worth distinguishing further between What do you think? |
Yes you are right here. I am experiencing on the check on |
Ah, didn't know if the last update was targeting this or not, apologies. :) |
Ah unfortunately no. I am still exploring what I can do. Removing the write check associated to |
We only check the write event associated with `Fre` when there is other writes in different processes. This is done by examine the process observation set, `obs` in `compute_cos`.
This change narrows generated final-condition value checks so they focus on events that are adjacent to communication edges. A node is considered adjacent if (1) its incoming edge (
node.prev.edge) or (2) outgoing edge (node.edge) is communication edge, or (3) both the read or write side of an RMW is adjacent to a communication edge.For reads,
check_valuewhen building the cycle incycle.mlis now only enabled when the read is adjacent to a communication edge and the location already requires value checking. This avoids emitting final-condition checks for plain program-order reads that do not witness communication. For example:diyone7 -arch AArch64 PodWW Rfe PodRR PosRR Amo.Swp Coe, now generates:For writes,
coherencewrite collection incycle.mlnow trims trailing local writes until it reaches either:store. Note thestoreedge always add an extra write to the beginning of the thread hence it should be considered adjacent to communication edge.This means the final write checks will ignore local writes inside a thread but only focus on those adjacent to communication edges. For example,
diyone7 -arch AArch64 PosWW PosWW Coi -oneloc -obs ooThis technical change also leads to more tests in
diy7, becausediy7by default only generates tests with up to 2 writes per locations, while now they are writes only adjacent to communication edges. All the new tests are forbidden.