[v5,9/9] bio: Fix bio_flagged() so that it can be combined

Message ID 167344732239.2425628.14636562879255014501.stgit@warthog.procyon.org.uk
State New
Headers
Series iov_iter: Add extraction helpers |

Commit Message

David Howells Jan. 11, 2023, 2:28 p.m. UTC
  Fix bio_flagged() so that multiple instances of it can be combined by the
compiler into a single test (arguably, this is a compiler optimisation
issue[1]).

The problem is that it compares the result of the bitwise-AND to zero.
This results in an out-of-line bio_release_page() that looks something
like:

   <+0>:     mov    0x14(%rdi),%eax
   <+3>:     test   $0x1,%al
   <+5>:     jne    0xffffffff816dac53 <bio_release_pages+11>
   <+7>:     test   $0x2,%al
   <+9>:     je     0xffffffff816dac5c <bio_release_pages+20>
   <+11>:    movzbl %sil,%esi
   <+15>:    jmp    0xffffffff816daba1 <__bio_release_pages>
   <+20>:    jmp    0xffffffff81d0b800 <__x86_return_thunk>

Removing the test (it's superfluous as the return type is bool - the
compiler will reduce the return to 0 or 1 as needed) results in:

   <+0>:     testb  $0x3,0x14(%rdi)
   <+4>:     je     0xffffffff816e4af4 <bio_release_pages+15>
   <+6>:     movzbl %sil,%esi
   <+10>:    jmp    0xffffffff816dab7c <__bio_release_pages>
   <+15>:    jmp    0xffffffff81d0b7c0 <__x86_return_thunk>

instead.

The MOVZBL instruction also looks unnecessary[2] - I think it's just
're-booling' the mark_dirty.

Fixes: b7c44ed9d2fc ("block: manipulate bio->bi_flags through helpers")
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Jens Axboe <axboe@kernel.dk>
cc: linux-block@vger.kernel.org
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108370 [1]
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108371 [2]
---

 include/linux/bio.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
  

Comments

Christoph Hellwig Jan. 12, 2023, 7:33 a.m. UTC | #1
I find the subject a little weird.  What you're doing is to clean up
the C version, which also tends to micro-optimize the x86 assembly
generation for a specifi compiler.  Which is good on two counts, so I'm
all for the patch, but I don't really think it's "combining", which
really made me think of testing two flags in one call.
  

Patch

diff --git a/include/linux/bio.h b/include/linux/bio.h
index 1c6f051f6ff2..2e6109b0fca8 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -227,7 +227,7 @@  static inline void bio_cnt_set(struct bio *bio, unsigned int count)
 
 static inline bool bio_flagged(struct bio *bio, unsigned int bit)
 {
-	return (bio->bi_flags & (1U << bit)) != 0;
+	return bio->bi_flags & (1U << bit);
 }
 
 static inline void bio_set_flag(struct bio *bio, unsigned int bit)