llvm.org GIT mirror llvm / testing test / CodeGen / X86 / fixup-bw-inst.mir
testing

Tree @testing (Download .tar.gz)

fixup-bw-inst.mir @testingraw · history · 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

...