diff options
author | Chris Lattner <sabre@nondot.org> | 2007-05-03 16:54:34 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-05-03 16:54:34 +0000 |
commit | 75c7d2bd551acd1ad4f0f58b763ec8840f1d9c34 (patch) | |
tree | 54047994e5fba1fbbec10ec9df91dcf6d7c7d4d8 /lib/CodeGen/SelectionDAG/TargetLowering.cpp | |
parent | b0d151540d03618ae6cf3378aecd8c01636520df (diff) |
Allow i/s to match (gv+c). This fixes CodeGen/PowerPC/2007-05-03-InlineAsm-S-Constraint.ll
and PR1382
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36672 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/TargetLowering.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/TargetLowering.cpp | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 90cf86f23c..1a8a4bc349 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1915,22 +1915,43 @@ SDOperand TargetLowering::isOperandValidForConstraint(SDOperand Op, case 'i': // Simple Integer or Relocatable Constant case 'n': // Simple Integer case 's': // Relocatable Constant - case 'X': // Allows any operand. - // These are okay if the operand is either a global variable address or a - // simple immediate value. If we have one of these, map to the TargetXXX - // version so that the value itself doesn't get selected. - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { + case 'X': { // Allows any operand. + // These operands are interested in values of the form (GV+C), where C may + // be folded in as an offset of GV, or it may be explicitly added. Also, it + // is possible and fine if either GV or C are missing. + ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op); + GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op); + + // If we have "(add GV, C)", pull out GV/C + if (Op.getOpcode() == ISD::ADD) { + C = dyn_cast<ConstantSDNode>(Op.getOperand(1)); + GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(0)); + if (C == 0 || GA == 0) { + C = dyn_cast<ConstantSDNode>(Op.getOperand(0)); + GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(1)); + } + if (C == 0 || GA == 0) + C = 0, GA = 0; + } + + // If we find a valid operand, map to the TargetXXX version so that the + // value itself doesn't get selected. + if (GA) { // Either &GV or &GV+C + if (ConstraintLetter != 'n') { + int64_t Offs = GA->getOffset(); + if (C) Offs += C->getValue(); + return DAG.getTargetGlobalAddress(GA->getGlobal(), Op.getValueType(), + Offs); + } + } + if (C) { // just C, no GV. // Simple constants are not allowed for 's'. if (ConstraintLetter != 's') return DAG.getTargetConstant(C->getValue(), Op.getValueType()); } - if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) { - if (ConstraintLetter != 'n') - return DAG.getTargetGlobalAddress(GA->getGlobal(), Op.getValueType(), - GA->getOffset()); - } break; } + } return SDOperand(0,0); } |