aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-05-08 18:23:14 +0000
committerChris Lattner <sabre@nondot.org>2009-05-08 18:23:14 +0000
commit49921963220485efb9610a45cb21952dd0cdb67f (patch)
tree332aa99786f8c6b1307eadf0aa0f9eb9baa53f89 /lib
parent2a6e0a2140f3fc3597fdefa8c4179a230b29b267 (diff)
Fix PR4152: asm constraint validation happens before dag combine, so we
need to work a bit to combine things like (x+c1+c2) into x+c3. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71232 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp57
1 files changed, 28 insertions, 29 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 72aadef384..9ac59df5bd 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -8519,40 +8519,39 @@ void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
// 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);
+ GlobalAddressSDNode *GA = 0;
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->getZExtValue();
- } else {
- C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
- GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(0));
- if (C && GA)
- Offset = GA->getOffset()+C->getZExtValue();
- else
- C = 0, GA = 0;
+ // Match either (GA), (GA+C), (GA+C1+C2), etc.
+ while (1) {
+ if ((GA = dyn_cast<GlobalAddressSDNode>(Op))) {
+ Offset += GA->getOffset();
+ break;
+ } else if (Op.getOpcode() == ISD::ADD) {
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
+ Offset += C->getZExtValue();
+ Op = Op.getOperand(0);
+ continue;
+ }
+ } else if (Op.getOpcode() == ISD::SUB) {
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
+ Offset += -C->getZExtValue();
+ Op = Op.getOperand(0);
+ continue;
+ }
}
+
+ // Otherwise, this isn't something we can handle, reject it.
+ return;
}
- if (GA) {
- if (hasMemory)
- Op = LowerGlobalAddress(GA->getGlobal(), Op.getDebugLoc(),
- Offset, DAG);
- else
- Op = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0),
- Offset);
- Result = Op;
- break;
- }
-
- // Otherwise, not valid for this mode.
- return;
+ if (hasMemory)
+ Op = LowerGlobalAddress(GA->getGlobal(), Op.getDebugLoc(), Offset, DAG);
+ else
+ Op = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0),
+ Offset);
+ Result = Op;
+ break;
}
}