From 7733e74e5454d6f18da28c06be917c1e73d12d01 Mon Sep 17 00:00:00 2001 From: Igor Breger Date: Sun, 26 Mar 2017 08:11:12 +0000 Subject: [PATCH] [GlobalISel][X86] support G_FRAME_INDEX instruction selection. Summary: Support G_FRAME_INDEX instruction selection. Reviewers: zvi, rovka, ab, qcolombet Reviewed By: ab Subscribers: llvm-commits, dberris, kristof.beyls, eladcohen, guyblank Differential Revision: https://reviews.llvm.org/D30980 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298800 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86InstructionSelector.cpp | 26 ++++++++++++++ lib/Target/X86/X86InstructionSelector.h | 2 ++ lib/Target/X86/X86LegalizerInfo.cpp | 13 +++++-- lib/Target/X86/X86LegalizerInfo.h | 6 ++-- lib/Target/X86/X86TargetMachine.cpp | 2 +- .../frameIndex-instructionselect.mir | 36 +++++++++++++++++++ test/CodeGen/X86/GlobalISel/frameIndex.ll | 30 ++++++++++++++++ 7 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/X86/GlobalISel/frameIndex-instructionselect.mir create mode 100644 test/CodeGen/X86/GlobalISel/frameIndex.ll diff --git a/lib/Target/X86/X86InstructionSelector.cpp b/lib/Target/X86/X86InstructionSelector.cpp index e45d12268fb..0f01bc4d1a8 100644 --- a/lib/Target/X86/X86InstructionSelector.cpp +++ b/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/lib/Target/X86/X86InstructionSelector.h b/lib/Target/X86/X86InstructionSelector.h index a8eb4ca6cea..fa258d4072f 100644 --- a/lib/Target/X86/X86InstructionSelector.h +++ b/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/lib/Target/X86/X86LegalizerInfo.cpp b/lib/Target/X86/X86LegalizerInfo.cpp index bda657946f7..3ab80c4f20c 100644 --- a/lib/Target/X86/X86LegalizerInfo.cpp +++ b/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/lib/Target/X86/X86LegalizerInfo.h b/lib/Target/X86/X86LegalizerInfo.h index b9cf42f8016..3f00898b423 100644 --- a/lib/Target/X86/X86LegalizerInfo.h +++ b/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/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index a0d62b70442..a3148195076 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/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/test/CodeGen/X86/GlobalISel/frameIndex-instructionselect.mir b/test/CodeGen/X86/GlobalISel/frameIndex-instructionselect.mir new file mode 100644 index 00000000000..2fa9ac23a7a --- /dev/null +++ b/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/test/CodeGen/X86/GlobalISel/frameIndex.ll b/test/CodeGen/X86/GlobalISel/frameIndex.ll new file mode 100644 index 00000000000..2bb11adcc3b --- /dev/null +++ b/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 +} -- 2.50.1