[llvm] r327482 - [GlobalIsel][X86] Support for G_ZEXT instruction

Alexander Ivchenko via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 14 02:11:24 PDT 2018


Author: aivchenk
Date: Wed Mar 14 02:11:23 2018
New Revision: 327482

URL: http://llvm.org/viewvc/llvm-project?rev=327482&view=rev
Log:
[GlobalIsel][X86] Support for G_ZEXT instruction

Reviewed By: igorb

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

Added:
    llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-irtranslator.ll
    llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-legalize-zext.mir
    llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-select-zext.mir
Modified:
    llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp

Modified: llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp?rev=327482&r1=327481&r2=327482&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp Wed Mar 14 02:11:23 2018
@@ -750,6 +750,70 @@ bool X86InstructionSelector::selectZext(
   const LLT DstTy = MRI.getType(DstReg);
   const LLT SrcTy = MRI.getType(SrcReg);
 
+  assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(32)) &&
+         "8=>32 Zext is handled by tablegen");
+  assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(32)) &&
+         "16=>32 Zext is handled by tablegen");
+
+  const static struct ZextEntry {
+    LLT SrcTy;
+    LLT DstTy;
+    unsigned MovOp;
+    bool NeedSubregToReg;
+  } OpTable[] = {
+      {LLT::scalar(8), LLT::scalar(16), X86::MOVZX16rr8, false},  // i8  => i16
+      {LLT::scalar(8), LLT::scalar(64), X86::MOVZX32rr8, true},   // i8  => i64
+      {LLT::scalar(16), LLT::scalar(64), X86::MOVZX32rr16, true}, // i16 => i64
+      {LLT::scalar(32), LLT::scalar(64), 0, true}                 // i32 => i64
+  };
+
+  auto ZextEntryIt =
+      std::find_if(std::begin(OpTable), std::end(OpTable),
+                   [SrcTy, DstTy](const ZextEntry &El) {
+                     return El.DstTy == DstTy && El.SrcTy == SrcTy;
+                   });
+
+  // Here we try to select Zext into a MOVZ and/or SUBREG_TO_REG instruction.
+  if (ZextEntryIt != std::end(OpTable)) {
+    const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
+    const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
+    const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
+    const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
+
+    if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
+        !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
+      DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
+                   << " operand\n");
+      return false;
+    }
+
+    unsigned TransitRegTo = DstReg;
+    unsigned TransitRegFrom = SrcReg;
+    if (ZextEntryIt->MovOp) {
+      // If we select Zext into MOVZ + SUBREG_TO_REG, we need to have
+      // a transit register in between: create it here.
+      if (ZextEntryIt->NeedSubregToReg) {
+        TransitRegFrom = MRI.createVirtualRegister(
+            getRegClass(LLT::scalar(32), DstReg, MRI));
+        TransitRegTo = TransitRegFrom;
+      }
+
+      BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ZextEntryIt->MovOp))
+          .addDef(TransitRegTo)
+          .addReg(SrcReg);
+    }
+    if (ZextEntryIt->NeedSubregToReg) {
+      BuildMI(*I.getParent(), I, I.getDebugLoc(),
+              TII.get(TargetOpcode::SUBREG_TO_REG))
+          .addDef(DstReg)
+          .addImm(0)
+          .addReg(TransitRegFrom)
+          .addImm(X86::sub_32bit);
+    }
+    I.eraseFromParent();
+    return true;
+  }
+
   if (SrcTy != LLT::scalar(1))
     return false;
 

