Index: lib/Target/X86/X86InstructionSelector.cpp =================================================================== --- lib/Target/X86/X86InstructionSelector.cpp +++ lib/Target/X86/X86InstructionSelector.cpp @@ -637,37 +637,40 @@ const LLT DstTy = MRI.getType(DstReg); const LLT SrcTy = MRI.getType(SrcReg); - if (SrcTy == LLT::scalar(1)) { - - unsigned AndOpc; - if (DstTy == LLT::scalar(32)) - AndOpc = X86::AND32ri8; - else if (DstTy == LLT::scalar(64)) - AndOpc = X86::AND64ri8; - else - return false; + if (SrcTy != LLT::scalar(1)) + return false; - unsigned DefReg = - MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI)); + unsigned AndOpc; + if (DstTy == LLT::scalar(8)) + AndOpc = X86::AND8ri8; + else if (DstTy == LLT::scalar(16)) + AndOpc = X86::AND16ri8; + else if (DstTy == LLT::scalar(32)) + AndOpc = X86::AND32ri8; + else if (DstTy == LLT::scalar(64)) + AndOpc = X86::AND64ri8; + else + return false; + unsigned DefReg = SrcReg; + if (DstTy != LLT::scalar(8)) { + DefReg = MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI)); BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::SUBREG_TO_REG), DefReg) .addImm(0) .addReg(SrcReg) .addImm(X86::sub_8bit); + } - MachineInstr &AndInst = - *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg) - .addReg(DefReg) - .addImm(1); - - constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI); + MachineInstr &AndInst = + *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg) + .addReg(DefReg) + .addImm(1); - I.eraseFromParent(); - return true; - } + constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI); - return false; + I.eraseFromParent(); + return true; } bool X86InstructionSelector::selectCmp(MachineInstr &I, Index: lib/Target/X86/X86LegalizerInfo.cpp =================================================================== --- lib/Target/X86/X86LegalizerInfo.cpp +++ lib/Target/X86/X86LegalizerInfo.cpp @@ -91,8 +91,10 @@ setAction({TargetOpcode::G_CONSTANT, s64}, NarrowScalar); // Extensions - setAction({G_ZEXT, s32}, Legal); - setAction({G_SEXT, s32}, Legal); + for (auto Ty : {s8, s16, s32}) { + setAction({G_ZEXT, Ty}, Legal); + setAction({G_SEXT, Ty}, Legal); + } for (auto Ty : {s1, s8, s16}) { setAction({G_ZEXT, 1, Ty}, Legal); @@ -148,7 +150,7 @@ setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar); // Extensions - for (auto Ty : {s32, s64}) { + for (auto Ty : {s8, s16, s32, s64}) { setAction({G_ZEXT, Ty}, Legal); setAction({G_SEXT, Ty}, Legal); } Index: test/CodeGen/X86/GlobalISel/ext.ll =================================================================== --- test/CodeGen/X86/GlobalISel/ext.ll +++ test/CodeGen/X86/GlobalISel/ext.ll @@ -2,6 +2,42 @@ ; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=X64 ; RUN: llc -mtriple=i386-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=X32 +define i8 @test_zext_i1toi8(i32 %a) { +; X64-LABEL: test_zext_i1toi8: +; X64: # BB#0: +; X64-NEXT: andb $1, %dil +; X64-NEXT: movl %edi, %eax +; X64-NEXT: retq +; +; X32-LABEL: test_zext_i1toi8: +; X32: # BB#0: +; X32-NEXT: movl 4(%esp), %eax +; X32-NEXT: andb $1, %al +; X32-NEXT: # kill: %AL %AL %EAX +; X32-NEXT: retl + %val = trunc i32 %a to i1 + %r = zext i1 %val to i8 + ret i8 %r +} + +define i16 @test_zext_i1toi16(i32 %a) { +; X64-LABEL: test_zext_i1toi16: +; X64: # BB#0: +; X64-NEXT: andw $1, %di +; X64-NEXT: movl %edi, %eax +; X64-NEXT: retq +; +; X32-LABEL: test_zext_i1toi16: +; X32: # BB#0: +; X32-NEXT: movl 4(%esp), %eax +; X32-NEXT: andw $1, %ax +; X32-NEXT: # kill: %AX %AX %EAX +; X32-NEXT: retl + %val = trunc i32 %a to i1 + %r = zext i1 %val to i16 + ret i16 %r +} + define i32 @test_zext_i1(i32 %a) { ; X64-LABEL: test_zext_i1: ; X64: # BB#0: Index: test/CodeGen/X86/GlobalISel/legalize-ext.mir =================================================================== --- test/CodeGen/X86/GlobalISel/legalize-ext.mir +++ test/CodeGen/X86/GlobalISel/legalize-ext.mir @@ -1,12 +1,28 @@ # RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32 # RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64 --- | - define i32 @test_zext_i1(i8 %a) { + + define i8 @test_zext_i1toi8(i1 %a) { + %r = zext i1 %a to i8 + ret i8 %r + } + + define i16 @test_zext_i1toi16(i1 %a) { + %r = zext i1 %a to i16 + ret i16 %r + } + + define i32 @test_zext_i1(i8 %a) { %val = trunc i8 %a to i1 %r = zext i1 %val to i32 ret i32 %r } + define i16 @test_zext_i8toi16(i8 %val) { + %r = zext i8 %val to i16 + ret i16 %r + } + define i32 @test_zext_i8(i8 %val) { %r = zext i8 %val to i32 ret i32 %r @@ -17,12 +33,27 @@ ret i32 %r } + define i8 @test_sext_i1toi8(i1 %a) { + %r = sext i1 %a to i8 + ret i8 %r + } + + define i16 @test_sext_i1toi16(i1 %a) { + %r = sext i1 %a to i16 + ret i16 %r + } + define i32 @test_sext_i1(i8 %a) { %val = trunc i8 %a to i1 %r = sext i1 %val to i32 ret i32 %r } + define i16 @test_sext_i8toi16(i8 %val) { + %r = sext i8 %val to i16 + ret i16 %r + } + define i32 @test_sext_i8(i8 %val) { %r = sext i8 %val to i32 ret i32 %r @@ -35,6 +66,52 @@ ... --- +name: test_zext_i1toi8 +# ALL-LABEL: name: test_zext_i1toi8 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +# ALL: %0(s1) = COPY %edi +# ALL-NEXT: %1(s8) = G_ZEXT %0(s1) +# ALL-NEXT: %al = COPY %1(s8) +# ALL-NEXT: RET 0, implicit %al +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s1) = COPY %edi + %1(s8) = G_ZEXT %0(s1) + %al = COPY %1(s8) + RET 0, implicit %al + +... +--- +name: test_zext_i1toi16 +# ALL-LABEL: name: test_zext_i1toi16 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +# ALL: %0(s1) = COPY %edi +# ALL-NEXT: %1(s16) = G_ZEXT %0(s1) +# ALL-NEXT: %ax = COPY %1(s16) +# ALL-NEXT: RET 0, implicit %ax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s1) = COPY %edi + %1(s16) = G_ZEXT %0(s1) + %ax = COPY %1(s16) + RET 0, implicit %ax + +... +--- name: test_zext_i1 # ALL-LABEL: name: test_zext_i1 alignment: 4 @@ -61,6 +138,29 @@ ... --- +name: test_zext_i8toi16 +# ALL-LABEL: name: test_zext_i8toi16 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +# ALL: %0(s8) = COPY %edi +# ALL-NEXT: %1(s16) = G_ZEXT %0(s8) +# ALL-NEXT: %ax = COPY %1(s16) +# ALL-NEXT: RET 0, implicit %ax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s16) = G_ZEXT %0(s8) + %ax = COPY %1(s16) + RET 0, implicit %ax + +... +--- name: test_zext_i8 # ALL-LABEL: name: test_zext_i8 alignment: 4 @@ -107,6 +207,52 @@ ... --- +name: test_sext_i1toi8 +# ALL-LABEL: name: test_sext_i1toi8 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +# ALL: %0(s1) = COPY %edi +# ALL-NEXT: %1(s8) = G_SEXT %0(s1) +# ALL-NEXT: %al = COPY %1(s8) +# ALL-NEXT: RET 0, implicit %al +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s1) = COPY %edi + %1(s8) = G_SEXT %0(s1) + %al = COPY %1(s8) + RET 0, implicit %al + +... +--- +name: test_sext_i1toi16 +# ALL-LABEL: name: test_sext_i1toi16 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +# ALL: %0(s1) = COPY %edi +# ALL-NEXT: %1(s16) = G_SEXT %0(s1) +# ALL-NEXT: %ax = COPY %1(s16) +# ALL-NEXT: RET 0, implicit %ax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s1) = COPY %edi + %1(s16) = G_SEXT %0(s1) + %ax = COPY %1(s16) + RET 0, implicit %ax + +... +--- name: test_sext_i1 # ALL-LABEL: name: test_sext_i1 alignment: 4 @@ -133,6 +279,29 @@ ... --- +name: test_sext_i8toi16 +# ALL-LABEL: name: test_sext_i8toi16 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +# ALL: %0(s8) = COPY %edi +# ALL-NEXT: %1(s16) = G_SEXT %0(s8) +# ALL-NEXT: %ax = COPY %1(s16) +# ALL-NEXT: RET 0, implicit %ax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s16) = G_SEXT %0(s8) + %ax = COPY %1(s16) + RET 0, implicit %ax + +... +--- name: test_sext_i8 # ALL-LABEL: name: test_sext_i8 alignment: 4 Index: test/CodeGen/X86/GlobalISel/select-ext.mir =================================================================== --- test/CodeGen/X86/GlobalISel/select-ext.mir +++ test/CodeGen/X86/GlobalISel/select-ext.mir @@ -2,6 +2,16 @@ # RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64 --- | + define i8 @test_zext_i1toi8(i1 %a) { + %r = zext i1 %a to i8 + ret i8 %r + } + + define i16 @test_zext_i1toi16(i1 %a) { + %r = zext i1 %a to i16 + ret i16 %r + } + define i32 @test_zext_i1(i1 %a) { %r = zext i1 %a to i32 ret i32 %r @@ -29,6 +39,60 @@ ... --- +name: test_zext_i1toi8 +# ALL-LABEL: name: test_zext_i1toi8 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr8, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } +# ALL: %0 = COPY %dil +# ALL-NEXT: %1 = AND8ri8 %0, 1, implicit-def %eflags +# ALL-NEXT: %al = COPY %1 +# ALL-NEXT: RET 0, implicit %al +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s1) = COPY %edi + %1(s8) = G_ZEXT %0(s1) + %al = COPY %1(s8) + RET 0, implicit %al + +... +--- +name: test_zext_i1toi16 +# ALL-LABEL: name: test_zext_i1toi16 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr16, preferred-register: '' } +# ALL-NEXT: - { id: 2, class: gr16, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } +# ALL: %0 = COPY %dil +# ALL-NEXT: %2 = SUBREG_TO_REG 0, %0, 1 +# ALL-NEXT: %1 = AND16ri8 %2, 1, implicit-def %eflags +# ALL-NEXT: %ax = COPY %1 +# ALL-NEXT: RET 0, implicit %ax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s1) = COPY %edi + %1(s16) = G_ZEXT %0(s1) + %ax = COPY %1(s16) + RET 0, implicit %ax + +... +--- name: test_zext_i1 # ALL-LABEL: name: test_zext_i1 alignment: 4