On Sat, Sep 21, 2019 at 12:12:33AM +0100, Al Viro wrote: > Neither hlist_add_before() nor hlist_add_behind() should ever > be called with both arguments pointing to the same hlist_node. > However, gcc doesn't know that, so it ends up with pointless reloads. > AFAICS, the following generates better code, is obviously equivalent > in case when arguments are different and actually even in case when > they are same, the end result is identical (if the hlist hadn't been > corrupted even earlier than that). > > Objections? > > Signed-off-by: Al Viro <v...@zeniv.linux.org.uk>
*gyah* git diff >/tmp/y1 <build> <fix a braino> <test> scp-out /tmp/y1 <send mail with the original diff> <several hours later: reread the sent mail> My apologies ;-/ Correct diff follows: diff --git a/include/linux/list.h b/include/linux/list.h index 85c92555e31f..5c84383675bc 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -793,21 +793,21 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next) { - n->pprev = next->pprev; + struct hlist_node **p = n->pprev = next->pprev; n->next = next; next->pprev = &n->next; - WRITE_ONCE(*(n->pprev), n); + WRITE_ONCE(*p, n); } static inline void hlist_add_behind(struct hlist_node *n, struct hlist_node *prev) { - n->next = prev->next; + struct hlist_node *p = n->next = prev->next; prev->next = n; n->pprev = &prev->next; - if (n->next) - n->next->pprev = &n->next; + if (p) + p->pprev = &n->next; } /* after that we'll appear to be on some hlist and hlist_del will work */