In function convertInstTo3Addr, after converting a two address instruction into three address instruction, only the last new instruction is inserted into DistanceMap. This is wrong, DistanceMap should track all instructions from the beginning of current MBB to the working instruction. When a two address instruction is converted to three address instruction, multiple instructions may be generated (usually an extra COPY is generated), all of them should be inserted into DistanceMap. Similarly when unfolding memory operand in function tryInstructionTransform DistanceMap is not maintained correctly. Differential Revision: https://reviews.llvm.org/D111857
96 lines
4.3 KiB
YAML
96 lines
4.3 KiB
YAML
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
|
# RUN: llc %s -o - -mtriple=x86_64-unknown-linux -run-pass=twoaddressinstruction -verify-machineinstrs | FileCheck %s
|
|
|
|
# In TwoAddressInstructionPass, new instructions should be added to DistanceMap.
|
|
# In this case, function convertInstTo3Addr is called on the first ADD
|
|
# instruction, extra COPY instructions are generated. If they are not added to
|
|
# DistanceMap, function noUseAfterLastDef computes a wrong value for the later
|
|
# ADD instruction, and a different commute decision is made.
|
|
|
|
--- |
|
|
; ModuleID = 't.ll'
|
|
source_filename = "t.ll"
|
|
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-unknown-linux"
|
|
|
|
declare i16 @llvm.sadd.sat.i16(i16, i16)
|
|
|
|
define signext i16 @func16(i16 signext %x, i16 signext %y, i16 signext %z) nounwind {
|
|
%a = mul i16 %y, %z
|
|
%tmp = call i16 @llvm.sadd.sat.i16(i16 %x, i16 %a)
|
|
ret i16 %tmp
|
|
}
|
|
|
|
...
|
|
---
|
|
name: func16
|
|
alignment: 16
|
|
tracksRegLiveness: true
|
|
registers:
|
|
- { id: 0, class: gr32 }
|
|
- { id: 1, class: gr32 }
|
|
- { id: 2, class: gr32 }
|
|
- { id: 3, class: gr16 }
|
|
- { id: 4, class: gr32 }
|
|
- { id: 5, class: gr16 }
|
|
- { id: 6, class: gr16 }
|
|
- { id: 7, class: gr32 }
|
|
- { id: 8, class: gr32 }
|
|
- { id: 9, class: gr32 }
|
|
- { id: 10, class: gr16 }
|
|
- { id: 11, class: gr32 }
|
|
- { id: 13, class: gr32 }
|
|
- { id: 14, class: gr16 }
|
|
frameInfo:
|
|
maxAlignment: 1
|
|
body: |
|
|
bb.0 :
|
|
liveins: $edi, $esi, $edx
|
|
; CHECK-LABEL: name: func16
|
|
; CHECK: liveins: $edi, $esi, $edx
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY killed $edx
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY killed $esi
|
|
; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY killed $edi
|
|
; CHECK-NEXT: [[COPY3:%[0-9]+]]:gr16 = COPY killed [[COPY2]].sub_16bit
|
|
; CHECK-NEXT: [[COPY4:%[0-9]+]]:gr32 = COPY [[COPY1]]
|
|
; CHECK-NEXT: [[IMUL32rr:%[0-9]+]]:gr32 = IMUL32rr [[IMUL32rr]], killed [[COPY]], implicit-def dead $eflags
|
|
; CHECK-NEXT: [[COPY4:%[0-9]+]]:gr16 = COPY killed [[IMUL32rr]].sub_16bit
|
|
; CHECK-NEXT: [[DEF:%[0-9]+]]:gr64_nosp = IMPLICIT_DEF
|
|
; CHECK-NEXT: [[DEF]].sub_16bit:gr64_nosp = COPY [[COPY3]]
|
|
; CHECK-NEXT: [[DEF1:%[0-9]+]]:gr64_nosp = IMPLICIT_DEF
|
|
; CHECK-NEXT: [[DEF1]].sub_16bit:gr64_nosp = COPY [[COPY4]]
|
|
; CHECK-NEXT: [[LEA64_32r:%[0-9]+]]:gr32 = LEA64_32r killed [[DEF]], 1, killed [[DEF1]], 0, $noreg
|
|
; CHECK-NEXT: [[COPY5:%[0-9]+]]:gr16 = COPY killed [[LEA64_32r]].sub_16bit
|
|
; CHECK-NEXT: [[MOVSX32rr16_:%[0-9]+]]:gr32 = MOVSX32rr16 killed [[COPY5]]
|
|
; CHECK-NEXT: [[COPY6:%[0-9]+]]:gr32 = COPY [[MOVSX32rr16_]]
|
|
; CHECK-NEXT: [[SAR32ri:%[0-9]+]]:gr32 = SAR32ri [[SAR32ri]], 15, implicit-def dead $eflags
|
|
; CHECK-NEXT: [[COPY6:%[0-9]+]]:gr32 = COPY [[SAR32ri]]
|
|
; CHECK-NEXT: [[XOR32ri:%[0-9]+]]:gr32 = XOR32ri [[XOR32ri]], -32768, implicit-def dead $eflags
|
|
; CHECK-NEXT: [[COPY6:%[0-9]+]]:gr16 = COPY [[COPY3]]
|
|
; CHECK-NEXT: [[ADD16rr:%[0-9]+]]:gr16 = ADD16rr [[ADD16rr]], killed [[COPY4]], implicit-def $eflags
|
|
; CHECK-NEXT: undef %11.sub_16bit:gr32 = COPY killed [[ADD16rr]]
|
|
; CHECK-NEXT: [[COPY6:%[0-9]+]]:gr32 = COPY [[XOR32ri]]
|
|
; CHECK-NEXT: [[CMOV32rr:%[0-9]+]]:gr32 = CMOV32rr [[CMOV32rr]], killed %11, 1, implicit killed $eflags
|
|
; CHECK-NEXT: [[COPY6:%[0-9]+]]:gr16 = COPY killed [[CMOV32rr]].sub_16bit
|
|
; CHECK-NEXT: $ax = COPY killed [[COPY6]]
|
|
; CHECK-NEXT: RET 0, killed $ax
|
|
%2:gr32 = COPY killed $edx
|
|
%1:gr32 = COPY killed $esi
|
|
%0:gr32 = COPY killed $edi
|
|
%3:gr16 = COPY killed %0.sub_16bit:gr32
|
|
%4:gr32 = IMUL32rr killed %1:gr32, killed %2:gr32, implicit-def dead $eflags
|
|
%5:gr16 = COPY killed %4.sub_16bit:gr32
|
|
%6:gr16 = ADD16rr %3:gr16, %5:gr16, implicit-def dead $eflags
|
|
%7:gr32 = MOVSX32rr16 killed %6:gr16
|
|
%8:gr32 = SAR32ri killed %7:gr32, 15, implicit-def dead $eflags
|
|
%9:gr32 = XOR32ri killed %8:gr32, -32768, implicit-def dead $eflags
|
|
%10:gr16 = ADD16rr killed %3:gr16, killed %5:gr16, implicit-def $eflags
|
|
%11:gr32 = INSERT_SUBREG undef %12:gr32, killed %10:gr16, %subreg.sub_16bit
|
|
%13:gr32 = CMOV32rr killed %11:gr32, killed %9:gr32, 0, implicit killed $eflags
|
|
%14:gr16 = COPY killed %13.sub_16bit:gr32
|
|
$ax = COPY killed %14:gr16
|
|
RET 0, killed $ax
|
|
|
|
...
|