]> granicus.if.org Git - llvm/commitdiff
[GlobalISel][X86] G_ZEXT i1 to i32/i64 support.
authorIgor Breger <igor.breger@intel.com>
Wed, 10 May 2017 06:52:58 +0000 (06:52 +0000)
committerIgor Breger <igor.breger@intel.com>
Wed, 10 May 2017 06:52:58 +0000 (06:52 +0000)
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

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

index d65eb1de8d0940c0629f8dfd36577ed10b41a3f1..2ec893796740257c7babb3b608dc062106f728fb 100644 (file)
@@ -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,
index 4f5e70414aa93e00d07bf578d0258767e9675396..0849ea98c3188b5357bca1d50b3f04bff26a771c 100644 (file)
@@ -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);
   }
index c4d3566008b11a626a687186c6b7760d6c1444de..64cd0e70a4fdd75f7b5cb6be0d5172345032ce7b 100644 (file)
@@ -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<def> %DIL<kill> %RDI<def>
+; 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:
index 3c032686130ec86b1238f846bdfad127ca5fca72..4d4e3b05ca28b6cbabf79470559195340d38fe12 100644 (file)
@@ -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:
index 25af600f2299f989716fc267b356cac0c1a743ed..6f051f1b6ea5e9ae4c6e8eb80eb12defff46c2e0 100644 (file)
@@ -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
     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
     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
index 46457e0fff596bfd2a645fb5397eb4593458e7df..c9add0dc4e95ca27ebf8b38420a0d9ac57e8c8d8 100644 (file)
@@ -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
     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
     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
index 85b3f61a9e448b54f662195971db970de463bcfe..0844701487bcc24369b6c34f908f9055feffe540 100644 (file)
@@ -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
     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
index 63aeae89bd1a1cc9084c3c9e33d8b3ad7f94fe0e..831d6efb75f12b5a561d5af0752e9d1141803c2c 100644 (file)
@@ -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
     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