Index: llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp +++ llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp @@ -64,6 +64,8 @@ MachineFunction &MF) const; bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; + bool selectGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI, + MachineFunction &MF) const; bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI, @@ -264,6 +266,8 @@ return true; if (selectFrameIndexOrGep(I, MRI, MF)) return true; + if (selectGlobalValue(I, MRI, MF)) + return true; if (selectConstant(I, MRI, MF)) return true; if (selectTrunc(I, MRI, MF)) @@ -427,6 +431,15 @@ return constrainSelectedInstRegOperands(I, TII, TRI, RBI); } +static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI) { + if (Ty == LLT::pointer(0, 64)) + return X86::LEA64r; + else if (Ty == LLT::pointer(0, 32)) + return STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r; + else + llvm_unreachable("Can't get LEA opcode. Unsupported type."); +} + bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const { @@ -439,14 +452,7 @@ LLT Ty = MRI.getType(DefReg); // Use LEA to calculate frame index and GEP - unsigned NewOpc; - if (Ty == LLT::pointer(0, 64)) - NewOpc = X86::LEA64r; - else if (Ty == LLT::pointer(0, 32)) - NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r; - else - llvm_unreachable("Can't select G_FRAME_INDEX/G_GEP, unsupported type."); - + unsigned NewOpc = getLeaOP(Ty, STI); I.setDesc(TII.get(NewOpc)); MachineInstrBuilder MIB(MF, I); @@ -462,6 +468,54 @@ return constrainSelectedInstRegOperands(I, TII, TRI, RBI); } +bool X86InstructionSelector::selectGlobalValue(MachineInstr &I, + MachineRegisterInfo &MRI, + MachineFunction &MF) const { + unsigned Opc = I.getOpcode(); + + if (Opc != TargetOpcode::G_GLOBAL_VALUE) + return false; + + auto GV = I.getOperand(1).getGlobal(); + if (GV->isThreadLocal()) { + return false; // TODO: we don't support TLS yet. + } + + // Can't handle alternate code models yet. + if (TM.getCodeModel() != CodeModel::Small) + return 0; + + X86AddressMode AM; + AM.GV = GV; + AM.GVOpFlags = STI.classifyGlobalReference(GV); + + // TODO: The ABI requires an extra load. not supported yet. + if (isGlobalStubReference(AM.GVOpFlags)) + return false; + + // TODO: This reference is relative to the pic base. not supported yet. + if (isGlobalRelativeToPICBase(AM.GVOpFlags)) + return false; + + if (STI.isPICStyleRIPRel()) { + // Use rip-relative addressing. + assert(AM.Base.Reg == 0 && AM.IndexReg == 0); + AM.Base.Reg = X86::RIP; + } + + const unsigned DefReg = I.getOperand(0).getReg(); + LLT Ty = MRI.getType(DefReg); + unsigned NewOpc = getLeaOP(Ty, STI); + + I.setDesc(TII.get(NewOpc)); + MachineInstrBuilder MIB(MF, I); + + I.RemoveOperand(1); + addFullAddress(MIB, AM); + + return constrainSelectedInstRegOperands(I, TII, TRI, RBI); +} + bool X86InstructionSelector::selectConstant(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const { Index: llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp +++ llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp @@ -75,6 +75,7 @@ // Pointer-handling setAction({G_FRAME_INDEX, p0}, Legal); + setAction({G_GLOBAL_VALUE, p0}, Legal); setAction({G_GEP, p0}, Legal); setAction({G_GEP, 1, s32}, Legal); @@ -131,6 +132,7 @@ // Pointer-handling setAction({G_FRAME_INDEX, p0}, Legal); + setAction({G_GLOBAL_VALUE, p0}, Legal); setAction({G_GEP, p0}, Legal); setAction({G_GEP, 1, s32}, Legal); Index: llvm/trunk/test/CodeGen/X86/GlobalISel/GV.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/GV.ll +++ llvm/trunk/test/CodeGen/X86/GlobalISel/GV.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=X64 +; RUN: llc -mtriple=x86_64-apple-darwin -global-isel -verify-machineinstrs -relocation-model=pic < %s -o - | FileCheck %s --check-prefix=X64_DARWIN_PIC +; RUN: llc -mtriple=i386-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=X32 +; RUN: llc -mtriple=x86_64-linux-gnux32 -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=X32ABI + +@g_int = global i32 0, align 4 + +; Function Attrs: noinline nounwind optnone uwtable +define i32* @test_global_ptrv() #3 { +; X64-LABEL: test_global_ptrv: +; X64: # BB#0: # %entry +; X64-NEXT: leaq g_int, %rax +; X64-NEXT: retq +; +; X64_DARWIN_PIC-LABEL: test_global_ptrv: +; X64_DARWIN_PIC: ## BB#0: ## %entry +; X64_DARWIN_PIC-NEXT: leaq _g_int(%rip), %rax +; X64_DARWIN_PIC-NEXT: retq +; +; X32-LABEL: test_global_ptrv: +; X32: # BB#0: # %entry +; X32-NEXT: leal g_int, %eax +; X32-NEXT: retl +; +; X32ABI-LABEL: test_global_ptrv: +; X32ABI: # BB#0: # %entry +; X32ABI-NEXT: leal g_int, %eax +; X32ABI-NEXT: retq +entry: + ret i32* @g_int +} + +; Function Attrs: noinline nounwind optnone uwtable +define i32 @test_global_valv() #3 { +; X64-LABEL: test_global_valv: +; X64: # BB#0: # %entry +; X64-NEXT: leaq g_int, %rax +; X64-NEXT: movl (%rax), %eax +; X64-NEXT: retq +; +; X64_DARWIN_PIC-LABEL: test_global_valv: +; X64_DARWIN_PIC: ## BB#0: ## %entry +; X64_DARWIN_PIC-NEXT: leaq _g_int(%rip), %rax +; X64_DARWIN_PIC-NEXT: movl (%rax), %eax +; X64_DARWIN_PIC-NEXT: retq +; +; X32-LABEL: test_global_valv: +; X32: # BB#0: # %entry +; X32-NEXT: leal g_int, %eax +; X32-NEXT: movl (%eax), %eax +; X32-NEXT: retl +; +; X32ABI-LABEL: test_global_valv: +; X32ABI: # BB#0: # %entry +; X32ABI-NEXT: leal g_int, %eax +; X32ABI-NEXT: movl (%eax), %eax +; X32ABI-NEXT: retq +entry: + %0 = load i32, i32* @g_int, align 4 + ret i32 %0 +} + Index: llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-GV.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-GV.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-GV.mir @@ -0,0 +1,31 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64 +# RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32 +--- | + + @g_int = global i32 0, align 4 + + define i32* @test_global_ptrv() { + entry: + ret i32* @g_int + } +... +--- +name: test_global_ptrv +# ALL-LABEL: name: test_global_ptrv +alignment: 4 +legalized: false +regBankSelected: false +# ALL: registers: +# ALL-NEXT: - { id: 0, class: _, preferred-register: '' } +registers: + - { id: 0, class: _, preferred-register: '' } +# ALL: %0(p0) = G_GLOBAL_VALUE @g_int +# ALL-NEXT: %rax = COPY %0(p0) +# ALL-NEXT: RET 0, implicit %rax +body: | + bb.1.entry: + %0(p0) = G_GLOBAL_VALUE @g_int + %rax = COPY %0(p0) + RET 0, implicit %rax + +... Index: llvm/trunk/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir @@ -174,6 +174,13 @@ ret i64 %ret } + @g_int = global i32 0, align 4 + + define i32* @test_global_ptrv() { + entry: + ret i32* @g_int + } + ... --- name: test_add_i8 @@ -1084,4 +1091,24 @@ RET 0, implicit %rax ... +--- +name: test_global_ptrv +# CHECK-LABEL: name: test_global_ptrv +alignment: 4 +legalized: true +regBankSelected: false +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } +registers: + - { id: 0, class: _, preferred-register: '' } +# CHECK: %0(p0) = G_GLOBAL_VALUE @g_int +# CHECK-NEXT: %rax = COPY %0(p0) +# CHECK-NEXT: RET 0, implicit %rax +body: | + bb.1.entry: + %0(p0) = G_GLOBAL_VALUE @g_int + %rax = COPY %0(p0) + RET 0, implicit %rax + +... Index: llvm/trunk/test/CodeGen/X86/GlobalISel/select-GV.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/select-GV.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/select-GV.mir @@ -0,0 +1,99 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=X64ALL --check-prefix=X64 +# RUN: llc -mtriple=x86_64-apple-darwin -relocation-model=pic -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=X64ALL --check-prefix=X64_DARWIN_PIC +# RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=X32ALL --check-prefix=X32 +# RUN: llc -mtriple=x86_64-linux-gnux32 -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=X32ALL --check-prefix=X32ABI + +--- | + + @g_int = global i32 0, align 4 + + define i32* @test_global_ptrv() { + entry: + ret i32* @g_int + } + + define i32 @test_global_valv() { + entry: + %0 = load i32, i32* @g_int, align 4 + ret i32 %0 + } + +... +--- +name: test_global_ptrv +# CHECK-LABEL: name: test_global_ptrv +alignment: 4 +legalized: true +regBankSelected: true +# X64ALL: registers: +# X64ALL-NEXT: - { id: 0, class: gr64, preferred-register: '' } +# +# X32ALL: registers: +# X32ALL-NEXT: - { id: 0, class: gr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } +# X64: %0 = LEA64r _, 1, _, @g_int, _ +# X64-NEXT: %rax = COPY %0 +# X64-NEXT: RET 0, implicit %rax +# +# X64_DARWIN_PIC: %0 = LEA64r %rip, 1, _, @g_int, _ +# X64_DARWIN_PIC-NEXT: %rax = COPY %0 +# X64_DARWIN_PIC-NEXT: RET 0, implicit %rax +# +# X32: %0 = LEA32r _, 1, _, @g_int, _ +# X32-NEXT: %rax = COPY %0 +# X32-NEXT: RET 0, implicit %rax +# +# X32ABI: %0 = LEA64_32r _, 1, _, @g_int, _ +# X32ABI-NEXT: %rax = COPY %0 +# X32ABI-NEXT: RET 0, implicit %rax +body: | + bb.1.entry: + %0(p0) = G_GLOBAL_VALUE @g_int + %rax = COPY %0(p0) + RET 0, implicit %rax + +... +--- +name: test_global_valv +# CHECK-LABEL: name: test_global_valv +alignment: 4 +legalized: true +regBankSelected: true +# X64ALL: registers: +# X64ALL-NEXT: - { id: 0, class: gr32, preferred-register: '' } +# X64ALL-NEXT: - { id: 1, class: gr64, preferred-register: '' } +# +# X32ALL: registers: +# X32ALL-NEXT: - { id: 0, class: gr32, preferred-register: '' } +# X32ALL-NEXT: - { id: 1, class: gr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } +# X64: %1 = LEA64r _, 1, _, @g_int, _ +# X64-NEXT: %0 = MOV32rm %1, 1, _, 0, _ :: (load 4 from @g_int) +# X64-NEXT: %eax = COPY %0 +# X64-NEXT: RET 0, implicit %eax +# +# X64_DARWIN_PIC: %1 = LEA64r %rip, 1, _, @g_int, _ +# X64_DARWIN_PIC-NEXT: %0 = MOV32rm %1, 1, _, 0, _ :: (load 4 from @g_int) +# X64_DARWIN_PIC-NEXT: %eax = COPY %0 +# X64_DARWIN_PIC-NEXT: RET 0, implicit %eax +# +# X32: %1 = LEA32r _, 1, _, @g_int, _ +# X32-NEXT: %0 = MOV32rm %1, 1, _, 0, _ :: (load 4 from @g_int) +# X32-NEXT: %eax = COPY %0 +# X32-NEXT: RET 0, implicit %eax +# +# X32ABI: %1 = LEA64_32r _, 1, _, @g_int, _ +# X32ABI-NEXT: %0 = MOV32rm %1, 1, _, 0, _ :: (load 4 from @g_int) +# X32ABI-NEXT: %eax = COPY %0 +# X32ABI-NEXT: RET 0, implicit %eax +body: | + bb.1.entry: + %1(p0) = G_GLOBAL_VALUE @g_int + %0(s32) = G_LOAD %1(p0) :: (load 4 from @g_int) + %eax = COPY %0(s32) + RET 0, implicit %eax + +...