-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[X86] Correct 32-bit immediate assertion and fix 64-bit lowering for huge frame offsets #123872
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
[X86] Correct 32-bit immediate assertion and fix 64-bit lowering for huge frame offsets #123872
Conversation
@llvm/pr-subscribers-backend-x86 Author: Wesley Wiser (wesleywiser) ChangesThe assertion previously did not work correctly because the operand was being truncated to an Change the assertion into a a reported error as suggested in #101840 (comment) by @arsenm Full diff: https://github.com/llvm/llvm-project/pull/123872.diff 1 Files Affected:
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 4faf8bca4f9e02..8a35de5ca98f11 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -965,11 +965,10 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
}
if (MI.getOperand(FIOperandNum+3).isImm()) {
- // Offset is a 32-bit integer.
- int Imm = (int)(MI.getOperand(FIOperandNum + 3).getImm());
- int Offset = FIOffset + Imm;
- assert((!Is64Bit || isInt<32>((long long)FIOffset + Imm)) &&
- "Requesting 64-bit offset in 32-bit immediate!");
+ int64_t Imm = MI.getOperand(FIOperandNum + 3).getImm();
+ int Offset = FIOffset + (int)Imm;
+ if (!Is64Bit && !isInt<32>((int64_t)FIOffset + Imm))
+ MI.emitGenericError(("Requesting 64-bit offset in 32-bit immediate: " + MF.getName()).str());
if (Offset != 0 || !tryOptimizeLEAtoMOV(II))
MI.getOperand(FIOperandNum + 3).ChangeToImmediate(Offset);
} else {
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
c82b6db
to
0dd16eb
Compare
Maybe the IR from #121932 could be added as test define dso_local i32 @main() #0 {
entry:
%x = alloca [2147483647 x i8], align 16
%arrayidx = getelementptr inbounds [2147483647 x i8], ptr %x, i64 0, i64 -42
store i8 33, ptr %arrayidx, align 2
ret i32 0
}
attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } |
0dd16eb
to
ecc78a2
Compare
Please can you add test coverage for #113856 as well - note its a fast-isel bug |
ecc78a2
to
79d4afd
Compare
Thanks for finding those issues! I've added a test to cover #113856. |
79d4afd
to
58e318d
Compare
58e318d
to
fd0853c
Compare
fd0853c
to
54a7703
Compare
Hi @RKSimon, just a friendly ping for review when you get a chance. Thanks! |
Hi @RKSimon, just wanted to remind you that I think this is ready for another round of review when you have some time. Thank you! |
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.
LGTM with one minor @phoebewang @arsenm any further comments?
If I read the code correctly, it not only emit error for 32-bit but also fix the bug in 64-bit. The title and description don't mention the latter? |
RS->enterBasicBlockEnd(MBB); | ||
RS->backward(std::next(II)); | ||
|
||
Register ScratchReg = RS->scavengeRegisterBackwards( | ||
X86::GR64RegClass, II, /*RestoreAfter=*/false, /*SPAdj=*/0, | ||
/*AllowSpill=*/true); | ||
assert(ScratchReg != 0 && "scratch reg was 0"); | ||
RS->setRegUsed(ScratchReg); | ||
|
||
BuildMI(MBB, II, DL, TII->get(X86::MOV64ri), ScratchReg).addImm(Offset); | ||
|
||
MI.getOperand(FIOperandNum + 3).setImm(0); | ||
MI.getOperand(FIOperandNum + 2).setReg(ScratchReg); | ||
|
||
return false; |
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.
Do we really need all this manual work with RegisterScavenging
? There is already an existing mechanism that is used for AArch64
. All we need here is to create a virtual register and define
bool X86RegisterInfo::requiresRegisterScavenging(
const MachineFunction &MF) const {
return !isInt<32>(MF.getFrameInfo().estimateStackSize(MF));
}
bool X86RegisterInfo::requiresFrameIndexScavenging(
const MachineFunction &MF) const {
return true;
}
I'm not very familiar with RegisterScavenging
, is the compilation time a concern here? Also, setting the requiresFrameIndexScavenging
to true allows to avoid unnecessary preemptive stack allocation in X86FrameLowering
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.
Thanks for the feedback! I'm not super familiar with this code and I was pointed to using RegisterScavenging
as a way to solve the issue of needing a scratch register here.
Looking at the mechanism in AArch64
, I think X86
is not currently set up to use the same thing. Locally, in addition to requiresFrameIndexScavenging
, I also needed to add an override to enable requiresVirtualBaseRegisters
for LocalStackSlotAllocation
to kick in. With that done, I also needed to override at least needsFrameBaseReg
, isFrameOffsetLegal
and materializeFrameBaseRegister
which is quite a bit more code than the few lines needed here to use RegisterScavenging
manually.
Have I misunderstood your suggestion or what is needed to implement it? Is this still the preferred approach in contrast to RegisterScavenging
directly?
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.
Hi @e-kud, just pinging you in case you missed the above message. Thanks!
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.
This is...complicated and requires a lot of other context to consider using or not. It's well beyond the scope of this patch
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.
lgtm with error message phrasing tweak
The assertion previously did not work correctly because the operand was being truncated to an `int` prior to comparison.
Enable RegisterScavenging for X86 so that we can scavenge a register to use if the frame is very, very large or if the displacement for an instruction is too large and we need to rewrite it to use the scavenged register.
54a7703
to
00bea8d
Compare
At this point, I believe all review feedback has been responded to and CI is green. If there's no other feedback, I would appreciate someone merging for me as I do not have merge rights. Thanks! |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/16/builds/23760 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/187/builds/8820 Here is the relevant piece of the build log for the reference
|
Looks like the |
// ... for 32-bit targets, this is a bug! | ||
if (!Is64Bit && !FitsIn32Bits) | ||
MI.emitGenericError(("64-bit offset calculated but target is 32-bit")); | ||
|
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.
I think the issue is that while we report an error here, we leave the operand in the instruction which the verifier then reports. What's the right approach to resolve that?
I guess we could replace the overside operand with a saturated value or 0
or something. Or perhaps replace the entire instruction with a trap, etc.
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.
Trap would be nicer, see #124217
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.
Thanks for the suggestion @phoebewang! I've implemented that in #152239.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/46/builds/21134 Here is the relevant piece of the build log for the reference
|
Based on the discussion in #151860 looks like this needs to be reverted for now. Is someone looking into that? |
@Xazax-hun @wesleywiser @abhishek-kaushik22 this has now been reverted |
…4-bit lowering for huge frame offsets" (#151975) Reverts llvm/llvm-project#123872 - this is breaking on EXPENSIVE_CHECKS builds Co-authored-by: Abhishek Kaushik <abhishek.kaushik@intel.com>
…huge frame offsets (llvm#123872) The assertion previously did not work correctly because the operand was being truncated to an `int` prior to comparison. Change the assertion into a a reported error as suggested in llvm#101840 (comment) by @arsenm Finally, fix the lowering on 64-bit targets so that offsets larger than 32-bit are correctly addressed and add tests for various reported issues.
…huge frame offsets (llvm#123872) The assertion previously did not work correctly because the operand was being truncated to an `int` prior to comparison. Change the assertion into a a reported error as suggested in llvm#101840 (comment) by @arsenm Finally, fix the lowering on 64-bit targets so that offsets larger than 32-bit are correctly addressed and add tests for various reported issues.
…huge frame offsets (llvm#123872) The assertion previously did not work correctly because the operand was being truncated to an `int` prior to comparison. Change the assertion into a a reported error as suggested in llvm#101840 (comment) by @arsenm Finally, fix the lowering on 64-bit targets so that offsets larger than 32-bit are correctly addressed and add tests for various reported issues.
…huge frame offsets (llvm#123872) The assertion previously did not work correctly because the operand was being truncated to an `int` prior to comparison. Change the assertion into a a reported error as suggested in llvm#101840 (comment) by @arsenm Finally, fix the lowering on 64-bit targets so that offsets larger than 32-bit are correctly addressed and add tests for various reported issues.
…ing for huge frame offsets" (llvm#151975) Reverts llvm#123872 - this is breaking on EXPENSIVE_CHECKS builds Co-authored-by: Abhishek Kaushik <abhishek.kaushik@intel.com>
The assertion previously did not work correctly because the operand was being truncated to an
int
prior to comparison.Change the assertion into a a reported error as suggested in #101840 (comment) by @arsenm
Finally, fix the lowering on 64-bit targets so that offsets larger than 32-bit are correctly addressed and add tests for various reported issues.