Coverage Report

Created: 2017-11-14 15:26

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/CodeGen/GlobalISel/LegalizerCombiner.h
Line
Count
Source (jump to first uncovered line)
1
//===-- llvm/CodeGen/GlobalISel/LegalizerCombiner.h --===========//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
// This file contains some helper functions which try to cleanup artifacts
10
// such as G_TRUNCs/G_[ZSA]EXTENDS that were created during legalization to make
11
// the types match. This file also contains some combines of merges that happens
12
// at the end of the legalization.
13
//===----------------------------------------------------------------------===//
14
15
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
16
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
17
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
18
#include "llvm/CodeGen/GlobalISel/Utils.h"
19
#include "llvm/CodeGen/MachineRegisterInfo.h"
20
#include "llvm/Support/Debug.h"
21
22
#define DEBUG_TYPE "legalizer"
23
24
namespace llvm {
25
class LegalizerCombiner {
26
  MachineIRBuilder &Builder;
27
  MachineRegisterInfo &MRI;
28
  const LegalizerInfo &LI;
29
30
public:
31
  LegalizerCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI,
32
                    const LegalizerInfo &LI)
33
10.4M
      : Builder(B), MRI(MRI), LI(LI) {}
34
35
  bool tryCombineAnyExt(MachineInstr &MI,
36
169k
                        SmallVectorImpl<MachineInstr *> &DeadInsts) {
37
169k
    if (MI.getOpcode() != TargetOpcode::G_ANYEXT)
38
0
      return false;
39
169k
    MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(1).getReg());
40
169k
    if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) {
41
147k
      DEBUG(dbgs() << ".. Combine MI: " << MI;);
42
147k
      unsigned DstReg = MI.getOperand(0).getReg();
43
147k
      unsigned SrcReg = DefMI->getOperand(1).getReg();
44
147k
      Builder.setInstr(MI);
45
147k
      // We get a copy/trunc/extend depending on the sizes
46
147k
      Builder.buildAnyExtOrTrunc(DstReg, SrcReg);
47
147k
      markInstAndDefDead(MI, *DefMI, DeadInsts);
48
147k
      return true;
49
147k
    }
50
22.0k
    return false;
51
22.0k
  }
52
53
  bool tryCombineZExt(MachineInstr &MI,
54
225k
                      SmallVectorImpl<MachineInstr *> &DeadInsts) {
55
225k
56
225k
    if (MI.getOpcode() != TargetOpcode::G_ZEXT)
57
0
      return false;
58
225k
    MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(1).getReg());
59
225k
    if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) {
60
119k
      unsigned DstReg = MI.getOperand(0).getReg();
61
119k
      LLT DstTy = MRI.getType(DstReg);
62
119k
      if (isInstUnsupported(TargetOpcode::G_AND, DstTy) ||
63
119k
          isInstUnsupported(TargetOpcode::G_CONSTANT, DstTy))
64
0
        return false;
65
119k
      DEBUG(dbgs() << ".. Combine MI: " << MI;);
66
119k
      Builder.setInstr(MI);
67
119k
      unsigned ZExtSrc = MI.getOperand(1).getReg();
68
119k
      LLT ZExtSrcTy = MRI.getType(ZExtSrc);
69
119k
      APInt Mask = APInt::getAllOnesValue(ZExtSrcTy.getSizeInBits());
70
119k
      auto MaskCstMIB = Builder.buildConstant(DstTy, Mask.getZExtValue());
71
119k
      unsigned TruncSrc = DefMI->getOperand(1).getReg();
72
119k
      // We get a copy/trunc/extend depending on the sizes
73
119k
      auto SrcCopyOrTrunc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc);
74
119k
      Builder.buildAnd(DstReg, SrcCopyOrTrunc, MaskCstMIB);
75
119k
      markInstAndDefDead(MI, *DefMI, DeadInsts);
76
119k
      return true;
77
119k
    }
78
106k
    return false;
79
106k
  }
