[MachineLICM] delete dead flag if the duplicated def outside of loop is dead.

Fixup dead flags for CSE-ed instructions.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D92557
This commit is contained in:
Chen Zheng 2020-12-03 04:53:23 -05:00
parent 1a883484af
commit 4dce7c2e20
2 changed files with 104 additions and 17 deletions

View File

@ -157,7 +157,7 @@ namespace {
SmallVector<SmallVector<unsigned, 8>, 16> BackTrace;
// For each opcode, keep a list of potential CSE instructions.
DenseMap<unsigned, std::vector<const MachineInstr *>> CSEMap;
DenseMap<unsigned, std::vector<MachineInstr *>> CSEMap;
enum {
SpeculateFalse = 0,
@ -259,13 +259,12 @@ namespace {
MachineInstr *ExtractHoistableLoad(MachineInstr *MI);
const MachineInstr *
LookForDuplicate(const MachineInstr *MI,
std::vector<const MachineInstr *> &PrevMIs);
MachineInstr *LookForDuplicate(const MachineInstr *MI,
std::vector<MachineInstr *> &PrevMIs);
bool EliminateCSE(
MachineInstr *MI,
DenseMap<unsigned, std::vector<const MachineInstr *>>::iterator &CI);
bool
EliminateCSE(MachineInstr *MI,
DenseMap<unsigned, std::vector<MachineInstr *>>::iterator &CI);
bool MayCSE(MachineInstr *MI);
@ -1405,10 +1404,10 @@ void MachineLICMBase::InitCSEMap(MachineBasicBlock *BB) {
/// Find an instruction amount PrevMIs that is a duplicate of MI.
/// Return this instruction if it's found.
const MachineInstr*
MachineInstr *
MachineLICMBase::LookForDuplicate(const MachineInstr *MI,
std::vector<const MachineInstr*> &PrevMIs) {
for (const MachineInstr *PrevMI : PrevMIs)
std::vector<MachineInstr *> &PrevMIs) {
for (MachineInstr *PrevMI : PrevMIs)
if (TII->produceSameValue(*MI, *PrevMI, (PreRegAlloc ? MRI : nullptr)))
return PrevMI;
@ -1419,14 +1418,15 @@ MachineLICMBase::LookForDuplicate(const MachineInstr *MI,
/// computes the same value. If it's found, do a RAU on with the definition of
/// the existing instruction rather than hoisting the instruction to the
/// preheader.
bool MachineLICMBase::EliminateCSE(MachineInstr *MI,
DenseMap<unsigned, std::vector<const MachineInstr *>>::iterator &CI) {
bool MachineLICMBase::EliminateCSE(
MachineInstr *MI,
DenseMap<unsigned, std::vector<MachineInstr *>>::iterator &CI) {
// Do not CSE implicit_def so ProcessImplicitDefs can properly propagate
// the undef property onto uses.
if (CI == CSEMap.end() || MI->isImplicitDef())
return false;
if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second)) {
if (MachineInstr *Dup = LookForDuplicate(MI, CI->second)) {
LLVM_DEBUG(dbgs() << "CSEing " << *MI << " with " << *Dup);
// Replace virtual registers defined by MI by their counterparts defined
@ -1466,6 +1466,9 @@ bool MachineLICMBase::EliminateCSE(MachineInstr *MI,
Register DupReg = Dup->getOperand(Idx).getReg();
MRI->replaceRegWith(Reg, DupReg);
MRI->clearKillFlags(DupReg);
// Clear Dup dead flag if any, we reuse it for Reg.
if (!MRI->use_nodbg_empty(DupReg))
Dup->getOperand(Idx).setIsDead(false);
}
MI->eraseFromParent();
@ -1479,8 +1482,8 @@ bool MachineLICMBase::EliminateCSE(MachineInstr *MI,
/// the loop.
bool MachineLICMBase::MayCSE(MachineInstr *MI) {
unsigned Opcode = MI->getOpcode();
DenseMap<unsigned, std::vector<const MachineInstr *>>::iterator
CI = CSEMap.find(Opcode);
DenseMap<unsigned, std::vector<MachineInstr *>>::iterator CI =
CSEMap.find(Opcode);
// Do not CSE implicit_def so ProcessImplicitDefs can properly propagate
// the undef property onto uses.
if (CI == CSEMap.end() || MI->isImplicitDef())
@ -1534,8 +1537,8 @@ bool MachineLICMBase::Hoist(MachineInstr *MI, MachineBasicBlock *Preheader) {
// Look for opportunity to CSE the hoisted instruction.
unsigned Opcode = MI->getOpcode();
DenseMap<unsigned, std::vector<const MachineInstr *>>::iterator
CI = CSEMap.find(Opcode);
DenseMap<unsigned, std::vector<MachineInstr *>>::iterator CI =
CSEMap.find(Opcode);
if (!EliminateCSE(MI, CI)) {
// Otherwise, splice the instruction to the preheader.
Preheader->splice(Preheader->getFirstTerminator(),MI->getParent(),MI);

View File

@ -0,0 +1,84 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -run-pass early-machinelicm -mtriple=powerpc64le-unknown-linux-gnu \
# RUN: -verify-machineinstrs %s -o - | FileCheck %s
---
name: deadFlagAfterCSE
# This case tests that after the dead %3 is CSE-ed with hoisted %5 in MachineLICM
# pass, the dead flag will be cleared for %3 if %5 has users.
tracksRegLiveness: true
body: |
; CHECK-LABEL: name: deadFlagAfterCSE
; CHECK: bb.0:
; CHECK: successors: %bb.1(0x80000000)
; CHECK: liveins: $x3, $x4
; CHECK: [[COPY:%[0-9]+]]:g8rc = COPY $x3
; CHECK: [[COPY1:%[0-9]+]]:g8rc = COPY $x4
; CHECK: [[ADD8_:%[0-9]+]]:g8rc_and_g8rc_nox0 = ADD8 [[COPY]], [[COPY1]]
; CHECK: [[ADDI8_:%[0-9]+]]:g8rc_and_g8rc_nox0 = ADDI8 [[ADD8_]], 100
; CHECK: B %bb.1
; CHECK: bb.1:
; CHECK: successors: %bb.1(0x80000000)
; CHECK: [[PHI:%[0-9]+]]:g8rc_and_g8rc_nox0 = PHI [[ADD8_]], %bb.0, %5, %bb.1
; CHECK: STDX [[PHI]], [[ADDI8_]], [[ADD8_]]
; CHECK: [[ADDI8_1:%[0-9]+]]:g8rc = nuw ADDI8 [[PHI]], 1
; CHECK: B %bb.1
; CHECK: bb.2:
; CHECK: BLR8 implicit $lr8, implicit $rm
bb.0:
liveins: $x3, $x4
%0:g8rc = COPY $x3
%1:g8rc = COPY $x4
%2:g8rc_and_g8rc_nox0 = ADD8 %0, %1
dead %3:g8rc_and_g8rc_nox0 = ADDI8 %2, 100
B %bb.1
bb.1:
%4:g8rc_and_g8rc_nox0 = PHI %2, %bb.0, %6, %bb.1
%5:g8rc_and_g8rc_nox0 = ADDI8 %2, 100
STDX %4, %5, %2
%6:g8rc = nuw ADDI8 %4, 1
B %bb.1
bb.2:
BLR8 implicit $lr8, implicit $rm
...
---
name: deadFlagAfterCSE2
# This case tests that after the dead %3 is CSE-ed with hoisted dead %5 in
# MachineLICM pass, the dead flag will be kept.
tracksRegLiveness: true
body: |
; CHECK-LABEL: name: deadFlagAfterCSE2
; CHECK: bb.0:
; CHECK: successors: %bb.1(0x80000000)
; CHECK: liveins: $x3, $x4
; CHECK: [[COPY:%[0-9]+]]:g8rc = COPY $x3
; CHECK: [[COPY1:%[0-9]+]]:g8rc = COPY $x4
; CHECK: [[ADD8_:%[0-9]+]]:g8rc_and_g8rc_nox0 = ADD8 [[COPY]], [[COPY1]]
; CHECK: dead %3:g8rc_and_g8rc_nox0 = ADDI8 [[ADD8_]], 100
; CHECK: B %bb.1
; CHECK: bb.1:
; CHECK: successors: %bb.1(0x80000000)
; CHECK: [[PHI:%[0-9]+]]:g8rc_and_g8rc_nox0 = PHI [[ADD8_]], %bb.0, %5, %bb.1
; CHECK: [[ADDI8_:%[0-9]+]]:g8rc = nuw ADDI8 [[PHI]], 1
; CHECK: B %bb.1
; CHECK: bb.2:
; CHECK: BLR8 implicit $lr8, implicit $rm
bb.0:
liveins: $x3, $x4
%0:g8rc = COPY $x3
%1:g8rc = COPY $x4
%2:g8rc_and_g8rc_nox0 = ADD8 %0, %1
dead %3:g8rc_and_g8rc_nox0 = ADDI8 %2, 100
B %bb.1
bb.1:
%4:g8rc_and_g8rc_nox0 = PHI %2, %bb.0, %6, %bb.1
dead %5:g8rc_and_g8rc_nox0 = ADDI8 %2, 100
%6:g8rc = nuw ADDI8 %4, 1
B %bb.1
bb.2:
BLR8 implicit $lr8, implicit $rm
...