forked from OSchip/llvm-project
[AArch64] Fix offset calculation
r374772 changed Offset to be an int64_t but left NewOffset as an int. Scale is unsigned, so in the calculation `Offset - NewOffset * Scale`, `NewOffset * Scale` was promoted to unsigned and was then zero-extended to 64 bits, leading to an incorrect computation which manifested as an out-of-memory when building the Swift standard library for Android aarch64. Promote NewOffset to int64_t to fix this, and promote EmittableOffset as well, since its one user passes it to a function which takes an int64_t anyway. Test case based on a suggestion by Sander de Smalen! Differential Revision: https://reviews.llvm.org/D69018 llvm-svn: 375043
This commit is contained in:
parent
34ed76e180
commit
6d1891c508
|
@ -3368,7 +3368,7 @@ int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI,
|
||||||
StackOffset &SOffset,
|
StackOffset &SOffset,
|
||||||
bool *OutUseUnscaledOp,
|
bool *OutUseUnscaledOp,
|
||||||
unsigned *OutUnscaledOp,
|
unsigned *OutUnscaledOp,
|
||||||
int *EmittableOffset) {
|
int64_t *EmittableOffset) {
|
||||||
// Set output values in case of early exit.
|
// Set output values in case of early exit.
|
||||||
if (EmittableOffset)
|
if (EmittableOffset)
|
||||||
*EmittableOffset = 0;
|
*EmittableOffset = 0;
|
||||||
|
@ -3430,7 +3430,7 @@ int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI,
|
||||||
"Cannot have remainder when using unscaled op");
|
"Cannot have remainder when using unscaled op");
|
||||||
|
|
||||||
assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
|
assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
|
||||||
int NewOffset = Offset / Scale;
|
int64_t NewOffset = Offset / Scale;
|
||||||
if (MinOff <= NewOffset && NewOffset <= MaxOff)
|
if (MinOff <= NewOffset && NewOffset <= MaxOff)
|
||||||
Offset = Remainder;
|
Offset = Remainder;
|
||||||
else {
|
else {
|
||||||
|
@ -3471,7 +3471,7 @@ bool llvm::rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NewOffset;
|
int64_t NewOffset;
|
||||||
unsigned UnscaledOp;
|
unsigned UnscaledOp;
|
||||||
bool UseUnscaledOp;
|
bool UseUnscaledOp;
|
||||||
int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
|
int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
|
||||||
|
|
|
@ -335,7 +335,7 @@ enum AArch64FrameOffsetStatus {
|
||||||
int isAArch64FrameOffsetLegal(const MachineInstr &MI, StackOffset &Offset,
|
int isAArch64FrameOffsetLegal(const MachineInstr &MI, StackOffset &Offset,
|
||||||
bool *OutUseUnscaledOp = nullptr,
|
bool *OutUseUnscaledOp = nullptr,
|
||||||
unsigned *OutUnscaledOp = nullptr,
|
unsigned *OutUnscaledOp = nullptr,
|
||||||
int *EmittableOffset = nullptr);
|
int64_t *EmittableOffset = nullptr);
|
||||||
|
|
||||||
static inline bool isUncondBranchOpcode(int Opc) { return Opc == AArch64::B; }
|
static inline bool isUncondBranchOpcode(int Opc) { return Opc == AArch64::B; }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s
|
||||||
|
---
|
||||||
|
name: framelayout_offset_immediate_change
|
||||||
|
tracksRegLiveness: true
|
||||||
|
fixedStack:
|
||||||
|
- { id: 0, offset: 0, size: 1}
|
||||||
|
body: |
|
||||||
|
bb.0:
|
||||||
|
$x0 = LDURXi %fixed-stack.0, -264
|
||||||
|
RET_ReallyLR
|
||||||
|
...
|
||||||
|
# CHECK: name: framelayout_offset_immediate_change
|
||||||
|
# CHECK: body: |
|
||||||
|
# CHECK-NEXT: bb.0:
|
||||||
|
# CHECK-NEXT: $x8 = SUBXri $sp, 8, 0
|
||||||
|
# CHECK-NEXT: $x0 = LDURXi killed $x8, -256
|
||||||
|
# CHECK-NEXT: RET_ReallyLR
|
Loading…
Reference in New Issue