Added: llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-irtranslator.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-irtranslator.ll?rev=327482&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-irtranslator.ll (added)
+++ llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-irtranslator.ll Wed Mar 14 02:11:23 2018
@@ -0,0 +1,131 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -mtriple=x86_64-linux-gnu -O0 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
+
+define i8 @zext_i1_to_i8(i1 %val) {
+  ; CHECK-LABEL: name: zext_i1_to_i8
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s8) = G_ZEXT [[TRUNC]](s1)
+  ; CHECK:   $al = COPY [[ZEXT]](s8)
+  ; CHECK:   RET 0, implicit $al
+  %res = zext i1 %val to i8
+  ret i8 %res
+}
+
+define i16 @zext_i1_to_i16(i1 %val) {
+  ; CHECK-LABEL: name: zext_i1_to_i16
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]](s1)
+  ; CHECK:   $ax = COPY [[ZEXT]](s16)
+  ; CHECK:   RET 0, implicit $ax
+  %res = zext i1 %val to i16
+  ret i16 %res
+}
+
+define i32 @zext_i1_to_i32(i1 %val) {
+  ; CHECK-LABEL: name: zext_i1_to_i32
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s1)
+  ; CHECK:   $eax = COPY [[ZEXT]](s32)
+  ; CHECK:   RET 0, implicit $eax
+  %res = zext i1 %val to i32
+  ret i32 %res
+}
+
+define i64 @zext_i1_to_i64(i1 %val) {
+  ; CHECK-LABEL: name: zext_i1_to_i64
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC]](s1)
+  ; CHECK:   $rax = COPY [[ZEXT]](s64)
+  ; CHECK:   RET 0, implicit $rax
+  %res = zext i1 %val to i64
+  ret i64 %res
+}
+
+define i16 @zext_i8_to_i16(i8 %val) {
+  ; CHECK-LABEL: name: zext_i8_to_i16
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]](s8)
+  ; CHECK:   $ax = COPY [[ZEXT]](s16)
+  ; CHECK:   RET 0, implicit $ax
+  %res = zext i8 %val to i16
+  ret i16 %res
+}
+
+define i32 @zext_i8_to_i32(i8 %val) {
+  ; CHECK-LABEL: name: zext_i8_to_i32
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8)
+  ; CHECK:   $eax = COPY [[ZEXT]](s32)
+  ; CHECK:   RET 0, implicit $eax
+  %res = zext i8 %val to i32
+  ret i32 %res
+}
+
+define i64 @zext_i8_to_i64(i8 %val) {
+  ; CHECK-LABEL: name: zext_i8_to_i64
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC]](s8)
+  ; CHECK:   $rax = COPY [[ZEXT]](s64)
+  ; CHECK:   RET 0, implicit $rax
+  %res = zext i8 %val to i64
+  ret i64 %res
+}
+
+define i32 @zext_i16_to_i32(i16 %val) {
+  ; CHECK-LABEL: name: zext_i16_to_i32
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16)
+  ; CHECK:   $eax = COPY [[ZEXT]](s32)
+  ; CHECK:   RET 0, implicit $eax
+  %res = zext i16 %val to i32
+  ret i32 %res
+}
+
+define i64 @zext_i16_to_i64(i16 %val) {
+  ; CHECK-LABEL: name: zext_i16_to_i64
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC]](s16)
+  ; CHECK:   $rax = COPY [[ZEXT]](s64)
+  ; CHECK:   RET 0, implicit $rax
+  %res = zext i16 %val to i64
+  ret i64 %res
+}
+
+define i64 @zext_i32_to_i64(i32 %val) {
+  ; CHECK-LABEL: name: zext_i32_to_i64
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $edi
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s32)
+  ; CHECK:   $rax = COPY [[ZEXT]](s64)
+  ; CHECK:   RET 0, implicit $rax
+  %res = zext i32 %val to i64
+  ret i64 %res
+}

