[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