split call handling out of X86SelectAddress into X86SelectCallAddress

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75228 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2009-07-10 05:33:42 +00:00
parent 8a537121cb
commit 0aa43de1d0

View File

@ -90,7 +90,8 @@ private:
bool X86FastEmitExtend(ISD::NodeType Opc, MVT DstVT, unsigned Src, MVT SrcVT, bool X86FastEmitExtend(ISD::NodeType Opc, MVT DstVT, unsigned Src, MVT SrcVT,
unsigned &ResultReg); unsigned &ResultReg);
bool X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall); bool X86SelectAddress(Value *V, X86AddressMode &AM);
bool X86SelectCallAddress(Value *V, X86AddressMode &AM);
bool X86SelectLoad(Instruction *I); bool X86SelectLoad(Instruction *I);
@ -318,7 +319,7 @@ bool X86FastISel::X86FastEmitExtend(ISD::NodeType Opc, MVT DstVT,
/// X86SelectAddress - Attempt to fill in an address from the given value. /// X86SelectAddress - Attempt to fill in an address from the given value.
/// ///
bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) { bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) {
User *U = NULL; User *U = NULL;
unsigned Opcode = Instruction::UserOp1; unsigned Opcode = Instruction::UserOp1;
if (Instruction *I = dyn_cast<Instruction>(V)) { if (Instruction *I = dyn_cast<Instruction>(V)) {
@ -333,22 +334,21 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
default: break; default: break;
case Instruction::BitCast: case Instruction::BitCast:
// Look past bitcasts. // Look past bitcasts.
return X86SelectAddress(U->getOperand(0), AM, isCall); return X86SelectAddress(U->getOperand(0), AM);
case Instruction::IntToPtr: case Instruction::IntToPtr:
// Look past no-op inttoptrs. // Look past no-op inttoptrs.
if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy()) if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy())
return X86SelectAddress(U->getOperand(0), AM, isCall); return X86SelectAddress(U->getOperand(0), AM);
break; break;
case Instruction::PtrToInt: case Instruction::PtrToInt:
// Look past no-op ptrtoints. // Look past no-op ptrtoints.
if (TLI.getValueType(U->getType()) == TLI.getPointerTy()) if (TLI.getValueType(U->getType()) == TLI.getPointerTy())
return X86SelectAddress(U->getOperand(0), AM, isCall); return X86SelectAddress(U->getOperand(0), AM);
break; break;
case Instruction::Alloca: { case Instruction::Alloca: {
if (isCall) break;
// Do static allocas. // Do static allocas.
const AllocaInst *A = cast<AllocaInst>(V); const AllocaInst *A = cast<AllocaInst>(V);
DenseMap<const AllocaInst*, int>::iterator SI = StaticAllocaMap.find(A); DenseMap<const AllocaInst*, int>::iterator SI = StaticAllocaMap.find(A);
@ -361,21 +361,19 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
} }
case Instruction::Add: { case Instruction::Add: {
if (isCall) break;
// Adds of constants are common and easy enough. // Adds of constants are common and easy enough.
if (ConstantInt *CI = dyn_cast<ConstantInt>(U->getOperand(1))) { if (ConstantInt *CI = dyn_cast<ConstantInt>(U->getOperand(1))) {
uint64_t Disp = (int32_t)AM.Disp + (uint64_t)CI->getSExtValue(); uint64_t Disp = (int32_t)AM.Disp + (uint64_t)CI->getSExtValue();
// They have to fit in the 32-bit signed displacement field though. // They have to fit in the 32-bit signed displacement field though.
if (isInt32(Disp)) { if (isInt32(Disp)) {
AM.Disp = (uint32_t)Disp; AM.Disp = (uint32_t)Disp;
return X86SelectAddress(U->getOperand(0), AM, isCall); return X86SelectAddress(U->getOperand(0), AM);
} }
} }
break; break;
} }
case Instruction::GetElementPtr: { case Instruction::GetElementPtr: {
if (isCall) break;
// Pattern-match simple GEPs. // Pattern-match simple GEPs.
uint64_t Disp = (int32_t)AM.Disp; uint64_t Disp = (int32_t)AM.Disp;
unsigned IndexReg = AM.IndexReg; unsigned IndexReg = AM.IndexReg;
@ -416,7 +414,7 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
AM.IndexReg = IndexReg; AM.IndexReg = IndexReg;
AM.Scale = Scale; AM.Scale = Scale;
AM.Disp = (uint32_t)Disp; AM.Disp = (uint32_t)Disp;
return X86SelectAddress(U->getOperand(0), AM, isCall); return X86SelectAddress(U->getOperand(0), AM);
unsupported_gep: unsupported_gep:
// Ok, the GEP indices weren't all covered. // Ok, the GEP indices weren't all covered.
break; break;
@ -443,8 +441,7 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
// Okay, we've committed to selecting this global. Set up the basic address. // Okay, we've committed to selecting this global. Set up the basic address.
AM.GV = GV; AM.GV = GV;
if (!isCall && if (TM.getRelocationModel() == Reloc::PIC_ &&
TM.getRelocationModel() == Reloc::PIC_ &&
!Subtarget->is64Bit()) { !Subtarget->is64Bit()) {
// FIXME: How do we know Base.Reg is free?? // FIXME: How do we know Base.Reg is free??
AM.Base.Reg = getInstrInfo()->getGlobalBaseReg(&MF); AM.Base.Reg = getInstrInfo()->getGlobalBaseReg(&MF);
@ -452,7 +449,7 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
// If the ABI doesn't require an extra load, return a direct reference to // If the ABI doesn't require an extra load, return a direct reference to
// the global. // the global.
if (!Subtarget->GVRequiresExtraLoad(GV, TM, isCall)) { if (!Subtarget->GVRequiresExtraLoad(GV, TM, false)) {
if (Subtarget->isPICStyleRIPRel()) { if (Subtarget->isPICStyleRIPRel()) {
// Use rip-relative addressing if we can. Above we verified that the // Use rip-relative addressing if we can. Above we verified that the
// base and index registers are unused. // base and index registers are unused.
@ -546,6 +543,155 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) {
return false; return false;
} }
/// X86SelectCallAddress - Attempt to fill in an address from the given value.
///
bool X86FastISel::X86SelectCallAddress(Value *V, X86AddressMode &AM) {
User *U = NULL;
unsigned Opcode = Instruction::UserOp1;
if (Instruction *I = dyn_cast<Instruction>(V)) {
Opcode = I->getOpcode();
U = I;
} else if (ConstantExpr *C = dyn_cast<ConstantExpr>(V)) {
Opcode = C->getOpcode();
U = C;
}
switch (Opcode) {
default: break;
case Instruction::BitCast:
// Look past bitcasts.
return X86SelectCallAddress(U->getOperand(0), AM);
case Instruction::IntToPtr:
// Look past no-op inttoptrs.
if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy())
return X86SelectCallAddress(U->getOperand(0), AM);
break;
case Instruction::PtrToInt:
// Look past no-op ptrtoints.
if (TLI.getValueType(U->getType()) == TLI.getPointerTy())
return X86SelectCallAddress(U->getOperand(0), AM);
break;
}
// Handle constant address.
if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
// Can't handle alternate code models yet.
if (TM.getCodeModel() != CodeModel::Default &&
TM.getCodeModel() != CodeModel::Small)
return false;
// RIP-relative addresses can't have additional register operands.
if (Subtarget->isPICStyleRIPRel() &&
(AM.Base.Reg != 0 || AM.IndexReg != 0))
return false;
// Can't handle TLS yet.
if (GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
if (GVar->isThreadLocal())
return false;
// Okay, we've committed to selecting this global. Set up the basic address.
AM.GV = GV;
// If the ABI doesn't require an extra load, return a direct reference to
// the global.
if (!Subtarget->GVRequiresExtraLoad(GV, TM, true)) {
if (Subtarget->isPICStyleRIPRel()) {
// Use rip-relative addressing if we can. Above we verified that the
// base and index registers are unused.
assert(AM.Base.Reg == 0 && AM.IndexReg == 0);
AM.Base.Reg = X86::RIP;
} else if (Subtarget->isPICStyleStub() &&
TM.getRelocationModel() == Reloc::PIC_) {
AM.GVOpFlags = X86II::MO_PIC_BASE_OFFSET;
} else if (Subtarget->isPICStyleGOT()) {
AM.GVOpFlags = X86II::MO_GOTOFF;
}
return true;
}
// Check to see if we've already materialized this stub loaded value into a
// register in this block. If so, just reuse it.
DenseMap<const Value*, unsigned>::iterator I = LocalValueMap.find(V);
unsigned LoadReg;
if (I != LocalValueMap.end() && I->second != 0) {
LoadReg = I->second;
} else {
// Issue load from stub.
unsigned Opc = 0;
const TargetRegisterClass *RC = NULL;
X86AddressMode StubAM;
StubAM.Base.Reg = AM.Base.Reg;
StubAM.GV = GV;
if (TLI.getPointerTy() == MVT::i64) {
Opc = X86::MOV64rm;
RC = X86::GR64RegisterClass;
if (Subtarget->isPICStyleRIPRel()) {
StubAM.GVOpFlags = X86II::MO_GOTPCREL;
StubAM.Base.Reg = X86::RIP;
}
} else {
Opc = X86::MOV32rm;
RC = X86::GR32RegisterClass;
if (Subtarget->isPICStyleGOT())
StubAM.GVOpFlags = X86II::MO_GOT;
else if (Subtarget->isPICStyleStub()) {
// In darwin, we have multiple different stub types, and we have both
// PIC and -mdynamic-no-pic. Determine whether we have a stub
// reference and/or whether the reference is relative to the PIC base
// or not.
bool IsPIC = TM.getRelocationModel() == Reloc::PIC_;
if (!GV->hasHiddenVisibility()) {
// Non-hidden $non_lazy_ptr reference.
StubAM.GVOpFlags = IsPIC ? X86II::MO_DARWIN_NONLAZY_PIC_BASE :
X86II::MO_DARWIN_NONLAZY;
} else {
// Hidden $non_lazy_ptr reference.
StubAM.GVOpFlags = IsPIC ? X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
X86II::MO_DARWIN_HIDDEN_NONLAZY;
}
}
}
LoadReg = createResultReg(RC);
addFullAddress(BuildMI(MBB, DL, TII.get(Opc), LoadReg), StubAM);
// Prevent loading GV stub multiple times in same MBB.
LocalValueMap[V] = LoadReg;
}
// Now construct the final address. Note that the Disp, Scale,
// and Index values may already be set here.
AM.Base.Reg = LoadReg;
AM.GV = 0;
return true;
}
// If all else fails, try to materialize the value in a register.
if (!AM.GV || !Subtarget->isPICStyleRIPRel()) {
if (AM.Base.Reg == 0) {
AM.Base.Reg = getRegForValue(V);
return AM.Base.Reg != 0;
}
if (AM.IndexReg == 0) {
assert(AM.Scale == 1 && "Scale with no index!");
AM.IndexReg = getRegForValue(V);
return AM.IndexReg != 0;
}
}
return false;
}
/// X86SelectStore - Select and emit code to implement store instructions. /// X86SelectStore - Select and emit code to implement store instructions.
bool X86FastISel::X86SelectStore(Instruction* I) { bool X86FastISel::X86SelectStore(Instruction* I) {
MVT VT; MVT VT;
@ -553,7 +699,7 @@ bool X86FastISel::X86SelectStore(Instruction* I) {
return false; return false;
X86AddressMode AM; X86AddressMode AM;
if (!X86SelectAddress(I->getOperand(1), AM, false)) if (!X86SelectAddress(I->getOperand(1), AM))
return false; return false;
return X86FastEmitStore(VT, I->getOperand(0), AM); return X86FastEmitStore(VT, I->getOperand(0), AM);
@ -567,7 +713,7 @@ bool X86FastISel::X86SelectLoad(Instruction *I) {
return false; return false;
X86AddressMode AM; X86AddressMode AM;
if (!X86SelectAddress(I->getOperand(0), AM, false)) if (!X86SelectAddress(I->getOperand(0), AM))
return false; return false;
unsigned ResultReg = 0; unsigned ResultReg = 0;
@ -1181,7 +1327,7 @@ bool X86FastISel::X86SelectCall(Instruction *I) {
// Materialize callee address in a register. FIXME: GV address can be // Materialize callee address in a register. FIXME: GV address can be
// handled with a CALLpcrel32 instead. // handled with a CALLpcrel32 instead.
X86AddressMode CalleeAM; X86AddressMode CalleeAM;
if (!X86SelectAddress(Callee, CalleeAM, true)) if (!X86SelectCallAddress(Callee, CalleeAM))
return false; return false;
unsigned CalleeOp = 0; unsigned CalleeOp = 0;
GlobalValue *GV = 0; GlobalValue *GV = 0;
@ -1540,7 +1686,7 @@ unsigned X86FastISel::TargetMaterializeConstant(Constant *C) {
// Materialize addresses with LEA instructions. // Materialize addresses with LEA instructions.
if (isa<GlobalValue>(C)) { if (isa<GlobalValue>(C)) {
X86AddressMode AM; X86AddressMode AM;
if (X86SelectAddress(C, AM, false)) { if (X86SelectAddress(C, AM)) {
if (TLI.getPointerTy() == MVT::i32) if (TLI.getPointerTy() == MVT::i32)
Opc = X86::LEA32r; Opc = X86::LEA32r;
else else
@ -1595,7 +1741,7 @@ unsigned X86FastISel::TargetMaterializeAlloca(AllocaInst *C) {
return 0; return 0;
X86AddressMode AM; X86AddressMode AM;
if (!X86SelectAddress(C, AM, false)) if (!X86SelectAddress(C, AM))
return 0; return 0;
unsigned Opc = Subtarget->is64Bit() ? X86::LEA64r : X86::LEA32r; unsigned Opc = Subtarget->is64Bit() ? X86::LEA64r : X86::LEA32r;
TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy()); TargetRegisterClass* RC = TLI.getRegClassFor(TLI.getPointerTy());