Added: llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-legalize-zext.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-legalize-zext.mir?rev=327482&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-legalize-zext.mir (added)
+++ llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-legalize-zext.mir Wed Mar 14 02:11:23 2018
@@ -0,0 +1,322 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+--- |
+
+  define i8 @zext_i1_to_i8(i1 %val) {
+    %res = zext i1 %val to i8
+    ret i8 %res
+  }
+
+  define i16 @zext_i1_to_i16(i1 %val) {
+    %res = zext i1 %val to i16
+    ret i16 %res
+  }
+
+  define i32 @zext_i1_to_i32(i1 %val) {
+    %res = zext i1 %val to i32
+    ret i32 %res
+  }
+
+  define i64 @zext_i1_to_i64(i1 %val) {
+    %res = zext i1 %val to i64
+    ret i64 %res
+  }
+
+  define i16 @zext_i8_to_i16(i8 %val) {
+    %res = zext i8 %val to i16
+    ret i16 %res
+  }
+
+  define i32 @zext_i8_to_i32(i8 %val) {
+    %res = zext i8 %val to i32
+    ret i32 %res
+  }
+
+  define i64 @zext_i8_to_i64(i8 %val) {
+    %res = zext i8 %val to i64
+    ret i64 %res
+  }
+
+  define i32 @zext_i16_to_i32(i16 %val) {
+    %res = zext i16 %val to i32
+    ret i32 %res
+  }
+
+  define i64 @zext_i16_to_i64(i16 %val) {
+    %res = zext i16 %val to i64
+    ret i64 %res
+  }
+
+  define i64 @zext_i32_to_i64(i32 %val) {
+    %res = zext i32 %val to i64
+    ret i64 %res
+  }
+
+...
+---
+name:            zext_i1_to_i8
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i1_to_i8
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
+    ; CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32)
+    ; CHECK: [[AND:%[0-9]+]]:_(s8) = G_AND [[TRUNC]], [[C]]
+    ; CHECK: $al = COPY [[AND]](s8)
+    ; CHECK: RET 0, implicit $al
+    %1:_(s32) = COPY $edi
+    %0:_(s1) = G_TRUNC %1(s32)
+    %2:_(s8) = G_ZEXT %0(s1)
+    $al = COPY %2(s8)
+    RET 0, implicit $al
+
+...
+---
+name:            zext_i1_to_i16
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i1_to_i16
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
+    ; CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
+    ; CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[TRUNC]], [[C]]
+    ; CHECK: $ax = COPY [[AND]](s16)
+    ; CHECK: RET 0, implicit $ax
+    %1:_(s32) = COPY $edi
+    %0:_(s1) = G_TRUNC %1(s32)
+    %2:_(s16) = G_ZEXT %0(s1)
+    $ax = COPY %2(s16)
+    RET 0, implicit $ax
+
+...
+---
+name:            zext_i1_to_i32
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i1_to_i32
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32)
+    ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C]]
+    ; CHECK: $eax = COPY [[AND]](s32)
+    ; CHECK: RET 0, implicit $eax
+    %1:_(s32) = COPY $edi
+    %0:_(s1) = G_TRUNC %1(s32)
+    %2:_(s32) = G_ZEXT %0(s1)
+    $eax = COPY %2(s32)
+    RET 0, implicit $eax
+
+...
+---
+name:            zext_i1_to_i64
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i1_to_i64
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+    ; CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[COPY]](s32)
+    ; CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK: $rax = COPY [[AND]](s64)
+    ; CHECK: RET 0, implicit $rax
+    %1:_(s32) = COPY $edi
+    %0:_(s1) = G_TRUNC %1(s32)
+    %2:_(s64) = G_ZEXT %0(s1)
+    $rax = COPY %2(s64)
+    RET 0, implicit $rax
+
+...
+---
+name:            zext_i8_to_i16
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i8_to_i16
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
+    ; CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
+    ; CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[TRUNC]], [[C]]
+    ; CHECK: $ax = COPY [[AND]](s16)
+    ; CHECK: RET 0, implicit $ax
+    %1:_(s32) = COPY $edi
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:_(s16) = G_ZEXT %0(s8)
+    $ax = COPY %2(s16)
+    RET 0, implicit $ax
+
+...
+---
+name:            zext_i8_to_i32
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i8_to_i32
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32)
+    ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C]]
+    ; CHECK: $eax = COPY [[AND]](s32)
+    ; CHECK: RET 0, implicit $eax
+    %1:_(s32) = COPY $edi
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:_(s32) = G_ZEXT %0(s8)
+    $eax = COPY %2(s32)
+    RET 0, implicit $eax
+
+...
+---
+name:            zext_i8_to_i64
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i8_to_i64
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[COPY]](s32)
+    ; CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK: $rax = COPY [[AND]](s64)
+    ; CHECK: RET 0, implicit $rax
+    %1:_(s32) = COPY $edi
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:_(s64) = G_ZEXT %0(s8)
+    $rax = COPY %2(s64)
+    RET 0, implicit $rax
+
+...
+---
+name:            zext_i16_to_i32
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i16_to_i32
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY [[COPY]](s32)
+    ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C]]
+    ; CHECK: $eax = COPY [[AND]](s32)
+    ; CHECK: RET 0, implicit $eax
+    %1:_(s32) = COPY $edi
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:_(s32) = G_ZEXT %0(s16)
+    $eax = COPY %2(s32)
+    RET 0, implicit $eax
+
+...
+---
+name:            zext_i16_to_i64
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i16_to_i64
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 65535
+    ; CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[COPY]](s32)
+    ; CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK: $rax = COPY [[AND]](s64)
+    ; CHECK: RET 0, implicit $rax
+    %1:_(s32) = COPY $edi
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:_(s64) = G_ZEXT %0(s16)
+    $rax = COPY %2(s64)
+    RET 0, implicit $rax
+
+...
+---
+name:            zext_i32_to_i64
+alignment:       4
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i32_to_i64
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s32)
+    ; CHECK: $rax = COPY [[ZEXT]](s64)
+    ; CHECK: RET 0, implicit $rax
+    %0:_(s32) = COPY $edi
+    %1:_(s64) = G_ZEXT %0(s32)
+    $rax = COPY %1(s64)
+    RET 0, implicit $rax
+
+...

