Index: llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp +++ llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp @@ -750,6 +750,70 @@ 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; Index: llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-irtranslator.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-irtranslator.ll +++ llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-irtranslator.ll @@ -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 +} Index: llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-legalize-zext.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-legalize-zext.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-legalize-zext.mir @@ -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 + +... Index: llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-select-zext.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-select-zext.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/x86_64-select-zext.mir @@ -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 + +...