diff options
author | Eric Christopher <echristo@apple.com> | 2010-10-14 09:29:41 +0000 |
---|---|---|
committer | Eric Christopher <echristo@apple.com> | 2010-10-14 09:29:41 +0000 |
commit | eae8439771a9dafd09e32026ca42bb81cceb2af1 (patch) | |
tree | 232a5b04b0e6866a269ef2a158ee0c70597c8e2b | |
parent | bbbdcd453d22258cb4dd217eddf016668fcebf84 (diff) |
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
-rw-r--r-- | lib/Target/ARM/ARMFastISel.cpp | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index 46f707ca95..e9acb7fa2c 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -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; } |