[llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Feb 22 01:05:01 PST 2004
Changes in directory llvm/lib/Target/X86:
InstSelectSimple.cpp updated: 1.164 -> 1.165
---
Log message:
Completely rewrite how getelementptr instructions are expanded. This has two
(minor) benefits right now:
1. An extra dummy MOVrr32 is gone. This move would often be coallesced by
both allocators anyway.
2. The code now uses the gep_type_iterator to walk the gep, which should future
proof it a bit. It still assumes that array indexes are Longs though.
These don't really justify rewriting the code. The big benefit will come later
though.
---
Diffs of the changes: (+70 -42)
Index: llvm/lib/Target/X86/InstSelectSimple.cpp
diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.164 llvm/lib/Target/X86/InstSelectSimple.cpp:1.165
--- llvm/lib/Target/X86/InstSelectSimple.cpp:1.164 Tue Feb 17 00:28:19 2004
+++ llvm/lib/Target/X86/InstSelectSimple.cpp Sun Feb 22 01:04:00 2004
@@ -27,6 +27,7 @@
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/CFG.h"
using namespace llvm;
@@ -2211,38 +2212,54 @@
Value *Src, User::op_iterator IdxBegin,
User::op_iterator IdxEnd, unsigned TargetReg) {
const TargetData &TD = TM.getTargetData();
- const Type *Ty = Src->getType();
- unsigned BaseReg = getReg(Src, MBB, IP);
- // GEPs have zero or more indices; we must perform a struct access
- // or array access for each one.
- for (GetElementPtrInst::op_iterator oi = IdxBegin,
- oe = IdxEnd; oi != oe; ++oi) {
- Value *idx = *oi;
- unsigned NextReg = BaseReg;
- if (const StructType *StTy = dyn_cast<StructType>(Ty)) {
- // It's a struct access. idx is the index into the structure,
- // which names the field. This index must have ubyte type.
- const ConstantUInt *CUI = cast<ConstantUInt>(idx);
- assert(CUI->getType() == Type::UByteTy
- && "Funny-looking structure index in GEP");
- // Use the TargetData structure to pick out what the layout of
- // the structure is in memory. Since the structure index must
- // be constant, we can get its value and use it to find the
- // right byte offset from the StructLayout class's list of
- // structure member offsets.
+ std::vector<Value*> GEPOps;
+ GEPOps.resize(IdxEnd-IdxBegin+1);
+ GEPOps[0] = Src;
+ std::copy(IdxBegin, IdxEnd, GEPOps.begin()+1);
+
+ std::vector<const Type*> GEPTypes;
+ GEPTypes.assign(gep_type_begin(Src->getType(), IdxBegin, IdxEnd),
+ gep_type_end(Src->getType(), IdxBegin, IdxEnd));
+
+ // Keep emitting instructions until we consume the entire GEP instruction.
+ while (!GEPOps.empty()) {
+ unsigned OldSize = GEPOps.size();
+
+ if (GEPTypes.empty()) {
+ // The getGEPIndex operation didn't want to build an LEA. Check to see if
+ // all operands are consumed but the base pointer. If so, just load it
+ // into the register.
+ unsigned BaseReg = getReg(GEPOps[0], MBB, IP);
+ BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg(BaseReg);
+ return; // we are now done
+ } else if (const StructType *StTy = dyn_cast<StructType>(GEPTypes.back())) {
+ // It's a struct access. CUI is the index into the structure,
+ // which names the field. This index must have unsigned type.
+ const ConstantUInt *CUI = cast<ConstantUInt>(GEPOps.back());
+ GEPOps.pop_back(); // Consume a GEP operand
+ GEPTypes.pop_back();
+
+ // Use the TargetData structure to pick out what the layout of the
+ // structure is in memory. Since the structure index must be constant, we
+ // can get its value and use it to find the right byte offset from the
+ // StructLayout class's list of structure member offsets.
unsigned idxValue = CUI->getValue();
unsigned FieldOff = TD.getStructLayout(StTy)->MemberOffsets[idxValue];
if (FieldOff) {
- NextReg = makeAnotherReg(Type::UIntTy);
+ unsigned Reg = makeAnotherReg(Type::UIntTy);
// Emit an ADD to add FieldOff to the basePtr.
- BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(FieldOff);
+ BMI(MBB, IP, X86::ADDri32, 2, TargetReg).addReg(Reg).addZImm(FieldOff);
+ --IP; // Insert the next instruction before this one.
+ TargetReg = Reg; // Codegen the rest of the GEP into this
}
- // The next type is the member of the structure selected by the
- // index.
- Ty = StTy->getElementType(idxValue);
- } else if (const SequentialType *SqTy = cast<SequentialType>(Ty)) {
+
+ } else {
// It's an array or pointer access: [ArraySize x ElementType].
+ const SequentialType *SqTy = cast<SequentialType>(GEPTypes.back());
+ Value *idx = GEPOps.back();
+ GEPOps.pop_back(); // Consume a GEP operand
+ GEPTypes.pop_back();
// idx is the index into the array. Unlike with structure
// indices, we may not know its actual value at code-generation
@@ -2259,41 +2276,52 @@
// We want to add BaseReg to(idxReg * sizeof ElementType). First, we
// must find the size of the pointed-to type (Not coincidentally, the next
// type is the type of the elements in the array).
- Ty = SqTy->getElementType();
- unsigned elementSize = TD.getTypeSize(Ty);
+ const Type *ElTy = SqTy->getElementType();
+ unsigned elementSize = TD.getTypeSize(ElTy);
// If idxReg is a constant, we don't need to perform the multiply!
if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
if (!CSI->isNullValue()) {
unsigned Offset = elementSize*CSI->getValue();
- NextReg = makeAnotherReg(Type::UIntTy);
- BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(Offset);
+ unsigned Reg = makeAnotherReg(Type::UIntTy);
+ BMI(MBB, IP, X86::ADDri32, 2, TargetReg).addReg(Reg).addZImm(Offset);
+ --IP; // Insert the next instruction before this one.
+ TargetReg = Reg; // Codegen the rest of the GEP into this
}
} else if (elementSize == 1) {
// If the element size is 1, we don't have to multiply, just add
unsigned idxReg = getReg(idx, MBB, IP);
- NextReg = makeAnotherReg(Type::UIntTy);
- BMI(MBB, IP, X86::ADDrr32, 2, NextReg).addReg(BaseReg).addReg(idxReg);
+ unsigned Reg = makeAnotherReg(Type::UIntTy);
+ BMI(MBB, IP, X86::ADDrr32, 2, TargetReg).addReg(Reg).addReg(idxReg);
+ --IP; // Insert the next instruction before this one.
+ TargetReg = Reg; // Codegen the rest of the GEP into this
} else {
unsigned idxReg = getReg(idx, MBB, IP);
unsigned OffsetReg = makeAnotherReg(Type::UIntTy);
+ // Make sure we can back the iterator up to point to the first
+ // instruction emitted.
+ MachineBasicBlock::iterator BeforeIt = IP;
+ if (IP == MBB->begin())
+ BeforeIt = MBB->end();
+ else
+ --BeforeIt;
doMultiplyConst(MBB, IP, OffsetReg, Type::IntTy, idxReg, elementSize);
// Emit an ADD to add OffsetReg to the basePtr.
- NextReg = makeAnotherReg(Type::UIntTy);
- BMI(MBB, IP, X86::ADDrr32, 2,NextReg).addReg(BaseReg).addReg(OffsetReg);
+ unsigned Reg = makeAnotherReg(Type::UIntTy);
+ BMI(MBB, IP, X86::ADDrr32, 2, TargetReg).addReg(Reg).addReg(OffsetReg);
+
+ // Step to the first instruction of the multiply.
+ if (BeforeIt == MBB->end())
+ IP = MBB->begin();
+ else
+ IP = ++BeforeIt;
+
+ TargetReg = Reg; // Codegen the rest of the GEP into this
}
}
- // Now that we are here, further indices refer to subtypes of this
- // one, so we don't need to worry about BaseReg itself, anymore.
- BaseReg = NextReg;
- }
- // After we have processed all the indices, the result is left in
- // BaseReg. Move it to the register where we were expected to
- // put the answer. A 32-bit move should do it, because we are in
- // ILP32 land.
- BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg(BaseReg);
+ }
}
More information about the llvm-commits
mailing list