From: Igor Breger Date: Wed, 10 May 2017 06:52:58 +0000 (+0000) Subject: [GlobalISel][X86] G_ZEXT i1 to i32/i64 support. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4d70cb577b729d95f47991f30ecbeafc78e4efd4;p=llvm [GlobalISel][X86] G_ZEXT i1 to i32/i64 support. Summary: Support G_ZEXT i1 to i32/i64 instruction selection. Reviewers: zvi, guyblank Reviewed By: guyblank Subscribers: rovka, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D32965 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302623 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86InstructionSelector.cpp b/lib/Target/X86/X86InstructionSelector.cpp index d65eb1de8d0..2ec89379674 100644 --- a/lib/Target/X86/X86InstructionSelector.cpp +++ b/lib/Target/X86/X86InstructionSelector.cpp @@ -71,6 +71,8 @@ private: MachineFunction &MF) const; bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; + bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI, + MachineFunction &MF) const; const X86TargetMachine &TM; const X86Subtarget &STI; @@ -226,7 +228,7 @@ bool X86InstructionSelector::select(MachineInstr &I) const { "Generic instruction has unexpected implicit operands\n"); if (selectImpl(I)) - return true; + return true; DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs())); @@ -241,6 +243,8 @@ bool X86InstructionSelector::select(MachineInstr &I) const { return true; if (selectTrunc(I, MRI, MF)) return true; + if (selectZext(I, MRI, MF)) + return true; return false; } @@ -562,6 +566,52 @@ bool X86InstructionSelector::selectTrunc(MachineInstr &I, return true; } +bool X86InstructionSelector::selectZext(MachineInstr &I, + MachineRegisterInfo &MRI, + MachineFunction &MF) const { + if (I.getOpcode() != TargetOpcode::G_ZEXT) + return false; + + const unsigned DstReg = I.getOperand(0).getReg(); + const unsigned SrcReg = I.getOperand(1).getReg(); + + 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; + + const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI); + unsigned DefReg = + MRI.createVirtualRegister(getRegClassForTypeOnBank(DstTy, RegBank)); + + 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); + + I.eraseFromParent(); + return true; + } + + return false; +} + InstructionSelector * llvm::createX86InstructionSelector(const X86TargetMachine &TM, X86Subtarget &Subtarget, diff --git a/lib/Target/X86/X86LegalizerInfo.cpp b/lib/Target/X86/X86LegalizerInfo.cpp index 4f5e70414aa..0849ea98c31 100644 --- a/lib/Target/X86/X86LegalizerInfo.cpp +++ b/lib/Target/X86/X86LegalizerInfo.cpp @@ -87,7 +87,7 @@ void X86LegalizerInfo::setLegalizerInfo32bit() { setAction({G_ZEXT, s32}, Legal); setAction({G_SEXT, s32}, Legal); - for (auto Ty : {s8, s16}) { + for (auto Ty : {s1, s8, s16}) { setAction({G_ZEXT, 1, Ty}, Legal); setAction({G_SEXT, 1, Ty}, Legal); } @@ -139,7 +139,7 @@ void X86LegalizerInfo::setLegalizerInfo64bit() { setAction({G_SEXT, Ty}, Legal); } - for (auto Ty : {s8, s16, s32}) { + for (auto Ty : {s1, s8, s16, s32}) { setAction({G_ZEXT, 1, Ty}, Legal); setAction({G_SEXT, 1, Ty}, Legal); } diff --git a/test/CodeGen/X86/GlobalISel/ext-x86-64.ll b/test/CodeGen/X86/GlobalISel/ext-x86-64.ll index c4d3566008b..64cd0e70a4f 100644 --- a/test/CodeGen/X86/GlobalISel/ext-x86-64.ll +++ b/test/CodeGen/X86/GlobalISel/ext-x86-64.ll @@ -1,7 +1,19 @@ ; 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 +; TODO merge with ext.ll after i64 sext suported on 32bit platform + +define i64 @test_zext_i1(i8 %a) { +; X64-LABEL: test_zext_i1: +; X64: # BB#0: +; X64-NEXT: # kill: %DIL %DIL %RDI +; X64-NEXT: andq $1, %rdi +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: retq + %val = trunc i8 %a to i1 + %r = zext i1 %val to i64 + ret i64 %r +} define i64 @test_sext_i8(i8 %val) { ; X64-LABEL: test_sext_i8: diff --git a/test/CodeGen/X86/GlobalISel/ext.ll b/test/CodeGen/X86/GlobalISel/ext.ll index 3c032686130..4d4e3b05ca2 100644 --- a/test/CodeGen/X86/GlobalISel/ext.ll +++ b/test/CodeGen/X86/GlobalISel/ext.ll @@ -2,6 +2,24 @@ ; 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_i1(i32 %a) { +; X64-LABEL: test_zext_i1: +; X64: # BB#0: +; X64-NEXT: andl $1, %edi +; X64-NEXT: movl %edi, %eax +; X64-NEXT: retq +; +; X32-LABEL: test_zext_i1: +; X32: # BB#0: +; X32-NEXT: leal 4(%esp), %eax +; X32-NEXT: movl (%eax), %eax +; X32-NEXT: andl $1, %eax +; X32-NEXT: retl + %val = trunc i32 %a to i1 + %r = zext i1 %val to i32 + ret i32 %r +} + define i32 @test_zext_i8(i8 %val) { ; X64-LABEL: test_zext_i8: ; X64: # BB#0: diff --git a/test/CodeGen/X86/GlobalISel/legalize-ext-x86-64.mir b/test/CodeGen/X86/GlobalISel/legalize-ext-x86-64.mir index 25af600f229..6f051f1b6ea 100644 --- a/test/CodeGen/X86/GlobalISel/legalize-ext-x86-64.mir +++ b/test/CodeGen/X86/GlobalISel/legalize-ext-x86-64.mir @@ -1,6 +1,12 @@ # RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --- | + define i64 @test_sext_i1(i8 %a) { + %val = trunc i8 %a to i1 + %r = sext i1 %val to i64 + ret i64 %r + } + define i64 @test_sext_i8(i8 %val) { %r = sext i8 %val to i64 ret i64 %r @@ -16,6 +22,12 @@ ret i64 %r } + define i64 @test_zext_i1(i8 %a) { + %val = trunc i8 %a to i1 + %r = zext i1 %val to i64 + ret i64 %r + } + define i64 @test_zext_i8(i8 %val) { %r = zext i8 %val to i64 ret i64 %r @@ -31,6 +43,32 @@ ret i64 %r } +... +--- +name: test_sext_i1 +# CHECK-LABEL: name: test_sext_i1 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +# CHECK: %0(s8) = COPY %edi +# CHECK-NEXT: %1(s1) = G_TRUNC %0(s8) +# CHECK-NEXT: %2(s64) = G_SEXT %1(s1) +# CHECK-NEXT: %rax = COPY %2(s64) +# CHECK-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s1) = G_TRUNC %0(s8) + %2(s64) = G_SEXT %1(s1) + %rax = COPY %2(s64) + RET 0, implicit %rax + ... --- name: test_sext_i8 @@ -100,6 +138,32 @@ body: | %rax = COPY %1(s64) RET 0, implicit %rax +... +--- +name: test_zext_i1 +# CHECK-LABEL: name: test_zext_i1 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +# CHECK: %0(s8) = COPY %edi +# CHECK-NEXT: %1(s1) = G_TRUNC %0(s8) +# CHECK-NEXT: %2(s64) = G_ZEXT %1(s1) +# CHECK-NEXT: %rax = COPY %2(s64) +# CHECK-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s1) = G_TRUNC %0(s8) + %2(s64) = G_ZEXT %1(s1) + %rax = COPY %2(s64) + RET 0, implicit %rax + ... --- name: test_zext_i8 diff --git a/test/CodeGen/X86/GlobalISel/legalize-ext.mir b/test/CodeGen/X86/GlobalISel/legalize-ext.mir index 46457e0fff5..c9add0dc4e9 100644 --- a/test/CodeGen/X86/GlobalISel/legalize-ext.mir +++ b/test/CodeGen/X86/GlobalISel/legalize-ext.mir @@ -1,6 +1,12 @@ # 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) { + %val = trunc i8 %a to i1 + %r = zext i1 %val to i32 + ret i32 %r + } + define i32 @test_zext_i8(i8 %val) { %r = zext i8 %val to i32 ret i32 %r @@ -11,6 +17,12 @@ ret i32 %r } + define i32 @test_sext_i1(i8 %a) { + %val = trunc i8 %a to i1 + %r = sext i1 %val to i32 + ret i32 %r + } + define i32 @test_sext_i8(i8 %val) { %r = sext i8 %val to i32 ret i32 %r @@ -21,6 +33,32 @@ ret i32 %r } +... +--- +name: test_zext_i1 +# ALL-LABEL: name: test_zext_i1 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +# ALL: %0(s8) = COPY %edi +# ALL-NEXT: %1(s1) = G_TRUNC %0(s8) +# ALL-NEXT: %2(s32) = G_ZEXT %1(s1) +# ALL-NEXT: %eax = COPY %2(s32) +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s1) = G_TRUNC %0(s8) + %2(s32) = G_ZEXT %1(s1) + %eax = COPY %2(s32) + RET 0, implicit %eax + ... --- name: test_zext_i8 @@ -67,6 +105,32 @@ body: | %eax = COPY %1(s32) RET 0, implicit %eax +... +--- +name: test_sext_i1 +# ALL-LABEL: name: test_sext_i1 +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +# ALL: %0(s8) = COPY %edi +# ALL-NEXT: %1(s1) = G_TRUNC %0(s8) +# ALL-NEXT: %2(s32) = G_SEXT %1(s1) +# ALL-NEXT: %eax = COPY %2(s32) +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s1) = G_TRUNC %0(s8) + %2(s32) = G_SEXT %1(s1) + %eax = COPY %2(s32) + RET 0, implicit %eax + ... --- name: test_sext_i8 diff --git a/test/CodeGen/X86/GlobalISel/select-ext-x86-64.mir b/test/CodeGen/X86/GlobalISel/select-ext-x86-64.mir index 85b3f61a9e4..0844701487b 100644 --- a/test/CodeGen/X86/GlobalISel/select-ext-x86-64.mir +++ b/test/CodeGen/X86/GlobalISel/select-ext-x86-64.mir @@ -1,6 +1,12 @@ # 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_zext_i1(i8 %a) { + %val = trunc i8 %a to i1 + %r = zext i1 %val to i64 + ret i64 %r + } + define i64 @test_sext_i8(i8 %val) { %r = sext i8 %val to i64 ret i64 %r @@ -11,6 +17,38 @@ ret i64 %r } +... +--- +name: test_zext_i1 +# ALL-LABEL: name: test_zext_i1 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8 } +# ALL-NEXT: - { id: 1, class: gr8 } +# ALL-NEXT: - { id: 2, class: gr64 } +# ALL-NEXT: - { id: 3, class: gr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } +# ALL: %0 = COPY %dil +# ALL-NEXT: %1 = COPY %0 +# ALL-NEXT: %3 = SUBREG_TO_REG 0, %1, 1 +# ALL-NEXT: %2 = AND64ri8 %3, 1, implicit-def %eflags +# ALL-NEXT: %rax = COPY %2 +# ALL-NEXT: RET 0, implicit %rax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s8) = COPY %edi + %1(s1) = G_TRUNC %0(s8) + %2(s64) = G_ZEXT %1(s1) + %rax = COPY %2(s64) + RET 0, implicit %rax + ... --- name: test_sext_i8 diff --git a/test/CodeGen/X86/GlobalISel/select-ext.mir b/test/CodeGen/X86/GlobalISel/select-ext.mir index 63aeae89bd1..831d6efb75f 100644 --- a/test/CodeGen/X86/GlobalISel/select-ext.mir +++ b/test/CodeGen/X86/GlobalISel/select-ext.mir @@ -2,6 +2,11 @@ # 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_i1(i1 %a) { + %r = zext i1 %a to i32 + ret i32 %r + } + define i32 @test_zext_i8(i8 %val) { %r = zext i8 %val to i32 ret i32 %r @@ -22,6 +27,34 @@ ret i32 %r } +... +--- +name: test_zext_i1 +# ALL-LABEL: name: test_zext_i1 +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 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# ALL: %0 = COPY %dil +# ALL-NEXT: %2 = SUBREG_TO_REG 0, %0, 1 +# ALL-NEXT: %1 = AND32ri8 %2, 1, implicit-def %eflags +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %edi + + %0(s1) = COPY %edi + %1(s32) = G_ZEXT %0(s1) + %eax = COPY %1(s32) + RET 0, implicit %eax + ... --- name: test_zext_i8