diff options
author | Chris Lattner <sabre@nondot.org> | 2009-05-08 18:23:14 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-05-08 18:23:14 +0000 |
commit | 49921963220485efb9610a45cb21952dd0cdb67f (patch) | |
tree | 332aa99786f8c6b1307eadf0aa0f9eb9baa53f89 /lib | |
parent | 2a6e0a2140f3fc3597fdefa8c4179a230b29b267 (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.cpp | 57 |
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; } } |