Reduce the number of arguments in the instruction builder and make some

improvements on instruction selection that account for register and frame
index bases.

Patch contributed by Jeff Cohen. Thanks Jeff!


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16110 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Spencer 2004-08-30 00:13:26 +00:00
parent 6386009ea6
commit fc989e1ee0
2 changed files with 137 additions and 160 deletions

View File

@ -237,23 +237,21 @@ namespace {
/// getAddressingMode - Get the addressing mode to use to address the /// getAddressingMode - Get the addressing mode to use to address the
/// specified value. The returned value should be used with addFullAddress. /// specified value. The returned value should be used with addFullAddress.
void getAddressingMode(Value *Addr, unsigned &BaseReg, unsigned &Scale, void getAddressingMode(Value *Addr, X86AddressMode &AM);
unsigned &IndexReg, unsigned &Disp);
/// getGEPIndex - This is used to fold GEP instructions into X86 addressing /// getGEPIndex - This is used to fold GEP instructions into X86 addressing
/// expressions. /// expressions.
void getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP, void getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
std::vector<Value*> &GEPOps, std::vector<Value*> &GEPOps,
std::vector<const Type*> &GEPTypes, unsigned &BaseReg, std::vector<const Type*> &GEPTypes,
unsigned &Scale, unsigned &IndexReg, unsigned &Disp); X86AddressMode &AM);
/// isGEPFoldable - Return true if the specified GEP can be completely /// isGEPFoldable - Return true if the specified GEP can be completely
/// folded into the addressing mode of a load/store or lea instruction. /// folded into the addressing mode of a load/store or lea instruction.
bool isGEPFoldable(MachineBasicBlock *MBB, bool isGEPFoldable(MachineBasicBlock *MBB,
Value *Src, User::op_iterator IdxBegin, Value *Src, User::op_iterator IdxBegin,
User::op_iterator IdxEnd, unsigned &BaseReg, User::op_iterator IdxEnd, X86AddressMode &AM);
unsigned &Scale, unsigned &IndexReg, unsigned &Disp);
/// emitGEPOperation - Common code shared between visitGetElementPtrInst and /// emitGEPOperation - Common code shared between visitGetElementPtrInst and
/// constant expression GEP support. /// constant expression GEP support.
@ -812,23 +810,28 @@ void ISel::InsertFPRegKills() {
} }
void ISel::getAddressingMode(Value *Addr, unsigned &BaseReg, unsigned &Scale, void ISel::getAddressingMode(Value *Addr, X86AddressMode &AM) {
unsigned &IndexReg, unsigned &Disp) { AM.BaseType = X86AddressMode::RegBase;
BaseReg = 0; Scale = 1; IndexReg = 0; Disp = 0; AM.Base.Reg = 0; AM.Scale = 1; AM.IndexReg = 0; AM.Disp = 0;
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr)) { if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr)) {
if (isGEPFoldable(BB, GEP->getOperand(0), GEP->op_begin()+1, GEP->op_end(), if (isGEPFoldable(BB, GEP->getOperand(0), GEP->op_begin()+1, GEP->op_end(),
BaseReg, Scale, IndexReg, Disp)) AM))
return; return;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Addr)) { } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Addr)) {
if (CE->getOpcode() == Instruction::GetElementPtr) if (CE->getOpcode() == Instruction::GetElementPtr)
if (isGEPFoldable(BB, CE->getOperand(0), CE->op_begin()+1, CE->op_end(), if (isGEPFoldable(BB, CE->getOperand(0), CE->op_begin()+1, CE->op_end(),
BaseReg, Scale, IndexReg, Disp)) AM))
return; return;
} else if (AllocaInst *AI = dyn_castFixedAlloca(Addr)) {
AM.BaseType = X86AddressMode::FrameIndexBase;
AM.Base.FrameIndex = getFixedSizedAllocaFI(AI);
return;
} }
// If it's not foldable, reset addr mode. // If it's not foldable, reset addr mode.
BaseReg = getReg(Addr); AM.BaseType = X86AddressMode::RegBase;
Scale = 1; IndexReg = 0; Disp = 0; AM.Base.Reg = getReg(Addr);
AM.Scale = 1; AM.IndexReg = 0; AM.Disp = 0;
} }
// canFoldSetCCIntoBranchOrSelect - Return the setcc instruction if we can fold // canFoldSetCCIntoBranchOrSelect - Return the setcc instruction if we can fold
@ -1995,12 +1998,10 @@ void ISel::visitSimpleBinary(BinaryOperator &B, unsigned OperatorClass) {
addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r), FI); addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r), FI);
} else { } else {
unsigned BaseReg, Scale, IndexReg, Disp; X86AddressMode AM;
getAddressingMode(cast<LoadInst>(Op1)->getOperand(0), BaseReg, getAddressingMode(cast<LoadInst>(Op1)->getOperand(0), AM);
Scale, IndexReg, Disp);
addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r), addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r), AM);
BaseReg, Scale, IndexReg, Disp);
} }
return; return;
} }
@ -2020,12 +2021,10 @@ void ISel::visitSimpleBinary(BinaryOperator &B, unsigned OperatorClass) {
unsigned FI = getFixedSizedAllocaFI(AI); unsigned FI = getFixedSizedAllocaFI(AI);
addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r), FI); addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r), FI);
} else { } else {
unsigned BaseReg, Scale, IndexReg, Disp; X86AddressMode AM;
getAddressingMode(cast<LoadInst>(Op0)->getOperand(0), BaseReg, getAddressingMode(cast<LoadInst>(Op0)->getOperand(0), AM);
Scale, IndexReg, Disp);
addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r), addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r), AM);
BaseReg, Scale, IndexReg, Disp);
} }
return; return;
} }
@ -2352,8 +2351,13 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
case 5: case 5:
case 9: case 9:
if (Class == cInt) { if (Class == cInt) {
addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, DestReg), X86AddressMode AM;
op0Reg, ConstRHS-1, op0Reg, 0); AM.BaseType = X86AddressMode::RegBase;
AM.Base.Reg = op0Reg;
AM.Scale = ConstRHS-1;
AM.IndexReg = op0Reg;
AM.Disp = 0;
addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, DestReg), AM);
return; return;
} }
case -3: case -3:
@ -2361,8 +2365,13 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
case -9: case -9:
if (Class == cInt) { if (Class == cInt) {
TmpReg = makeAnotherReg(DestTy); TmpReg = makeAnotherReg(DestTy);
addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, TmpReg), X86AddressMode AM;
op0Reg, -ConstRHS-1, op0Reg, 0); AM.BaseType = X86AddressMode::RegBase;
AM.Base.Reg = op0Reg;
AM.Scale = -ConstRHS-1;
AM.IndexReg = op0Reg;
AM.Disp = 0;
addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, TmpReg), AM);
BuildMI(*MBB, IP, NEGrTab[Class], 1, DestReg).addReg(TmpReg); BuildMI(*MBB, IP, NEGrTab[Class], 1, DestReg).addReg(TmpReg);
return; return;
} }
@ -2444,12 +2453,10 @@ void ISel::visitMul(BinaryOperator &I) {
unsigned FI = getFixedSizedAllocaFI(AI); unsigned FI = getFixedSizedAllocaFI(AI);
addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI); addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI);
} else { } else {
unsigned BaseReg, Scale, IndexReg, Disp; X86AddressMode AM;
getAddressingMode(LI->getOperand(0), BaseReg, getAddressingMode(LI->getOperand(0), AM);
Scale, IndexReg, Disp);
addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), AM);
BaseReg, Scale, IndexReg, Disp);
} }
return; return;
} }
@ -2588,12 +2595,10 @@ void ISel::visitDivRem(BinaryOperator &I) {
unsigned FI = getFixedSizedAllocaFI(AI); unsigned FI = getFixedSizedAllocaFI(AI);
addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI); addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI);
} else { } else {
unsigned BaseReg, Scale, IndexReg, Disp; X86AddressMode AM;
getAddressingMode(LI->getOperand(0), BaseReg, getAddressingMode(LI->getOperand(0), AM);
Scale, IndexReg, Disp);
addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), AM);
BaseReg, Scale, IndexReg, Disp);
} }
return; return;
} }
@ -2609,10 +2614,9 @@ void ISel::visitDivRem(BinaryOperator &I) {
unsigned FI = getFixedSizedAllocaFI(AI); unsigned FI = getFixedSizedAllocaFI(AI);
addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r), FI); addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r), FI);
} else { } else {
unsigned BaseReg, Scale, IndexReg, Disp; X86AddressMode AM;
getAddressingMode(LI->getOperand(0), BaseReg, Scale, IndexReg, Disp); getAddressingMode(LI->getOperand(0), AM);
addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r), addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r), AM);
BaseReg, Scale, IndexReg, Disp);
} }
return; return;
} }
@ -2938,10 +2942,9 @@ void ISel::visitLoadInst(LoadInst &I) {
unsigned FI = getFixedSizedAllocaFI(AI); unsigned FI = getFixedSizedAllocaFI(AI);
addFrameReference(BuildMI(BB, Opcode[Class], 4, DestReg), FI); addFrameReference(BuildMI(BB, Opcode[Class], 4, DestReg), FI);
} else { } else {
unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0; X86AddressMode AM;
getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp); getAddressingMode(I.getOperand(0), AM);
addFullAddress(BuildMI(BB, Opcode[Class], 4, DestReg), addFullAddress(BuildMI(BB, Opcode[Class], 4, DestReg), AM);
BaseReg, Scale, IndexReg, Disp);
} }
return; return;
} else { } else {
@ -3011,17 +3014,15 @@ void ISel::visitLoadInst(LoadInst &I) {
addFrameReference(BuildMI(BB, Opcode, 4, DestReg), FI); addFrameReference(BuildMI(BB, Opcode, 4, DestReg), FI);
} }
} else { } else {
unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0; X86AddressMode AM;
getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp); getAddressingMode(I.getOperand(0), AM);
if (Class == cLong) { if (Class == cLong) {
addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg), addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg), AM);
BaseReg, Scale, IndexReg, Disp); AM.Disp += 4;
addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg+1), addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg+1), AM);
BaseReg, Scale, IndexReg, Disp+4);
} else { } else {
addFullAddress(BuildMI(BB, Opcode, 4, DestReg), addFullAddress(BuildMI(BB, Opcode, 4, DestReg), AM);
BaseReg, Scale, IndexReg, Disp);
} }
} }
} }
@ -3030,13 +3031,8 @@ void ISel::visitLoadInst(LoadInst &I) {
/// instruction. /// instruction.
/// ///
void ISel::visitStoreInst(StoreInst &I) { void ISel::visitStoreInst(StoreInst &I) {
unsigned BaseReg = ~0U, Scale = ~0U, IndexReg = ~0U, Disp = ~0U; X86AddressMode AM;
unsigned AllocaFrameIdx = ~0U; getAddressingMode(I.getOperand(1), AM);
if (AllocaInst *AI = dyn_castFixedAlloca(I.getOperand(1)))
AllocaFrameIdx = getFixedSizedAllocaFI(AI);
else
getAddressingMode(I.getOperand(1), BaseReg, Scale, IndexReg, Disp);
const Type *ValTy = I.getOperand(0)->getType(); const Type *ValTy = I.getOperand(0)->getType();
unsigned Class = getClassB(ValTy); unsigned Class = getClassB(ValTy);
@ -3044,42 +3040,20 @@ void ISel::visitStoreInst(StoreInst &I) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(0))) { if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(0))) {
uint64_t Val = CI->getRawValue(); uint64_t Val = CI->getRawValue();
if (Class == cLong) { if (Class == cLong) {
if (AllocaFrameIdx != ~0U) { addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(Val & ~0U);
addFrameReference(BuildMI(BB, X86::MOV32mi, 5), AM.Disp += 4;
AllocaFrameIdx).addImm(Val & ~0U); addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(Val>>32);
addFrameReference(BuildMI(BB, X86::MOV32mi, 5),
AllocaFrameIdx, 4).addImm(Val>>32);
} else {
addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
BaseReg, Scale, IndexReg, Disp).addImm(Val & ~0U);
addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
BaseReg, Scale, IndexReg, Disp+4).addImm(Val>>32);
}
} else { } else {
static const unsigned Opcodes[] = { static const unsigned Opcodes[] = {
X86::MOV8mi, X86::MOV16mi, X86::MOV32mi X86::MOV8mi, X86::MOV16mi, X86::MOV32mi
}; };
unsigned Opcode = Opcodes[Class]; unsigned Opcode = Opcodes[Class];
if (AllocaFrameIdx != ~0U) addFullAddress(BuildMI(BB, Opcode, 5), AM).addImm(Val);
addFrameReference(BuildMI(BB, Opcode, 5), AllocaFrameIdx).addImm(Val);
else
addFullAddress(BuildMI(BB, Opcode, 5),
BaseReg, Scale, IndexReg, Disp).addImm(Val);
} }
} else if (isa<ConstantPointerNull>(I.getOperand(0))) { } else if (isa<ConstantPointerNull>(I.getOperand(0))) {
if (AllocaFrameIdx != ~0U) addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(0);
addFrameReference(BuildMI(BB, X86::MOV32mi, 5), AllocaFrameIdx).addImm(0);
else
addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
BaseReg, Scale, IndexReg, Disp).addImm(0);
} else if (ConstantBool *CB = dyn_cast<ConstantBool>(I.getOperand(0))) { } else if (ConstantBool *CB = dyn_cast<ConstantBool>(I.getOperand(0))) {
if (AllocaFrameIdx != ~0U) addFullAddress(BuildMI(BB, X86::MOV8mi, 5), AM).addImm(CB->getValue());
addFrameReference(BuildMI(BB, X86::MOV8mi, 5),
AllocaFrameIdx).addImm(CB->getValue());
else
addFullAddress(BuildMI(BB, X86::MOV8mi, 5),
BaseReg, Scale, IndexReg, Disp).addImm(CB->getValue());
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0))) { } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0))) {
// Store constant FP values with integer instructions to avoid having to // Store constant FP values with integer instructions to avoid having to
// load the constants from the constant pool then do a store. // load the constants from the constant pool then do a store.
@ -3089,45 +3063,24 @@ void ISel::visitStoreInst(StoreInst &I) {
float F; float F;
} V; } V;
V.F = CFP->getValue(); V.F = CFP->getValue();
if (AllocaFrameIdx != ~0U) addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(V.I);
addFrameReference(BuildMI(BB, X86::MOV32mi, 5),
AllocaFrameIdx).addImm(V.I);
else
addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
BaseReg, Scale, IndexReg, Disp).addImm(V.I);
} else { } else {
union { union {
uint64_t I; uint64_t I;
double F; double F;
} V; } V;
V.F = CFP->getValue(); V.F = CFP->getValue();
if (AllocaFrameIdx != ~0U) { addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm((unsigned)V.I);
addFrameReference(BuildMI(BB, X86::MOV32mi, 5), AM.Disp += 4;
AllocaFrameIdx).addImm((unsigned)V.I); addFullAddress(BuildMI(BB, X86::MOV32mi, 5), AM).addImm(
addFrameReference(BuildMI(BB, X86::MOV32mi, 5),
AllocaFrameIdx, 4).addImm(unsigned(V.I >> 32));
} else {
addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
BaseReg, Scale, IndexReg, Disp).addImm((unsigned)V.I);
addFullAddress(BuildMI(BB, X86::MOV32mi, 5),
BaseReg, Scale, IndexReg, Disp+4).addImm(
unsigned(V.I >> 32)); unsigned(V.I >> 32));
}
} }
} else if (Class == cLong) { } else if (Class == cLong) {
unsigned ValReg = getReg(I.getOperand(0)); unsigned ValReg = getReg(I.getOperand(0));
if (AllocaFrameIdx != ~0U) { addFullAddress(BuildMI(BB, X86::MOV32mr, 5), AM).addReg(ValReg);
addFrameReference(BuildMI(BB, X86::MOV32mr, 5), AM.Disp += 4;
AllocaFrameIdx).addReg(ValReg); addFullAddress(BuildMI(BB, X86::MOV32mr, 5), AM).addReg(ValReg+1);
addFrameReference(BuildMI(BB, X86::MOV32mr, 5),
AllocaFrameIdx, 4).addReg(ValReg+1);
} else {
addFullAddress(BuildMI(BB, X86::MOV32mr, 5),
BaseReg, Scale, IndexReg, Disp).addReg(ValReg);
addFullAddress(BuildMI(BB, X86::MOV32mr, 5),
BaseReg, Scale, IndexReg, Disp+4).addReg(ValReg+1);
}
} else { } else {
unsigned ValReg = getReg(I.getOperand(0)); unsigned ValReg = getReg(I.getOperand(0));
static const unsigned Opcodes[] = { static const unsigned Opcodes[] = {
@ -3136,11 +3089,7 @@ void ISel::visitStoreInst(StoreInst &I) {
unsigned Opcode = Opcodes[Class]; unsigned Opcode = Opcodes[Class];
if (ValTy == Type::DoubleTy) Opcode = X86::FST64m; if (ValTy == Type::DoubleTy) Opcode = X86::FST64m;
if (AllocaFrameIdx != ~0U) addFullAddress(BuildMI(BB, Opcode, 1+4), AM).addReg(ValReg);
addFrameReference(BuildMI(BB, Opcode, 5), AllocaFrameIdx).addReg(ValReg);
else
addFullAddress(BuildMI(BB, Opcode, 1+4),
BaseReg, Scale, IndexReg, Disp).addReg(ValReg);
} }
} }
@ -3539,8 +3488,8 @@ void ISel::visitVAArgInst(VAArgInst &I) {
void ISel::visitGetElementPtrInst(GetElementPtrInst &I) { void ISel::visitGetElementPtrInst(GetElementPtrInst &I) {
// If this GEP instruction will be folded into all of its users, we don't need // If this GEP instruction will be folded into all of its users, we don't need
// to explicitly calculate it! // to explicitly calculate it!
unsigned A, B, C, D; X86AddressMode AM;
if (isGEPFoldable(0, I.getOperand(0), I.op_begin()+1, I.op_end(), A,B,C,D)) { if (isGEPFoldable(0, I.getOperand(0), I.op_begin()+1, I.op_end(), AM)) {
// Check all of the users of the instruction to see if they are loads and // Check all of the users of the instruction to see if they are loads and
// stores. // stores.
bool AllWillFold = true; bool AllWillFold = true;
@ -3575,15 +3524,16 @@ void ISel::visitGetElementPtrInst(GetElementPtrInst &I) {
/// ///
void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP, void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
std::vector<Value*> &GEPOps, std::vector<Value*> &GEPOps,
std::vector<const Type*> &GEPTypes, unsigned &BaseReg, std::vector<const Type*> &GEPTypes,
unsigned &Scale, unsigned &IndexReg, unsigned &Disp) { X86AddressMode &AM) {
const TargetData &TD = TM.getTargetData(); const TargetData &TD = TM.getTargetData();
// Clear out the state we are working with... // Clear out the state we are working with...
BaseReg = 0; // No base register AM.BaseType = X86AddressMode::RegBase;
Scale = 1; // Unit scale AM.Base.Reg = 0; // No base register
IndexReg = 0; // No index register AM.Scale = 1; // Unit scale
Disp = 0; // No displacement AM.IndexReg = 0; // No index register
AM.Disp = 0; // No displacement
// While there are GEP indexes that can be folded into the current address, // While there are GEP indexes that can be folded into the current address,
// keep processing them. // keep processing them.
@ -3597,7 +3547,7 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
// structure is in memory. Since the structure index must be constant, we // 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 // can get its value and use it to find the right byte offset from the
// StructLayout class's list of structure member offsets. // StructLayout class's list of structure member offsets.
Disp += TD.getStructLayout(StTy)->MemberOffsets[CUI->getValue()]; AM.Disp += TD.getStructLayout(StTy)->MemberOffsets[CUI->getValue()];
GEPOps.pop_back(); // Consume a GEP operand GEPOps.pop_back(); // Consume a GEP operand
GEPTypes.pop_back(); GEPTypes.pop_back();
} else { } else {
@ -3612,18 +3562,18 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
// If idx is a constant, fold it into the offset. // If idx is a constant, fold it into the offset.
unsigned TypeSize = TD.getTypeSize(SqTy->getElementType()); unsigned TypeSize = TD.getTypeSize(SqTy->getElementType());
if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) { if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
Disp += TypeSize*CSI->getValue(); AM.Disp += TypeSize*CSI->getValue();
} else if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(idx)) { } else if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(idx)) {
Disp += TypeSize*CUI->getValue(); AM.Disp += TypeSize*CUI->getValue();
} else { } else {
// If the index reg is already taken, we can't handle this index. // If the index reg is already taken, we can't handle this index.
if (IndexReg) return; if (AM.IndexReg) return;
// If this is a size that we can handle, then add the index as // If this is a size that we can handle, then add the index as
switch (TypeSize) { switch (TypeSize) {
case 1: case 2: case 4: case 8: case 1: case 2: case 4: case 8:
// These are all acceptable scales on X86. // These are all acceptable scales on X86.
Scale = TypeSize; AM.Scale = TypeSize;
break; break;
default: default:
// Otherwise, we can't handle this scale // Otherwise, we can't handle this scale
@ -3635,7 +3585,7 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
CI->getOperand(0)->getType() == Type::UIntTy) CI->getOperand(0)->getType() == Type::UIntTy)
idx = CI->getOperand(0); idx = CI->getOperand(0);
IndexReg = MBB ? getReg(idx, MBB, IP) : 1; AM.IndexReg = MBB ? getReg(idx, MBB, IP) : 1;
} }
GEPOps.pop_back(); // Consume a GEP operand GEPOps.pop_back(); // Consume a GEP operand
@ -3646,22 +3596,23 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
// GEPTypes is empty, which means we have a single operand left. Set it as // GEPTypes is empty, which means we have a single operand left. Set it as
// the base register. // the base register.
// //
assert(BaseReg == 0); assert(AM.Base.Reg == 0);
#if 0 // FIXME: TODO! if (AllocaInst *AI = dyn_castFixedAlloca(GEPOps.back())) {
if (AllocaInst *AI = dyn_castFixedAlloca(V)) { AM.BaseType = X86AddressMode::FrameIndexBase;
// FIXME: When we can add FrameIndex values as the first operand, we can AM.Base.FrameIndex = getFixedSizedAllocaFI(AI);
// make GEP's of allocas MUCH more efficient!
unsigned FI = getFixedSizedAllocaFI(AI);
GEPOps.pop_back(); GEPOps.pop_back();
return; return;
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) { }
#if 0 // FIXME: TODO!
if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
// FIXME: When addressing modes are more powerful/correct, we could load // FIXME: When addressing modes are more powerful/correct, we could load
// global addresses directly as 32-bit immediates. // global addresses directly as 32-bit immediates.
} }
#endif #endif
BaseReg = MBB ? getReg(GEPOps[0], MBB, IP) : 1; AM.Base.Reg = MBB ? getReg(GEPOps[0], MBB, IP) : 1;
GEPOps.pop_back(); // Consume the last GEP operand GEPOps.pop_back(); // Consume the last GEP operand
} }
@ -3670,8 +3621,7 @@ void ISel::getGEPIndex(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
/// folded into the addressing mode of a load/store or lea instruction. /// folded into the addressing mode of a load/store or lea instruction.
bool ISel::isGEPFoldable(MachineBasicBlock *MBB, bool ISel::isGEPFoldable(MachineBasicBlock *MBB,
Value *Src, User::op_iterator IdxBegin, Value *Src, User::op_iterator IdxBegin,
User::op_iterator IdxEnd, unsigned &BaseReg, User::op_iterator IdxEnd, X86AddressMode &AM) {
unsigned &Scale, unsigned &IndexReg, unsigned &Disp) {
std::vector<Value*> GEPOps; std::vector<Value*> GEPOps;
GEPOps.resize(IdxEnd-IdxBegin+1); GEPOps.resize(IdxEnd-IdxBegin+1);
@ -3684,7 +3634,7 @@ bool ISel::isGEPFoldable(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP; MachineBasicBlock::iterator IP;
if (MBB) IP = MBB->end(); if (MBB) IP = MBB->end();
getGEPIndex(MBB, IP, GEPOps, GEPTypes, BaseReg, Scale, IndexReg, Disp); getGEPIndex(MBB, IP, GEPOps, GEPTypes, AM);
// We can fold it away iff the getGEPIndex call eliminated all operands. // We can fold it away iff the getGEPIndex call eliminated all operands.
return GEPOps.empty(); return GEPOps.empty();
@ -3723,23 +3673,23 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
// Keep emitting instructions until we consume the entire GEP instruction. // Keep emitting instructions until we consume the entire GEP instruction.
while (!GEPOps.empty()) { while (!GEPOps.empty()) {
unsigned OldSize = GEPOps.size(); unsigned OldSize = GEPOps.size();
unsigned BaseReg, Scale, IndexReg, Disp; X86AddressMode AM;
getGEPIndex(MBB, IP, GEPOps, GEPTypes, BaseReg, Scale, IndexReg, Disp); getGEPIndex(MBB, IP, GEPOps, GEPTypes, AM);
if (GEPOps.size() != OldSize) { if (GEPOps.size() != OldSize) {
// getGEPIndex consumed some of the input. Build an LEA instruction here. // getGEPIndex consumed some of the input. Build an LEA instruction here.
unsigned NextTarget = 0; unsigned NextTarget = 0;
if (!GEPOps.empty()) { if (!GEPOps.empty()) {
assert(BaseReg == 0 && assert(AM.Base.Reg == 0 &&
"getGEPIndex should have left the base register open for chaining!"); "getGEPIndex should have left the base register open for chaining!");
NextTarget = BaseReg = makeAnotherReg(Type::UIntTy); NextTarget = AM.Base.Reg = makeAnotherReg(Type::UIntTy);
} }
if (IndexReg == 0 && Disp == 0) if (AM.BaseType == X86AddressMode::RegBase &&
BuildMI(*MBB, IP, X86::MOV32rr, 1, TargetReg).addReg(BaseReg); AM.IndexReg == 0 && AM.Disp == 0)
BuildMI(*MBB, IP, X86::MOV32rr, 1, TargetReg).addReg(AM.Base.Reg);
else else
addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, TargetReg), addFullAddress(BuildMI(*MBB, IP, X86::LEA32r, 5, TargetReg), AM);
BaseReg, Scale, IndexReg, Disp);
--IP; --IP;
TargetReg = NextTarget; TargetReg = NextTarget;
} else if (GEPTypes.empty()) { } else if (GEPTypes.empty()) {

View File

@ -28,6 +28,29 @@
namespace llvm { namespace llvm {
/// X86AddressMode - This struct holds a generalized full x86 address mode.
/// The base register can be a frame index, which will eventually be replaced
/// with BP or SP and Disp being offsetted accordingly.
/// FIXME: add support for globals as a new base type.
struct X86AddressMode {
enum {
UnknownBase,
RegBase,
FrameIndexBase
} BaseType;
union {
unsigned Reg;
int FrameIndex;
} Base;
unsigned Scale;
unsigned IndexReg;
unsigned Disp;
X86AddressMode() : BaseType(UnknownBase) {}
};
/// addDirectMem - This function is used to add a direct memory reference to the /// addDirectMem - This function is used to add a direct memory reference to the
/// current instruction -- that is, a dereference of an address in a register, /// current instruction -- that is, a dereference of an address in a register,
/// with no scale, index or displacement. An example is: DWORD PTR [EAX]. /// with no scale, index or displacement. An example is: DWORD PTR [EAX].
@ -50,12 +73,16 @@ inline const MachineInstrBuilder &addRegOffset(const MachineInstrBuilder &MIB,
} }
inline const MachineInstrBuilder &addFullAddress(const MachineInstrBuilder &MIB, inline const MachineInstrBuilder &addFullAddress(const MachineInstrBuilder &MIB,
unsigned BaseReg, const X86AddressMode &AM) {
unsigned Scale, assert (AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8);
unsigned IndexReg,
unsigned Disp) { if (AM.BaseType == X86AddressMode::RegBase)
assert (Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8); MIB.addReg(AM.Base.Reg);
return MIB.addReg(BaseReg).addZImm(Scale).addReg(IndexReg).addSImm(Disp); else if (AM.BaseType == X86AddressMode::FrameIndexBase)
MIB.addFrameIndex(AM.Base.FrameIndex);
else
assert (0);
return MIB.addZImm(AM.Scale).addReg(AM.IndexReg).addSImm(AM.Disp);
} }
/// addFrameReference - This function is used to add a reference to the base of /// addFrameReference - This function is used to add a reference to the base of