[llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sat Dec 28 14:26:01 PST 2002
Changes in directory llvm/lib/Target/X86:
InstSelectSimple.cpp updated: 1.78 -> 1.79
---
Log message:
* Use the new Abstract Frame Manager to handle incoming arguments and
fixed size allocas
* Revamp call emission to work with new frame manager
---
Diffs of the changes:
Index: llvm/lib/Target/X86/InstSelectSimple.cpp
diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.78 llvm/lib/Target/X86/InstSelectSimple.cpp:1.79
--- llvm/lib/Target/X86/InstSelectSimple.cpp:1.78 Tue Dec 24 23:13:53 2002
+++ llvm/lib/Target/X86/InstSelectSimple.cpp Sat Dec 28 14:24:02 2002
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/CodeGen/FunctionFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Target/MRegisterInfo.h"
@@ -73,29 +74,12 @@
bool runOnFunction(Function &Fn) {
F = &MachineFunction::construct(&Fn, TM);
+ // Create all of the machine basic blocks for the function...
for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));
- // Emit instructions to load the arguments... The function's arguments
- // look like this:
- //
- // [EBP] -- copy of old EBP
- // [EBP + 4] -- return address
- // [EBP + 8] -- first argument (leftmost lexically)
- //
- // So we want to start with counter = 2.
- //
BB = &F->front();
- unsigned ArgOffset = 8;
- for (Function::aiterator I = Fn.abegin(), E = Fn.aend(); I != E;
- ++I, ArgOffset += 4) {
- unsigned Reg = getReg(*I);
-
- // Load it out of the stack frame at EBP + 4*argPos.
-
- // FIXME: This should load the argument of the appropriate size!!
- addRegOffset(BuildMI(BB, X86::MOVmr32, 4, Reg), X86::EBP, ArgOffset);
- }
+ LoadArgumentsToVirtualRegs(Fn);
// Instruction select everything except PHI nodes
visit(Fn);
@@ -123,6 +107,10 @@
BB = MBBMap[&LLVM_BB];
}
+ /// LoadArgumentsToVirtualRegs - Load all of the arguments to this function
+ /// from the stack into virtual registers.
+ ///
+ void LoadArgumentsToVirtualRegs(Function &F);
/// SelectPHINodes - Insert machine code to generate phis. This is tricky
/// because we have to generate our sources into the source basic blocks,
@@ -170,9 +158,12 @@
void visitLoadInst(LoadInst &I);
void visitStoreInst(StoreInst &I);
void visitGetElementPtrInst(GetElementPtrInst &I);
- void visitMallocInst(MallocInst &I);
- void visitFreeInst(FreeInst &I);
void visitAllocaInst(AllocaInst &I);
+
+ // We assume that by this point, malloc instructions have been
+ // lowered to calls, and dlsym will magically find malloc for us.
+ void visitMallocInst(MallocInst &I) { visitInstruction (I); }
+ void visitFreeInst(FreeInst &I) { visitInstruction(I); }
// Other operators
void visitShiftInst(ShiftInst &I);
@@ -341,6 +332,59 @@
}
}
+/// LoadArgumentsToVirtualRegs - Load all of the arguments to this function from
+/// the stack into virtual registers.
+///
+void ISel::LoadArgumentsToVirtualRegs(Function &Fn) {
+ // Emit instructions to load the arguments... On entry to a function on the
+ // X86, the stack frame looks like this:
+ //
+ // [ESP] -- return address
+ // [ESP + 4] -- first argument (leftmost lexically) if four bytes in size
+ // [ESP + 8] -- second argument, if four bytes in size
+ // ...
+ //
+ unsigned ArgOffset = 0;
+ FunctionFrameInfo *FFI = F->getFrameInfo();
+
+ for (Function::aiterator I = Fn.abegin(), E = Fn.aend(); I != E; ++I) {
+ unsigned Reg = getReg(*I);
+
+ ArgOffset += 4; // Each argument takes at least 4 bytes on the stack...
+ int FI; // Frame object index
+
+ switch (getClassB(I->getType())) {
+ case cByte:
+ FI = FFI->CreateFixedObject(1, ArgOffset);
+ addFrameReference(BuildMI(BB, X86::MOVmr8, 4, Reg), FI);
+ break;
+ case cShort:
+ FI = FFI->CreateFixedObject(2, ArgOffset);
+ addFrameReference(BuildMI(BB, X86::MOVmr16, 4, Reg), FI);
+ break;
+ case cInt:
+ FI = FFI->CreateFixedObject(4, ArgOffset);
+ addFrameReference(BuildMI(BB, X86::MOVmr32, 4, Reg), FI);
+ break;
+ case cFP:
+ unsigned Opcode;
+ if (I->getType() == Type::FloatTy) {
+ Opcode = X86::FLDr32;
+ FI = FFI->CreateFixedObject(4, ArgOffset);
+ } else {
+ Opcode = X86::FLDr64;
+ ArgOffset += 4; // doubles require 4 additional bytes
+ FI = FFI->CreateFixedObject(8, ArgOffset);
+ }
+ addFrameReference(BuildMI(BB, Opcode, 4, Reg), FI);
+ break;
+ default:
+ assert(0 && "Unhandled argument type!");
+ }
+ }
+}
+
+
/// SelectPHINodes - Insert machine code to generate phis. This is tricky
/// because we have to generate our sources into the source basic blocks, not
/// the current one.
@@ -366,7 +410,8 @@
// available in a virtual register, insert the computation code into
// PredMBB
//
-
+ // FIXME: This should insert the code into the BOTTOM of the block, not
+ // the top of the block. This just makes for huge live ranges...
MachineBasicBlock::iterator PI = PredMBB->begin();
while ((*PI)->getOpcode() == X86::PHI) ++PI;
@@ -532,7 +577,7 @@
// Compare condition with zero, followed by jump-if-equal to ifFalse, and
// jump-if-nonequal to ifTrue
- unsigned int condReg = getReg(BI.getCondition());
+ unsigned condReg = getReg(BI.getCondition());
BuildMI(BB, X86::CMPri8, 2).addReg(condReg).addZImm(0);
BuildMI(BB, X86::JNE, 1).addPCDisp(BI.getSuccessor(0));
BuildMI(BB, X86::JE, 1).addPCDisp(BI.getSuccessor(1));
@@ -543,32 +588,64 @@
/// visitCallInst - Push args on stack and do a procedure call instruction.
void ISel::visitCallInst(CallInst &CI) {
- // keep a counter of how many bytes we pushed on the stack
- unsigned bytesPushed = 0;
+ // Count how many bytes are to be pushed on the stack...
+ unsigned NumBytes = 0;
- // Push the arguments on the stack in reverse order, as specified by
- // the ABI.
- for (unsigned i = CI.getNumOperands()-1; i >= 1; --i) {
- Value *v = CI.getOperand(i);
- switch (getClass(v->getType())) {
- case cByte:
- case cShort:
- // Promote V to 32 bits wide, and move the result into EAX,
- // then push EAX.
- promote32 (X86::EAX, v);
- BuildMI(BB, X86::PUSHr32, 1).addReg(X86::EAX);
- bytesPushed += 4;
- break;
- case cInt: {
- unsigned Reg = getReg(v);
- BuildMI(BB, X86::PUSHr32, 1).addReg(Reg);
- bytesPushed += 4;
- break;
- }
- default:
- // FIXME: long/ulong/float/double args not handled.
- visitInstruction(CI);
- break;
+ if (CI.getNumOperands() > 1) {
+ for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
+ switch (getClass(CI.getOperand(i)->getType())) {
+ case cByte: case cShort: case cInt:
+ NumBytes += 4;
+ break;
+ case cLong:
+ NumBytes += 8;
+ break;
+ case cFP:
+ NumBytes += CI.getOperand(i)->getType() == Type::FloatTy ? 4 : 8;
+ break;
+ default: assert(0 && "Unknown class!");
+ }
+
+ // Adjust the stack pointer for the new arguments...
+ BuildMI(BB, X86::ADJCALLSTACKDOWN, 1).addZImm(NumBytes);
+
+ // Arguments go on the stack in reverse order, as specified by the ABI.
+ unsigned ArgOffset = 0;
+ for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i) {
+ Value *Arg = CI.getOperand(i);
+ switch (getClass(Arg->getType())) {
+ case cByte:
+ case cShort: {
+ // Promote arg to 32 bits wide into a temporary register...
+ unsigned R = makeAnotherReg(Type::UIntTy);
+ promote32(R, Arg);
+ addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
+ X86::ESP, ArgOffset).addReg(R);
+ break;
+ }
+ case cInt:
+ addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
+ X86::ESP, ArgOffset).addReg(getReg(Arg));
+ break;
+
+ case cFP:
+ if (Arg->getType() == Type::FloatTy) {
+ addRegOffset(BuildMI(BB, X86::FSTr32, 5),
+ X86::ESP, ArgOffset).addReg(getReg(Arg));
+ } else {
+ assert(Arg->getType() == Type::DoubleTy && "Unknown FP type!");
+ ArgOffset += 4;
+ addRegOffset(BuildMI(BB, X86::FSTr32, 5),
+ X86::ESP, ArgOffset).addReg(getReg(Arg));
+ }
+ break;
+
+ default:
+ // FIXME: long/ulong/float/double args not handled.
+ visitInstruction(CI);
+ break;
+ }
+ ArgOffset += 4;
}
}
@@ -580,9 +657,7 @@
BuildMI(BB, X86::CALLr32, 1).addReg(Reg);
}
- // Adjust the stack by `bytesPushed' amount if non-zero
- if (bytesPushed > 0)
- BuildMI(BB, X86::ADDri32,2, X86::ESP).addReg(X86::ESP).addZImm(bytesPushed);
+ BuildMI(BB, X86::ADJCALLSTACKUP, 1).addZImm(NumBytes);
// If there is a return value, scavenge the result from the location the call
// leaves it in...
@@ -771,7 +846,7 @@
if (OperandClass > cInt)
visitInstruction(I); // Can't handle longs yet!
- if (ConstantUInt *CUI = dyn_cast <ConstantUInt> (I.getOperand (1)))
+ if (ConstantUInt *CUI = dyn_cast<ConstantUInt> (I.getOperand (1)))
{
// The shift amount is constant, guaranteed to be a ubyte. Get its value.
assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
@@ -956,9 +1031,9 @@
{
const Type *targetType = CI.getType ();
Value *operand = CI.getOperand (0);
- unsigned int operandReg = getReg (operand);
+ unsigned operandReg = getReg (operand);
const Type *sourceType = operand->getType ();
- unsigned int destReg = getReg (CI);
+ unsigned destReg = getReg (CI);
//
// Currently we handle:
//
@@ -1075,11 +1150,11 @@
oe = IdxEnd; oi != oe; ++oi) {
Value *idx = *oi;
unsigned nextBasePtrReg = makeAnotherReg(Type::UIntTy);
- if (const StructType *StTy = dyn_cast <StructType> (Ty)) {
+ 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
+ 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
@@ -1088,14 +1163,14 @@
// structure member offsets.
unsigned idxValue = CUI->getValue();
unsigned memberOffset =
- TD.getStructLayout (StTy)->MemberOffsets[idxValue];
+ TD.getStructLayout(StTy)->MemberOffsets[idxValue];
// Emit an ADD to add memberOffset to the basePtr.
BMI(MBB, IP, X86::ADDri32, 2,
- nextBasePtrReg).addReg (basePtrReg).addZImm (memberOffset);
+ nextBasePtrReg).addReg(basePtrReg).addZImm(memberOffset);
// The next type is the member of the structure selected by the
// index.
- Ty = StTy->getElementTypes ()[idxValue];
- } else if (const SequentialType *SqTy = cast <SequentialType>(Ty)) {
+ Ty = StTy->getElementTypes()[idxValue];
+ } else if (const SequentialType *SqTy = cast<SequentialType>(Ty)) {
// It's an array or pointer access: [ArraySize x ElementType].
// idx is the index into the array. Unlike with structure
@@ -1103,7 +1178,7 @@
// time.
assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
- // We want to add basePtrReg to (idxReg * sizeof ElementType). First, we
+ // We want to add basePtrReg 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();
@@ -1143,7 +1218,7 @@
}
// Emit an ADD to add OffsetReg to the basePtr.
BMI(MBB, IP, X86::ADDrr32, 2,
- nextBasePtrReg).addReg (basePtrReg).addReg (OffsetReg);
+ nextBasePtrReg).addReg(basePtrReg).addReg(OffsetReg);
}
}
// Now that we are here, further indices refer to subtypes of this
@@ -1154,51 +1229,62 @@
// basePtrReg. 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 (basePtrReg);
-}
-
-
-/// visitMallocInst - I know that personally, whenever I want to remember
-/// something, I have to clear off some space in my brain.
-void
-ISel::visitMallocInst (MallocInst &I)
-{
- // We assume that by this point, malloc instructions have been
- // lowered to calls, and dlsym will magically find malloc for us.
- // So we do not want to see malloc instructions here.
- visitInstruction (I);
+ BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg(basePtrReg);
}
-/// visitFreeInst - same story as MallocInst
-void
-ISel::visitFreeInst (FreeInst &I)
-{
- // We assume that by this point, free instructions have been
- // lowered to calls, and dlsym will magically find free for us.
- // So we do not want to see free instructions here.
- visitInstruction (I);
-}
+/// visitAllocaInst - If this is a fixed size alloca, allocate space from the
+/// frame manager, otherwise do it the hard way.
+///
+void ISel::visitAllocaInst(AllocaInst &I) {
+ // Find the data size of the alloca inst's getAllocatedType.
+ const Type *Ty = I.getAllocatedType();
+ unsigned TySize = TM.getTargetData().getTypeSize(Ty);
+ // If this is a fixed size alloca in the entry block for the function,
+ // statically stack allocate the space.
+ //
+ if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(I.getArraySize())) {
+ if (I.getParent() == I.getParent()->getParent()->begin()) {
+ TySize *= CUI->getValue(); // Get total allocated size...
+ unsigned Alignment = TM.getTargetData().getTypeAlignment(Ty);
+
+ // Create a new stack object using the frame manager...
+ int FrameIdx = F->getFrameInfo()->CreateStackObject(TySize, Alignment);
+ addFrameReference(BuildMI(BB, X86::LEAr32, 5, getReg(I)), FrameIdx);
+ return;
+ }
+ }
+
+ // Create a register to hold the temporary result of multiplying the type size
+ // constant by the variable amount.
+ unsigned TotalSizeReg = makeAnotherReg(Type::UIntTy);
+ unsigned SrcReg1 = getReg(I.getArraySize());
+ unsigned SizeReg = makeAnotherReg(Type::UIntTy);
+ BuildMI(BB, X86::MOVir32, 1, SizeReg).addZImm(TySize);
+
+ // TotalSizeReg = mul <numelements>, <TypeSize>
+ MachineBasicBlock::iterator MBBI = BB->end();
+ doMultiply(BB, MBBI, TotalSizeReg, Type::UIntTy, SrcReg1, SizeReg);
-/// visitAllocaInst - I want some stack space. Come on, man, I said I
-/// want some freakin' stack space.
-void
-ISel::visitAllocaInst (AllocaInst &I)
-{
- // Find the data size of the alloca inst's getAllocatedType.
- const Type *allocatedType = I.getAllocatedType ();
- const TargetData &TD = TM.DataLayout;
- unsigned allocatedTypeSize = TD.getTypeSize (allocatedType);
- // Keep stack 32-bit aligned.
- unsigned int allocatedTypeWords = allocatedTypeSize / 4;
- if (allocatedTypeSize % 4 != 0) { allocatedTypeWords++; }
+ // AddedSize = add <TotalSizeReg>, 15
+ unsigned AddedSizeReg = makeAnotherReg(Type::UIntTy);
+ BuildMI(BB, X86::ADDri32, 2, AddedSizeReg).addReg(TotalSizeReg).addZImm(15);
+
+ // AlignedSize = and <AddedSize>, ~15
+ unsigned AlignedSize = makeAnotherReg(Type::UIntTy);
+ BuildMI(BB, X86::ANDri32, 2, AlignedSize).addReg(AddedSizeReg).addZImm(~15);
+
// Subtract size from stack pointer, thereby allocating some space.
- BuildMI(BB, X86::SUBri32, 2,
- X86::ESP).addReg(X86::ESP).addZImm(allocatedTypeWords * 4);
+ BuildMI(BB, X86::SUBri32, 2, X86::ESP).addReg(X86::ESP).addZImm(AlignedSize);
+
// Put a pointer to the space into the result register, by copying
// the stack pointer.
- BuildMI (BB, X86::MOVrr32, 1, getReg (I)).addReg (X86::ESP);
+ BuildMI(BB, X86::MOVrr32, 1, getReg(I)).addReg(X86::ESP);
+
+ // Inform the Frame Information that we have just allocated a variable sized
+ // object.
+ F->getFrameInfo()->CreateVariableSizedObject();
}
More information about the llvm-commits
mailing list