Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/Lanai/LanaiDelaySlotFiller.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- LanaiDelaySlotFiller.cpp - Lanai delay slot filler ----------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Simple pass to fills delay slots with useful instructions.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "Lanai.h"
14
#include "LanaiTargetMachine.h"
15
#include "llvm/ADT/SmallSet.h"
16
#include "llvm/ADT/Statistic.h"
17
#include "llvm/CodeGen/MachineFunctionPass.h"
18
#include "llvm/CodeGen/MachineInstrBuilder.h"
19
#include "llvm/CodeGen/TargetInstrInfo.h"
20
#include "llvm/Support/CommandLine.h"
21
22
using namespace llvm;
23
24
#define DEBUG_TYPE "delay-slot-filler"
25
26
STATISTIC(FilledSlots, "Number of delay slots filled");
27
28
static cl::opt<bool>
29
    NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false),
30
                       cl::desc("Fill Lanai delay slots with NOPs."),
31
                       cl::Hidden);
32
33
namespace {
34
struct Filler : public MachineFunctionPass {
35
  // Target machine description which we query for reg. names, data
36
  // layout, etc.
37
  const TargetInstrInfo *TII;
38
  const TargetRegisterInfo *TRI;
39
  MachineBasicBlock::instr_iterator LastFiller;
40
41
  static char ID;
42
22
  explicit Filler() : MachineFunctionPass(ID) {}
43
44
114
  StringRef getPassName() const override { return "Lanai Delay Slot Filler"; }
45
46
  bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
47
48
92
  bool runOnMachineFunction(MachineFunction &MF) override {
49
92
    const LanaiSubtarget &Subtarget = MF.getSubtarget<LanaiSubtarget>();
50
92
    TII = Subtarget.getInstrInfo();
51
92
    TRI = Subtarget.getRegisterInfo();
52
92
53
92
    bool Changed = false;
54
211
    for (MachineFunction::iterator FI = MF.begin(), FE = MF.end(); FI != FE;
55
119
         ++FI)
56
119
      Changed |= runOnMachineBasicBlock(*FI);
57
92
    return Changed;
58
92
  }
59
60
22
  MachineFunctionProperties getRequiredProperties() const override {
61
22
    return MachineFunctionProperties().set(
62
22
        MachineFunctionProperties::Property::NoVRegs);
63
22
  }
64
65
  void insertDefsUses(MachineBasicBlock::instr_iterator MI,
66
                      SmallSet<unsigned, 32> &RegDefs,
67
                      SmallSet<unsigned, 32> &RegUses);
68
69
  bool isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg);
70
71
  bool delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
72
                      bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
73
                      SmallSet<unsigned, 32> &RegUses);
74
75
  bool findDelayInstr(MachineBasicBlock &MBB,
76
                      MachineBasicBlock::instr_iterator Slot,
77
                      MachineBasicBlock::instr_iterator &Filler);
78
};
79
char Filler::ID = 0;
80
} // end of anonymous namespace
81
82
// createLanaiDelaySlotFillerPass - Returns a pass that fills in delay
83
// slots in Lanai MachineFunctions
84
FunctionPass *
85
22
llvm::createLanaiDelaySlotFillerPass(const LanaiTargetMachine & /*tm*/) {
86
22
  return new Filler();
87
22
}
88
89
// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
90
// There is one or two delay slot per delayed instruction.
91
119
bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
92
119
  bool Changed = false;
93
119
  LastFiller = MBB.instr_end();
94
119
95
119
  for (MachineBasicBlock::instr_iterator I = MBB.instr_begin();
96
1.11k
       I != MBB.instr_end(); 
++I1.00k
) {
97
1.00k
    if (I->getDesc().hasDelaySlot()) {
98
123
      MachineBasicBlock::instr_iterator InstrWithSlot = I;
99
123
      MachineBasicBlock::instr_iterator J = I;
100
123
101
123
      // Treat RET specially as it is only instruction with 2 delay slots
102
123
      // generated while all others generated have 1 delay slot.
103
123
      if (I->getOpcode() == Lanai::RET) {
104
90
        // RET is generated as part of epilogue generation and hence we know
105
90
        // what the two instructions preceding it are and that it is safe to
106
90
        // insert RET above them.
107
90
        MachineBasicBlock::reverse_instr_iterator RI = ++I.getReverse();
108
90
        assert(RI->getOpcode() == Lanai::LDW_RI && RI->getOperand(0).isReg() &&
109
90
               RI->getOperand(0).getReg() == Lanai::FP &&
110
90
               RI->getOperand(1).isReg() &&
111
90
               RI->getOperand(1).getReg() == Lanai::FP &&
112
90
               RI->getOperand(2).isImm() && RI->getOperand(2).getImm() == -8);
113
90
        ++RI;
114
90
        assert(RI->getOpcode() == Lanai::ADD_I_LO &&
115
90
               RI->getOperand(0).isReg() &&
116
90
               RI->getOperand(0).getReg() == Lanai::SP &&
117
90
               RI->getOperand(1).isReg() &&
118
90
               RI->getOperand(1).getReg() == Lanai::FP);
119
90
        MachineBasicBlock::instr_iterator FI = RI.getReverse();
120
90
        MBB.splice(std::next(I), &MBB, FI, I);
121
90
        FilledSlots += 2;
122
90
      } else {
123
33
        if (!NopDelaySlotFiller && 
findDelayInstr(MBB, I, J)30
) {
124
22
          MBB.splice(std::next(I), &MBB, J);
125
22
        } else {
126
11
          BuildMI(MBB, std::next(I), DebugLoc(), TII->get(Lanai::NOP));
127
11
        }
128
33
        ++FilledSlots;
129
33
      }
130
123
131
123
      Changed = true;
132
123
      // Record the filler instruction that filled the delay slot.
133
123
      // The instruction after it will be visited in the next iteration.
134
123
      LastFiller = ++I;
135
123
136
123
      // Bundle the delay slot filler to InstrWithSlot so that the machine
137
123
      // verifier doesn't expect this instruction to be a terminator.
138
123
      MIBundleBuilder(MBB, InstrWithSlot, std::next(LastFiller));
139
123
    }
140
1.00k
  }
