aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2013-06-01 09:55:14 +0000
committerTim Northover <tnorthover@apple.com>2013-06-01 09:55:14 +0000
commit85c622d6b6633c19d2729e82453c6c7f56ee7cd9 (patch)
tree7926a5dac9bd3ca0f95366bf9e0f7aea89a84253
parent72ad17c48c15562fe31c65f6daa09c83f42860c1 (diff)
downloadexternal_llvm-85c622d6b6633c19d2729e82453c6c7f56ee7cd9.zip
external_llvm-85c622d6b6633c19d2729e82453c6c7f56ee7cd9.tar.gz
external_llvm-85c622d6b6633c19d2729e82453c6c7f56ee7cd9.tar.bz2
X86: change MOV64ri64i32 into MOV32ri64
The MOV64ri64i32 instruction required hacky MCInst lowering because it was allocated as setting a GR64, but the eventual instruction ("movl") only set a GR32. This converts it into a so-called "MOV32ri64" which still accepts a (appropriate) 64-bit immediate but defines a GR32. This is then converted to the full GR64 by a SUBREG_TO_REG operation, thus keeping everyone happy. This fixes a typo in the opcode field of the original patch, which should make the legact JIT work again (& adds test for that problem). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183068 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/X86CodeEmitter.cpp2
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp28
-rw-r--r--lib/Target/X86/X86InstrCompiler.td30
-rw-r--r--lib/Target/X86/X86MCInstLower.cpp17
-rw-r--r--test/CodeGen/X86/abi-isel.ll20
-rw-r--r--test/ExecutionEngine/mov64zext32.ll17
6 files changed, 72 insertions, 42 deletions
diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp
index 8fea6ed..c3734a2 100644
--- a/lib/Target/X86/X86CodeEmitter.cpp
+++ b/lib/Target/X86/X86CodeEmitter.cpp
@@ -1270,7 +1270,7 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
: (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
- if (Opcode == X86::MOV64ri64i32)
+ if (Opcode == X86::MOV32ri64)
rt = X86::reloc_absolute_word; // FIXME: add X86II flag?
// This should not occur on Darwin for relocatable objects.
if (Opcode == X86::MOV64ri)
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index 0b6940e..02f5fe4 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -200,6 +200,7 @@ namespace {
bool SelectAddr(SDNode *Parent, SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index, SDValue &Disp,
SDValue &Segment);
+ bool SelectMOV64Imm32(SDValue N, SDValue &Imm);
bool SelectLEAAddr(SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index, SDValue &Disp,
SDValue &Segment);
@@ -1380,6 +1381,33 @@ bool X86DAGToDAGISel::SelectScalarSSELoad(SDNode *Root,
}
+bool X86DAGToDAGISel::SelectMOV64Imm32(SDValue N, SDValue &Imm) {
+ if (const ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) {
+ uint64_t ImmVal = CN->getZExtValue();
+ if ((uint32_t)ImmVal != (uint64_t)ImmVal)
+ return false;
+
+ Imm = CurDAG->getTargetConstant(ImmVal, MVT::i64);
+ return true;
+ }
+
+ // In static codegen with small code model, we can get the address of a label
+ // into a register with 'movl'. TableGen has already made sure we're looking
+ // at a label of some kind.
+ assert(N->getOpcode() == X86ISD::Wrapper && "Unexpected node type for MOV32ri64");
+ N = N.getOperand(0);
+
+ if (N->getOpcode() != ISD::TargetConstantPool &&
+ N->getOpcode() != ISD::TargetJumpTable &&
+ N->getOpcode() != ISD::TargetGlobalAddress &&
+ N->getOpcode() != ISD::TargetExternalSymbol &&
+ N->getOpcode() != ISD::TargetBlockAddress)
+ return false;
+
+ Imm = N;
+ return TM.getCodeModel() == CodeModel::Small;
+}
+
/// SelectLEAAddr - it calls SelectAddr and determines if the maximal addressing
/// mode it matches can be cost effectively emitted as an LEA instruction.
bool X86DAGToDAGISel::SelectLEAAddr(SDValue N,
diff --git a/lib/Target/X86/X86InstrCompiler.td b/lib/Target/X86/X86InstrCompiler.td
index 213993a..8a7ee7d 100644
--- a/lib/Target/X86/X86InstrCompiler.td
+++ b/lib/Target/X86/X86InstrCompiler.td
@@ -236,10 +236,18 @@ def : Pat<(i64 0), (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit)> {
// use MOV32ri with a SUBREG_TO_REG to represent the zero-extension, however
// that would make it more difficult to rematerialize.
let AddedComplexity = 1, isReMaterializable = 1, isAsCheapAsAMove = 1,
- isCodeGenOnly = 1 in
-def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src),
- "", [(set GR64:$dst, i64immZExt32:$src)],
- IIC_ALU_NONMEM>, Sched<[WriteALU]>;
+ isCodeGenOnly = 1, neverHasSideEffects = 1 in
+def MOV32ri64 : Ii32<0xb8, AddRegFrm, (outs GR32:$dst), (ins i64i32imm:$src),
+ "", [], IIC_ALU_NONMEM>, Sched<[WriteALU]>;
+
+// This 64-bit pseudo-move can be used for both a 64-bit constant that is
+// actually the zero-extension of a 32-bit constant, and for labels in the
+// x86-64 small code model.
+def mov64imm32 : ComplexPattern<i64, 1, "SelectMOV64Imm32", [imm, X86Wrapper]>;
+
+let AddedComplexity = 1 in
+def : Pat<(i64 mov64imm32:$src),
+ (SUBREG_TO_REG (i64 0), (MOV32ri64 mov64imm32:$src), sub_32bit)>;
// Use sbb to materialize carry bit.
let Uses = [EFLAGS], Defs = [EFLAGS], isPseudo = 1, SchedRW = [WriteALU] in {
@@ -924,20 +932,6 @@ def : Pat<(i64 (X86Wrapper texternalsym:$dst)),
def : Pat<(i64 (X86Wrapper tblockaddress:$dst)),
(MOV64ri tblockaddress:$dst)>, Requires<[FarData]>;
-// In static codegen with small code model, we can get the address of a label
-// into a register with 'movl'. FIXME: This is a hack, the 'imm' predicate of
-// the MOV64ri64i32 should accept these.
-def : Pat<(i64 (X86Wrapper tconstpool :$dst)),
- (MOV64ri64i32 tconstpool :$dst)>, Requires<[SmallCode]>;
-def : Pat<(i64 (X86Wrapper tjumptable :$dst)),
- (MOV64ri64i32 tjumptable :$dst)>, Requires<[SmallCode]>;
-def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)),
- (MOV64ri64i32 tglobaladdr :$dst)>, Requires<[SmallCode]>;
-def : Pat<(i64 (X86Wrapper texternalsym:$dst)),
- (MOV64ri64i32 texternalsym:$dst)>, Requires<[SmallCode]>;
-def : Pat<(i64 (X86Wrapper tblockaddress:$dst)),
- (MOV64ri64i32 tblockaddress:$dst)>, Requires<[SmallCode]>;
-
// In kernel code model, we can get the address of a label
// into a register with 'movq'. FIXME: This is a hack, the 'imm' predicate of
// the MOV64ri32 should accept these.
diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp
index b423e1e..4b6503b 100644
--- a/lib/Target/X86/X86MCInstLower.cpp
+++ b/lib/Target/X86/X86MCInstLower.cpp
@@ -226,13 +226,6 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
-static void lower_subreg32(MCInst *MI, unsigned OpNo) {
- // Convert registers in the addr mode according to subreg32.
- unsigned Reg = MI->getOperand(OpNo).getReg();
- if (Reg != 0)
- MI->getOperand(OpNo).setReg(getX86SubSuperRegister(Reg, MVT::i32));
-}
-
static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {
// Convert registers in the addr mode according to subreg64.
for (unsigned i = 0; i != 4; ++i) {
@@ -246,11 +239,6 @@ static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {
}
}
-/// LowerSubReg32_Op0 - Things like MOVZX16rr8 -> MOVZX32rr8.
-static void LowerSubReg32_Op0(MCInst &OutMI, unsigned NewOpc) {
- OutMI.setOpcode(NewOpc);
- lower_subreg32(&OutMI, 0);
-}
/// LowerUnaryToTwoAddr - R = setb -> R = sbb R, R
static void LowerUnaryToTwoAddr(MCInst &OutMI, unsigned NewOpc) {
OutMI.setOpcode(NewOpc);
@@ -388,9 +376,12 @@ ReSimplify:
assert(OutMI.getOperand(1+X86::AddrSegmentReg).getReg() == 0 &&
"LEA has segment specified!");
break;
- case X86::MOV64ri64i32: LowerSubReg32_Op0(OutMI, X86::MOV32ri); break;
case X86::MOV32r0: LowerUnaryToTwoAddr(OutMI, X86::XOR32rr); break;
+ case X86::MOV32ri64:
+ OutMI.setOpcode(X86::MOV32ri);
+ break;
+
// Commute operands to get a smaller encoding by using VEX.R instead of VEX.B
// if one of the registers is extended, but other isn't.
case X86::VMOVAPDrr:
diff --git a/test/CodeGen/X86/abi-isel.ll b/test/CodeGen/X86/abi-isel.ll
index 658ccaa..955fc62 100644
--- a/test/CodeGen/X86/abi-isel.ll
+++ b/test/CodeGen/X86/abi-isel.ll
@@ -6629,8 +6629,8 @@ entry:
; LINUX-32-PIC-NEXT: ret
; LINUX-64-PIC: bam02:
-; LINUX-64-PIC: movq ptr@GOTPCREL(%rip), [[RCX:%r.x]]
-; LINUX-64-PIC-NEXT: movl $262144, %eax
+; LINUX-64-PIC: movl $262144, %eax
+; LINUX-64-PIC-NEXT: movq ptr@GOTPCREL(%rip), [[RCX:%r.x]]
; LINUX-64-PIC-NEXT: addq ([[RCX]]), %rax
; LINUX-64-PIC-NEXT: ret
@@ -6655,20 +6655,20 @@ entry:
; DARWIN-32-PIC-NEXT: ret
; DARWIN-64-STATIC: _bam02:
-; DARWIN-64-STATIC: movq _ptr@GOTPCREL(%rip), [[RCX:%r.x]]
-; DARWIN-64-STATIC-NEXT: movl $262144, %eax
+; DARWIN-64-STATIC: movl $262144, %eax
+; DARWIN-64-STATIC-NEXT: movq _ptr@GOTPCREL(%rip), [[RCX:%r.x]]
; DARWIN-64-STATIC-NEXT: addq ([[RCX]]), %rax
; DARWIN-64-STATIC-NEXT: ret
; DARWIN-64-DYNAMIC: _bam02:
-; DARWIN-64-DYNAMIC: movq _ptr@GOTPCREL(%rip), [[RCX:%r.x]]
-; DARWIN-64-DYNAMIC-NEXT: movl $262144, %eax
+; DARWIN-64-DYNAMIC: movl $262144, %eax
+; DARWIN-64-DYNAMIC-NEXT: movq _ptr@GOTPCREL(%rip), [[RCX:%r.x]]
; DARWIN-64-DYNAMIC-NEXT: addq ([[RCX]]), %rax
; DARWIN-64-DYNAMIC-NEXT: ret
; DARWIN-64-PIC: _bam02:
-; DARWIN-64-PIC: movq _ptr@GOTPCREL(%rip), [[RCX:%r.x]]
-; DARWIN-64-PIC-NEXT: movl $262144, %eax
+; DARWIN-64-PIC: movl $262144, %eax
+; DARWIN-64-PIC-NEXT: movq _ptr@GOTPCREL(%rip), [[RCX:%r.x]]
; DARWIN-64-PIC-NEXT: addq ([[RCX]]), %rax
; DARWIN-64-PIC-NEXT: ret
}
@@ -6791,8 +6791,8 @@ entry:
; LINUX-32-PIC-NEXT: ret
; LINUX-64-PIC: bam05:
-; LINUX-64-PIC: movq dptr@GOTPCREL(%rip), [[RCX:%r.x]]
-; LINUX-64-PIC-NEXT: movl $262144, %eax
+; LINUX-64-PIC: movl $262144, %eax
+; LINUX-64-PIC-NEXT: movq dptr@GOTPCREL(%rip), [[RCX:%r.x]]
; LINUX-64-PIC-NEXT: addq ([[RCX]]), %rax
; LINUX-64-PIC-NEXT: ret
diff --git a/test/ExecutionEngine/mov64zext32.ll b/test/ExecutionEngine/mov64zext32.ll
new file mode 100644
index 0000000..00241c8
--- /dev/null
+++ b/test/ExecutionEngine/mov64zext32.ll
@@ -0,0 +1,17 @@
+; RUN: %lli %s > /dev/null
+
+define i64 @foo() {
+ ret i64 42
+}
+
+define i32 @main() {
+ %val = call i64 @foo()
+ %is42 = icmp eq i64 %val, 42
+ br i1 %is42, label %good, label %bad
+
+good:
+ ret i32 0
+
+bad:
+ ret i32 1
+} \ No newline at end of file