80
81
  bool tryCombineSExt(MachineInstr &MI,
82
15.0k
                      SmallVectorImpl<MachineInstr *> &DeadInsts) {
83
15.0k
84
15.0k
    if (MI.getOpcode() != TargetOpcode::G_SEXT)
85
0
      return false;
86
15.0k
    MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(1).getReg());
87
15.0k
    if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) {
88
10.9k
      unsigned DstReg = MI.getOperand(0).getReg();
89
10.9k
      LLT DstTy = MRI.getType(DstReg);
90
10.9k
      if (isInstUnsupported(TargetOpcode::G_SHL, DstTy) ||
91
10.9k
          isInstUnsupported(TargetOpcode::G_ASHR, DstTy) ||
92
10.9k
          isInstUnsupported(TargetOpcode::G_CONSTANT, DstTy))
93
0
        return false;
94
10.9k
      DEBUG(dbgs() << ".. Combine MI: " << MI;);
95
10.9k
      Builder.setInstr(MI);
96
10.9k
      unsigned SExtSrc = MI.getOperand(1).getReg();
97
10.9k
      LLT SExtSrcTy = MRI.getType(SExtSrc);
98
10.9k
      unsigned SizeDiff = DstTy.getSizeInBits() - SExtSrcTy.getSizeInBits();
99
10.9k
      auto SizeDiffMIB = Builder.buildConstant(DstTy, SizeDiff);
100
10.9k
      unsigned TruncSrcReg = DefMI->getOperand(1).getReg();
101
10.9k
      // We get a copy/trunc/extend depending on the sizes
102
10.9k
      auto SrcCopyExtOrTrunc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrcReg);
103
10.9k
      auto ShlMIB = Builder.buildInstr(TargetOpcode::G_SHL, DstTy,
104
10.9k
                                       SrcCopyExtOrTrunc, SizeDiffMIB);
105
10.9k
      Builder.buildInstr(TargetOpcode::G_ASHR, DstReg, ShlMIB, SizeDiffMIB);
106
10.9k
      markInstAndDefDead(MI, *DefMI, DeadInsts);
107
10.9k
      return true;
108
10.9k
    }
109
4.10k
    return false;
110
4.10k
  }
111
112
  bool tryCombineMerges(MachineInstr &MI,
113
19.5M
                        SmallVectorImpl<MachineInstr *> &DeadInsts) {
114
19.5M
115
19.5M
    if (MI.getOpcode() != TargetOpcode::G_UNMERGE_VALUES)
116
19.5M
      return false;
117
31.8k
118
31.8k
    unsigned NumDefs = MI.getNumOperands() - 1;
119
31.8k
    unsigned SrcReg = MI.getOperand(NumDefs).getReg();
120
31.8k
    MachineInstr *MergeI = MRI.getVRegDef(SrcReg);
121
31.8k
    if (!MergeI || (MergeI->getOpcode() != TargetOpcode::G_MERGE_VALUES))
122
1.34k
      return false;
123
30.5k
124
30.5k
    const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;
125
30.5k
126
30.5k
    if (NumMergeRegs < NumDefs) {
127
10
      if (NumDefs % NumMergeRegs != 0)
128
0
        return false;
129
10
130
10
      Builder.setInstr(MI);
131
10
      // Transform to UNMERGEs, for example
132
10
      //   %1 = G_MERGE_VALUES %4, %5
133
10
      //   %9, %10, %11, %12 = G_UNMERGE_VALUES %1
134
10
      // to
135
10
      //   %9, %10 = G_UNMERGE_VALUES %4
136
10
      //   %11, %12 = G_UNMERGE_VALUES %5
137
10
138
10
      const unsigned NewNumDefs = NumDefs / NumMergeRegs;
139
30
      for (unsigned Idx = 0; Idx < NumMergeRegs; 
++Idx20
) {
140
20
        SmallVector<unsigned, 2> DstRegs;
141
60
        for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;
142
40
             ++j, ++DefIdx)
143
40
          DstRegs.push_back(MI.getOperand(DefIdx).getReg());
144
20
145
20
        Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg());
146
20
      }
