/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 |