bool X86DAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset,
X86ISelAddressMode &AM) {
- // If the final displacement is 0, we don't need to do any work. We may have
- // already matched a displacement and the caller just added the symbolic
- // displacement with an offset of 0. So recheck everything if Val is non-zero.
- int64_t Val = AM.Disp + Offset;
- if (Val == 0)
+ // If there's no offset to fold, we don't need to do any work.
+ if (Offset == 0)
return false;
// Cannot combine ExternalSymbol displacements with integer offsets.
if (AM.ES || AM.MCSym)
return true;
+ int64_t Val = AM.Disp + Offset;
CodeModel::Model M = TM.getCodeModel();
if (Subtarget->is64Bit()) {
if (!X86::isOffsetSuitableForCodeModel(Val, M,
if (!matchAddressRecursively(N.getOperand(0), AM, Depth+1) &&
!matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth+1))
return false;
- AM = Backup;
- // Try again after commutating the operands.
- if (!matchAddressRecursively(Handle.getValue().getOperand(1), AM,
- Depth + 1) &&
- !matchAddressRecursively(Handle.getValue().getOperand(0), AM, Depth + 1))
- return false;
+ // Don't try commuting operands if the address is in the form of
+ // sym+disp(%rip). foldOffsetIntoAddress() currently does not know there is a
+ // symbolic displacement and would fold disp. If disp is just a bit smaller
+ // than 2**31, it can easily cause a relocation overflow.
+ bool NoCommutate = false;
+ if (AM.isRIPRelative() && AM.hasSymbolicDisplacement())
+ if (ConstantSDNode *Cst =
+ dyn_cast<ConstantSDNode>(Handle.getValue().getOperand(1)))
+ NoCommutate = Cst->getSExtValue() != 0;
+
+ AM = Backup;
+ if (!NoCommutate) {
+ // Try again after commutating the operands.
+ if (!matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1) &&
+ !matchAddressRecursively(Handle.getValue().getOperand(0), AM, Depth + 1))
+ return false;
+ }
AM = Backup;
// If we couldn't fold both operands into the address at the same time,