[llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp
Chris Lattner
lattner at cs.uiuc.edu
Tue Feb 24 21:47:01 PST 2004
Changes in directory llvm/lib/Target/X86:
InstSelectSimple.cpp updated: 1.175 -> 1.176
---
Log message:
add an inefficient way of folding structure and constant array indexes together
into a single LEA instruction. This should improve the code generated for
things like X->A.B.C[12].D.
The bigger benefit is still coming though. Note that this uses an LEA instruction
instead of an add, giving the register allocator more freedom. We should probably
never generate ADDri32's.
---
Diffs of the changes: (+90 -22)
Index: llvm/lib/Target/X86/InstSelectSimple.cpp
diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.175 llvm/lib/Target/X86/InstSelectSimple.cpp:1.176
--- llvm/lib/Target/X86/InstSelectSimple.cpp:1.175 Tue Feb 24 20:56:58 2004
+++ llvm/lib/Target/X86/InstSelectSimple.cpp Tue Feb 24 21:45:50 2004
@@ -2308,6 +2308,76 @@
I.op_begin()+1, I.op_end(), outputReg);
}
+/// getGEPIndex - Inspect the getelementptr operands specified with GEPOps and
+/// GEPTypes (the derived types being stepped through at each level). On return
+/// from this function, if some indexes of the instruction are representable as
+/// an X86 lea instruction, the machine operands are put into the Ops
+/// instruction and the consumed indexes are poped from the GEPOps/GEPTypes
+/// lists. Otherwise, GEPOps.size() is returned. If this returns a an
+/// addressing mode that only partially consumes the input, the BaseReg input of
+/// the addressing mode must be left free.
+///
+/// Note that there is one fewer entry in GEPTypes than there is in GEPOps.
+///
+static void getGEPIndex(std::vector<Value*> &GEPOps,
+ std::vector<const Type*> &GEPTypes,
+ MachineInstr *Ops, const TargetData &TD){
+ // Clear out the state we are working with...
+ Ops->getOperand(0).setReg(0); // No base register
+ Ops->getOperand(1).setImmedValue(1); // Unit scale
+ Ops->getOperand(2).setReg(0); // No index register
+ Ops->getOperand(3).setImmedValue(0); // No displacement
+
+ // While there are GEP indexes that can be folded into the current address,
+ // keep processing them.
+ while (!GEPTypes.empty()) {
+ 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());
+
+ // 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) {
+ if (Ops->getOperand(2).getReg())
+ return; // Already has an index, can't add offset.
+ Ops->getOperand(3).setImmedValue(FieldOff+
+ Ops->getOperand(3).getImmedValue());
+ }
+ GEPOps.pop_back(); // Consume a GEP operand
+ GEPTypes.pop_back();
+ } else {
+ // It's an array or pointer access: [ArraySize x ElementType].
+ const SequentialType *SqTy = cast<SequentialType>(GEPTypes.back());
+ Value *idx = GEPOps.back();
+
+ // idx is the index into the array. Unlike with structure
+ // indices, we may not know its actual value at code-generation
+ // time.
+ assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
+
+ // If idx is a constant, fold it into the offset.
+ if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
+ unsigned elementSize = TD.getTypeSize(SqTy->getElementType());
+ unsigned Offset = elementSize*CSI->getValue();
+ Ops->getOperand(3).setImmedValue(Offset+
+ Ops->getOperand(3).getImmedValue());
+ } else {
+ // If we can't handle it, return.
+ return;
+ }
+
+ GEPOps.pop_back(); // Consume a GEP operand
+ GEPTypes.pop_back();
+ }
+ }
+}
+
+
void ISel::emitGEPOperation(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
Value *Src, User::op_iterator IdxBegin,
@@ -2326,11 +2396,28 @@
GEPTypes.assign(gep_type_begin(Src->getType(), IdxBegin, IdxEnd),
gep_type_end(Src->getType(), IdxBegin, IdxEnd));
+ // DummyMI - A dummy instruction to pass into getGEPIndex. The opcode doesn't
+ // matter, we just need 4 MachineOperands.
+ MachineInstr *DummyMI =
+ BuildMI(X86::PHI, 4).addReg(0).addZImm(1).addReg(0).addSImm(0);
+
// Keep emitting instructions until we consume the entire GEP instruction.
while (!GEPOps.empty()) {
unsigned OldSize = GEPOps.size();
+ getGEPIndex(GEPOps, GEPTypes, DummyMI, TD);
- if (GEPTypes.empty()) {
+ if (GEPOps.size() != OldSize) {
+ // getGEPIndex consumed some of the input. Build an LEA instruction here.
+ assert(DummyMI->getOperand(0).getReg() == 0 &&
+ DummyMI->getOperand(1).getImmedValue() == 1 &&
+ DummyMI->getOperand(2).getReg() == 0 &&
+ "Unhandled GEP fold!");
+ if (unsigned Offset = DummyMI->getOperand(3).getImmedValue()) {
+ unsigned Reg = makeAnotherReg(Type::UIntTy);
+ addRegOffset(BMI(MBB, IP, X86::LEAr32, 5, TargetReg), Reg, Offset);
+ TargetReg = Reg;
+ }
+ } else 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.
@@ -2341,27 +2428,6 @@
BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg(BaseReg);
}
break; // 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) {
- unsigned Reg = makeAnotherReg(Type::UIntTy);
- // Emit an ADD to add FieldOff to the basePtr.
- 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
- }
-
} else {
// It's an array or pointer access: [ArraySize x ElementType].
const SequentialType *SqTy = cast<SequentialType>(GEPTypes.back());
@@ -2430,6 +2496,8 @@
}
}
}
+
+ delete DummyMI;
}
More information about the llvm-commits
mailing list