blob: 77d13bd06519813c671a237ee552f70b7a030908 [file] [log] [blame]
# 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 EAX<imp-def> 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 EAX<imp-use> 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
}
...
---
# 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, _, 0, _
; 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, _, 0, _, implicit-def %eax :: (load 2 from %ir.p)
; CHECK: %eax = MOVZX32rm16 killed %rdi, 1, _, 0, _, 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
...