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);
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);
}
// 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;
Reg, Reg, Offset, Pred, PredReg,
static_cast<const ARMBaseInstrInfo&>(TII));
}
+
+ Offset = 0;
}
- return true;
+
+ return Reg;
}
bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg,
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;
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;
}