Properly handle 'm' inline asm constraints. If a GV is being selected for the addressing mode, it requires the same logic for PIC relative addressing, etc.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@56526 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2008-09-24 00:05:32 +00:00
parent dd4924c564
commit da43bcf624
11 changed files with 78 additions and 25 deletions

View File

@ -1169,9 +1169,11 @@ public:
/// type to use for the specific AsmOperandInfo, setting /// type to use for the specific AsmOperandInfo, setting
/// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand /// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand
/// being passed in is available, it can be passed in as Op, otherwise an /// being passed in is available, it can be passed in as Op, otherwise an
/// empty SDValue can be passed. /// empty SDValue can be passed. If hasMemory is true it means one of the asm
/// constraint of the inline asm instruction being processed is 'm'.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo,
SDValue Op, SDValue Op,
bool hasMemory,
SelectionDAG *DAG = 0) const; SelectionDAG *DAG = 0) const;
/// getConstraintType - Given a constraint, return the type of constraint it /// getConstraintType - Given a constraint, return the type of constraint it
@ -1206,8 +1208,11 @@ public:
virtual const char *LowerXConstraint(MVT ConstraintVT) const; virtual const char *LowerXConstraint(MVT ConstraintVT) const;
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops. /// vector. If it is invalid, don't add anything to Ops. If hasMemory is true
/// it means one of the asm constraint of the inline asm instruction being
/// processed is 'm'.
virtual void LowerAsmOperandForConstraint(SDValue Op, char ConstraintLetter, virtual void LowerAsmOperandForConstraint(SDValue Op, char ConstraintLetter,
bool hasMemory,
std::vector<SDValue> &Ops, std::vector<SDValue> &Ops,
SelectionDAG &DAG) const; SelectionDAG &DAG) const;

View File

@ -4629,6 +4629,22 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber,
// Otherwise, we couldn't allocate enough registers for this. // Otherwise, we couldn't allocate enough registers for this.
} }
/// hasInlineAsmMemConstraint - Return true if the inline asm instruction being
/// processed uses a memory 'm' constraint.
static bool
hasInlineAsmMemConstraint(std::vector<InlineAsm::ConstraintInfo> &CInfos,
TargetLowering &TLI) {
for (unsigned i = 0, e = CInfos.size(); i != e; ++i) {
InlineAsm::ConstraintInfo &CI = CInfos[i];
for (unsigned j = 0, ee = CI.Codes.size(); j != ee; ++j) {
TargetLowering::ConstraintType CType = TLI.getConstraintType(CI.Codes[j]);
if (CType == TargetLowering::C_Memory)
return true;
}
}
return false;
}
/// visitInlineAsm - Handle a call to an InlineAsm object. /// visitInlineAsm - Handle a call to an InlineAsm object.
/// ///
@ -4652,6 +4668,8 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
// constraint. If so, we can't let the register allocator allocate any input // constraint. If so, we can't let the register allocator allocate any input
// registers, because it will not know to avoid the earlyclobbered output reg. // registers, because it will not know to avoid the earlyclobbered output reg.
bool SawEarlyClobber = false; bool SawEarlyClobber = false;
bool hasMemory = hasInlineAsmMemConstraint(ConstraintInfos, TLI);
unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
unsigned ResNo = 0; // ResNo - The result number of the next output. unsigned ResNo = 0; // ResNo - The result number of the next output.
@ -4724,7 +4742,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
OpInfo.ConstraintVT = OpVT; OpInfo.ConstraintVT = OpVT;
// Compute the constraint code and ConstraintType to use. // Compute the constraint code and ConstraintType to use.
TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, &DAG); TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, hasMemory, &DAG);
// Keep track of whether we see an earlyclobber. // Keep track of whether we see an earlyclobber.
SawEarlyClobber |= OpInfo.isEarlyClobber; SawEarlyClobber |= OpInfo.isEarlyClobber;
@ -4927,7 +4945,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
std::vector<SDValue> Ops; std::vector<SDValue> Ops;
TLI.LowerAsmOperandForConstraint(InOperandVal, OpInfo.ConstraintCode[0], TLI.LowerAsmOperandForConstraint(InOperandVal, OpInfo.ConstraintCode[0],
Ops, DAG); hasMemory, Ops, DAG);
if (Ops.empty()) { if (Ops.empty()) {
cerr << "Invalid operand for inline asm constraint '" cerr << "Invalid operand for inline asm constraint '"
<< OpInfo.ConstraintCode << "'!\n"; << OpInfo.ConstraintCode << "'!\n";

View File

@ -1855,6 +1855,7 @@ const char *TargetLowering::LowerXConstraint(MVT ConstraintVT) const{
/// vector. If it is invalid, don't add anything to Ops. /// vector. If it is invalid, don't add anything to Ops.
void TargetLowering::LowerAsmOperandForConstraint(SDValue Op, void TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
char ConstraintLetter, char ConstraintLetter,
bool hasMemory,
std::vector<SDValue> &Ops, std::vector<SDValue> &Ops,
SelectionDAG &DAG) const { SelectionDAG &DAG) const {
switch (ConstraintLetter) { switch (ConstraintLetter) {
@ -1997,7 +1998,7 @@ static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
/// 'm' over 'r', for example. /// 'm' over 'r', for example.
/// ///
static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo,
const TargetLowering &TLI, bool hasMemory, const TargetLowering &TLI,
SDValue Op, SelectionDAG *DAG) { SDValue Op, SelectionDAG *DAG) {
assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options"); assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options");
unsigned BestIdx = 0; unsigned BestIdx = 0;
@ -2017,7 +2018,7 @@ static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo,
assert(OpInfo.Codes[i].size() == 1 && assert(OpInfo.Codes[i].size() == 1 &&
"Unhandled multi-letter 'other' constraint"); "Unhandled multi-letter 'other' constraint");
std::vector<SDValue> ResultOps; std::vector<SDValue> ResultOps;
TLI.LowerAsmOperandForConstraint(Op, OpInfo.Codes[i][0], TLI.LowerAsmOperandForConstraint(Op, OpInfo.Codes[i][0], hasMemory,
ResultOps, *DAG); ResultOps, *DAG);
if (!ResultOps.empty()) { if (!ResultOps.empty()) {
BestType = CType; BestType = CType;
@ -2044,6 +2045,7 @@ static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo,
/// OpInfo.ConstraintCode and OpInfo.ConstraintType. /// OpInfo.ConstraintCode and OpInfo.ConstraintType.
void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo, void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo,
SDValue Op, SDValue Op,
bool hasMemory,
SelectionDAG *DAG) const { SelectionDAG *DAG) const {
assert(!OpInfo.Codes.empty() && "Must have at least one constraint"); assert(!OpInfo.Codes.empty() && "Must have at least one constraint");
@ -2052,7 +2054,7 @@ void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo,
OpInfo.ConstraintCode = OpInfo.Codes[0]; OpInfo.ConstraintCode = OpInfo.Codes[0];
OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode); OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode);
} else { } else {
ChooseConstraint(OpInfo, *this, Op, DAG); ChooseConstraint(OpInfo, hasMemory, *this, Op, DAG);
} }
// 'X' matches anything. // 'X' matches anything.

View File

@ -3040,10 +3040,12 @@ SPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
void void
SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op, SPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
char ConstraintLetter, char ConstraintLetter,
bool hasMemory,
std::vector<SDValue> &Ops, std::vector<SDValue> &Ops,
SelectionDAG &DAG) const { SelectionDAG &DAG) const {
// Default, for the time being, to the base class handler // Default, for the time being, to the base class handler
TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, Ops, DAG); TargetLowering::LowerAsmOperandForConstraint(Op, ConstraintLetter, hasMemory,
Ops, DAG);
} }
/// isLegalAddressImmediate - Return true if the integer value can be used /// isLegalAddressImmediate - Return true if the integer value can be used

