]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Merge compiler-rt trunk r291476.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / CodeGen / GlobalISel / LegalizerHelper.cpp
1 //===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
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 //
10 /// \file This file implements the LegalizerHelper class to legalize
11 /// individual instructions and the LegalizeMachineIR wrapper pass for the
12 /// primary legalization.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
17 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
18 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/Target/TargetLowering.h"
23 #include "llvm/Target/TargetSubtargetInfo.h"
24
25 #include <sstream>
26
27 #define DEBUG_TYPE "legalize-mir"
28
29 using namespace llvm;
30
31 LegalizerHelper::LegalizerHelper(MachineFunction &MF)
32   : MRI(MF.getRegInfo()) {
33   MIRBuilder.setMF(MF);
34 }
35
36 LegalizerHelper::LegalizeResult
37 LegalizerHelper::legalizeInstrStep(MachineInstr &MI,
38                                    const LegalizerInfo &LegalizerInfo) {
39   auto Action = LegalizerInfo.getAction(MI, MRI);
40   switch (std::get<0>(Action)) {
41   case LegalizerInfo::Legal:
42     return AlreadyLegal;
43   case LegalizerInfo::Libcall:
44     return libcall(MI);
45   case LegalizerInfo::NarrowScalar:
46     return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
47   case LegalizerInfo::WidenScalar:
48     return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
49   case LegalizerInfo::Lower:
50     return lower(MI, std::get<1>(Action), std::get<2>(Action));
51   case LegalizerInfo::FewerElements:
52     return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
53   default:
54     return UnableToLegalize;
55   }
56 }
57
58 LegalizerHelper::LegalizeResult
59 LegalizerHelper::legalizeInstr(MachineInstr &MI,
60                                const LegalizerInfo &LegalizerInfo) {
61   SmallVector<MachineInstr *, 4> WorkList;
62   MIRBuilder.recordInsertions(
63       [&](MachineInstr *MI) { WorkList.push_back(MI); });
64   WorkList.push_back(&MI);
65
66   bool Changed = false;
67   LegalizeResult Res;
68   unsigned Idx = 0;
69   do {
70     Res = legalizeInstrStep(*WorkList[Idx], LegalizerInfo);
71     if (Res == UnableToLegalize) {
72       MIRBuilder.stopRecordingInsertions();
73       return UnableToLegalize;
74     }
75     Changed |= Res == Legalized;
76     ++Idx;
77   } while (Idx < WorkList.size());
78
79   MIRBuilder.stopRecordingInsertions();
80
81   return Changed ? Legalized : AlreadyLegal;
82 }
83
84 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
85                                    SmallVectorImpl<unsigned> &VRegs) {
86   unsigned Size = Ty.getSizeInBits();
87   SmallVector<uint64_t, 4> Indexes;
88   for (int i = 0; i < NumParts; ++i) {
89     VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
90     Indexes.push_back(i * Size);
91   }
92   MIRBuilder.buildExtract(VRegs, Indexes, Reg);
93 }
94
95 LegalizerHelper::LegalizeResult
96 LegalizerHelper::libcall(MachineInstr &MI) {
97   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
98   unsigned Size = Ty.getSizeInBits();
99   MIRBuilder.setInstr(MI);
100
101   switch (MI.getOpcode()) {
102   default:
103     return UnableToLegalize;
104   case TargetOpcode::G_FREM: {
105     auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
106     Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
107     auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
108     auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
109     const char *Name =
110         TLI.getLibcallName(Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32);
111
112     CLI.lowerCall(
113         MIRBuilder, MachineOperand::CreateES(Name),
114         {MI.getOperand(0).getReg(), Ty},
115         {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
116     MI.eraseFromParent();
117     return Legalized;
118   }
119   }
120 }
121
122 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
123                                                               unsigned TypeIdx,
124                                                               LLT NarrowTy) {
125   // FIXME: Don't know how to handle secondary types yet.
126   if (TypeIdx != 0)
127     return UnableToLegalize;
128   switch (MI.getOpcode()) {
129   default:
130     return UnableToLegalize;
131   case TargetOpcode::G_ADD: {
132     // Expand in terms of carry-setting/consuming G_ADDE instructions.
133     unsigned NarrowSize = NarrowTy.getSizeInBits();
134     int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
135                    NarrowTy.getSizeInBits();
136
137     MIRBuilder.setInstr(MI);
138
139     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
140     SmallVector<uint64_t, 2> Indexes;
141     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
142     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
143
144     unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
145     MIRBuilder.buildConstant(CarryIn, 0);
146
147     for (int i = 0; i < NumParts; ++i) {
148       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
149       unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
150
151       MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
152                             Src2Regs[i], CarryIn);
153
154       DstRegs.push_back(DstReg);
155       Indexes.push_back(i * NarrowSize);
156       CarryIn = CarryOut;
157     }
158     unsigned DstReg = MI.getOperand(0).getReg();
159     MIRBuilder.buildSequence(DstReg, DstRegs, Indexes);
160     MI.eraseFromParent();
161     return Legalized;
162   }
163   }
164 }
165
166 LegalizerHelper::LegalizeResult
167 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
168   MIRBuilder.setInstr(MI);
169
170   switch (MI.getOpcode()) {
171   default:
172     return UnableToLegalize;
173   case TargetOpcode::G_ADD:
174   case TargetOpcode::G_AND:
175   case TargetOpcode::G_MUL:
176   case TargetOpcode::G_OR:
177   case TargetOpcode::G_XOR:
178   case TargetOpcode::G_SUB: {
179     // Perform operation at larger width (any extension is fine here, high bits
180     // don't affect the result) and then truncate the result back to the
181     // original type.
182     unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
183     unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
184     MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
185     MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
186
187     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
188     MIRBuilder.buildInstr(MI.getOpcode())
189         .addDef(DstExt)
190         .addUse(Src1Ext)
191         .addUse(Src2Ext);
192
193     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
194     MI.eraseFromParent();
195     return Legalized;
196   }
197   case TargetOpcode::G_SDIV:
198   case TargetOpcode::G_UDIV: {
199     unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV
200                           ? TargetOpcode::G_SEXT
201                           : TargetOpcode::G_ZEXT;
202
203     unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
204     MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
205         MI.getOperand(1).getReg());
206
207     unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
208     MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
209         MI.getOperand(2).getReg());
210
211     unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
212     MIRBuilder.buildInstr(MI.getOpcode())
213         .addDef(ResExt)
214         .addUse(LHSExt)
215         .addUse(RHSExt);
216
217     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
218     MI.eraseFromParent();
219     return Legalized;
220   }
221   case TargetOpcode::G_LOAD: {
222     assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
223                WideTy.getSizeInBits() &&
224            "illegal to increase number of bytes loaded");
225
226     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
227     MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
228                          **MI.memoperands_begin());
229     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
230     MI.eraseFromParent();
231     return Legalized;
232   }
233   case TargetOpcode::G_STORE: {
234     assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
235                WideTy.getSizeInBits() &&
236            "illegal to increase number of bytes modified by a store");
237
238     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
239     MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg());
240     MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
241                           **MI.memoperands_begin());
242     MI.eraseFromParent();
243     return Legalized;
244   }
245   case TargetOpcode::G_CONSTANT: {
246     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
247     MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
248     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
249     MI.eraseFromParent();
250     return Legalized;
251   }
252   case TargetOpcode::G_FCONSTANT: {
253     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
254     MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
255     MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
256     MI.eraseFromParent();
257     return Legalized;
258   }
259   case TargetOpcode::G_BRCOND: {
260     unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
261     MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
262     MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
263     MI.eraseFromParent();
264     return Legalized;
265   }
266   case TargetOpcode::G_ICMP: {
267     assert(TypeIdx == 1 && "unable to legalize predicate");
268     bool IsSigned = CmpInst::isSigned(
269         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
270     unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
271     unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
272     if (IsSigned) {
273       MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
274       MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
275     } else {
276       MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
277       MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
278     }
279     MIRBuilder.buildICmp(
280         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
281         MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
282     MI.eraseFromParent();
283     return Legalized;
284   }
285   case TargetOpcode::G_GEP: {
286     assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
287     unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
288     MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
289     MI.getOperand(2).setReg(OffsetExt);
290     return Legalized;
291   }
292   }
293 }
294
295 LegalizerHelper::LegalizeResult
296 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
297   using namespace TargetOpcode;
298   MIRBuilder.setInstr(MI);
299
300   switch(MI.getOpcode()) {
301   default:
302     return UnableToLegalize;
303   case TargetOpcode::G_SREM:
304   case TargetOpcode::G_UREM: {
305     unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
306     MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
307         .addDef(QuotReg)
308         .addUse(MI.getOperand(1).getReg())
309         .addUse(MI.getOperand(2).getReg());
310
311     unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
312     MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
313     MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
314                         ProdReg);
315     MI.eraseFromParent();
316     return Legalized;
317   }
318   }
319 }
320
321 LegalizerHelper::LegalizeResult
322 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
323                                      LLT NarrowTy) {
324   // FIXME: Don't know how to handle secondary types yet.
325   if (TypeIdx != 0)
326     return UnableToLegalize;
327   switch (MI.getOpcode()) {
328   default:
329     return UnableToLegalize;
330   case TargetOpcode::G_ADD: {
331     unsigned NarrowSize = NarrowTy.getSizeInBits();
332     unsigned DstReg = MI.getOperand(0).getReg();
333     int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
334
335     MIRBuilder.setInstr(MI);
336
337     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
338     SmallVector<uint64_t, 2> Indexes;
339     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
340     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
341
342     for (int i = 0; i < NumParts; ++i) {
343       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
344       MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
345       DstRegs.push_back(DstReg);
346       Indexes.push_back(i * NarrowSize);
347     }
348
349     MIRBuilder.buildSequence(DstReg, DstRegs, Indexes);
350     MI.eraseFromParent();
351     return Legalized;
352   }
353   }
354 }