Added: llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-select-zext.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-select-zext.mir?rev=327482&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-select-zext.mir (added)
+++ llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-select-zext.mir Wed Mar 14 02:11:23 2018
@@ -0,0 +1,359 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+
+--- |
+
+  define i8 @zext_i1_to_i8(i1 %val) {
+    %res = zext i1 %val to i8
+    ret i8 %res
+  }
+
+  define i16 @zext_i1_to_i16(i1 %val) {
+    %res = zext i1 %val to i16
+    ret i16 %res
+  }
+
+  define i32 @zext_i1_to_i32(i1 %val) {
+    %res = zext i1 %val to i32
+    ret i32 %res
+  }
+
+  define i64 @zext_i1_to_i64(i1 %val) {
+    %res = zext i1 %val to i64
+    ret i64 %res
+  }
+
+  define i16 @zext_i8_to_i16(i8 %val) {
+    %res = zext i8 %val to i16
+    ret i16 %res
+  }
+
+  define i32 @zext_i8_to_i32(i8 %val) {
+    %res = zext i8 %val to i32
+    ret i32 %res
+  }
+
+  define i64 @zext_i8_to_i64(i8 %val) {
+    %res = zext i8 %val to i64
+    ret i64 %res
+  }
+
+  define i32 @zext_i16_to_i32(i16 %val) {
+    %res = zext i16 %val to i32
+    ret i32 %res
+  }
+
+  define i64 @zext_i16_to_i64(i16 %val) {
+    %res = zext i16 %val to i64
+    ret i64 %res
+  }
+
+  define i64 @zext_i32_to_i64(i32 %val) {
+    %res = zext i32 %val to i64
+    ret i64 %res
+  }
+
+...
+---
+name:            zext_i1_to_i8
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i1_to_i8
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[COPY1:%[0-9]+]]:gr8 = COPY [[COPY]].sub_8bit
+    ; CHECK: [[AND8ri:%[0-9]+]]:gr8 = AND8ri [[COPY1]], 1, implicit-def $eflags
+    ; CHECK: $al = COPY [[AND8ri]]
+    ; CHECK: RET 0, implicit $al
+    %1:gpr(s32) = COPY $edi
+    %3:gpr(s8) = G_CONSTANT i8 1
+    %4:gpr(s8) = G_TRUNC %1(s32)
+    %2:gpr(s8) = G_AND %4, %3
+    $al = COPY %2(s8)
+    RET 0, implicit $al
+
+...
+---
+name:            zext_i1_to_i16
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i1_to_i16
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[COPY1:%[0-9]+]]:gr16 = COPY [[COPY]].sub_16bit
+    ; CHECK: [[AND16ri8_:%[0-9]+]]:gr16 = AND16ri8 [[COPY1]], 1, implicit-def $eflags
+    ; CHECK: $ax = COPY [[AND16ri8_]]
+    ; CHECK: RET 0, implicit $ax
+    %1:gpr(s32) = COPY $edi
+    %3:gpr(s16) = G_CONSTANT i16 1
+    %4:gpr(s16) = G_TRUNC %1(s32)
+    %2:gpr(s16) = G_AND %4, %3
+    $ax = COPY %2(s16)
+    RET 0, implicit $ax
+
+...
+---
+name:            zext_i1_to_i32
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i1_to_i32
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[AND32ri8_:%[0-9]+]]:gr32 = AND32ri8 [[COPY]], 1, implicit-def $eflags
+    ; CHECK: $eax = COPY [[AND32ri8_]]
+    ; CHECK: RET 0, implicit $eax
+    %1:gpr(s32) = COPY $edi
+    %3:gpr(s32) = G_CONSTANT i32 1
+    %4:gpr(s32) = COPY %1(s32)
+    %2:gpr(s32) = G_AND %4, %3
+    $eax = COPY %2(s32)
+    RET 0, implicit $eax
+
+...
+---
+name:            zext_i1_to_i64
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i1_to_i64
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, [[COPY]], %subreg.sub_32bit
+    ; CHECK: [[AND64ri8_:%[0-9]+]]:gr64 = AND64ri8 [[SUBREG_TO_REG]], 1, implicit-def $eflags
+    ; CHECK: $rax = COPY [[AND64ri8_]]
+    ; CHECK: RET 0, implicit $rax
+    %1:gpr(s32) = COPY $edi
+    %3:gpr(s64) = G_CONSTANT i64 1
+    %4:gpr(s64) = G_ANYEXT %1(s32)
+    %2:gpr(s64) = G_AND %4, %3
+    $rax = COPY %2(s64)
+    RET 0, implicit $rax
+
+...
+---
+name:            zext_i8_to_i16
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i8_to_i16
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[COPY1:%[0-9]+]]:gr16 = COPY [[COPY]].sub_16bit
+    ; CHECK: [[AND16ri:%[0-9]+]]:gr16 = AND16ri [[COPY1]], 255, implicit-def $eflags
+    ; CHECK: $ax = COPY [[AND16ri]]
+    ; CHECK: RET 0, implicit $ax
+    %1:gpr(s32) = COPY $edi
+    %3:gpr(s16) = G_CONSTANT i16 255
+    %4:gpr(s16) = G_TRUNC %1(s32)
+    %2:gpr(s16) = G_AND %4, %3
+    $ax = COPY %2(s16)
+    RET 0, implicit $ax
+
+...
+---
+name:            zext_i8_to_i32
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i8_to_i32
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[COPY1:%[0-9]+]]:gr8 = COPY [[COPY]].sub_8bit
+    ; CHECK: [[MOVZX32rr8_:%[0-9]+]]:gr32 = MOVZX32rr8 [[COPY1]]
+    ; CHECK: $eax = COPY [[MOVZX32rr8_]]
+    ; CHECK: RET 0, implicit $eax
+    %1:gpr(s32) = COPY $edi
+    %3:gpr(s32) = G_CONSTANT i32 255
+    %4:gpr(s32) = COPY %1(s32)
+    %2:gpr(s32) = G_AND %4, %3
+    $eax = COPY %2(s32)
+    RET 0, implicit $eax
+
+...
+---
+name:            zext_i8_to_i64
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i8_to_i64
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, [[COPY]], %subreg.sub_32bit
+    ; CHECK: [[AND64ri32_:%[0-9]+]]:gr64 = AND64ri32 [[SUBREG_TO_REG]], 255, implicit-def $eflags
+    ; CHECK: $rax = COPY [[AND64ri32_]]
+    ; CHECK: RET 0, implicit $rax
+    %1:gpr(s32) = COPY $edi
+    %3:gpr(s64) = G_CONSTANT i64 255
+    %4:gpr(s64) = G_ANYEXT %1(s32)
+    %2:gpr(s64) = G_AND %4, %3
+    $rax = COPY %2(s64)
+    RET 0, implicit $rax
+
+...
+---
+name:            zext_i16_to_i32
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i16_to_i32
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[COPY1:%[0-9]+]]:gr16 = COPY [[COPY]].sub_16bit
+    ; CHECK: [[MOVZX32rr16_:%[0-9]+]]:gr32 = MOVZX32rr16 [[COPY1]]
+    ; CHECK: $eax = COPY [[MOVZX32rr16_]]
+    ; CHECK: RET 0, implicit $eax
+    %1:gpr(s32) = COPY $edi
+    %3:gpr(s32) = G_CONSTANT i32 65535
+    %4:gpr(s32) = COPY %1(s32)
+    %2:gpr(s32) = G_AND %4, %3
+    $eax = COPY %2(s32)
+    RET 0, implicit $eax
+
+...
+---
+name:            zext_i16_to_i64
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i16_to_i64
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, [[COPY]], %subreg.sub_32bit
+    ; CHECK: [[AND64ri32_:%[0-9]+]]:gr64 = AND64ri32 [[SUBREG_TO_REG]], 65535, implicit-def $eflags
+    ; CHECK: $rax = COPY [[AND64ri32_]]
+    ; CHECK: RET 0, implicit $rax
+    %1:gpr(s32) = COPY $edi
+    %3:gpr(s64) = G_CONSTANT i64 65535
+    %4:gpr(s64) = G_ANYEXT %1(s32)
+    %2:gpr(s64) = G_AND %4, %3
+    $rax = COPY %2(s64)
+    RET 0, implicit $rax
+
+...
+---
+name:            zext_i32_to_i64
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gpr }
+  - { id: 1, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    liveins: $edi
+
+    ; CHECK-LABEL: name: zext_i32_to_i64
+    ; CHECK: liveins: $edi
+    ; CHECK: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+    ; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, [[COPY]], %subreg.sub_32bit
+    ; CHECK: $rax = COPY [[SUBREG_TO_REG]]
+    ; CHECK: RET 0, implicit $rax
+    %0:gpr(s32) = COPY $edi
+    %1:gpr(s64) = G_ZEXT %0(s32)
+    $rax = COPY %1(s64)
+    RET 0, implicit $rax
+
+...




More information about the llvm-commits mailing list