141
119
  return Changed;
142
119
}
143
144
bool Filler::findDelayInstr(MachineBasicBlock &MBB,
145
                            MachineBasicBlock::instr_iterator Slot,
146
30
                            MachineBasicBlock::instr_iterator &Filler) {
147
30
  SmallSet<unsigned, 32> RegDefs;
148
30
  SmallSet<unsigned, 32> RegUses;
149
30
150
30
  insertDefsUses(Slot, RegDefs, RegUses);
151
30
152
30
  bool SawLoad = false;
153
30
  bool SawStore = false;
154
30
155
30
  for (MachineBasicBlock::reverse_instr_iterator I = ++Slot.getReverse();
156
68
       I != MBB.instr_rend(); 
++I38
) {
157
62
    // skip debug value
158
62
    if (I->isDebugInstr())
159
0
      continue;
160
62
161
62
    // Convert to forward iterator.
162
62
    MachineBasicBlock::instr_iterator FI = I.getReverse();
163
62
164
62
    if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isLabel() ||
165
62
        FI == LastFiller || 
I->isPseudo()61
)
166
2
      break;
167
60
168
60
    if (delayHasHazard(FI, SawLoad, SawStore, RegDefs, RegUses)) {
169
38
      insertDefsUses(FI, RegDefs, RegUses);
170
38
      continue;
171
38
    }
172
22
    Filler = FI;
173
22
    return true;
174
22
  }
175
30
  
return false8
;
176
30
}
177
178
bool Filler::delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
179
                            bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
180
60
                            SmallSet<unsigned, 32> &RegUses) {
181
60
  if (MI->isImplicitDef() || MI->isKill())
182
0
    return true;
183
60
184
60
  // Loads or stores cannot be moved past a store to the delay slot
185
60
  // and stores cannot be moved past a load.
186
60
  if (MI->mayLoad()) {
187
10
    if (SawStore)
188
0
      return true;
189
10
    SawLoad = true;
190
10
  }
191
60
192
60
  if (MI->mayStore()) {
193
2
    if (SawStore)
194
0
      return true;
195
2
    SawStore = true;
196
2
    if (SawLoad)
197
0
      return true;
198
60
  }
199
60
200
60
  assert((!MI->isCall() && !MI->isReturn()) &&
201
60
         "Cannot put calls or returns in delay slot.");
202
60
203
182
  for (unsigned I = 0, E = MI->getNumOperands(); I != E; 
++I122
) {
204
160
    const MachineOperand &MO = MI->getOperand(I);
205
160
    unsigned Reg;
206
160
207
160
    if (!MO.isReg() || 
!(Reg = MO.getReg())119
)
208
41
      continue; // skip
209
119
210
119
    if (MO.isDef()) {
211
64
      // check whether Reg is defined or used before delay slot.
212
64
      if (isRegInSet(RegDefs, Reg) || 
isRegInSet(RegUses, Reg)48
)
213
36
        return true;
214
83
    }
215
83
    if (MO.isUse()) {
216
55
      // check whether Reg is defined before delay slot.
217
55
      if (isRegInSet(RegDefs, Reg))
218
2
        return true;
219
55
    }
220
83
  }
221
60
  
return false22
;
222
60
}
223
224
// Insert Defs and Uses of MI into the sets RegDefs and RegUses.
225
void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI,
226
                            SmallSet<unsigned, 32> &RegDefs,
227
68
                            SmallSet<unsigned, 32> &RegUses) {
228
68
  // If MI is a call or return, just examine the explicit non-variadic operands.
229
68
  MCInstrDesc MCID = MI->getDesc();
230
68
  unsigned E = MI->isCall() || 
MI->isReturn()56
?
MCID.getNumOperands()12
231
68
                                              : 
MI->getNumOperands()56
;
232
255
  for (unsigned I = 0; I != E; 
++I187
) {
233
187
    const MachineOperand &MO = MI->getOperand(I);
234
187
    unsigned Reg;
235
187
236
187
    if (!MO.isReg() || 
!(Reg = MO.getReg())101
)
237
86
      continue;
238
101
239
101
    if (MO.isDef())
240
42
      RegDefs.insert(Reg);
241
59
    else if (MO.isUse())
242
59
      RegUses.insert(Reg);
243
101
  }
244
68
245
68
  // Call & return instructions defines SP implicitly. Implicit defines are not
246
68
  // included in the RegDefs set of calls but instructions modifying SP cannot
247
68
  // be inserted in the delay slot of a call/return as these instructions are
248
68
  // expanded to multiple instructions with SP modified before the branch that
249
68
  // has the delay slot.
250
68
  if (MI->isCall() || 
MI->isReturn()56
)
251
12
    RegDefs.insert(Lanai::SP);
252
68
}
253
254
// Returns true if the Reg or its alias is in the RegSet.
255
167
bool Filler::isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg) {
256
167
  // Check Reg and all aliased Registers.
257
337
  for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); 
++AI170
)
258
208
    if (RegSet.count(*AI))
259
38
      return true;
260
167
  
return false129
;
261
167
}