[GlobalISel][X86] extend G_ZEXT support.
authorIgor Breger <igor.breger@intel.com>
Mon, 10 Jul 2017 09:07:34 +0000 (09:07 +0000)
committerIgor Breger <igor.breger@intel.com>
Mon, 10 Jul 2017 09:07:34 +0000 (09:07 +0000)
Summary:
Mark G_ZEXT/G_SEXT i1 to i8/i16,  i8 to i16 as legal.
Support G_ZEXT i1 to i8/i16 instruction selection ( C++ code).
This patch requred to support G_LOAD/G_STORE i1.

Reviewers: zvi, guyblank

Reviewed By: guyblank

Subscribers: rovka, llvm-commits, kristof.beyls

Differential Revision: https://reviews.llvm.org/D35177

llvm-svn: 307526

llvm/lib/Target/X86/X86InstructionSelector.cpp
llvm/lib/Target/X86/X86LegalizerInfo.cpp
llvm/test/CodeGen/X86/GlobalISel/ext.ll
llvm/test/CodeGen/X86/GlobalISel/legalize-ext.mir
llvm/test/CodeGen/X86/GlobalISel/select-ext.mir

index 9552d78..e912ebc 100644 (file)
@@ -637,37 +637,40 @@ bool X86InstructionSelector::selectZext(MachineInstr &I,
   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 62dd088..ea3c3b9 100644 (file)
@@ -91,8 +91,10 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
   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 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
   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 392c973..d9a0967 100644 (file)
@@ -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<def> %AL<kill> %EAX<kill>
+; 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<def> %AX<kill> %EAX<kill>
+; 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 c9add0d..c86bfd9 100644 (file)
@@ -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
     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
 
 ...
 ---
+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 @@ body:             |
 
 ...
 ---
+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 @@ body:             |
 
 ...
 ---
+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 @@ body:             |
 
 ...
 ---
+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 b52f1f6..d8d48f6 100644 (file)
@@ -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
 
 ...
 ---
+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