diff --git a/llvm/lib/Target/X86/X86InstructionSelector.cpp b/llvm/lib/Target/X86/X86InstructionSelector.cpp index e45d12268fb3..0f01bc4d1a8d 100644 --- a/llvm/lib/Target/X86/X86InstructionSelector.cpp +++ b/llvm/lib/Target/X86/X86InstructionSelector.cpp @@ -159,6 +159,8 @@ bool X86InstructionSelector::select(MachineInstr &I) const { return true; if (selectLoadStoreOp(I, MRI, MF)) return true; + if (selectFrameIndex(I, MRI, MF)) + return true; return selectImpl(I); } @@ -389,3 +391,27 @@ bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I, 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); +} diff --git a/llvm/lib/Target/X86/X86InstructionSelector.h b/llvm/lib/Target/X86/X86InstructionSelector.h index a8eb4ca6cea5..fa258d4072fa 100644 --- a/llvm/lib/Target/X86/X86InstructionSelector.h +++ b/llvm/lib/Target/X86/X86InstructionSelector.h @@ -53,6 +53,8 @@ private: 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; diff --git a/llvm/lib/Target/X86/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/X86LegalizerInfo.cpp index bda657946f7d..3ab80c4f20ca 100644 --- a/llvm/lib/Target/X86/X86LegalizerInfo.cpp +++ b/llvm/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 @@ using namespace TargetOpcode; #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 @@ void X86LegalizerInfo::setLegalizerInfo32bit() { // 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 @@ void X86LegalizerInfo::setLegalizerInfo64bit() { 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 @@ void X86LegalizerInfo::setLegalizerInfo64bit() { // And everything's fine in addrspace 0. setAction({MemOp, 1, p0}, Legal); } + + // Pointer-handling + setAction({G_FRAME_INDEX, p0}, Legal); } void X86LegalizerInfo::setLegalizerInfoSSE1() { diff --git a/llvm/lib/Target/X86/X86LegalizerInfo.h b/llvm/lib/Target/X86/X86LegalizerInfo.h index b9cf42f8016d..3f00898b4232 100644 --- a/llvm/lib/Target/X86/X86LegalizerInfo.h +++ b/llvm/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 @@ private: /// 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 @@ private: void setLegalizerInfoSSE1(); void setLegalizerInfoSSE2(); }; -} // End llvm namespace. +} // namespace llvm #endif diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index a0d62b704423..a31481950763 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -283,7 +283,7 @@ X86TargetMachine::getSubtargetImpl(const Function &F) const { 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); diff --git a/llvm/test/CodeGen/X86/GlobalISel/frameIndex-instructionselect.mir b/llvm/test/CodeGen/X86/GlobalISel/frameIndex-instructionselect.mir new file mode 100644 index 000000000000..2fa9ac23a7af --- /dev/null +++ b/llvm/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 + +... diff --git a/llvm/test/CodeGen/X86/GlobalISel/frameIndex.ll b/llvm/test/CodeGen/X86/GlobalISel/frameIndex.ll new file mode 100644 index 000000000000..2bb11adcc3b5 --- /dev/null +++ b/llvm/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 +}