1 # RUN: llc -run-pass wasm-reg-stackify %s -o - | FileCheck %s
3 # Tests for DBG_VALUE hanlding in RegStackify + DebugValueManager
6 target triple = "wasm32-unknown-unknown"
9 declare void @use_2(i32, i32)
11 define void @sink_simple() {
12 call void @llvm.dbg.value(metadata i32 0, metadata !5, metadata !DIExpression()), !dbg !10
13 call void @llvm.dbg.value(metadata i32 0, metadata !11, metadata !DIExpression()), !dbg !10
14 call void @llvm.dbg.value(metadata i32 0, metadata !12, metadata !DIExpression()), !dbg !10
15 call void @llvm.dbg.value(metadata i32 0, metadata !13, metadata !DIExpression()), !dbg !10
18 define void @sink_non_consecutive() {
21 define void @dont_sink_above_def() {
24 define void @sink_to_same_place() {
27 define void @cannot_sink_across_same_variable() {
30 define void @cannot_sink_across_same_variable2() {
33 define void @can_sink_across_same_variable_with_same_const() {
36 define void @sink_multiple_defs() {
39 define void @clone_same_bb() {
42 define void @clone_different_bb() {
45 define void @tee_with_two_use_insts() {
48 define void @tee_with_one_inst_with_two_uses() {
51 declare void @llvm.dbg.value(metadata, metadata, metadata)
54 !llvm.module.flags = !{!2, !3, !4}
56 ; Note the current mapping variable metadata and their names, which we will
57 ; use in all functions in ths file:
58 ; - "var_a" / VAR_A: !5
59 ; - "var_b" / VAR_B: !11
60 ; - "var_c" / VAR_C: !12
61 ; - "var_d" / VAR_D: !13
62 ; We will use VAR_? in the CHECK lines for robustness in case of metadata
63 ; renumbering, but currently in mir tests we cannot use variable names like
64 ; "var_a" directly in the input, which can be confusing to read.
66 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug)
67 !1 = !DIFile(filename: "test.c", directory: "")
68 !2 = !{i32 7, !"Dwarf Version", i32 5}
69 !3 = !{i32 2, !"Debug Info Version", i32 3}
70 !4 = !{i32 1, !"wchar_size", i32 4}
71 !5 = !DILocalVariable(name: "var_a", scope: !6, file: !1, line: 2, type: !9)
72 ; CHECK: ![[VAR_A:[0-9]+]] = !DILocalVariable(name: "var_a"
73 !6 = distinct !DISubprogram(name: "sink_simple", scope: !1, file: !1, line: 1, type: !7, scopeLine: 1, unit: !0)
74 !7 = !DISubroutineType(types: !8)
76 !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
77 !10 = !DILocation(line: 0, scope: !6)
78 !11 = !DILocalVariable(name: "var_b", scope: !6, file: !1, line: 2, type: !9)
79 ; CHECK: ![[VAR_B:[0-9]+]] = !DILocalVariable(name: "var_b"
80 !12 = !DILocalVariable(name: "var_c", scope: !6, file: !1, line: 2, type: !9)
81 ; CHECK: ![[VAR_C:[0-9]+]] = !DILocalVariable(name: "var_c"
82 !13 = !DILocalVariable(name: "var_d", scope: !6, file: !1, line: 2, type: !9)
83 ; CHECK: ![[VAR_D:[0-9]+]] = !DILocalVariable(name: "var_d"
87 # A simple sinking example.
88 # '%0 = CONST_I32 1' will sink to the place before 'CALL %use', and the two
89 # DBG_VALUEs will sink with it, leaving the original DBG_VALUEs to be set to
90 # undef (= DBG_VALUE $noreg).
91 # CHECK-LABEL: name: sink_simple
94 - { reg: '$arguments' }
95 tracksRegLiveness: true
99 %0:i32 = CONST_I32 1, implicit-def $arguments
100 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
101 DBG_VALUE %0:i32, $noreg, !11, !DIExpression(), debug-location !10
102 NOP implicit-def $arguments
103 CALL @use, %0:i32, implicit-def $arguments
104 RETURN implicit-def $arguments
106 ; CHECK: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
107 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
108 ; CHECK-NEXT: NOP implicit-def $arguments
109 ; CHECK-NEXT: %0:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
110 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_A]], !DIExpression()
111 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_B]], !DIExpression()
112 ; CHECK-NEXT: CALL @use, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
113 ; CHECK-NEXT: RETURN implicit-def $arguments
117 # Sinking when DBG_VALUEs are non-consecutive.
118 # '%0 = CONST_I32 1' will sink to the place before 'CALL %use', and the two
119 # DBG_VALUEs will sink with it, even though they are not consecutive. The
120 # original DBG_VALUEs will be set to undef.
121 # CHECK-LABEL: name: sink_non_consecutive
122 name: sink_non_consecutive
124 - { reg: '$arguments' }
125 tracksRegLiveness: true
129 %0:i32 = CONST_I32 1, implicit-def $arguments
130 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
131 NOP implicit-def $arguments
132 DBG_VALUE %0:i32, $noreg, !11, !DIExpression(), debug-location !10
133 NOP implicit-def $arguments
134 CALL @use, %0:i32, implicit-def $arguments
135 RETURN implicit-def $arguments
137 ; CHECK: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
138 ; CHECK-NEXT: NOP implicit-def $arguments
139 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
140 ; CHECK-NEXT: NOP implicit-def $arguments
141 ; CHECK-NEXT: %0:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
142 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_A]], !DIExpression()
143 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_B]], !DIExpression()
144 ; CHECK-NEXT: CALL @use, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
145 ; CHECK-NEXT: RETURN implicit-def $arguments
149 # Only DBG_VALUEs following a def should be sunk together.
150 # '%0 = CONST_I32 1' will sink to the place before 'CALL %use', but the
151 # DBG_VALUE above it should be untouched.
152 # CHECK-LABEL: name: dont_sink_above_def
153 name: dont_sink_above_def
155 - { reg: '$arguments' }
156 tracksRegLiveness: true
160 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
161 %0:i32 = CONST_I32 1, implicit-def $arguments
162 NOP implicit-def $arguments
163 CALL @use, %0:i32, implicit-def $arguments
164 RETURN implicit-def $arguments
166 ; CHECK: DBG_VALUE %0, $noreg, ![[VAR_A]], !DIExpression()
167 ; CHECK-NEXT: NOP implicit-def $arguments
168 ; CHECK-NEXT: %0:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
169 ; CHECK-NEXT: CALL @use, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
170 ; CHECK-NEXT: RETURN implicit-def $arguments
175 # '%0 = CONST_I32 1' will sink to the place before 'CALL %use', but it's already
176 # right before the CALL so it should be effectively a no-op. But currently
177 # sinking happens anyway so this will create unnecessary two undef DBG_VALUEs.
178 # This increases the number of DBG_VALUEs but doesn't hurt the coverage or
179 # generate incorrect debug info. TODO Improve this?
180 # CHECK-LABEL: name: sink_to_same_place
181 name: sink_to_same_place
183 - { reg: '$arguments' }
184 tracksRegLiveness: true
188 %0:i32 = CONST_I32 1, implicit-def $arguments
189 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
190 DBG_VALUE %0:i32, $noreg, !11, !DIExpression(), debug-location !10
191 CALL @use, %0:i32, implicit-def $arguments
192 RETURN implicit-def $arguments
194 ; CHECK: %0:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
195 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_A]], !DIExpression()
196 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_B]], !DIExpression()
197 ; CHECK-NEXT: CALL @use, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
198 ; CHECK-NEXT: RETURN implicit-def $arguments
202 # A DBG_VALUE cannot be sunk across another DBG_VALUE that has the same
203 # DebugVariable, because it will reorder assignments.
204 # '%0 = CONST_I32 1' will sink to the place before 'CALL %use'. But from the two
205 # DBG_VALUEs following it, only the DBG_VALUE for "var_b" can sink with it,
206 # because there is another 'DBG_VALUE 10' for "var_a" in the middle.
207 # CHECK-LABEL: name: cannot_sink_across_same_variable
208 name: cannot_sink_across_same_variable
210 - { reg: '$arguments' }
211 tracksRegLiveness: true
215 %0:i32 = CONST_I32 1, implicit-def $arguments
216 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
217 DBG_VALUE %0:i32, $noreg, !11, !DIExpression(), debug-location !10
218 DBG_VALUE 10, $noreg, !5, !DIExpression(), debug-location !10
219 NOP implicit-def $arguments
220 CALL @use, %0:i32, implicit-def $arguments
221 RETURN implicit-def $arguments
223 ; CHECK: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
224 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
225 ; CHECK-NEXT: DBG_VALUE 10, $noreg, ![[VAR_A]], !DIExpression()
226 ; CHECK-NEXT: NOP implicit-def $arguments
227 ; CHECK-NEXT: %0:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
228 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_B]], !DIExpression()
229 ; CHECK-NEXT: CALL @use, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
230 ; CHECK-NEXT: RETURN implicit-def $arguments
234 # Another case in which a DBG_VALUE cannot be sunk across another DBG_VALUE with
235 # the same DebugVariable, because it will reorder assignments.
236 # '%0 = CONST_I32 1' will sink to the place before 'CALL %use'. But from the two
237 # DBG_VALUEs following it, only the DBG_VALUE for "var_b" can sink with it,
238 # because there is another 'DBG_VALUE %1, "var_a"' in the middle.
239 # CHECK-LABEL: name: cannot_sink_across_same_variable2
240 name: cannot_sink_across_same_variable2
242 - { reg: '$arguments' }
243 tracksRegLiveness: true
247 %0:i32 = CONST_I32 1, implicit-def $arguments
248 %1:i32 = CONST_I32 2, implicit-def $arguments
249 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
250 DBG_VALUE %0:i32, $noreg, !11, !DIExpression(), debug-location !10
251 DBG_VALUE %1:i32, $noreg, !5, !DIExpression(), debug-location !10
252 NOP implicit-def $arguments
253 CALL @use, %0:i32, implicit-def $arguments
254 RETURN implicit-def $arguments
256 ; CHECK: %1:i32 = CONST_I32 2, implicit-def $arguments
257 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
258 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
259 ; CHECK-NEXT: DBG_VALUE %1, $noreg, ![[VAR_A]], !DIExpression()
260 ; CHECK-NEXT: NOP implicit-def $arguments
261 ; CHECK-NEXT: %0:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
262 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_B]], !DIExpression()
263 ; CHECK-NEXT: CALL @use, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
264 ; CHECK-NEXT: RETURN implicit-def $arguments
268 # There is a exception in which a DBG_VALUE can be sunk across another DBG_VALUE
269 # with the same DebugVariable: when the interfering DBG_VALUE refers to the same
270 # CONST_[I32/I64/F32/F64] instruction, in which case we don't reorder
273 # This is the same test with the previous one with one difference: %1 has the
274 # same CONST instruction with %0 'CONST_I32 1'. We can sink the DBG_VALUE for
275 # "var_a" here as well.
276 # CHECK-LABEL: name: can_sink_across_same_variable_with_same_const
277 name: can_sink_across_same_variable_with_same_const
279 - { reg: '$arguments' }
280 tracksRegLiveness: true
284 %0:i32 = CONST_I32 1, implicit-def $arguments
285 %1:i32 = CONST_I32 1, implicit-def $arguments ; Same CONST_I32
286 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
287 DBG_VALUE %0:i32, $noreg, !11, !DIExpression(), debug-location !10
288 DBG_VALUE %1:i32, $noreg, !5, !DIExpression(), debug-location !10
289 NOP implicit-def $arguments
290 CALL @use, %0:i32, implicit-def $arguments
291 RETURN implicit-def $arguments
293 ; CHECK: %1:i32 = CONST_I32 1, implicit-def $arguments
294 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
295 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
296 ; CHECK-NEXT: DBG_VALUE %1, $noreg, ![[VAR_A]], !DIExpression()
297 ; CHECK-NEXT: NOP implicit-def $arguments
298 ; CHECK-NEXT: %0:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
299 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_A]], !DIExpression()
300 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_B]], !DIExpression()
301 ; CHECK-NEXT: CALL @use, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
302 ; CHECK-NEXT: RETURN implicit-def $arguments
306 # Both %0 and %1 will be sunk to the place before ADD_I32. DBG_VALUEs associated
307 # with those two defs will be sunk as well, leaving the original DBG_VALUEs set
309 # CHECK-LABEL: name: sink_multiple_defs
310 name: sink_multiple_defs
312 - { reg: '$arguments' }
313 tracksRegLiveness: true
317 %0:i32 = CONST_I32 1, implicit-def $arguments
318 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
319 DBG_VALUE %0:i32, $noreg, !11, !DIExpression(), debug-location !10
320 NOP implicit-def $arguments
321 %1:i32 = CONST_I32 2, implicit-def $arguments
322 DBG_VALUE %1:i32, $noreg, !12, !DIExpression(), debug-location !10
323 DBG_VALUE %1:i32, $noreg, !13, !DIExpression(), debug-location !10
324 NOP implicit-def $arguments
325 %2:i32 = ADD_I32 %0:i32, %1:i32, implicit-def $arguments
326 RETURN implicit-def $arguments
328 ; CHECK: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
329 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
330 ; CHECK-NEXT: NOP implicit-def $arguments
331 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_C]], !DIExpression()
332 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_D]], !DIExpression()
333 ; CHECK-NEXT: NOP implicit-def $arguments
334 ; CHECK-NEXT: %0:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
335 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_A]], !DIExpression()
336 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_B]], !DIExpression()
337 ; CHECK-NEXT: %1:i32 = CONST_I32 2, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
338 ; CHECK-NEXT: DBG_VALUE %1, $noreg, ![[VAR_C]], !DIExpression()
339 ; CHECK-NEXT: DBG_VALUE %1, $noreg, ![[VAR_D]], !DIExpression()
340 ; CHECK-NEXT: dead %2:i32 = ADD_I32 %0, %1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
341 ; CHECK-NEXT: RETURN implicit-def $arguments
345 # A simple cloning example.
346 # When processing the second 'CALL @use', because %0 has multiple uses, the def
347 # '%0 = CONST_I32 1' is cloned before the CALL, along with its DBG_VALUEs. And
348 # then when processing the first 'CALL @use', by that time %0 has only one use
349 # remaining, so it is just sink with the DBG_VALUEs, leaving the original
351 # CHECK-LABEL: name: clone_same_bb
354 - { reg: '$arguments' }
355 tracksRegLiveness: true
359 %0:i32 = CONST_I32 1, implicit-def $arguments
360 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
361 DBG_VALUE %0:i32, $noreg, !11, !DIExpression(), debug-location !10
362 NOP implicit-def $arguments
363 CALL @use, %0:i32, implicit-def $arguments
364 CALL @use, %0:i32, implicit-def $arguments
365 RETURN implicit-def $arguments
367 ; CHECK: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
368 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
369 ; CHECK-NEXT: NOP implicit-def $arguments
370 ; CHECK-NEXT: %0:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
371 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_A]], !DIExpression()
372 ; CHECK-NEXT: DBG_VALUE %0, $noreg, ![[VAR_B]], !DIExpression()
373 ; CHECK-NEXT: CALL @use, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
374 ; CHECK-NEXT: %1:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
375 ; CHECK-NEXT: DBG_VALUE %1, $noreg, ![[VAR_A]], !DIExpression()
376 ; CHECK-NEXT: DBG_VALUE %1, $noreg, ![[VAR_B]], !DIExpression()
377 ; CHECK-NEXT: CALL @use, %1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
378 ; CHECK-NEXT: RETURN implicit-def $arguments
382 # Cloning across different BBs.
383 # First, when bb.0's 'CALL @use' is procssed, '%0 = CONST_I32 1' and its
384 # DBG_VALUEs are cloned before the CALL. And when bb.1's 'CALL @use' is
385 # processed, '%0 = CONST_I32 1' and its DBG_VALUEs are cloned to bb.1 this time.
386 # Even though there are (previously cloned) DBG_VALUEs for "var_a" and "var_b"
387 # in the middle, it's fine because they point to the same 'CONST_I32 1'
389 # After the second cloning, the original '%0 = CONST_I32 1' is removed because
390 # it doesn't have any users anymore, leaving its original DBG_VALUEs as undef.
391 # CHECK-LABEL: name: clone_different_bb
392 name: clone_different_bb
394 - { reg: '$arguments' }
395 tracksRegLiveness: true
400 %0:i32 = CONST_I32 1, implicit-def $arguments
401 DBG_VALUE %0:i32, $noreg, !5, !DIExpression(), debug-location !10
402 DBG_VALUE %0:i32, $noreg, !11, !DIExpression(), debug-location !10
403 NOP implicit-def $arguments
404 CALL @use, %0:i32, implicit-def $arguments
405 BR %bb.1, implicit-def $arguments
408 ; CHECK: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
409 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
410 ; CHECK-NEXT: NOP implicit-def $arguments
411 ; CHECK-NEXT: %1:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
412 ; CHECK-NEXT: DBG_VALUE %1, $noreg, ![[VAR_A]], !DIExpression()
413 ; CHECK-NEXT: DBG_VALUE %1, $noreg, ![[VAR_B]], !DIExpression()
414 ; CHECK-NEXT: CALL @use, %1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
415 ; CHECK-NEXT: BR %bb.1, implicit-def $arguments
418 ; predecessors: %bb.0
419 CALL @use, %0:i32, implicit-def $arguments
420 RETURN implicit-def $arguments
423 ; CHECK: %2:i32 = CONST_I32 1, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
424 ; CHECK-NEXT: DBG_VALUE %2, $noreg, ![[VAR_A]], !DIExpression()
425 ; CHECK-NEXT: DBG_VALUE %2, $noreg, ![[VAR_B]], !DIExpression()
426 ; CHECK-NEXT: CALL @use, %2, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
427 ; CHECK-NEXT: RETURN implicit-def $arguments
431 # TEE conversion example.
433 # Reg = INST ... // Def
435 # INST ..., Reg, ... // Insert
438 # DefReg = INST ... // Def (to become the new Insert)
439 # DBG_VALUE DefReg, ...
440 # TeeReg, Reg = TEE_... DefReg
441 # DBG_VALUE TeeReg, ...
442 # INST ..., TeeReg, ... // Insert
444 # CHECK-LABEL: name: tee_with_two_use_insts
445 name: tee_with_two_use_insts
447 - { reg: '$arguments' }
448 tracksRegLiveness: true
452 %0:i32 = ARGUMENT_i32 0, implicit $arguments
453 %1:i32 = ARGUMENT_i32 1, implicit $arguments
454 %2:i32 = MUL_I32 %1:i32, %0:i32, implicit-def $arguments
455 DBG_VALUE %2:i32, $noreg, !5, !DIExpression(), debug-location !10
456 DBG_VALUE %2:i32, $noreg, !11, !DIExpression(), debug-location !10
457 NOP implicit-def $arguments
458 CALL @use, %2:i32, implicit-def $arguments
459 CALL @use, %2:i32, implicit-def $arguments
460 RETURN implicit-def $arguments
462 ; CHECK: %0:i32 = ARGUMENT_i32 0, implicit $arguments
463 ; CHECK-NEXT: %1:i32 = ARGUMENT_i32 1, implicit $arguments
464 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
465 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
466 ; CHECK-NEXT: NOP implicit-def $arguments
467 ; CHECK-NEXT: %4:i32 = MUL_I32 %1, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
468 ; CHECK-NEXT: DBG_VALUE %4, $noreg, ![[VAR_A]], !DIExpression()
469 ; CHECK-NEXT: DBG_VALUE %4, $noreg, ![[VAR_B]], !DIExpression()
470 ; CHECK-NEXT: %3:i32, %2:i32 = TEE_I32 %4, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
471 ; CHECK-NEXT: DBG_VALUE %3, $noreg, ![[VAR_A]], !DIExpression()
472 ; CHECK-NEXT: DBG_VALUE %3, $noreg, ![[VAR_B]], !DIExpression()
473 ; CHECK-NEXT: CALL @use, %3, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
474 ; CHECK-NEXT: CALL @use, %2, implicit-def $arguments
475 ; CHECK-NEXT: RETURN implicit-def $arguments
479 # Another TEE conversion example. The previous example had two instructions
480 # that use a single register, whereas this has one instructions that has two
481 # same use operands. The resulting transformation is the same.
482 # CHECK-LABEL: name: tee_with_one_inst_with_two_uses
483 name: tee_with_one_inst_with_two_uses
485 - { reg: '$arguments' }
486 tracksRegLiveness: true
490 %0:i32 = ARGUMENT_i32 0, implicit $arguments
491 %1:i32 = ARGUMENT_i32 1, implicit $arguments
492 %2:i32 = MUL_I32 %1:i32, %0:i32, implicit-def $arguments
493 DBG_VALUE %2:i32, $noreg, !5, !DIExpression(), debug-location !10
494 DBG_VALUE %2:i32, $noreg, !11, !DIExpression(), debug-location !10
495 NOP implicit-def $arguments
496 CALL @use_2, %2:i32, %2:i32, implicit-def $arguments
497 RETURN implicit-def $arguments
499 ; CHECK: %0:i32 = ARGUMENT_i32 0, implicit $arguments
500 ; CHECK-NEXT: %1:i32 = ARGUMENT_i32 1, implicit $arguments
501 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_A]], !DIExpression()
502 ; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[VAR_B]], !DIExpression()
503 ; CHECK-NEXT: NOP implicit-def $arguments
504 ; CHECK-NEXT: %4:i32 = MUL_I32 %1, %0, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
505 ; CHECK-NEXT: DBG_VALUE %4, $noreg, ![[VAR_A]], !DIExpression()
506 ; CHECK-NEXT: DBG_VALUE %4, $noreg, ![[VAR_B]], !DIExpression()
507 ; CHECK-NEXT: %3:i32, %2:i32 = TEE_I32 %4, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
508 ; CHECK-NEXT: DBG_VALUE %3, $noreg, ![[VAR_A]], !DIExpression()
509 ; CHECK-NEXT: DBG_VALUE %3, $noreg, ![[VAR_B]], !DIExpression()
510 ; CHECK-NEXT: CALL @use_2, %3, %2, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
511 ; CHECK-NEXT: RETURN implicit-def $arguments