diff options
author | Chris Lattner <sabre@nondot.org> | 2007-05-03 16:52:29 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-05-03 16:52:29 +0000 |
commit | dc43a88b81f3d1766688082aa23a5203731fd248 (patch) | |
tree | 32778f07f9bf26044c91cb061818d01c3d741a47 /lib/Target | |
parent | 388488d604a63fc25d5f6b2c598f7cc4499c9db5 (diff) |
Fix two classes of bugs:
1. x86 backend rejected (&gv+c) for the 'i' constraint when in static mode.
2. the matcher didn't correctly reject and accept some global addresses.
the right predicate is GVRequiresExtraLoad, not "relomodel = pic".
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36670 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 9366f9a6e3..da95925848 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -4734,25 +4734,49 @@ isOperandValidForConstraint(SDOperand Op, char Constraint, SelectionDAG &DAG) { return Op; } return SDOperand(0,0); - case 'i': + case 'i': { // Literal immediates are always ok. if (isa<ConstantSDNode>(Op)) return Op; - // If we are in non-pic codegen mode, we allow the address of a global to - // be used with 'i'. - if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) { - if (getTargetMachine().getRelocationModel() == Reloc::PIC_) + // If we are in non-pic codegen mode, we allow the address of a global (with + // an optional displacement) to be used with 'i'. + GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op); + int64_t Offset = 0; + + // Match either (GA) or (GA+C) + if (GA) { + Offset = GA->getOffset(); + } else if (Op.getOpcode() == ISD::ADD) { + ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1)); + GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(0)); + if (C && GA) { + Offset = GA->getOffset()+C->getValue(); + } else { + C = dyn_cast<ConstantSDNode>(Op.getOperand(1)); + GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(0)); + if (C && GA) + Offset = GA->getOffset()+C->getValue(); + else + C = 0, GA = 0; + } + } + + if (GA) { + // If addressing this global requires a load (e.g. in PIC mode), we can't + // match. + if (Subtarget->GVRequiresExtraLoad(GA->getGlobal(), getTargetMachine(), + false)) return SDOperand(0, 0); - if (GA->getOpcode() != ISD::TargetGlobalAddress) - Op = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0), - GA->getOffset()); + Op = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0), + Offset); return Op; } // Otherwise, not valid for this mode. return SDOperand(0, 0); } + } return TargetLowering::isOperandValidForConstraint(Op, Constraint, DAG); } |