summaryrefslogtreecommitdiffstats
path: root/llvm/test/CodeGen/X86/fixup-bw-inst.mir
blob: e5a5e16108fb52fd4f9f7239d446d51f3fd75dd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# 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
...
OpenPOWER on IntegriCloud