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.cpp =================================================================== --- lib/Target/X86/X86LegalizerInfo.cpp +++ lib/Target/X86/X86LegalizerInfo.cpp @@ -56,6 +56,9 @@ // And everything's fine in addrspace 0. setAction({MemOp, 1, p0}, Legal); } + + // Pointer-handling + setAction({G_FRAME_INDEX, p0}, Legal); } void X86LegalizerInfo::setLegalizerInfo64bit() { @@ -80,6 +83,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 +120,4 @@ for (unsigned BinOp : {G_ADD, G_SUB}) for (auto Ty : {v4s32}) setAction({BinOp, Ty}, Legal); - } Index: test/CodeGen/X86/GlobalISel/frameIndex-instructionselect.mir =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/frameIndex-instructionselect.mir @@ -0,0 +1,45 @@ +# 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 +--- | + define i32 @test_frame_index(i32 %arg1) { + %ret = add i32 %arg1, %arg1 + ret i32 %ret + } + +... +--- +name: test_frame_index +alignment: 4 +legalized: true +regBankSelected: true +selected: false +# CHECK-LABEL: name: test_frame_index +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gr32 } + +# X64-NEXT: - { id: 1, class: gr64 } +# X32-NEXT: - { id: 1, class: gr32 } + +# CHECK-NEXT: - { id: 2, class: gr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } +fixedStack: + - { id: 0, offset: 0, size: 4, alignment: 16, isImmutable: true, isAliased: false } + +# X64: %1 = LEA64r %fixed-stack.0, 1, _, 0, _ +# X32: %1 = LEA32r %fixed-stack.0, 1, _, 0, _ + +# CHECK-NEXT: %0 = MOV32rm %1, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.0, align 0) +# CHECK-NEXT: %2 = ADD32rr %0, %0 + +body: | + bb.1 (%ir-block.0): + %1(p0) = G_FRAME_INDEX %fixed-stack.0 + %0(s32) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.0, align 0) + %2(s32) = G_ADD %0, %0 + %eax = COPY %2(s32) + RET 0, implicit %eax + +... Index: test/CodeGen/X86/GlobalISel/frameIndex.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/frameIndex.ll @@ -0,0 +1,25 @@ +; 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=i386-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=X32 + +define i32 @test_i32_frame_index(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4, i32 %arg5, i32 %arg6, i32 %arg7, i32 %arg8) { +; X64-LABEL: test_i32_frame_index: +; X64: # BB#0: +; X64-NEXT: leaq 8(%rsp), %rax +; X64-NEXT: movl (%rax), %eax +; X64-NEXT: leaq 16(%rsp), %rcx +; X64-NEXT: subl (%rcx), %eax +; X64-NEXT: retq +; +; X32-LABEL: test_i32_frame_index: +; X32: # BB#0: +; X32-NEXT: leal 28(%esp), %eax +; X32-NEXT: movl (%eax), %eax +; X32-NEXT: leal 32(%esp), %ecx +; X32-NEXT: subl (%ecx), %eax +; X32-NEXT: retl + + %ret = sub i32 %arg7, %arg8 + ret i32 %ret +} +