# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass x86-fixup-bw-insts %s -o - | FileCheck %s --- | define void @test1() { ret void } define void @test2() { ret void } define i16 @test3(i16* readonly %p) { ; Keep original IR to show how the situation like this might happen ; due to preceding CG passes. ; ; %0 is used in %if.end BB (before tail-duplication), so its ; corresponding super-register (EAX) is live-in into that BB (%if.end) ; and also has an implicit-def EAX flag. Make sure that we still change ; the movw into movzwl because EAX is not live before the load (which ; can be seen by the fact that implicit EAX flag is missing). entry: %tobool = icmp eq i16* %p, null br i1 %tobool, label %if.end, label %if.then if.then: ; preds = %entry %0 = load i16, i16* %p, align 2 br label %if.end if.end: ; preds = %if.then, %entry %i.0 = phi i16 [ %0, %if.then ], [ 0, %entry ] ret i16 %i.0 } define i16 @test4() { entry: %t1 = zext i1 undef to i16 %t2 = or i16 undef, %t1 ret i16 %t2 } ... --- # CHECK-LABEL: name: test1 name: test1 alignment: 4 exposesReturnsTwice: false legalized: false regBankSelected: false selected: false tracksRegLiveness: true registers: liveins: - { reg: '%rax' } frameInfo: stackSize: 0 fixedStack: stack: constants: # Verify that "movw (%rax), %ax" is changed to "movzwl (%rax), %rax". # # For that to happen, the liveness information after the MOV16rm # instruction should be used, not before it because %rax is live # before the MOV and is killed by it. body: | bb.0: liveins: %rax %ax = MOV16rm killed %rax, 1, %noreg, 0, %noreg ; CHECK: %eax = MOVZX32rm16 killed %rax RETQ %ax ... --- # CHECK-LABEL: name: test2 name: test2 alignment: 4 exposesReturnsTwice: false legalized: false regBankSelected: false selected: false tracksRegLiveness: true registers: liveins: - { reg: '%rax' } frameInfo: stackSize: 0 fixedStack: stack: constants: # Imp-use of any super-register means the register is live before the MOV body: | bb.0: liveins: %dl, %rbx, %rcx, %r14 %cl = MOV8rr killed %dl, implicit killed %rcx, implicit-def %rcx ; CHECK: %cl = MOV8rr killed %dl, implicit killed %rcx, implicit-def %rcx JMP_1 %bb.1 bb.1: liveins: %rcx RETQ %cl ... --- # CHECK-LABEL: name: test3 name: test3 alignment: 4 exposesReturnsTwice: false legalized: false regBankSelected: false selected: false tracksRegLiveness: true registers: liveins: - { reg: '%rdi', virtual-reg: '' } frameInfo: isFrameAddressTaken: false isReturnAddressTaken: false hasStackMap: false hasPatchPoint: false stackSize: 0 offsetAdjustment: 0 maxAlignment: 0 adjustsStack: false hasCalls: false stackProtector: '' maxCallFrameSize: 0 hasOpaqueSPAdjustment: false hasVAStart: false hasMustTailInVarArgFunc: false savePoint: '' restorePoint: '' fixedStack: stack: constants: # After MOV16rm the whole %eax is not *really* live, as can be seen by # missing implicit-uses of it in that MOV. Make sure that MOV is # transformed into MOVZX. # See the comment near the original IR on what preceding decisions can # lead to that. body: | bb.0.entry: successors: %bb.1(0x30000000), %bb.2.if.then(0x50000000) liveins: %rdi TEST64rr %rdi, %rdi, implicit-def %eflags JE_1 %bb.1, implicit %eflags bb.2.if.then: liveins: %rdi %ax = MOV16rm killed %rdi, 1, %noreg, 0, %noreg, implicit-def %eax :: (load 2 from %ir.p) ; CHECK: %eax = MOVZX32rm16 killed %rdi, 1, %noreg, 0, %noreg, implicit-def %eax :: (load 2 from %ir.p) %ax = KILL %ax, implicit killed %eax RETQ %ax bb.1: %eax = XOR32rr undef %eax, undef %eax, implicit-def dead %eflags %ax = KILL %ax, implicit killed %eax RETQ %ax ... --- # CHECK-LABEL: name: test4 name: test4 alignment: 4 exposesReturnsTwice: false legalized: false regBankSelected: false selected: false tracksRegLiveness: true registers: liveins: - { reg: '%r9d' } frameInfo: isFrameAddressTaken: false isReturnAddressTaken: false hasStackMap: false hasPatchPoint: false stackSize: 0 offsetAdjustment: 0 maxAlignment: 0 adjustsStack: false hasCalls: false stackProtector: '' maxCallFrameSize: 0 hasOpaqueSPAdjustment: false hasVAStart: false hasMustTailInVarArgFunc: false savePoint: '' restorePoint: '' fixedStack: stack: constants: # This code copies r10b into r9b and then uses r9w. We would like to promote # the copy to a 32-bit copy, but because r9w is used this is not acceptable. body: | bb.0.entry: successors: liveins: %r9d %r9b = MOV8rr undef %r10b, implicit-def %r9d, implicit killed %r9d, implicit-def %eflags ; CHECK-NOT: MOV32rr %ax = OR16rr undef %ax, %r9w, implicit-def %eflags RETQ %ax ...