147
10
148
30.5k
    } else if (NumMergeRegs > NumDefs) {
149
5
      if (NumMergeRegs % NumDefs != 0)
150
0
        return false;
151
5
152
5
      Builder.setInstr(MI);
153
5
      // Transform to MERGEs
154
5
      //   %6 = G_MERGE_VALUES %17, %18, %19, %20
155
5
      //   %7, %8 = G_UNMERGE_VALUES %6
156
5
      // to
157
5
      //   %7 = G_MERGE_VALUES %17, %18
158
5
      //   %8 = G_MERGE_VALUES %19, %20
159
5
160
5
      const unsigned NumRegs = NumMergeRegs / NumDefs;
161
15
      for (unsigned DefIdx = 0; DefIdx < NumDefs; 
++DefIdx10
) {
162
10
        SmallVector<unsigned, 2> Regs;
163
30
        for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;
164
20
             ++j, ++Idx)
165
20
          Regs.push_back(MergeI->getOperand(Idx).getReg());
166
10
167
10
        Builder.buildMerge(MI.getOperand(DefIdx).getReg(), Regs);
168
10
      }
169
5
170
30.5k
    } else {
171
30.5k
      // FIXME: is a COPY appropriate if the types mismatch? We know both
172
30.5k
      // registers are allocatable by now.
173
30.5k
      if (MRI.getType(MI.getOperand(0).getReg()) !=
174
30.5k
          MRI.getType(MergeI->getOperand(1).getReg()))
175
0
        return false;
176
30.5k
177
92.3k
      
for (unsigned Idx = 0; 30.5k
Idx < NumDefs;
++Idx61.8k
)
178
61.8k
        MRI.replaceRegWith(MI.getOperand(Idx).getReg(),
179
61.8k
                           MergeI->getOperand(Idx + 1).getReg());
180
30.5k
    }
181
30.5k
182
30.5k
    markInstAndDefDead(MI, *MergeI, DeadInsts);
183
30.5k
    return true;
184
19.5M
  }
185
186
  /// Try to combine away MI.
187
  /// Returns true if it combined away the MI.
188
  /// Adds instructions that are dead as a result of the combine
189
  /// into DeadInsts, which can include MI.
190
  bool tryCombineInstruction(MachineInstr &MI,
191
3.31M
                             SmallVectorImpl<MachineInstr *> &DeadInsts) {
192
3.31M
    switch (MI.getOpcode()) {
193
3.31M
    default:
194
2.87M
      return false;
195
3.31M
    case TargetOpcode::G_ANYEXT:
196
169k
      return tryCombineAnyExt(MI, DeadInsts);
197
3.31M
    case TargetOpcode::G_ZEXT:
198
225k
      return tryCombineZExt(MI, DeadInsts);
199
3.31M
    case TargetOpcode::G_SEXT:
200
15.0k
      return tryCombineSExt(MI, DeadInsts);
201
3.31M
    case TargetOpcode::G_UNMERGE_VALUES:
202
31.1k
      return tryCombineMerges(MI, DeadInsts);
203
0
    }
204
0
  }
205
206
private:
207
  /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be
208
  /// dead due to MI being killed, then mark DefMI as dead too.
209
  void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI,
210
308k
                          SmallVectorImpl<MachineInstr *> &DeadInsts) {
211
308k
    DeadInsts.push_back(&MI);
212
308k
    if (MRI.hasOneUse(DefMI.getOperand(0).getReg()))
213
196k
      DeadInsts.push_back(&DefMI);
214
308k
  }
215
  /// Checks if the target legalizer info has specified anything about the
216
  /// instruction, or if unsupported.
217
271k
  bool isInstUnsupported(unsigned Opcode, const LLT &DstTy) const {
218
271k
    auto Action = LI.getAction({Opcode, 0, DstTy});
219
271k
    return Action.first == LegalizerInfo::LegalizeAction::Unsupported ||
220
271k
           Action.first == LegalizerInfo::LegalizeAction::NotFound;
221
271k
  }
222
};
223
224
} // namespace llvm