[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:
Juergen Ributzka 2014-10-27 18:21:58 +00:00
parent 4f8f0c5aa2
commit 6de054a25a
2 changed files with 46 additions and 23 deletions

View File

@ -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)

View File

@ -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
}