aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm16/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp
blob: b97d75a822f753f5996e54690785deba03f1c964 (plain) (blame)
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
//===- ReduceInstructionsMIR.cpp - Specialized Delta Pass -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce uninteresting MachineInstr from the MachineFunction.
//
//===----------------------------------------------------------------------===//

#include "ReduceInstructionsMIR.h"
#include "Delta.h"

#include "llvm/ADT/SetVector.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"

using namespace llvm;

static Register getPrevDefOfRCInMBB(MachineBasicBlock &MBB,
                                    MachineBasicBlock::reverse_iterator &RI,
                                    const RegClassOrRegBank &RC, LLT Ty,
                                    SetVector<MachineInstr *> &ExcludeMIs) {
  auto MRI = &MBB.getParent()->getRegInfo();
  for (MachineBasicBlock::reverse_instr_iterator E = MBB.instr_rend(); RI != E;
       ++RI) {
    auto &MI = *RI;
    // All Def operands explicit and implicit.
    for (auto &MO : MI.operands()) {
      if (!MO.isReg() || !MO.isDef() || MO.isDead())
        continue;
      auto Reg = MO.getReg();
      if (Reg.isPhysical())
        continue;

      if (MRI->getRegClassOrRegBank(Reg) == RC && MRI->getType(Reg) == Ty &&
          !ExcludeMIs.count(MO.getParent()))
        return Reg;
    }
  }
  return 0;
}

static bool shouldNotRemoveInstruction(const TargetInstrInfo &TII,
                                       const MachineInstr &MI) {
  if (MI.isTerminator())
    return true;

  // The MIR is almost certainly going to be invalid if frame instructions are
  // deleted individually since they need to come in balanced pairs, so don't
  // try to delete them.
  if (MI.getOpcode() == TII.getCallFrameSetupOpcode() ||
      MI.getOpcode() == TII.getCallFrameDestroyOpcode())
    return true;

  return false;
}

static void extractInstrFromFunction(Oracle &O, MachineFunction &MF) {
  MachineDominatorTree MDT;
  MDT.runOnMachineFunction(MF);

  auto MRI = &MF.getRegInfo();
  SetVector<MachineInstr *> ToDelete;

  const TargetSubtargetInfo &STI = MF.getSubtarget();
  const TargetInstrInfo *TII = STI.getInstrInfo();
  MachineBasicBlock *EntryMBB = &*MF.begin();
  MachineBasicBlock::iterator EntryInsPt =
      EntryMBB->SkipPHIsLabelsAndDebug(EntryMBB->begin());

  // Mark MIs for deletion according to some criteria.
  for (auto &MBB : MF) {
    for (auto &MI : MBB) {
      if (shouldNotRemoveInstruction(*TII, MI))
        continue;
      if (!O.shouldKeep())
        ToDelete.insert(&MI);
    }
  }

  // For each MI to be deleted update users of regs defined by that MI to use
  // some other dominating definition (that is not to be deleted).
  for (auto *MI : ToDelete) {
    for (auto &MO : MI->operands()) {
      if (!MO.isReg() || !MO.isDef() || MO.isDead())
        continue;
      auto Reg = MO.getReg();
      if (Reg.isPhysical())
        continue;
      auto UI = MRI->use_begin(Reg);
      auto UE = MRI->use_end();

      const auto &RegRC = MRI->getRegClassOrRegBank(Reg);
      LLT RegTy = MRI->getType(Reg);

      Register NewReg = 0;
      // If this is not a physical register and there are some uses.
      if (UI != UE) {
        MachineBasicBlock::reverse_iterator RI(*MI);
        MachineBasicBlock *BB = MI->getParent();
        ++RI;

        if (MDT.isReachableFromEntry(BB)) {
          while (NewReg == 0 && BB) {
            NewReg = getPrevDefOfRCInMBB(*BB, RI, RegRC, RegTy, ToDelete);
            // Prepare for idom(BB).
            if (auto *IDM = MDT.getNode(BB)->getIDom()) {
              BB = IDM->getBlock();
              RI = BB->rbegin();
            } else {
              BB = nullptr;
            }
          }
        }
      }

      // If no dominating definition was found then add an implicit def to the
      // top of the entry block.
      if (!NewReg) {
        NewReg = MRI->cloneVirtualRegister(Reg);
        bool IsGeneric = MRI->getRegClassOrNull(Reg) == nullptr;
        unsigned ImpDef = IsGeneric ? TargetOpcode::G_IMPLICIT_DEF
                                    : TargetOpcode::IMPLICIT_DEF;

        unsigned State = getRegState(MO);
        if (MO.getSubReg())
          State |= RegState::Undef;

        BuildMI(*EntryMBB, EntryInsPt, DebugLoc(), TII->get(ImpDef))
          .addReg(NewReg, State, MO.getSubReg());
      }

      // Update all uses.
      while (UI != UE) {
        auto &UMO = *UI++;
        UMO.setReg(NewReg);
      }
    }
  }

  // Finally delete the MIs.
  for (auto *MI : ToDelete)
    MI->eraseFromParent();
}

static void extractInstrFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
  for (const Function &F : WorkItem.getModule()) {
    if (MachineFunction *MF = WorkItem.MMI->getMachineFunction(F))
      extractInstrFromFunction(O, *MF);
  }
}

void llvm::reduceInstructionsMIRDeltaPass(TestRunner &Test) {
  runDeltaPass(Test, extractInstrFromModule, "Reducing Instructions");
}