Fix a x86-64 codegen deficiency. Allow gv + offset when using rip addressing mode.
Before:
_main:
subq $8, %rsp
leaq _X(%rip), %rax
movsd 8(%rax), %xmm1
movss _X(%rip), %xmm0
call _t
xorl %ecx, %ecx
movl %ecx, %eax
addq $8, %rsp
ret
Now:
_main:
subq $8, %rsp
movsd _X+8(%rip), %xmm1
movss _X(%rip), %xmm0
call _t
xorl %ecx, %ecx
movl %ecx, %eax
addq $8, %rsp
ret
Notice there is another idiotic codegen issue that needs to be fixed asap:
xorl %ecx, %ecx
movl %ecx, %eax
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46850 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index c51cd80..0703563 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -63,7 +63,7 @@
int FrameIndex;
} Base;
- bool isRIPRel; // RIP relative?
+ bool isRIPRel; // RIP as base?
unsigned Scale;
SDOperand IndexReg;
unsigned Disp;
@@ -664,7 +664,9 @@
case X86ISD::Wrapper: {
bool is64Bit = Subtarget->is64Bit();
// Under X86-64 non-small code model, GV (and friends) are 64-bits.
- if (is64Bit && TM.getCodeModel() != CodeModel::Small)
+ // Also, base and index reg must be 0 in order to use rip as base.
+ if (is64Bit && (TM.getCodeModel() != CodeModel::Small ||
+ AM.Base.Reg.Val || AM.IndexReg.Val))
break;
if (AM.GV != 0 || AM.CP != 0 || AM.ES != 0 || AM.JT != -1)
break;
@@ -672,39 +674,27 @@
// been picked, we can't fit the result available in the register in the
// addressing mode. Duplicate GlobalAddress or ConstantPool as displacement.
if (!AlreadySelected || (AM.Base.Reg.Val && AM.IndexReg.Val)) {
- bool isStatic = TM.getRelocationModel() == Reloc::Static;
SDOperand N0 = N.getOperand(0);
- // Mac OS X X86-64 lower 4G address is not available.
- bool isAbs32 = !is64Bit ||
- (isStatic && Subtarget->hasLow4GUserSpaceAddress());
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
GlobalValue *GV = G->getGlobal();
- if (isAbs32 || isRoot) {
- AM.GV = GV;
- AM.Disp += G->getOffset();
- AM.isRIPRel = !isAbs32;
- return false;
- }
+ AM.GV = GV;
+ AM.Disp += G->getOffset();
+ AM.isRIPRel = is64Bit;
+ return false;
} else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
- if (isAbs32 || isRoot) {
- AM.CP = CP->getConstVal();
- AM.Align = CP->getAlignment();
- AM.Disp += CP->getOffset();
- AM.isRIPRel = !isAbs32;
- return false;
- }
+ AM.CP = CP->getConstVal();
+ AM.Align = CP->getAlignment();
+ AM.Disp += CP->getOffset();
+ AM.isRIPRel = is64Bit;
+ return false;
} else if (ExternalSymbolSDNode *S =dyn_cast<ExternalSymbolSDNode>(N0)) {
- if (isAbs32 || isRoot) {
- AM.ES = S->getSymbol();
- AM.isRIPRel = !isAbs32;
- return false;
- }
+ AM.ES = S->getSymbol();
+ AM.isRIPRel = is64Bit;
+ return false;
} else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
- if (isAbs32 || isRoot) {
- AM.JT = J->getIndex();
- AM.isRIPRel = !isAbs32;
- return false;
- }
+ AM.JT = J->getIndex();
+ AM.isRIPRel = is64Bit;
+ return false;
}
}
break;
@@ -719,7 +709,7 @@
break;
case ISD::SHL:
- if (AlreadySelected || AM.IndexReg.Val != 0 || AM.Scale != 1)
+ if (AlreadySelected || AM.IndexReg.Val != 0 || AM.Scale != 1 || AM.isRIPRel)
break;
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1))) {
@@ -759,7 +749,8 @@
if (!AlreadySelected &&
AM.BaseType == X86ISelAddressMode::RegBase &&
AM.Base.Reg.Val == 0 &&
- AM.IndexReg.Val == 0) {
+ AM.IndexReg.Val == 0 &&
+ !AM.isRIPRel) {
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1)))
if (CN->getValue() == 3 || CN->getValue() == 5 || CN->getValue() == 9) {
AM.Scale = unsigned(CN->getValue())-1;
@@ -834,6 +825,9 @@
// Scale must not be used already.
if (AM.IndexReg.Val != 0 || AM.Scale != 1) break;
+
+ // Not when RIP is used as the base.
+ if (AM.isRIPRel) break;
ConstantSDNode *C2 = dyn_cast<ConstantSDNode>(N.getOperand(1));
ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(Shift.getOperand(1));
@@ -874,7 +868,7 @@
// Is the base register already occupied?
if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base.Reg.Val) {
// If so, check to see if the scale index register is set.
- if (AM.IndexReg.Val == 0) {
+ if (AM.IndexReg.Val == 0 && !AM.isRIPRel) {
AM.IndexReg = N;
AM.Scale = 1;
return false;