View File

@ -131,6 +131,7 @@ namespace llvm {
MVT VT) const; MVT VT) const;
void LowerAsmOperandForConstraint(SDValue Op, char ConstraintLetter, void LowerAsmOperandForConstraint(SDValue Op, char ConstraintLetter,
bool hasMemory,
std::vector<SDValue> &Ops, std::vector<SDValue> &Ops,
SelectionDAG &DAG) const; SelectionDAG &DAG) const;

View File

@ -4763,8 +4763,11 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops. /// vector. If it is invalid, don't add anything to Ops. If hasMemory is true
/// it means one of the asm constraint of the inline asm instruction being
/// processed is 'm'.
void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op, char Letter, void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op, char Letter,
bool hasMemory,
std::vector<SDValue>&Ops, std::vector<SDValue>&Ops,
SelectionDAG &DAG) const { SelectionDAG &DAG) const {
SDValue Result(0,0); SDValue Result(0,0);
@ -4823,7 +4826,7 @@ void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op, char Letter,
} }
// Handle standard constraint letters. // Handle standard constraint letters.
TargetLowering::LowerAsmOperandForConstraint(Op, Letter, Ops, DAG); TargetLowering::LowerAsmOperandForConstraint(Op, Letter, hasMemory, Ops, DAG);
} }
// isLegalAddressingMode - Return true if the addressing mode represented // isLegalAddressingMode - Return true if the addressing mode represented

View File

