Handle more complex GEP based loads and add a few TODOs to deal with

GEP + alloca.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116474 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Christopher 2010-10-14 09:29:41 +00:00
parent bbbdcd453d
commit eae8439771

View File

@ -138,6 +138,7 @@ class ARMFastISel : public FastISel {
bool ARMEmitLoad(EVT VT, unsigned &ResultReg, unsigned Reg, int Offset);
bool ARMEmitStore(EVT VT, unsigned SrcReg, unsigned Reg, int Offset);
bool ARMComputeRegOffset(const Value *Obj, unsigned &Reg, int &Offset);
unsigned ARMSimplifyRegOffset(unsigned Reg, int &Offset);
unsigned ARMMaterializeFP(const ConstantFP *CFP, EVT VT);
unsigned ARMMaterializeInt(const Constant *C, EVT VT);
unsigned ARMMaterializeGV(const GlobalValue *GV, EVT VT);
@ -602,7 +603,39 @@ bool ARMFastISel::ARMComputeRegOffset(const Value *Obj, unsigned &Reg,
return ARMComputeRegOffset(U->getOperand(0), Reg, Offset);
break;
}
case Instruction::GetElementPtr: {
int SavedOffset = Offset;
int TmpOffset = Offset;
// Iterate through the GEP folding the constants into offsets where
// we can.
gep_type_iterator GTI = gep_type_begin(U);
for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end();
i != e; ++i, ++GTI) {
const Value *Op = *i;
if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
const StructLayout *SL = TD.getStructLayout(STy);
unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
TmpOffset += SL->getElementOffset(Idx);
} else {
goto unsupported_gep;
}
}
Offset = TmpOffset;
if (ARMComputeRegOffset(U->getOperand(0), Reg, Offset)) return true;
Offset = SavedOffset;
break;
unsupported_gep:
// errs() << "GEP: " << *U << "\n";
break;
}
case Instruction::Alloca: {
// TODO: Fix this to do intermediate loads, etc.
if (Offset != 0) return false;
const AllocaInst *AI = cast<AllocaInst>(Obj);
DenseMap<const AllocaInst*, int>::iterator SI =
FuncInfo.StaticAllocaMap.find(AI);
@ -629,16 +662,16 @@ bool ARMFastISel::ARMComputeRegOffset(const Value *Obj, unsigned &Reg,
}
// Try to get this in a register if nothing else has worked.
Reg = getRegForValue(Obj);
if (Reg == 0) return false;
if (Reg == 0) Reg = getRegForValue(Obj);
return Reg != 0;
}
unsigned ARMFastISel::ARMSimplifyRegOffset(unsigned Reg, int &Offset) {
// Since the offset may be too large for the load instruction
// get the reg+offset into a register.
// TODO: Verify the additions work, otherwise we'll need to add the
// offset instead of 0 to the instructions and do all sorts of operand
// munging.
// TODO: Optimize this somewhat.
if (Offset != 0) {
if (Reg != ARM::SP && Offset != 0) {
ARMCC::CondCodes Pred = ARMCC::AL;
unsigned PredReg = 0;
@ -652,8 +685,11 @@ bool ARMFastISel::ARMComputeRegOffset(const Value *Obj, unsigned &Reg,
Reg, Reg, Offset, Pred, PredReg,
static_cast<const ARMBaseInstrInfo&>(TII));
}
Offset = 0;
}
return true;
return Reg;
}
bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg,
@ -731,8 +767,10 @@ bool ARMFastISel::SelectLoad(const Instruction *I) {
if (!ARMComputeRegOffset(I->getOperand(0), Reg, Offset))
return false;
unsigned BaseReg = ARMSimplifyRegOffset(Reg, Offset);
unsigned ResultReg;
if (!ARMEmitLoad(VT, ResultReg, Reg, Offset /* 0 */)) return false;
if (!ARMEmitLoad(VT, ResultReg, BaseReg, Offset)) return false;
UpdateValueMap(I, ResultReg);
return true;
@ -808,7 +846,9 @@ bool ARMFastISel::SelectStore(const Instruction *I) {
if (!ARMComputeRegOffset(I->getOperand(1), Reg, Offset))
return false;
if (!ARMEmitStore(VT, SrcReg, Reg, Offset /* 0 */)) return false;
unsigned BaseReg = ARMSimplifyRegOffset(Reg, Offset);
if (!ARMEmitStore(VT, SrcReg, BaseReg, Offset)) return false;
return true;
}