Index: lib/Target/X86/X86InstructionSelector.h =================================================================== --- lib/Target/X86/X86InstructionSelector.h +++ lib/Target/X86/X86InstructionSelector.h @@ -53,6 +53,8 @@ MachineFunction &MF) const; bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; + bool selectFrameIndex(MachineInstr &I, MachineRegisterInfo &MRI, + MachineFunction &MF) const; const X86Subtarget &STI; const X86InstrInfo &TII; Index: lib/Target/X86/X86InstructionSelector.cpp =================================================================== --- lib/Target/X86/X86InstructionSelector.cpp +++ lib/Target/X86/X86InstructionSelector.cpp @@ -159,6 +159,8 @@ return true; if (selectLoadStoreOp(I, MRI, MF)) return true; + if (selectFrameIndex(I, MRI, MF)) + return true; return selectImpl(I); } @@ -390,3 +392,27 @@ return constrainSelectedInstRegOperands(I, TII, TRI, RBI); } +bool X86InstructionSelector::selectFrameIndex(MachineInstr &I, + MachineRegisterInfo &MRI, + MachineFunction &MF) const { + if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX) + return false; + + const unsigned DefReg = I.getOperand(0).getReg(); + LLT Ty = MRI.getType(DefReg); + + // Use LEA to calculate frame index. + 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, unsupported type."); + + I.setDesc(TII.get(NewOpc)); + MachineInstrBuilder MIB(MF, I); + addOffset(MIB, 0); + + return constrainSelectedInstRegOperands(I, TII, TRI, RBI); +} Index: lib/Target/X86/X86LegalizerInfo.h =================================================================== --- lib/Target/X86/X86LegalizerInfo.h +++ lib/Target/X86/X86LegalizerInfo.h @@ -20,6 +20,7 @@ namespace llvm { class X86Subtarget; +class X86TargetMachine; /// This class provides the information for the target register banks. class X86LegalizerInfo : public LegalizerInfo { @@ -27,9 +28,10 @@ /// Keep a reference to the X86Subtarget around so that we can /// make the right decision when generating code for different targets. const X86Subtarget &Subtarget; + const X86TargetMachine &TM; public: - X86LegalizerInfo(const X86Subtarget &STI); + X86LegalizerInfo(const X86Subtarget &STI, const X86TargetMachine &TM); private: void setLegalizerInfo32bit(); @@ -37,5 +39,5 @@ void setLegalizerInfoSSE1(); void setLegalizerInfoSSE2(); }; -} // End llvm namespace. +} // namespace llvm #endif Index: lib/Target/X86/X86LegalizerInfo.cpp =================================================================== --- lib/Target/X86/X86LegalizerInfo.cpp +++ lib/Target/X86/X86LegalizerInfo.cpp @@ -13,6 +13,7 @@ #include "X86LegalizerInfo.h" #include "X86Subtarget.h" +#include "X86TargetMachine.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Type.h" @@ -25,7 +26,9 @@ #error "You shouldn't build this" #endif -X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI) : Subtarget(STI) { +X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, + const X86TargetMachine &TM) + : Subtarget(STI), TM(TM) { setLegalizerInfo32bit(); setLegalizerInfo64bit(); @@ -56,6 +59,9 @@ // And everything's fine in addrspace 0. setAction({MemOp, 1, p0}, Legal); } + + // Pointer-handling + setAction({G_FRAME_INDEX, p0}, Legal); } void X86LegalizerInfo::setLegalizerInfo64bit() { @@ -63,7 +69,7 @@ if (!Subtarget.is64Bit()) return; - const LLT p0 = LLT::pointer(0, 64); + const LLT p0 = LLT::pointer(0, TM.getPointerSize() * 8); const LLT s8 = LLT::scalar(8); const LLT s16 = LLT::scalar(16); const LLT s32 = LLT::scalar(32); @@ -80,6 +86,9 @@ // And everything's fine in addrspace 0. setAction({MemOp, 1, p0}, Legal); } + + // Pointer-handling + setAction({G_FRAME_INDEX, p0}, Legal); } void X86LegalizerInfo::setLegalizerInfoSSE1() { @@ -114,5 +123,4 @@ for (unsigned BinOp : {G_ADD, G_SUB}) for (auto Ty : {v4s32}) setAction({BinOp, Ty}, Legal); - } Index: lib/Target/X86/X86TargetMachine.cpp =================================================================== --- lib/Target/X86/X86TargetMachine.cpp +++ lib/Target/X86/X86TargetMachine.cpp @@ -283,7 +283,7 @@ X86GISelActualAccessor *GISel = new X86GISelActualAccessor(); GISel->CallLoweringInfo.reset(new X86CallLowering(*I->getTargetLowering())); - GISel->Legalizer.reset(new X86LegalizerInfo(*I)); + GISel->Legalizer.reset(new X86LegalizerInfo(*I, *this)); auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo()); GISel->RegBankInfo.reset(RBI); Index: test/CodeGen/X86/GlobalISel/frameIndex-instructionselect.mir =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/frameIndex-instructionselect.mir @@ -0,0 +1,36 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=X64 +# RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=X32 +# RUN: llc -mtriple=x86_64-linux-gnux32 -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=X32ABI + +--- | + define i32* @allocai32() { + %ptr1 = alloca i32 + ret i32* %ptr1 + } + +... +--- +name: allocai32 +legalized: true +regBankSelected: true +selected: false +# CHECK-LABEL: name: allocai32 +# CHECK: registers: +# CHECK-X32: - { id: 0, class: gr32 } +# CHECK-X32ABI: - { id: 0, class: gr32 } +# CHECK-X64: - { id: 0, class: gr64 } +registers: + - { id: 0, class: gpr } +stack: + - { id: 0, name: ptr1, offset: 0, size: 4, alignment: 4 } + +# CHECK-X32: %0 = LEA32r %stack.0.ptr1, 1, _, 0, _ +# CHECK-X32ABI: %0 = LEA64_32r %stack.0.ptr1, 1, _, 0, _ +# CHECK-X64: %0 = LEA64r %stack.0.ptr1, 1, _, 0, _ +body: | + bb.1 (%ir-block.0): + %0(p0) = G_FRAME_INDEX %stack.0.ptr1 + %eax = COPY %0(p0) + RET 0, implicit %eax + +... Index: test/CodeGen/X86/GlobalISel/frameIndex.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/frameIndex.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=X64 +; RUN: llc -mtriple=x86_64-linux-gnu < %s -o - | FileCheck %s --check-prefix=X64 +; RUN: llc -mtriple=i386-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=X32 +; RUN: llc -mtriple=i386-linux-gnu < %s -o - | FileCheck %s --check-prefix=X32 +; RUN: llc -mtriple=x86_64-linux-gnux32 -global-isel < %s -o - | FileCheck %s --check-prefix=X32ABI +; RUN: llc -mtriple=x86_64-linux-gnux32 < %s -o - | FileCheck %s --check-prefix=X32ABI + +define i32* @allocai32() { +; X64-LABEL: allocai32: +; X64: # BB#0: +; X64-NEXT: leaq -4(%rsp), %rax +; X64-NEXT: retq +; +; X32-LABEL: allocai32: +; X32: # BB#0: +; X32-NEXT: pushl %eax +; X32-NEXT: .Lcfi0: +; X32-NEXT: .cfi_def_cfa_offset 8 +; X32-NEXT: movl %esp, %eax +; X32-NEXT: popl %ecx +; X32-NEXT: retl +; +; X32ABI-LABEL: allocai32: +; X32ABI: # BB#0: +; X32ABI-NEXT: leal -4(%rsp), %eax +; X32ABI-NEXT: retq + %ptr1 = alloca i32 + ret i32* %ptr1 +}