@ -300,9 +300,12 @@ namespace llvm {
unsigned getByValTypeAlignment(const Type *Ty) const; unsigned getByValTypeAlignment(const Type *Ty) const;
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops. /// vector. If it is invalid, don't add anything to Ops. If hasMemory is
/// true it means one of the asm constraint of the inline asm instruction
/// being processed is 'm'.
virtual void LowerAsmOperandForConstraint(SDValue Op, virtual void LowerAsmOperandForConstraint(SDValue Op,
char ConstraintLetter, char ConstraintLetter,
bool hasMemory,
std::vector<SDValue> &Ops, std::vector<SDValue> &Ops,
SelectionDAG &DAG) const; SelectionDAG &DAG) const;

View File

@ -767,7 +767,7 @@ void X86DAGToDAGISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {
/// addressing mode. /// addressing mode.
bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM, bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
bool isRoot, unsigned Depth) { bool isRoot, unsigned Depth) {
DOUT << "MatchAddress: "; DEBUG(AM.dump()); DOUT << "MatchAddress: "; DEBUG(AM.dump());
// Limit recursion. // Limit recursion.
if (Depth > 5) if (Depth > 5)
return MatchAddressBase(N, AM, isRoot, Depth); return MatchAddressBase(N, AM, isRoot, Depth);

View File

@ -1593,7 +1593,7 @@ SDValue X86TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
if (CallRequiresFnAddressInReg(Is64Bit, IsTailCall)) { if (CallRequiresFnAddressInReg(Is64Bit, IsTailCall)) {
// Note: The actual moving to ecx is done further down. // Note: The actual moving to ecx is done further down.
GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee); GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee);
if (G && !G->getGlobal()->hasHiddenVisibility() && if (G && !G->getGlobal()->hasHiddenVisibility() &&
!G->getGlobal()->hasProtectedVisibility()) !G->getGlobal()->hasProtectedVisibility())
Callee = LowerGlobalAddress(Callee, DAG); Callee = LowerGlobalAddress(Callee, DAG);
else if (isa<ExternalSymbolSDNode>(Callee)) else if (isa<ExternalSymbolSDNode>(Callee))
@ -4300,8 +4300,8 @@ X86TargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) {
} }
SDValue SDValue
X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { X86TargetLowering::LowerGlobalAddress(const GlobalValue *GV,
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); SelectionDAG &DAG) const {
SDValue Result = DAG.getTargetGlobalAddress(GV, getPointerTy()); SDValue Result = DAG.getTargetGlobalAddress(GV, getPointerTy());
Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result); Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result);
// With PIC, the address is actually $g + Offset. // With PIC, the address is actually $g + Offset.
@ -4324,6 +4324,12 @@ X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) {
return Result; return Result;
} }
SDValue
X86TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) {
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
return LowerGlobalAddress(GV, DAG);
}
// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit // Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit
static SDValue static SDValue
LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG, LowerToTLSGeneralDynamicModel32(GlobalAddressSDNode *GA, SelectionDAG &DAG,
@ -7067,6 +7073,7 @@ LowerXConstraint(MVT ConstraintVT) const {
/// vector. If it is invalid, don't add anything to Ops. /// vector. If it is invalid, don't add anything to Ops.
void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op, void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
char Constraint, char Constraint,
bool hasMemory,
std::vector<SDValue>&Ops, std::vector<SDValue>&Ops,
SelectionDAG &DAG) const { SelectionDAG &DAG) const {
SDValue Result(0, 0); SDValue Result(0, 0);
@ -7128,14 +7135,11 @@ void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
} }
if (GA) { if (GA) {
// If addressing this global requires a load (e.g. in PIC mode), we can't if (hasMemory)
// match. Op = LowerGlobalAddress(GA->getGlobal(), DAG);
if (Subtarget->GVRequiresExtraLoad(GA->getGlobal(), getTargetMachine(), else
false)) Op = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0),
return; Offset);
Op = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0),
Offset);
Result = Op; Result = Op;
break; break;
} }
@ -7149,7 +7153,8 @@ void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
Ops.push_back(Result); Ops.push_back(Result);
return; return;
} }
return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, hasMemory,
Ops, DAG);
} }
std::vector<unsigned> X86TargetLowering:: std::vector<unsigned> X86TargetLowering::

View File

@ -403,9 +403,12 @@ namespace llvm {
virtual const char *LowerXConstraint(MVT ConstraintVT) const; virtual const char *LowerXConstraint(MVT ConstraintVT) const;
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops. /// vector. If it is invalid, don't add anything to Ops. If hasMemory is
/// true it means one of the asm constraint of the inline asm instruction
/// being processed is 'm'.
virtual void LowerAsmOperandForConstraint(SDValue Op, virtual void LowerAsmOperandForConstraint(SDValue Op,
char ConstraintLetter, char ConstraintLetter,
bool hasMemory,
std::vector<SDValue> &Ops, std::vector<SDValue> &Ops,
SelectionDAG &DAG) const; SelectionDAG &DAG) const;
@ -529,6 +532,7 @@ namespace llvm {
SDValue LowerINSERT_VECTOR_ELT_SSE4(SDValue Op, SelectionDAG &DAG); SDValue LowerINSERT_VECTOR_ELT_SSE4(SDValue Op, SelectionDAG &DAG);
SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG); SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG);
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG); SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddress(const GlobalValue *GV, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG); SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG); SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG); SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG);

View File

@ -0,0 +1,10 @@
; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -relocation-model=pic | grep lea
; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -relocation-model=pic | grep call
@main_q = internal global i8* null ; <i8**> [#uses=1]
define void @func2() nounwind {
entry:
tail call void asm "mov $1,%gs:$0", "=*m,ri,~{dirflag},~{fpsr},~{flags}"(i8** inttoptr (i32 152 to i8**), i8* bitcast (i8** @main_q to i8*)) nounwind
ret void
}