Skip to content

Conversation

@sushgokh
Copy link
Contributor

@sushgokh sushgokh commented Oct 8, 2025

wrapping

Shrink wrapping treats a load from constant pool as a stack access. This is not correct. Constants are basically stored in read only section AFAIU. This prevents shrink wrapping from kicking in.

(Related to PR #160257. PR #160257 will be closed.)

wrapping

Shrink wrapping treats a load from constant pool as a stack access. This
is not correct. Constants are basically stored in read only section
AFAIU. This prevents shrink wrapping from kicking in.

(Related to PR llvm#160257. PR llvm#160257 will be closed.)
@llvmbot
Copy link
Member

llvmbot commented Oct 8, 2025

@llvm/pr-subscribers-backend-aarch64

Author: Sushant Gokhale (sushgokh)

Changes

wrapping

Shrink wrapping treats a load from constant pool as a stack access. This is not correct. Constants are basically stored in read only section AFAIU. This prevents shrink wrapping from kicking in.

(Related to PR #160257. PR #160257 will be closed.)


Full diff: https://github.com/llvm/llvm-project/pull/162476.diff

1 Files Affected:

  • (added) llvm/test/CodeGen/AArch64/shrink-wrap-const-pool-access.mir (+71)
diff --git a/llvm/test/CodeGen/AArch64/shrink-wrap-const-pool-access.mir b/llvm/test/CodeGen/AArch64/shrink-wrap-const-pool-access.mir
new file mode 100644
index 0000000000000..ff652a58cae88
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/shrink-wrap-const-pool-access.mir
@@ -0,0 +1,71 @@
+--- |
+ ; RUN: llc -x=mir -simplify-mir -run-pass=shrink-wrap -o - %s | FileCheck %s
+ ; CHECK-NOT: savePoint
+ ; CHECK-NOT: restorePoint
+
+  declare double @foo()
+
+  define double @shrink_wrap_load_from_const_pool(double %q) {
+  entry:
+    %0 = fcmp oeq double %q, 3.125500e+02
+    br i1 %0, label %common.ret, label %if.else
+
+  common.ret:                                       ; preds = %if.else, %entry, %exit1
+    %common.ret.op = phi double [ %3, %exit1 ], [ 0.000000e+00, %entry ], [ 0.000000e+00, %if.else ]
+    ret double %common.ret.op
+
+  if.else:                                          ; preds = %entry
+    %1 = call double @foo()
+    %2 = fcmp oeq double %1, 0.000000e+00
+    br i1 %2, label %exit1, label %common.ret
+
+  exit1:                                            ; preds = %if.else
+    %3 = call double @foo()
+    br label %common.ret
+  }
+...
+---
+name:            shrink_wrap_load_from_const_pool
+tracksRegLiveness: true
+constants:
+  - id:              0
+    value:           'double 3.125500e+02'
+    alignment:       8
+body:             |
+  bb.0.entry:
+    successors: %bb.4(0x50000000), %bb.2(0x30000000)
+    liveins: $d0
+
+    renamable $d1 = COPY $d0
+    renamable $x8 = ADRP target-flags(aarch64-page) %const.0
+    renamable $d2 = LDRDui killed renamable $x8, target-flags(aarch64-pageoff, aarch64-nc) %const.0 :: (load (s64) from constant-pool)
+    renamable $d0 = FMOVD0
+    nofpexcept FCMPDrr killed renamable $d1, killed renamable $d2, implicit-def $nzcv, implicit $fpcr
+    Bcc 1, %bb.2, implicit killed $nzcv
+
+  bb.4:
+    liveins: $d0
+
+  bb.1.common.ret:
+    liveins: $d0
+
+    RET_ReallyLR implicit $d0
+
+  bb.2.if.else:
+    successors: %bb.3(0x50000000), %bb.1(0x30000000)
+
+    ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
+    BL @foo, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $d0
+    ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
+    renamable $d1 = COPY $d0
+    renamable $d0 = FMOVD0
+    nofpexcept FCMPDri killed renamable $d1, implicit-def $nzcv, implicit $fpcr
+    Bcc 1, %bb.1, implicit killed $nzcv
+    B %bb.3
+
+  bb.3.exit1:
+    ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
+    BL @foo, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $d0
+    ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
+    B %bb.1
+...

@@ -0,0 +1,71 @@
--- |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need the LLVM section?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel it can just be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IR section is not needed. But, for someone like me who is not that great with codegen, I feel LLVM IR gives good sense of how the mir code was derived in the first place.
If you still insist, will remove it.

--- |
; RUN: llc -x=mir -simplify-mir -run-pass=shrink-wrap -o - %s | FileCheck %s
; CHECK-NOT: savePoint
; CHECK-NOT: restorePoint
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment on what this is testing and what we are checking here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

value: 'double 3.125500e+02'
alignment: 8
body: |
bb.0.entry:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get rid of the .llvmir_names in the basic block names so that you don't need the LLVM IR section.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keeping the IR names for the reason mentioned above.
Additionally, if the BB name is just like bb.0 or bb.2, MBB->getName() prints blank and this makes debugging difficult. Having names eases this.

@sushgokh sushgokh requested a review from qcolombet October 9, 2025 17:49
}
...
# Following code has a load from constant pool. Accessing constant pool must not
# be considered as a stack access and hence, shrink wrapping must happen.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put the check lines next to this comment (you just need to change the prefix to # if you move them here)
Also, this doesn't tell me why the check lines are what we want to check to match what you mentioned.

At the very least, I would expect that we check that the constant pool is used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this doesn't tell me why the check lines are what we want to check to match what you mentioned.

Have prepended the comment with 'FIXME' so that it better explains the intent. Does that look good?

# must not be considered as a stack access and hence, shrink wrapping must
# happen.
# CHECK-NOT: savePoint
# CHECK-NOT: restorePoint
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a CHECK line that match on the constant pool load.

The CHECK-NOT line still don't tell me why this is testing that shrink wrapping happens/doesn't happen.
I don't remember the implementation details, but assuming that when shrink wrapping happens we create a savePoint or restorePoint basic block, just check for that and say it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to give some context on why I am doing this:
Right now, shrink wrapping is not happening due to this constant pool load. So, by default, it considers entry/exit of the function as save/restore point and it does not emit any information on savePoint/restorePoint BB. e.g. for the concerned test,

...
---
name:            shrink_wrap_load_from_const_pool
alignment:       1
tracksRegLiveness: true
noPhis:          true
isSSA:           true
noVRegs:         true
hasFakeUses:     false
frameInfo:
  maxAlignment:    1
  maxCallFrameSize: 0
constants:
  - id:              0
    value:           'double 3.125500e+02'
    alignment:       8
machineFunctionInfo: {}
body:             |
  bb.0.entry:

Hence, the CHECK-NOT.

Now, once I have a patch to address this issue, we will have savePoint/restorePoint BBs emitted by the pass as you say e.g.

; CHECK:      name:            compiler_pop_stack
 ; CHECK:      frameInfo:
 ; CHECK:        savePoint:
 ; CHECK-NEXT:     - point:           '%bb.1'
 ; CHECK:        restorePoint:
 ; CHECK-NEXT:     - point:           '%bb.7'

Is there still any correction needed? If yes, I am not able to understand what's needed. Maybe you can give example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a CHECK line that match on the constant pool load.

I hope my above reasoning makes sense and thats the reason why I didnt add CHECK for this(anyway this CHECK line is not going to change even after Shrink wrapping)

@davemgreen
Copy link
Collaborator

Hello. Do you have the shrink wrapping patch yet that uses this?

@sushgokh
Copy link
Contributor Author

Hello. Do you have the shrink wrapping patch yet that uses this?

yes, the patch should be just one liner change I believe(have tried the patch with the test case). I am just waiting for someone to approve this test case.

@davemgreen
Copy link
Collaborator

You can put the patch up with both the test and the fix. It will help show that the test is decent.

Copy link
Collaborator

@davemgreen davemgreen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - with #164393 this LGTM.

@sushgokh
Copy link
Contributor Author

Thanks - with #164393 this LGTM.

With #164393 in place, do I still need to commit this PR?

@davemgreen
Copy link
Collaborator

Up to you. Sometimes it is nice to have the tests and the change separately in the git history. Otherwise you can squash them in #164393.

@sushgokh sushgokh merged commit cde4457 into llvm:main Oct 22, 2025
10 checks passed
@sushgokh sushgokh deleted the features/sgokhale/constpoolaccess-does-not-access-stack branch October 22, 2025 11:02
sushgokh added a commit that referenced this pull request Oct 22, 2025
As far as I understand, constant pool access does not access stack and
accesses read-only memory.

This patch considers constant pool access as non-stack access allowing
shrink wrapping to happen in the concerned test.

We should be seeing perf improvement with povray benchmark from
SPEC17(around 12% with -flto -Ofast) after this patch.


An NFC PR #162476 already exists to upload the test before the patch but
approval has got delayed. So, as @davemgreen suggested in that PR, I
have uploaded the test and patch in this single PR to show how test
looks like.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants