forked from OSchip/llvm-project
152 lines
3.8 KiB
Plaintext
152 lines
3.8 KiB
Plaintext
|
# 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
|
||
|
|
||
|
...
|