-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Check for all frame instructions in finalize isel. #85945
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-systemz Author: Jonas Paulsson (JonPsson1) ChangesCheck for all frame instructions in finalize isel, not just for the frame setup opcode. This has proved necessary as reported on The probelm seems to be related to the SystemZ handling of multiple select instructions where it scans multiple Select64 and skips the ADJCALLSTACKDOWN pseudo:
FinalizeISel now continues with the new MBB (bb.1.entry), and so doesn't see the ADJCALLSTACKDOWN instruction and fails to set adjustsStack. I think either the SystemZ backend could recognize the frame instructions and either stop the optimization of selects or set AdjustsStack, or the FinalizeISel pass could recognize also the frame destroy opcode. I have chosen the latter as I think this would be generally useful while resolving this particular case. I also think it was a mistake to remove the assertion in PEI - we should rather have both the assertion and the verifier detecting this. Assertion reinstated. @arsenm @uweigand @nathanchance Full diff: https://github.com/llvm/llvm-project/pull/85945.diff 3 Files Affected:
diff --git a/llvm/lib/CodeGen/FinalizeISel.cpp b/llvm/lib/CodeGen/FinalizeISel.cpp
index 978355f8eb1bbf..bf967eac22f177 100644
--- a/llvm/lib/CodeGen/FinalizeISel.cpp
+++ b/llvm/lib/CodeGen/FinalizeISel.cpp
@@ -59,8 +59,7 @@ bool FinalizeISel::runOnMachineFunction(MachineFunction &MF) {
// Set AdjustsStack to true if the instruction selector emits a stack
// frame setup instruction or a stack aligning inlineasm.
- if (MI.getOpcode() == TII->getCallFrameSetupOpcode() ||
- MI.isStackAligningInlineAsm())
+ if (TII->isFrameInstr(MI) || MI.isStackAligningInlineAsm())
MF.getFrameInfo().setAdjustsStack(true);
// If MI is a pseudo, expand it.
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index c942b8a3e26880..eaf96ec5cbde8c 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -372,6 +372,8 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) {
MFI.computeMaxCallFrameSize(MF, &FrameSDOps);
assert(MFI.getMaxCallFrameSize() <= MaxCFSIn &&
"Recomputing MaxCFS gave a larger value.");
+ assert((FrameSDOps.empty() || MF.getFrameInfo().adjustsStack()) &&
+ "AdjustsStack not set in presence of a frame pseudo instruction.");
if (TFI->canSimplifyCallFramePseudos(MF)) {
// If call frames are not being included as part of the stack frame, and
diff --git a/llvm/test/CodeGen/SystemZ/frame-adjstack.ll b/llvm/test/CodeGen/SystemZ/frame-adjstack.ll
new file mode 100644
index 00000000000000..c072a596c7c29c
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/frame-adjstack.ll
@@ -0,0 +1,16 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+;
+; Test that inserting a new MBB near a call during finalize isel custom
+; insertion does not cause all frame instructions to be missed. That would
+; result in a missing to set the AdjustsStack flag.
+
+; CHECK-LABEL: fun
+define void @fun(i1 %cc) {
+ %sel = select i1 %cc, i32 5, i32 0
+ tail call void @input_report_abs(i32 %sel)
+ %sel2 = select i1 %cc, i32 6, i32 1
+ tail call void @input_report_abs(i32 %sel2)
+ ret void
+}
+
+declare void @input_report_abs(i32)
|
3ad8b63
to
c9b89f7
Compare
Thanks, this fixes that reported issue and the whole configuration builds fine for me with this patch. It'll get more intensive testing later today but I will only report back if something breaks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change itself is fine but your description of the problem sounds like there's an iteration bug where the finalizeisel isn't resuming after a block split in the correct point. Is the SystemZ implementation of EmitInstrWithCustomInserter splitting the block incorrectly, or returning the wrong MBB pointer?
The SystemZ EmitInstrWithCustomInserter is scanning forward in MBB in order to handle multiple selects at a time. It however stops on any instruction that clobbers CC (or another pseudo), which would include the call instruction in this case. The logical fix here might be to also stop an a frame setup instruction, but as the isel finalization continues with the new block where the call is, it will also reach the frame destroy instruction. So I think this looks ok. |
c9b89f7
to
d5e3b60
Compare
Check for all frame instructions in finalize isel, not just for the frame setup opcode. This was proven necessary, see llvm#78001 for discussion.
I agree it is slightly troublesome that the code in the backend can return any new MBB while making assumptions about which instructions to skip, and also by that have the FinalizeISelPass skip them. This was trivial as long as FinalizeISel only was interested in pseudos with custom insertion. As this changed, the backends assumption also had to change. In this case the SystemZ backend will be ok as long as the frame destroy opcode is also checked. Maybe EmitInstrWithCustomInserter() should always return an iterator from where FinalizeISel should continue? That way the backend could scan forward a bit and skip things its unaware of while still returning an iterator so that this range is checked by FinalizeISel still. Alternatively, maybe a comment something like this:
|
Check for all frame instructions in finalize isel, not just for the frame setup opcode. This has proved necessary as reported on
#78001 (comment).
The probelm seems to be related to the SystemZ handling of multiple select instructions where it scans multiple Select64 and skips the ADJCALLSTACKDOWN pseudo:
FinalizeISel now continues with the new MBB (bb.1.entry), and so doesn't see the ADJCALLSTACKDOWN instruction and fails to set adjustsStack.
I think either the SystemZ backend could recognize the frame instructions and either stop the optimization of selects or set AdjustsStack, or the FinalizeISel pass could recognize also the frame destroy opcode. I have chosen the latter as I think this would be generally useful while resolving this particular case.
I also think it was a mistake to remove the assertion in PEI - we should rather have both the assertion and the verifier detecting this. Assertion reinstated.
@arsenm @uweigand @nathanchance