Index: lib/Target/X86/X86LegalizerInfo.cpp =================================================================== --- lib/Target/X86/X86LegalizerInfo.cpp +++ lib/Target/X86/X86LegalizerInfo.cpp @@ -71,6 +71,15 @@ setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar); setAction({TargetOpcode::G_CONSTANT, s64}, NarrowScalar); + + // Extensions + setAction({G_ZEXT, s32}, Legal); + setAction({G_SEXT, s32}, Legal); + + for (auto Ty : {s8, s16}) { + setAction({G_ZEXT, 1, Ty}, Legal); + setAction({G_SEXT, 1, Ty}, Legal); + } } void X86LegalizerInfo::setLegalizerInfo64bit() { @@ -105,6 +114,17 @@ setAction({TargetOpcode::G_CONSTANT, Ty}, Legal); setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar); + + // Extensions + for (auto Ty : {s32, s64}) { + setAction({G_ZEXT, Ty}, Legal); + setAction({G_SEXT, Ty}, Legal); + } + + for (auto Ty : {s8, s16, s32}) { + setAction({G_ZEXT, 1, Ty}, Legal); + setAction({G_SEXT, 1, Ty}, Legal); + } } void X86LegalizerInfo::setLegalizerInfoSSE1() { Index: test/CodeGen/X86/GlobalISel/ext-x86-64.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/ext-x86-64.ll @@ -0,0 +1,29 @@ +; 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 + +; TODO merge with ext.ll after i64 sext suported on 32bit platform + +define i64 @test_sext_i8(i8 %val) { +; X64-LABEL: test_sext_i8: +; X64: # BB#0: +; X64-NEXT: movsbq %dil, %rax +; X64-NEXT: retq + %r = sext i8 %val to i64 + ret i64 %r +} + +define i64 @test_sext_i16(i16 %val) { +; X64-LABEL: test_sext_i16: +; X64: # BB#0: +; X64-NEXT: movswq %di, %rax +; X64-NEXT: retq + %r = sext i16 %val to i64 + ret i64 %r +} + +; TODO enable after selection supported +;define i64 @test_sext_i32(i32 %val) { +; %r = sext i32 %val to i64 +; ret i64 %r +;} + Index: test/CodeGen/X86/GlobalISel/ext.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/ext.ll @@ -0,0 +1,64 @@ +; 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_zext_i8(i8 %val) { +; X64-LABEL: test_zext_i8: +; X64: # BB#0: +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: retq +; +; X32-LABEL: test_zext_i8: +; X32: # BB#0: +; X32-NEXT: leal 4(%esp), %eax +; X32-NEXT: movzbl (%eax), %eax +; X32-NEXT: retl + %r = zext i8 %val to i32 + ret i32 %r +} + +define i32 @test_zext_i16(i16 %val) { +; X64-LABEL: test_zext_i16: +; X64: # BB#0: +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: retq +; +; X32-LABEL: test_zext_i16: +; X32: # BB#0: +; X32-NEXT: leal 4(%esp), %eax +; X32-NEXT: movzwl (%eax), %eax +; X32-NEXT: retl + %r = zext i16 %val to i32 + ret i32 %r +} + +define i32 @test_sext_i8(i8 %val) { +; X64-LABEL: test_sext_i8: +; X64: # BB#0: +; X64-NEXT: movsbl %dil, %eax +; X64-NEXT: retq +; +; X32-LABEL: test_sext_i8: +; X32: # BB#0: +; X32-NEXT: leal 4(%esp), %eax +; X32-NEXT: movsbl (%eax), %eax +; X32-NEXT: retl + %r = sext i8 %val to i32 + ret i32 %r +} + +define i32 @test_sext_i16(i16 %val) { +; X64-LABEL: test_sext_i16: +; X64: # BB#0: +; X64-NEXT: movswl %di, %eax +; X64-NEXT: retq +; +; X32-LABEL: test_sext_i16: +; X32: # BB#0: +; X32-NEXT: leal 4(%esp), %eax +; X32-NEXT: movswl (%eax), %eax +; X32-NEXT: retl + %r = sext i16 %val to i32 + ret i32 %r +} + Index: test/CodeGen/X86/GlobalISel/legalize-ext-x86-64.mir =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/legalize-ext-x86-64.mir @@ -0,0 +1,172 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s + +--- | + define i64 @test_sext_i8(i8 %val) { + %r = sext i8 %val to i64 + ret i64 %r + } + + define i64 @test_sext_i16(i16 %val) { + %r = sext i16 %val to i64 + ret i64 %r + } + + define i64 @test_sext_i32(i32 %val) { + %r = sext i32 %val to i64 + ret i64 %r + } + + define i64 @test_zext_i8(i8 %val) { + %r = zext i8 %val to i64 + ret i64 %r + } + + define i64 @test_zext_i16(i16 %val) { + %r = zext i16 %val to i64 + ret i64 %r + } + + define i64 @test_zext_i32(i32 %val) { + %r = zext i32 %val to i64 + ret i64 %r + } + +... +--- +name: test_sext_i8 +# CHECK-LABEL: name: test_sext_i8 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +# CHECK: %0(s8) = COPY %edi +# CHECK-NEXT: %1(s64) = G_SEXT %0(s8) +# CHECK-NEXT: %rax = COPY %1(s64) +# CHECK-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s64) = G_SEXT %0(s8) + %rax = COPY %1(s64) + RET 0, implicit %rax + +... +--- +name: test_sext_i16 +# CHECK-LABEL: name: test_sext_i16 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +# CHECK: %0(s16) = COPY %edi +# CHECK-NEXT: %1(s64) = G_SEXT %0(s16) +# CHECK-NEXT: %rax = COPY %1(s64) +# CHECK-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s16) = COPY %edi + %1(s64) = G_SEXT %0(s16) + %rax = COPY %1(s64) + RET 0, implicit %rax + +... +--- +name: test_sext_i32 +# CHECK-LABEL: name: test_sext_i32 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +# CHECK: %0(s32) = COPY %edi +# CHECK-NEXT: %1(s64) = G_SEXT %0(s32) +# CHECK-NEXT: %rax = COPY %1(s64) +# CHECK-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s32) = COPY %edi + %1(s64) = G_SEXT %0(s32) + %rax = COPY %1(s64) + RET 0, implicit %rax + +... +--- +name: test_zext_i8 +# CHECK-LABEL: name: test_zext_i8 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +# CHECK: %0(s8) = COPY %edi +# CHECK-NEXT: %1(s64) = G_ZEXT %0(s8) +# CHECK-NEXT: %rax = COPY %1(s64) +# CHECK-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s64) = G_ZEXT %0(s8) + %rax = COPY %1(s64) + RET 0, implicit %rax + +... +--- +name: test_zext_i16 +# CHECK-LABEL: name: test_zext_i16 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +# CHECK: %0(s16) = COPY %edi +# CHECK-NEXT: %1(s64) = G_ZEXT %0(s16) +# CHECK-NEXT: %rax = COPY %1(s64) +# CHECK-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s16) = COPY %edi + %1(s64) = G_ZEXT %0(s16) + %rax = COPY %1(s64) + RET 0, implicit %rax + +... +--- +name: test_zext_i32 +# CHECK-LABEL: name: test_zext_i32 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +# CHECK: %0(s32) = COPY %edi +# CHECK-NEXT: %1(s64) = G_ZEXT %0(s32) +# CHECK-NEXT: %rax = COPY %1(s64) +# CHECK-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s32) = COPY %edi + %1(s64) = G_ZEXT %0(s32) + %rax = COPY %1(s64) + RET 0, implicit %rax + +... Index: test/CodeGen/X86/GlobalISel/select-ext-x86-64.mir =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/select-ext-x86-64.mir @@ -0,0 +1,66 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64 + +--- | + define i64 @test_sext_i8(i8 %val) { + %r = sext i8 %val to i64 + ret i64 %r + } + + define i64 @test_sext_i16(i16 %val) { + %r = sext i16 %val to i64 + ret i64 %r + } + +... +--- +name: test_sext_i8 +# ALL-LABEL: name: test_sext_i8 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8 } +# ALL-NEXT: - { id: 1, class: gr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# ALL: %0 = COPY %dil +# ALL-NEXT: %1 = MOVSX64rr8 %0 +# ALL-NEXT: %rax = COPY %1 +# ALL-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s64) = G_SEXT %0(s8) + %rax = COPY %1(s64) + RET 0, implicit %rax + +... +--- +name: test_sext_i16 +# ALL-LABEL: name: test_sext_i16 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr16 } +# ALL-NEXT: - { id: 1, class: gr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# ALL: %0 = COPY %di +# ALL-NEXT: %1 = MOVSX64rr16 %0 +# ALL-NEXT: %rax = COPY %1 +# ALL-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s16) = COPY %edi + %1(s64) = G_SEXT %0(s16) + %rax = COPY %1(s64) + RET 0, implicit %rax + +... Index: test/CodeGen/X86/GlobalISel/select-ext.mir =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/select-ext.mir @@ -0,0 +1,129 @@ +# RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32 +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64 + +--- | + define i32 @test_zext_i8(i8 %val) { + %r = zext i8 %val to i32 + ret i32 %r + } + + define i32 @test_zext_i16(i16 %val) { + %r = zext i16 %val to i32 + ret i32 %r + } + + define i32 @test_sext_i8(i8 %val) { + %r = sext i8 %val to i32 + ret i32 %r + } + + define i32 @test_sext_i16(i16 %val) { + %r = sext i16 %val to i32 + ret i32 %r + } + +... +--- +name: test_zext_i8 +# ALL-LABEL: name: test_zext_i8 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8 } +# ALL-NEXT: - { id: 1, class: gr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# ALL: %0 = COPY %dil +# ALL-NEXT: %1 = MOVZX32rr8 %0 +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s32) = G_ZEXT %0(s8) + %eax = COPY %1(s32) + RET 0, implicit %eax + +... +--- +name: test_zext_i16 +# ALL-LABEL: name: test_zext_i16 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr16 } +# ALL-NEXT: - { id: 1, class: gr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# ALL: %0 = COPY %di +# ALL-NEXT: %1 = MOVZX32rr16 %0 +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s16) = COPY %edi + %1(s32) = G_ZEXT %0(s16) + %eax = COPY %1(s32) + RET 0, implicit %eax + +... +--- +name: test_sext_i8 +# ALL-LABEL: name: test_sext_i8 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8 } +# ALL-NEXT: - { id: 1, class: gr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# ALL: %0 = COPY %dil +# ALL-NEXT: %1 = MOVSX32rr8 %0 +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s32) = G_SEXT %0(s8) + %eax = COPY %1(s32) + RET 0, implicit %eax + +... +--- +name: test_sext_i16 +# ALL-LABEL: name: test_sext_i16 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr16 } +# ALL-NEXT: - { id: 1, class: gr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# ALL: %0 = COPY %di +# ALL-NEXT: %1 = MOVSX32rr16 %0 +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s16) = COPY %edi + %1(s32) = G_SEXT %0(s16) + %eax = COPY %1(s32) + RET 0, implicit %eax + +...