Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp
Line
Count
Source (jump to first uncovered line)
1
//===------------- PPCEarlyReturn.cpp - Form Early Returns ----------------===//
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
// A pass that form early (predicated) returns. If-conversion handles some of
10
// this, but this pass picks up some remaining cases.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "MCTargetDesc/PPCPredicates.h"
15
#include "PPC.h"
16
#include "PPCInstrBuilder.h"
17
#include "PPCInstrInfo.h"
18
#include "PPCMachineFunctionInfo.h"
19
#include "PPCTargetMachine.h"
20
#include "llvm/ADT/STLExtras.h"
21
#include "llvm/ADT/Statistic.h"
22
#include "llvm/CodeGen/MachineFrameInfo.h"
23
#include "llvm/CodeGen/MachineFunctionPass.h"
24
#include "llvm/CodeGen/MachineInstrBuilder.h"
25
#include "llvm/CodeGen/MachineMemOperand.h"
26
#include "llvm/CodeGen/MachineRegisterInfo.h"
27
#include "llvm/MC/MCAsmInfo.h"
28
#include "llvm/Support/Debug.h"
29
#include "llvm/Support/ErrorHandling.h"
30
#include "llvm/Support/TargetRegistry.h"
31
#include "llvm/Support/raw_ostream.h"
32
33
using namespace llvm;
34
35
#define DEBUG_TYPE "ppc-early-ret"
36
STATISTIC(NumBCLR, "Number of early conditional returns");
37
STATISTIC(NumBLR,  "Number of early returns");
38
39
namespace {
40
  // PPCEarlyReturn pass - For simple functions without epilogue code, move
41
  // returns up, and create conditional returns, to avoid unnecessary
42
  // branch-to-blr sequences.
43
  struct PPCEarlyReturn : public MachineFunctionPass {
44
    static char ID;
45
1.66k
    PPCEarlyReturn() : MachineFunctionPass(ID) {
46
1.66k
      initializePPCEarlyReturnPass(*PassRegistry::getPassRegistry());
47
1.66k
    }
48
49
    const TargetInstrInfo *TII;
50
51
protected:
52
7.02k
    bool processBlock(MachineBasicBlock &ReturnMBB) {
53
7.02k
      bool Changed = false;
54
7.02k
55
7.02k
      MachineBasicBlock::iterator I = ReturnMBB.begin();
56
7.02k
      I = ReturnMBB.SkipPHIsLabelsAndDebug(I);
57
7.02k
58
7.02k
      // The block must be essentially empty except for the blr.
59
7.02k
      if (I == ReturnMBB.end() ||
60
7.02k
          
(6.71k
I->getOpcode() != PPC::BLR6.71k
&&
I->getOpcode() != PPC::BLR86.68k
) ||
61
7.02k
          
I != ReturnMBB.getLastNonDebugInstr()275
)
62
6.74k
        return Changed;
63
275
64
275
      SmallVector<MachineBasicBlock*, 8> PredToRemove;
65
275
      for (MachineBasicBlock::pred_iterator PI = ReturnMBB.pred_begin(),
66
668
           PIE = ReturnMBB.pred_end(); PI != PIE; 
++PI393
) {
67
393
        bool OtherReference = false, BlockChanged = false;
68
393
69
393
        if ((*PI)->empty())
70
0
          continue;
71
393
72
836
        
for (MachineBasicBlock::iterator J = (*PI)->getLastNonDebugInstr();;)393
{
73
836
          if (J == (*PI)->end())
74
0
            break;
75
836
76
836
          if (J->getOpcode() == PPC::B) {
77
93
            if (J->getOperand(0).getMBB() == &ReturnMBB) {
78
93
              // This is an unconditional branch to the return. Replace the
79
93
              // branch with a blr.
80
93
              BuildMI(**PI, J, J->getDebugLoc(), TII->get(I->getOpcode()))
81
93
                  .copyImplicitOps(*I);
82
93
              MachineBasicBlock::iterator K = J--;
83
93
              K->eraseFromParent();
84
93
              BlockChanged = true;
85
93
              ++NumBLR;
86
93
              continue;
87
93
            }
88
743
          } else if (J->getOpcode() == PPC::BCC) {
89
65
            if (J->getOperand(2).getMBB() == &ReturnMBB) {
90
14
              // This is a conditional branch to the return. Replace the branch
91
14
              // with a bclr.
92
14
              BuildMI(**PI, J, J->getDebugLoc(), TII->get(PPC::BCCLR))
93
14
                  .addImm(J->getOperand(0).getImm())
94
14
                  .addReg(J->getOperand(1).getReg())
95
14
                  .copyImplicitOps(*I);
96
14
              MachineBasicBlock::iterator K = J--;
97
14
              K->eraseFromParent();
98
14
              BlockChanged = true;
99
14
              ++NumBCLR;
100
14
              continue;
101
14
            }
102
678
          } else if (J->getOpcode() == PPC::BC || 
J->getOpcode() == PPC::BCn620
) {
103
77
            if (J->getOperand(1).getMBB() == &ReturnMBB) {
104
38
              // This is a conditional branch to the return. Replace the branch
105
38
              // with a bclr.
106
38
              BuildMI(
107
38
                  **PI, J, J->getDebugLoc(),
108
38
                  TII->get(J->getOpcode() == PPC::BC ? 
PPC::BCLR30
:
PPC::BCLRn8
))
109
38
                  .addReg(J->getOperand(0).getReg())
110
38
                  .copyImplicitOps(*I);
111
38
              MachineBasicBlock::iterator K = J--;
112
38
              K->eraseFromParent();
113
38
              BlockChanged = true;
114
38
              ++NumBCLR;
115
38
              continue;
116
38
            }
117
601
          } else if (J->isBranch()) {
118
142
            if (J->isIndirectBranch()) {
119
2
              if (ReturnMBB.hasAddressTaken())
120
0
                OtherReference = true;
121
2
            } else
122
697
              
for (unsigned i = 0; 140
i < J->getNumOperands();
++i557
)
123
557
                if (J->getOperand(i).isMBB() &&
124
557
                    
J->getOperand(i).getMBB() == &ReturnMBB88
)
125
0
                  OtherReference = true;
126
459
          } else if (!J->isTerminator() && 
!J->isDebugInstr()366
)
127
366
            break;
128
325
129
325
          if (J == (*PI)->begin())
130
27
            break;
131
298
132
298
          --J;
133
298
        }
134
393
135
393
        if ((*PI)->canFallThrough() && 
(*PI)->isLayoutSuccessor(&ReturnMBB)298
)
136
246
          OtherReference = true;
137
393
138
393
        // Predecessors are stored in a vector and can't be removed here.
139
393
        if (!OtherReference && 
BlockChanged147
) {
140
145
          PredToRemove.push_back(*PI);
141
145
        }
142
393
143
393
        if (BlockChanged)
144
145
          Changed = true;
145
393
      }
146
275
147
420
      for (unsigned i = 0, ie = PredToRemove.size(); i != ie; 
++i145
)
148
145
        PredToRemove[i]->removeSuccessor(&ReturnMBB, true);
149
275
150
275
      if (Changed && 
!ReturnMBB.hasAddressTaken()126
) {
151
126
        // We now might be able to merge this blr-only block into its
152
126
        // by-layout predecessor.
153
126
        if (ReturnMBB.pred_size() == 1) {
154
97
          MachineBasicBlock &PrevMBB = **ReturnMBB.pred_begin();
155
97
          if (PrevMBB.isLayoutSuccessor(&ReturnMBB) && PrevMBB.canFallThrough()) {
156
97
            // Move the blr into the preceding block.
157
97
            PrevMBB.splice(PrevMBB.end(), &ReturnMBB, I);
158
97
            PrevMBB.removeSuccessor(&ReturnMBB, true);
159
97
          }
160
97
        }
161
126
162
126
        if (ReturnMBB.pred_empty())
163
126
          ReturnMBB.eraseFromParent();
164
126
      }
165
275
166
275
      return Changed;
167
275
    }
168
169
public:
170
10.4k
    bool runOnMachineFunction(MachineFunction &MF) override {
171
10.4k
      if (skipFunction(MF.getFunction()))
172
1
        return false;
173
10.4k
174
10.4k
      TII = MF.getSubtarget().getInstrInfo();
175
10.4k
176
10.4k
      bool Changed = false;
177
10.4k
178
10.4k
      // If the function does not have at least two blocks, then there is
179
10.4k
      // nothing to do.
180
10.4k
      if (MF.size() < 2)
181
8.77k
        return Changed;
182
1.66k
      
183
1.66k
      // We can't use a range-based for loop due to clobbering the iterator.
184
8.69k
      
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); 1.66k
I != E;) {
185
7.02k
        MachineBasicBlock &B = *I++;
186
7.02k
        Changed |= processBlock(B);
187
7.02k
      }
188
1.66k
189
1.66k
      return Changed;
190
1.66k
    }
191
192
1.63k
    MachineFunctionProperties getRequiredProperties() const override {
193
1.63k
      return MachineFunctionProperties().set(
194
1.63k
          MachineFunctionProperties::Property::NoVRegs);
195
1.63k
    }
196
197
1.62k
    void getAnalysisUsage(AnalysisUsage &AU) const override {
198
1.62k
      MachineFunctionPass::getAnalysisUsage(AU);
199
1.62k
    }
200
  };
201
}
202
203
INITIALIZE_PASS(PPCEarlyReturn, DEBUG_TYPE,
204
                "PowerPC Early-Return Creation", false, false)
205
206
char PPCEarlyReturn::ID = 0;
207
FunctionPass*
208
1.66k
llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }