From 85c622d6b6633c19d2729e82453c6c7f56ee7cd9 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Sat, 1 Jun 2013 09:55:14 +0000 Subject: [PATCH] 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 --- lib/Target/X86/X86CodeEmitter.cpp | 2 +- lib/Target/X86/X86ISelDAGToDAG.cpp | 28 +++++++++++++++++++++++++++ lib/Target/X86/X86InstrCompiler.td | 30 ++++++++++++----------------- lib/Target/X86/X86MCInstLower.cpp | 17 ++++------------ test/CodeGen/X86/abi-isel.ll | 20 +++++++++---------- test/ExecutionEngine/mov64zext32.ll | 17 ++++++++++++++++ 6 files changed, 72 insertions(+), 42 deletions(-) create mode 100644 test/ExecutionEngine/mov64zext32.ll diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index 8fea6edc8d7..c3734a2ee32 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -1270,7 +1270,7 @@ void Emitter::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 0b6940ec71d..02f5fe49525 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(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 213993a56cd..8a7ee7d077f 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; + +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 b423e1e7d19..4b6503b6f62 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 658ccaa71dc..955fc629048 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 00000000000..00241c81bed --- /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 -- 2.34.1