-
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
//===----------------------------------------------------------------------===// | ||
|
||
#include "X86RegisterInfo.h" | ||
#include "MCTargetDesc/X86BaseInfo.h" | ||
#include "X86FrameLowering.h" | ||
#include "X86MachineFunctionInfo.h" | ||
#include "X86Subtarget.h" | ||
|
@@ -21,8 +22,8 @@ | |
#include "llvm/ADT/SmallSet.h" | ||
#include "llvm/CodeGen/LiveRegMatrix.h" | ||
#include "llvm/CodeGen/MachineFrameInfo.h" | ||
#include "llvm/CodeGen/MachineFunction.h" | ||
#include "llvm/CodeGen/MachineRegisterInfo.h" | ||
#include "llvm/CodeGen/RegisterScavenging.h" | ||
#include "llvm/CodeGen/TargetFrameLowering.h" | ||
#include "llvm/CodeGen/TargetInstrInfo.h" | ||
#include "llvm/CodeGen/TileShapeInfo.h" | ||
|
@@ -907,7 +908,7 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, | |
int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); | ||
|
||
// Determine base register and offset. | ||
int FIOffset; | ||
int64_t FIOffset; | ||
Register BasePtr; | ||
if (MI.isReturn()) { | ||
assert((!hasStackRealignment(MF) || | ||
|
@@ -958,11 +959,37 @@ 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(); | ||
int64_t Offset = FIOffset + Imm; | ||
bool FitsIn32Bits = isInt<32>(Offset); | ||
// If the offset will not fit in a 32-bit displacement, then for 64-bit | ||
// targets, scavenge a register to hold it. Otherwise... | ||
if (Is64Bit && !FitsIn32Bits) { | ||
assert(RS && "RegisterScavenger was NULL"); | ||
const X86InstrInfo *TII = MF.getSubtarget<X86Subtarget>().getInstrInfo(); | ||
const DebugLoc &DL = MI.getDebugLoc(); | ||
|
||
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; | ||
Comment on lines
+972
to
+986
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really need all this manual work with
I'm not very familiar with There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 Looking at the mechanism in Have I misunderstood your suggestion or what is needed to implement it? Is this still the preferred approach in contrast to There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 |
||
} | ||
|
||
// ... for 32-bit targets, this is a bug! | ||
if (!Is64Bit && !FitsIn32Bits) | ||
MI.emitGenericError(("64-bit offset calculated but target is 32-bit")); | ||
|
||
Comment on lines
+989
to
+992
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion @phoebewang! I've implemented that in #152239. |
||
if (Offset != 0 || !tryOptimizeLEAtoMOV(II)) | ||
wesleywiser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
MI.getOperand(FIOperandNum + 3).ChangeToImmediate(Offset); | ||
} else { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --no_x86_scrub_sp --version 4 | ||
; RUN: llc -O0 -mtriple=x86_64 -mattr=+avx512f < %s | FileCheck %s --check-prefix=CHECK | ||
define void @f(i16 %LGV2, i1 %LGV3) { | ||
; CHECK-LABEL: f: | ||
; CHECK: # %bb.0: # %BB | ||
; CHECK-NEXT: subq $2147483528, %rsp # imm = 0x7FFFFF88 | ||
; CHECK-NEXT: .cfi_def_cfa_offset 2147483536 | ||
; CHECK-NEXT: movb %sil, %cl | ||
; CHECK-NEXT: movw %di, %ax | ||
; CHECK-NEXT: movswq %ax, %rax | ||
; CHECK-NEXT: andb $1, %cl | ||
; CHECK-NEXT: movabsq $-2147483768, %rdx # imm = 0xFFFFFFFF7FFFFF88 | ||
; CHECK-NEXT: movb %cl, (%rsp,%rdx) | ||
; CHECK-NEXT: addq $2147483528, %rsp # imm = 0x7FFFFF88 | ||
; CHECK-NEXT: .cfi_def_cfa_offset 8 | ||
; CHECK-NEXT: retq | ||
BB: | ||
%A = alloca i1, i33 2147483648, align 1 | ||
%G = getelementptr i1, ptr %A, i16 %LGV2 | ||
%G4 = getelementptr i1, ptr %G, i32 -2147483648 | ||
store i1 %LGV3, ptr %G4, align 1 | ||
ret void | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 | ||
; RUN: llc < %s -mtriple=x86_64 -O=0 | FileCheck %s | ||
@G = global i8 0 | ||
|
||
; Regression test for PR113856 - incorrect FastISel assert | ||
|
||
define i32 @main() { | ||
; CHECK-LABEL: main: | ||
; CHECK: # %bb.0: | ||
; CHECK-NEXT: movabsq $-2147483652, %rax # imm = 0xFFFFFFFF7FFFFFFC | ||
; CHECK-NEXT: movl $0, (%rsp,%rax) | ||
; CHECK-NEXT: xorl %eax, %eax | ||
; CHECK-NEXT: retq | ||
%1 = alloca i32, align 4 | ||
%G = getelementptr i8, ptr %1, i32 -2147483648 | ||
store i32 0, ptr %G, align 4 | ||
ret i32 0 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
; RUN: not llc < %s -mtriple=i686 -filetype=null 2>&1 | FileCheck %s -check-prefix=ERR-i686 | ||
; RUN: llc < %s -mtriple=x86_64 | FileCheck %s -check-prefix=x86_64 | ||
|
||
wesleywiser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
; Regression test for #121932, #113856, #106352, #69365, #25051 which are caused by | ||
; an incorrectly written assertion for 64-bit offsets when compiling for 32-bit X86. | ||
|
||
define i32 @main() #0 { | ||
; ERR-i686: error: <unknown>:0:0: 64-bit offset calculated but target is 32-bit | ||
; | ||
; x86_64-LABEL: main: | ||
; x86_64: # %bb.0: # %entry | ||
; x86_64-NEXT: movl $4294967192, %eax # imm = 0xFFFFFF98 | ||
; x86_64-NEXT: subq %rax, %rsp | ||
; x86_64-NEXT: .cfi_def_cfa_offset 4294967200 | ||
; x86_64-NEXT: movabsq $3221225318, %rax # imm = 0xBFFFFF66 | ||
; x86_64-NEXT: movb $32, (%rsp,%rax) | ||
; x86_64-NEXT: movb $33, 2147483494(%rsp) | ||
; x86_64-NEXT: movb $34, 1073741670(%rsp) | ||
; x86_64-NEXT: movb $35, -154(%rsp) | ||
; x86_64-NEXT: xorl %eax, %eax | ||
; x86_64-NEXT: movl $4294967192, %ecx # imm = 0xFFFFFF98 | ||
; x86_64-NEXT: addq %rcx, %rsp | ||
; x86_64-NEXT: .cfi_def_cfa_offset 8 | ||
; x86_64-NEXT: retq | ||
entry: | ||
%a = alloca [1073741824 x i8], align 16 | ||
%b = alloca [1073741824 x i8], align 16 | ||
%c = alloca [1073741824 x i8], align 16 | ||
%d = alloca [1073741824 x i8], align 16 | ||
|
||
%arrayida = getelementptr inbounds [1073741824 x i8], ptr %a, i64 0, i64 -42 | ||
%arrayidb = getelementptr inbounds [1073741824 x i8], ptr %b, i64 0, i64 -42 | ||
%arrayidc = getelementptr inbounds [1073741824 x i8], ptr %c, i64 0, i64 -42 | ||
%arrayidd = getelementptr inbounds [1073741824 x i8], ptr %d, i64 0, i64 -42 | ||
|
||
store i8 32, ptr %arrayida, align 2 | ||
store i8 33, ptr %arrayidb, align 2 | ||
store i8 34, ptr %arrayidc, align 2 | ||
store i8 35, ptr %arrayidd, align 2 | ||
|
||
ret i32 0 | ||
} | ||
|
||
; Same test as above but for an anonymous function. | ||
define i32 @0() #0 { | ||
wesleywiser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
; ERR-i686: error: <unknown>:0:0: 64-bit offset calculated but target is 32-bit | ||
; | ||
; x86_64-LABEL: __unnamed_1: | ||
; x86_64: # %bb.0: # %entry | ||
; x86_64-NEXT: movl $4294967192, %eax # imm = 0xFFFFFF98 | ||
; x86_64-NEXT: subq %rax, %rsp | ||
; x86_64-NEXT: .cfi_def_cfa_offset 4294967200 | ||
; x86_64-NEXT: movabsq $3221225318, %rax # imm = 0xBFFFFF66 | ||
; x86_64-NEXT: movb $32, (%rsp,%rax) | ||
; x86_64-NEXT: movb $33, 2147483494(%rsp) | ||
; x86_64-NEXT: movb $34, 1073741670(%rsp) | ||
; x86_64-NEXT: movb $35, -154(%rsp) | ||
; x86_64-NEXT: xorl %eax, %eax | ||
; x86_64-NEXT: movl $4294967192, %ecx # imm = 0xFFFFFF98 | ||
; x86_64-NEXT: addq %rcx, %rsp | ||
; x86_64-NEXT: .cfi_def_cfa_offset 8 | ||
; x86_64-NEXT: retq | ||
entry: | ||
%a = alloca [1073741824 x i8], align 16 | ||
%b = alloca [1073741824 x i8], align 16 | ||
%c = alloca [1073741824 x i8], align 16 | ||
%d = alloca [1073741824 x i8], align 16 | ||
|
||
%arrayida = getelementptr inbounds [1073741824 x i8], ptr %a, i64 0, i64 -42 | ||
%arrayidb = getelementptr inbounds [1073741824 x i8], ptr %b, i64 0, i64 -42 | ||
%arrayidc = getelementptr inbounds [1073741824 x i8], ptr %c, i64 0, i64 -42 | ||
%arrayidd = getelementptr inbounds [1073741824 x i8], ptr %d, i64 0, i64 -42 | ||
|
||
store i8 32, ptr %arrayida, align 2 | ||
store i8 33, ptr %arrayidb, align 2 | ||
store i8 34, ptr %arrayidc, align 2 | ||
store i8 35, ptr %arrayidd, align 2 | ||
|
||
ret i32 0 | ||
} | ||
|
||
wesleywiser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
attributes #0 = { optnone noinline } |
Uh oh!
There was an error while loading. Please reload this page.