summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-05-03 16:52:29 +0000
committerChris Lattner <sabre@nondot.org>2007-05-03 16:52:29 +0000
commit83df45a95937fa31c62a9cfedad5e428a13b04e9 (patch)
tree3a82bd42aa0572bcede96476a713723a9f337471 /llvm/lib
parent9a8c7cf00b9ed24ac8387a3ccfc150f9afb3b28c (diff)
downloadbcm5719-llvm-83df45a95937fa31c62a9cfedad5e428a13b04e9.tar.gz
bcm5719-llvm-83df45a95937fa31c62a9cfedad5e428a13b04e9.zip
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". llvm-svn: 36670
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp40
1 files changed, 32 insertions, 8 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 9366f9a6e37..da95925848f 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/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);
}
OpenPOWER on IntegriCloud