Index: llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp +++ llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp @@ -400,7 +400,7 @@ } else if (Ty == LLT::scalar(16)) { if (X86::GPRRegBankID == RB.getID()) return Isload ? X86::MOV16rm : X86::MOV16mr; - } else if (Ty == LLT::scalar(32)) { + } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) { if (X86::GPRRegBankID == RB.getID()) return Isload ? X86::MOV32rm : X86::MOV32mr; if (X86::VECRRegBankID == RB.getID()) @@ -408,7 +408,7 @@ : HasAVX ? X86::VMOVSSrm : X86::MOVSSrm) : (HasAVX512 ? X86::VMOVSSZmr : HasAVX ? X86::VMOVSSmr : X86::MOVSSmr); - } else if (Ty == LLT::scalar(64)) { + } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) { if (X86::GPRRegBankID == RB.getID()) return Isload ? X86::MOV64rm : X86::MOV64mr; if (X86::VECRRegBankID == RB.getID()) Index: llvm/trunk/test/CodeGen/X86/GlobalISel/memop-x32.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/memop-x32.ll +++ llvm/trunk/test/CodeGen/X86/GlobalISel/memop-x32.ll @@ -0,0 +1,101 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=i386-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=SSE --check-prefix=SSE_FAST +; RUN: llc -mtriple=i386-linux-gnu -regbankselect-greedy -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=SSE --check-prefix=SSE_GREEDY + +;TODO merge with x86-64 tests (many operations not suppored yet) + +define i8 @test_load_i8(i8 * %p1) { +; ALL-LABEL: test_load_i8: +; ALL: # BB#0: +; ALL-NEXT: leal 4(%esp), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: movb (%eax), %al +; ALL-NEXT: retl + %r = load i8, i8* %p1 + ret i8 %r +} + +define i16 @test_load_i16(i16 * %p1) { +; ALL-LABEL: test_load_i16: +; ALL: # BB#0: +; ALL-NEXT: leal 4(%esp), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: movzwl (%eax), %eax +; ALL-NEXT: retl + %r = load i16, i16* %p1 + ret i16 %r +} + +define i32 @test_load_i32(i32 * %p1) { +; ALL-LABEL: test_load_i32: +; ALL: # BB#0: +; ALL-NEXT: leal 4(%esp), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: retl + %r = load i32, i32* %p1 + ret i32 %r +} + +define i8 * @test_store_i8(i8 %val, i8 * %p1) { +; ALL-LABEL: test_store_i8: +; ALL: # BB#0: +; ALL-NEXT: leal 4(%esp), %eax +; ALL-NEXT: movb (%eax), %cl +; ALL-NEXT: leal 8(%esp), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: movb %cl, (%eax) +; ALL-NEXT: retl + store i8 %val, i8* %p1 + ret i8 * %p1; +} + +define i16 * @test_store_i16(i16 %val, i16 * %p1) { +; ALL-LABEL: test_store_i16: +; ALL: # BB#0: +; ALL-NEXT: leal 4(%esp), %eax +; ALL-NEXT: movzwl (%eax), %ecx +; ALL-NEXT: leal 8(%esp), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: movw %cx, (%eax) +; ALL-NEXT: retl + store i16 %val, i16* %p1 + ret i16 * %p1; +} + +define i32 * @test_store_i32(i32 %val, i32 * %p1) { +; ALL-LABEL: test_store_i32: +; ALL: # BB#0: +; ALL-NEXT: leal 4(%esp), %eax +; ALL-NEXT: movl (%eax), %ecx +; ALL-NEXT: leal 8(%esp), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: movl %ecx, (%eax) +; ALL-NEXT: retl + store i32 %val, i32* %p1 + ret i32 * %p1; +} + +define i32* @test_load_ptr(i32** %ptr1) { +; ALL-LABEL: test_load_ptr: +; ALL: # BB#0: +; ALL-NEXT: leal 4(%esp), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: retl + %p = load i32*, i32** %ptr1 + ret i32* %p +} + +define void @test_store_ptr(i32** %ptr1, i32* %a) { +; ALL-LABEL: test_store_ptr: +; ALL: # BB#0: +; ALL-NEXT: leal 4(%esp), %eax +; ALL-NEXT: movl (%eax), %eax +; ALL-NEXT: leal 8(%esp), %ecx +; ALL-NEXT: movl (%ecx), %ecx +; ALL-NEXT: movl %ecx, (%eax) +; ALL-NEXT: retl + store i32* %a, i32** %ptr1 + ret void +} Index: llvm/trunk/test/CodeGen/X86/GlobalISel/memop.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/memop.ll +++ llvm/trunk/test/CodeGen/X86/GlobalISel/memop.ll @@ -187,3 +187,20 @@ ret double * %p1; } +define i32* @test_load_ptr(i32** %ptr1) { +; ALL-LABEL: test_load_ptr: +; ALL: # BB#0: +; ALL-NEXT: movq (%rdi), %rax +; ALL-NEXT: retq + %p = load i32*, i32** %ptr1 + ret i32* %p +} + +define void @test_store_ptr(i32** %ptr1, i32* %a) { +; ALL-LABEL: test_store_ptr: +; ALL: # BB#0: +; ALL-NEXT: movq %rsi, (%rdi) +; ALL-NEXT: retq + store i32* %a, i32** %ptr1 + ret void +} Index: llvm/trunk/test/CodeGen/X86/GlobalISel/select-memop-x32.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/select-memop-x32.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/select-memop-x32.mir @@ -0,0 +1,310 @@ +# RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=ALL + +--- | + define i8 @test_load_i8(i8* %p1) { + %r = load i8, i8* %p1 + ret i8 %r + } + + define i16 @test_load_i16(i16* %p1) { + %r = load i16, i16* %p1 + ret i16 %r + } + + define i32 @test_load_i32(i32* %p1) { + %r = load i32, i32* %p1 + ret i32 %r + } + + define i8* @test_store_i8(i8 %val, i8* %p1) { + store i8 %val, i8* %p1 + ret i8* %p1 + } + + define i16* @test_store_i16(i16 %val, i16* %p1) { + store i16 %val, i16* %p1 + ret i16* %p1 + } + + define i32* @test_store_i32(i32 %val, i32* %p1) { + store i32 %val, i32* %p1 + ret i32* %p1 + } + + define i32* @test_load_ptr(i32** %ptr1) { + %p = load i32*, i32** %ptr1 + ret i32* %p + } + + define void @test_store_ptr(i32** %ptr1, i32* %a) { + store i32* %a, i32** %ptr1 + ret void + } + +... +--- +name: test_load_i8 +# ALL-LABEL: name: test_load_i8 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32 } +# ALL-NEXT: - { id: 1, class: gr32 } +# ALL-NEXT: - { id: 2, class: gr8 } +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 } +# ALL: %1 = LEA32r %fixed-stack.0, 1, _, 0, _ +# ALL-NEXT: %0 = MOV32rm %1, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.0, align 0) +# ALL-NEXT: %2 = MOV8rm %0, 1, _, 0, _ :: (load 1 from %ir.p1) +# ALL-NEXT: %al = COPY %2 +# ALL-NEXT: RET 0, implicit %al +body: | + bb.1 (%ir-block.0): + %1(p0) = G_FRAME_INDEX %fixed-stack.0 + %0(p0) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.0, align 0) + %2(s8) = G_LOAD %0(p0) :: (load 1 from %ir.p1) + %al = COPY %2(s8) + RET 0, implicit %al + +... +--- +name: test_load_i16 +# ALL-LABEL: name: test_load_i16 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32 } +# ALL-NEXT: - { id: 1, class: gr32 } +# ALL-NEXT: - { id: 2, class: gr16 } +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 } +# ALL: %1 = LEA32r %fixed-stack.0, 1, _, 0, _ +# ALL-NEXT: %0 = MOV32rm %1, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.0, align 0) +# ALL-NEXT: %2 = MOV16rm %0, 1, _, 0, _ :: (load 2 from %ir.p1) +# ALL-NEXT: %ax = COPY %2 +# ALL-NEXT: RET 0, implicit %ax +body: | + bb.1 (%ir-block.0): + %1(p0) = G_FRAME_INDEX %fixed-stack.0 + %0(p0) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.0, align 0) + %2(s16) = G_LOAD %0(p0) :: (load 2 from %ir.p1) + %ax = COPY %2(s16) + RET 0, implicit %ax + +... +--- +name: test_load_i32 +# ALL-LABEL: name: test_load_i32 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32 } +# ALL-NEXT: - { id: 1, class: gr32 } +# ALL-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 } +# ALL: %1 = LEA32r %fixed-stack.0, 1, _, 0, _ +# ALL-NEXT: %0 = MOV32rm %1, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.0, align 0) +# ALL-NEXT: %2 = MOV32rm %0, 1, _, 0, _ :: (load 4 from %ir.p1) +# ALL-NEXT: %eax = COPY %2 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + %1(p0) = G_FRAME_INDEX %fixed-stack.0 + %0(p0) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.0, align 0) + %2(s32) = G_LOAD %0(p0) :: (load 4 from %ir.p1) + %eax = COPY %2(s32) + RET 0, implicit %eax + +... +--- +name: test_store_i8 +# ALL-LABEL: name: test_store_i8 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8 } +# ALL-NEXT: - { id: 1, class: gr32 } +# ALL-NEXT: - { id: 2, class: gr32 } +# ALL-NEXT: - { id: 3, class: gr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } +fixedStack: + - { id: 0, offset: 4, size: 4, alignment: 4, isImmutable: true, isAliased: false } + - { id: 1, offset: 0, size: 1, alignment: 16, isImmutable: true, isAliased: false } +# ALL: %2 = LEA32r %fixed-stack.0, 1, _, 0, _ +# ALL-NEXT: %0 = MOV8rm %2, 1, _, 0, _ :: (invariant load 1 from %fixed-stack.0, align 0) +# ALL-NEXT: %3 = LEA32r %fixed-stack.1, 1, _, 0, _ +# ALL-NEXT: %1 = MOV32rm %3, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.1, align 0) +# ALL-NEXT: MOV8mr %1, 1, _, 0, _, %0 :: (store 1 into %ir.p1) +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + %2(p0) = G_FRAME_INDEX %fixed-stack.1 + %0(s8) = G_LOAD %2(p0) :: (invariant load 1 from %fixed-stack.1, align 0) + %3(p0) = G_FRAME_INDEX %fixed-stack.0 + %1(p0) = G_LOAD %3(p0) :: (invariant load 4 from %fixed-stack.0, align 0) + G_STORE %0(s8), %1(p0) :: (store 1 into %ir.p1) + %eax = COPY %1(p0) + RET 0, implicit %eax + +... +--- +name: test_store_i16 +# ALL-LABEL: name: test_store_i16 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr16 } +# ALL-NEXT: - { id: 1, class: gr32 } +# ALL-NEXT: - { id: 2, class: gr32 } +# ALL-NEXT: - { id: 3, class: gr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } +fixedStack: + - { id: 0, offset: 4, size: 4, alignment: 4, isImmutable: true, isAliased: false } + - { id: 1, offset: 0, size: 2, alignment: 16, isImmutable: true, isAliased: false } +# ALL: %2 = LEA32r %fixed-stack.0, 1, _, 0, _ +# ALL-NEXT: %0 = MOV16rm %2, 1, _, 0, _ :: (invariant load 2 from %fixed-stack.0, align 0) +# ALL-NEXT: %3 = LEA32r %fixed-stack.1, 1, _, 0, _ +# ALL-NEXT: %1 = MOV32rm %3, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.1, align 0) +# ALL-NEXT: MOV16mr %1, 1, _, 0, _, %0 :: (store 2 into %ir.p1) +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + %2(p0) = G_FRAME_INDEX %fixed-stack.1 + %0(s16) = G_LOAD %2(p0) :: (invariant load 2 from %fixed-stack.1, align 0) + %3(p0) = G_FRAME_INDEX %fixed-stack.0 + %1(p0) = G_LOAD %3(p0) :: (invariant load 4 from %fixed-stack.0, align 0) + G_STORE %0(s16), %1(p0) :: (store 2 into %ir.p1) + %eax = COPY %1(p0) + RET 0, implicit %eax + +... +--- +name: test_store_i32 +# ALL-LABEL: name: test_store_i32 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32 } +# ALL-NEXT: - { id: 1, class: gr32 } +# ALL-NEXT: - { id: 2, class: gr32 } +# ALL-NEXT: - { id: 3, class: gr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } +fixedStack: + - { id: 0, offset: 4, size: 4, alignment: 4, isImmutable: true, isAliased: false } + - { id: 1, offset: 0, size: 4, alignment: 16, isImmutable: true, isAliased: false } +# ALL: %2 = LEA32r %fixed-stack.0, 1, _, 0, _ +# ALL-NEXT: %0 = MOV32rm %2, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.0, align 0) +# ALL-NEXT: %3 = LEA32r %fixed-stack.1, 1, _, 0, _ +# ALL-NEXT: %1 = MOV32rm %3, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.1, align 0) +# ALL-NEXT: MOV32mr %1, 1, _, 0, _, %0 :: (store 4 into %ir.p1) +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + %2(p0) = G_FRAME_INDEX %fixed-stack.1 + %0(s32) = G_LOAD %2(p0) :: (invariant load 4 from %fixed-stack.1, align 0) + %3(p0) = G_FRAME_INDEX %fixed-stack.0 + %1(p0) = G_LOAD %3(p0) :: (invariant load 4 from %fixed-stack.0, align 0) + G_STORE %0(s32), %1(p0) :: (store 4 into %ir.p1) + %eax = COPY %1(p0) + RET 0, implicit %eax + +... +--- +name: test_load_ptr +# ALL-LABEL: name: test_load_ptr +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32 } +# ALL-NEXT: - { id: 1, class: gr32 } +# ALL-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 } +# ALL: %1 = LEA32r %fixed-stack.0, 1, _, 0, _ +# ALL-NEXT: %0 = MOV32rm %1, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.0, align 0) +# ALL-NEXT: %2 = MOV32rm %0, 1, _, 0, _ :: (load 4 from %ir.ptr1) +# ALL-NEXT: %eax = COPY %2 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + %1(p0) = G_FRAME_INDEX %fixed-stack.0 + %0(p0) = G_LOAD %1(p0) :: (invariant load 4 from %fixed-stack.0, align 0) + %2(p0) = G_LOAD %0(p0) :: (load 4 from %ir.ptr1) + %eax = COPY %2(p0) + RET 0, implicit %eax + +... +--- +name: test_store_ptr +# ALL-LABEL: name: test_store_ptr +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32 } +# ALL-NEXT: - { id: 1, class: gr32 } +# ALL-NEXT: - { id: 2, class: gr32 } +# ALL-NEXT: - { id: 3, class: gr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } +fixedStack: + - { id: 0, offset: 4, size: 4, alignment: 4, isImmutable: true, isAliased: false } + - { id: 1, offset: 0, size: 4, alignment: 16, isImmutable: true, isAliased: false } +# ALL: %2 = LEA32r %fixed-stack.0, 1, _, 0, _ +# ALL-NEXT: %0 = MOV32rm %2, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.0, align 0) +# ALL-NEXT: %3 = LEA32r %fixed-stack.1, 1, _, 0, _ +# ALL-NEXT: %1 = MOV32rm %3, 1, _, 0, _ :: (invariant load 4 from %fixed-stack.1, align 0) +# ALL-NEXT: MOV32mr %0, 1, _, 0, _, %1 :: (store 4 into %ir.ptr1) +# ALL-NEXT: RET 0 +body: | + bb.1 (%ir-block.0): + %2(p0) = G_FRAME_INDEX %fixed-stack.1 + %0(p0) = G_LOAD %2(p0) :: (invariant load 4 from %fixed-stack.1, align 0) + %3(p0) = G_FRAME_INDEX %fixed-stack.0 + %1(p0) = G_LOAD %3(p0) :: (invariant load 4 from %fixed-stack.0, align 0) + G_STORE %1(p0), %0(p0) :: (store 4 into %ir.ptr1) + RET 0 + +... Index: llvm/trunk/test/CodeGen/X86/GlobalISel/select-memop.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/select-memop.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/select-memop.mir @@ -95,6 +95,15 @@ ret <4 x i32>* %p1 } + define i32* @test_load_ptr(i32** %ptr1) { + %p = load i32*, i32** %ptr1 + ret i32* %p + } + + define void @test_store_ptr(i32** %ptr1, i32* %a) { + store i32* %a, i32** %ptr1 + ret void + } ... --- # ALL-LABEL: name: test_load_i8 @@ -580,3 +589,49 @@ RET 0, implicit %rax ... +--- +# ALL-LABEL: name: test_load_ptr +name: test_load_ptr +alignment: 4 +legalized: true +regBankSelected: true +selected: false +registers: +# ALL: - { id: 0, class: gr64 } +# ALL: - { id: 1, class: gr64 } + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# ALL: %1 = MOV64rm %0, 1, _, 0, _ :: (load 8 from %ir.ptr1) +body: | + bb.1 (%ir-block.0): + liveins: %rdi + + %0(p0) = COPY %rdi + %1(p0) = G_LOAD %0(p0) :: (load 8 from %ir.ptr1) + %rax = COPY %1(p0) + RET 0, implicit %rax + +... +--- +# ALL-LABEL: name: test_store_ptr +name: test_store_ptr +alignment: 4 +legalized: true +regBankSelected: true +selected: false +registers: +# ALL: - { id: 0, class: gr64 } +# ALL: - { id: 1, class: gr64 } + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# ALL: MOV64mr %0, 1, _, 0, _, %1 :: (store 8 into %ir.ptr1) +body: | + bb.1 (%ir-block.0): + liveins: %rdi, %rsi + + %0(p0) = COPY %rdi + %1(p0) = COPY %rsi + G_STORE %1(p0), %0(p0) :: (store 8 into %ir.ptr1) + RET 0 + +...