Skip to contentSkip to conversation

mm/page_alloc.c: Micro-optimisation Remove unnecessary branch

RFC PATCH Applied [email protected] 3 participants 3 messages Mar 7, 2020 – Mar 8, 2020

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 mm/page_alloc.c: Micro-optimisation Remove unnecessary branch

From: Mateusz Nosek <[email protected]>

Previously if branch condition was false, the assignment was not executed. The assignment can be safely executed even when the condition is false and it is not incorrect as it assigns the value of 'nodemask' to 'ac.nodemask' which already has the same value.

So as the assignment can be executed unconditionally, the branch can be removed.

---
 mm/page_alloc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
mm/page_alloc.c +1 -2
index 79e950d76ffc..75456d04b5c5 100644
@@ -4819,8 +4819,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid,
 	 * Restore the original nodemask if it was potentially replaced with
 	 * &cpuset_current_mems_allowed to optimize the fast-path attempt.
 	 */
-	if (unlikely(ac.nodemask != nodemask))
-		ac.nodemask = nodemask;
+	ac.nodemask = nodemask;
 
 	page = __alloc_pages_slowpath(alloc_mask, order, &ac);
 
Signature · 1 line
2.17.1
maintainer
#1 lore raw
Quoted 15 lines · On Sat, 7 Mar 2020 23:53:35 +0100 [email protected] wrote:

From: Mateusz Nosek <[email protected]>

Previously if branch condition was false, the assignment was not executed. The assignment can be safely executed even when the condition is false and it is not incorrect as it assigns the value of 'nodemask' to 'ac.nodemask' which already has the same value.

So as the assignment can be executed unconditionally, the branch can be removed.

...

mm/page_alloc.c __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid, · line 4823

Quoted 7 lines
mm/page_alloc.c +1 -2
@@ -4819,8 +4819,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid,
 	 * Restore the original nodemask if it was potentially replaced with
 	 * &cpuset_current_mems_allowed to optimize the fast-path attempt.
 	 */
-	if (unlikely(ac.nodemask != nodemask))
-		ac.nodemask = nodemask;
+	ac.nodemask = nodemask;
 

This will now unconditionally dirty the ac.nodemask cacheline, which means that cacheline will need to be written back. If it is truly unlikely that the write was needed then the thinking goes that the test-and-branch is worthwhile, by saving on memory traffic.

At least, I assume that's why the code is the way it is.

I don't know whether this optimisation is valid on a majority of modern platforms. But that's the thinking!

Reviewed-by
#2 lore raw
Quoted 11 lines · Andrew Morton

mm/page_alloc.c __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid, · line 4822

Quoted 3 lines · On Sat, 7 Mar 2020 23:53:35 +0100 [email protected] wrote:
mm/page_alloc.c +1 -2
-	if (unlikely(ac.nodemask != nodemask))
-		ac.nodemask = nodemask;
+	ac.nodemask = nodemask;

This will now unconditionally dirty the ac.nodemask cacheline, which means that cacheline will need to be written back. If it is truly unlikely that the write was needed then the thinking goes that the test-and-branch is worthwhile, by saving on memory traffic.

At least, I assume that's why the code is the way it is.

The line immediately before this hunk is:

        ac.spread_dirty_pages = false;

ac is on-stack and is only 32 bytes. I don't see a reason not to do this.