forked from OSchip/llvm-project
[FastISel][AArch64] Fix load/store with frame indices.
At higher optimization levels the LLVM IR may contain more complex patterns for loads/stores from/to frame indices. The 'computeAddress' function wasn't able to handle this and triggered an assertion. This fix extends the possible addressing modes for frame indices. This fixes rdar://problem/18783298. llvm-svn: 220700
This commit is contained in:
parent
4f8f0c5aa2
commit
6de054a25a
|
@ -78,11 +78,9 @@ class AArch64FastISel final : public FastISel {
|
|||
return Base.Reg;
|
||||
}
|
||||
void setOffsetReg(unsigned Reg) {
|
||||
assert(isRegBase() && "Invalid offset register access!");
|
||||
OffsetReg = Reg;
|
||||
}
|
||||
unsigned getOffsetReg() const {
|
||||
assert(isRegBase() && "Invalid offset register access!");
|
||||
return OffsetReg;
|
||||
}
|
||||
void setFI(unsigned FI) {
|
||||
|
@ -810,22 +808,23 @@ bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr, Type *Ty)
|
|||
}
|
||||
} // end switch
|
||||
|
||||
if (Addr.getReg()) {
|
||||
if (!Addr.getOffsetReg()) {
|
||||
unsigned Reg = getRegForValue(Obj);
|
||||
if (!Reg)
|
||||
return false;
|
||||
Addr.setOffsetReg(Reg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (Addr.isRegBase() && !Addr.getReg()) {
|
||||
unsigned Reg = getRegForValue(Obj);
|
||||
if (!Reg)
|
||||
return false;
|
||||
Addr.setReg(Reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned Reg = getRegForValue(Obj);
|
||||
if (!Reg)
|
||||
return false;
|
||||
Addr.setReg(Reg);
|
||||
return true;
|
||||
if (!Addr.getOffsetReg()) {
|
||||
unsigned Reg = getRegForValue(Obj);
|
||||
if (!Reg)
|
||||
return false;
|
||||
Addr.setOffsetReg(Reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AArch64FastISel::computeCallAddress(const Value *V, Address &Addr) {
|
||||
|
@ -942,8 +941,7 @@ bool AArch64FastISel::simplifyAddress(Address &Addr, MVT VT) {
|
|||
// Cannot encode an offset register and an immediate offset in the same
|
||||
// instruction. Fold the immediate offset into the load/store instruction and
|
||||
// emit an additonal add to take care of the offset register.
|
||||
if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.isRegBase() &&
|
||||
Addr.getOffsetReg())
|
||||
if (!ImmediateOffsetNeedsLowering && Addr.getOffset() && Addr.getOffsetReg())
|
||||
RegisterOffsetNeedsLowering = true;
|
||||
|
||||
// Cannot encode zero register as base.
|
||||
|
@ -953,7 +951,8 @@ bool AArch64FastISel::simplifyAddress(Address &Addr, MVT VT) {
|
|||
// If this is a stack pointer and the offset needs to be simplified then put
|
||||
// the alloca address into a register, set the base type back to register and
|
||||
// continue. This should almost never happen.
|
||||
if (ImmediateOffsetNeedsLowering && Addr.isFIBase()) {
|
||||
if ((ImmediateOffsetNeedsLowering || Addr.getOffsetReg()) && Addr.isFIBase())
|
||||
{
|
||||
unsigned ResultReg = createResultReg(&AArch64::GPR64spRegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::ADDXri),
|
||||
ResultReg)
|
||||
|
@ -1050,10 +1049,8 @@ void AArch64FastISel::addLoadStoreOperands(Address &Addr,
|
|||
MIB.addReg(Addr.getOffsetReg());
|
||||
MIB.addImm(IsSigned);
|
||||
MIB.addImm(Addr.getShift() != 0);
|
||||
} else {
|
||||
MIB.addReg(Addr.getReg());
|
||||
MIB.addImm(Offset);
|
||||
}
|
||||
} else
|
||||
MIB.addReg(Addr.getReg()).addImm(Offset);
|
||||
}
|
||||
|
||||
if (MMO)
|
||||
|
|
|
@ -599,3 +599,29 @@ define i64 @kill_reg(i64 %a) {
|
|||
ret i64 %5
|
||||
}
|
||||
|
||||
define void @store_fi(i64 %i) {
|
||||
; CHECK-LABEL: store_fi
|
||||
; CHECK: mov [[REG:x[0-9]+]], sp
|
||||
; CHECK: str {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
|
||||
%1 = alloca [8 x i32]
|
||||
%2 = ptrtoint [8 x i32]* %1 to i64
|
||||
%3 = mul i64 %i, 4
|
||||
%4 = add i64 %2, %3
|
||||
%5 = inttoptr i64 %4 to i32*
|
||||
store i32 47, i32* %5, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @load_fi(i64 %i) {
|
||||
; CHECK-LABEL: load_fi
|
||||
; CHECK: mov [[REG:x[0-9]+]], sp
|
||||
; CHECK: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
|
||||
%1 = alloca [8 x i32]
|
||||
%2 = ptrtoint [8 x i32]* %1 to i64
|
||||
%3 = mul i64 %i, 4
|
||||
%4 = add i64 %2, %3
|
||||
%5 = inttoptr i64 %4 to i32*
|
||||
%6 = load i32* %5, align 4
|
||||
ret i32 %6
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue