Skip to content

Commit 33b07d6

Browse files
committedJul 22, 2016
GlobalISel: implement legalization pass, with just one transformation.
This adds the actual MachineLegalizeHelper to do the work and a trivial pass wrapper that legalizes all instructions in a MachineFunction. Currently the only transformation supported is splitting up a vector G_ADD into one acting on smaller vectors. llvm-svn: 276461
1 parent e4a4f33 commit 33b07d6

25 files changed

+554
-16
lines changed
 

‎llvm/include/llvm/CodeGen/GlobalISel/GISelAccessor.h

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace llvm {
1919
class CallLowering;
20+
class MachineLegalizer;
2021
class RegisterBankInfo;
2122

2223
/// The goal of this helper class is to gather the accessor to all
@@ -27,6 +28,9 @@ class RegisterBankInfo;
2728
struct GISelAccessor {
2829
virtual ~GISelAccessor() {}
2930
virtual const CallLowering *getCallLowering() const { return nullptr;}
31+
virtual const MachineLegalizer *getMachineLegalizer() const {
32+
return nullptr;
33+
}
3034
virtual const RegisterBankInfo *getRegBankInfo() const { return nullptr;}
3135
};
3236
} // End namespace llvm;

‎llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

+32-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class MachineIRBuilder {
8080
/// Set the insertion point to before (\p Before = true) or after
8181
/// (\p Before = false) \p MI.
8282
/// \pre MI must be in getMF().
83-
void setInstr(MachineInstr &MI, bool Before = false);
83+
void setInstr(MachineInstr &MI, bool Before = true);
8484
/// @}
8585

8686
/// Set the debug location to \p DL for all the next build instructions.
@@ -152,6 +152,37 @@ class MachineIRBuilder {
152152
/// \return The newly created instruction.
153153
MachineInstr *buildFrameIndex(LLT Ty, unsigned Res, int Idx);
154154

155+
/// Build and insert \p Res<def> = G_ADD \p Ty \p Op0, \p Op1
156+
///
157+
/// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
158+
/// truncated to their width.
159+
///
160+
/// \pre setBasicBlock or setMI must have been called.
161+
///
162+
/// \return The newly created instruction.
163+
MachineInstr *buildAdd(LLT Ty, unsigned Res, unsigned Op0, unsigned Op1);
164+
165+
/// Build and insert `Res0<def>, ... = G_EXTRACT Ty Src, Idx0, ...`.
166+
///
167+
/// If \p Ty has size N bits, G_EXTRACT sets \p Res[0] to bits `[Idxs[0],
168+
/// Idxs[0] + N)` of \p Src and similarly for subsequent bit-indexes.
169+
///
170+
/// \pre setBasicBlock or setMI must have been called.
171+
///
172+
/// \return The newly created instruction.
173+
MachineInstr *buildExtract(LLT Ty, ArrayRef<unsigned> Results, unsigned Src,
174+
ArrayRef<unsigned> Indexes);
175+
176+
/// Build and insert \p Res<def> = G_SEQUENCE \p Ty \p Ops[0], ...
177+
///
178+
/// G_SEQUENCE concatenates each element in Ops into a single register, where
179+
/// Ops[0] starts at bit 0 of \p Res.
180+
///
181+
/// \pre setBasicBlock or setMI must have been called.
182+
/// \pre The sum of the input sizes must equal the result's size.
183+
///
184+
/// \return The newly created instruction.
185+
MachineInstr *buildSequence(LLT Ty, unsigned Res, ArrayRef<unsigned> Ops);
155186
};
156187

157188
} // End namespace llvm.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//== llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h ----------- -*- C++ -*-==//
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 A pass to convert the target-illegal operations created by IR -> MIR
11+
/// translation into ones the target expects to be able to select. This may
12+
/// occur in multiple phases, for example G_ADD <2 x i8> -> G_ADD <2 x i16> ->
13+
/// G_ADD <4 x i16>.
14+
///
15+
/// The MachineLegalizeHelper class is where most of the work happens, and is
16+
/// designed to be callable from other passes that find themselves with an
17+
/// illegal instruction.
18+
//
19+
//===----------------------------------------------------------------------===//
20+
21+
#ifndef LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H
22+
#define LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H
23+
24+
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
25+
#include "llvm/CodeGen/MachineFunctionPass.h"
26+
#include "llvm/CodeGen/LowLevelType.h"
27+
28+
namespace llvm {
29+
// Forward declarations.
30+
class MachineLegalizeInfo;
31+
class MachineLegalizer;
32+
class MachineRegisterInfo;
33+
34+
class MachineLegalizeHelper {
35+
public:
36+
enum LegalizeResult {
37+
/// Instruction was already legal and no change was made to the
38+
/// MachineFunction.
39+
AlreadyLegal,
40+
41+
/// Instruction has been legalized and the MachineFunction changed.
42+
Legalized,
43+
44+
/// Some kind of error has occurred and we could not legalize this
45+
/// instruction.
46+
UnableToLegalize,
47+
};
48+
49+
MachineLegalizeHelper(MachineFunction &MF);
50+
51+
/// Replace \p MI by a sequence of legal instructions that can implement the
52+
/// same operation. Note that this means \p MI may be deleted, so any iterator
53+
/// steps should be performed before calling this function. \p Helper should
54+
/// be initialized to the MachineFunction containing \p MI.
55+
///
56+
/// Considered as an opaque blob, the legal code will use and define the same
57+
/// registers as \p MI.
58+
LegalizeResult legalizeInstr(MachineInstr &MI,
59+
const MachineLegalizer &Legalizer);
60+
61+
/// Legalize an instruction by reducing the width of the underlying scalar
62+
/// type.
63+
LegalizeResult narrowScalar(MachineInstr &MI, LLT NarrowTy);
64+
65+
/// Legalize an instruction by performing the operation on a wider scalar type
66+
/// (for example a 16-bit addition can be safely performed at 32-bits
67+
/// precision, ignoring the unused bits).
68+
LegalizeResult widenScalar(MachineInstr &MI, LLT WideTy);
69+
70+
/// Legalize a vector instruction by splitting into multiple components, each
71+
/// acting on the same scalar type as the original but with fewer elements.
72+
LegalizeResult fewerElementsVector(MachineInstr &MI, LLT NarrowTy);
73+
74+
/// Legalize a vector instruction by increasing the number of vector elements
75+
/// involved and ignoring the added elements later.
76+
LegalizeResult moreElementsVector(MachineInstr &MI, LLT WideTy);
77+
78+
private:
79+
80+
/// Helper function to split a wide generic register into bitwise blocks with
81+
/// the given Type (which implies the number of blocks needed). The generic
82+
/// registers created are appended to Ops, starting at bit 0 of Reg.
83+
void extractParts(unsigned Reg, LLT Ty, int NumParts,
84+
SmallVectorImpl<unsigned> &Ops);
85+
86+
MachineIRBuilder MIRBuilder;
87+
MachineRegisterInfo &MRI;
88+
};
89+
90+
} // End namespace llvm.
91+
92+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//== llvm/CodeGen/GlobalISel/MachineLegalizePass.h ------------- -*- C++ -*-==//
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 A pass to convert the target-illegal operations created by IR -> MIR
11+
/// translation into ones the target expects to be able to select. This may
12+
/// occur in multiple phases, for example G_ADD <2 x i8> -> G_ADD <2 x i16> ->
13+
/// G_ADD <4 x i16>.
14+
///
15+
/// The LegalizeHelper class is where most of the work happens, and is designed
16+
/// to be callable from other passes that find themselves with an illegal
17+
/// instruction.
18+
//
19+
//===----------------------------------------------------------------------===//
20+
21+
#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZEMACHINEIRPASS_H
22+
#define LLVM_CODEGEN_GLOBALISEL_LEGALIZEMACHINEIRPASS_H
23+
24+
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
25+
#include "llvm/CodeGen/MachineFunctionPass.h"
26+
27+
namespace llvm {
28+
29+
class MachineLegalizePass : public MachineFunctionPass {
30+
public:
31+
static char ID;
32+
33+
private:
34+
35+
/// Initialize the field members using \p MF.
36+
void init(MachineFunction &MF);
37+
38+
public:
39+
// Ctor, nothing fancy.
40+
MachineLegalizePass();
41+
42+
const char *getPassName() const override {
43+
return "MachineLegalizePass";
44+
}
45+
46+
bool runOnMachineFunction(MachineFunction &MF) override;
47+
};
48+
} // End namespace llvm.
49+
50+
#endif

‎llvm/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h

-11
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,6 @@ class MachineLegalizer {
7171

7272
MachineLegalizer();
7373

74-
/// Replace \p MI by a sequence of legal instructions that can implement the
75-
/// same operation. Note that this means \p MI may be deleted, so any iterator
76-
/// steps should be performed before calling this function.
77-
///
78-
/// Considered as an opaque blob, the legal code will use and define the same
79-
/// registers as \p MI.
80-
///
81-
/// \returns true if the function is modified, false if the instruction was
82-
/// already legal.
83-
bool legalizeInstr(MachineInstr &MI) const;
84-
8574
/// Compute any ancillary tables needed to quickly decide how an operation
8675
/// should be handled. This must be called after all "set*Action"methods but
8776
/// before any query is made or incorrect results may be returned.

‎llvm/include/llvm/CodeGen/TargetPassConfig.h

+8
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,14 @@ class TargetPassConfig : public ImmutablePass {
217217
/// LLVM code to machine instructions with possibly generic opcodes.
218218
virtual bool addIRTranslator() { return true; }
219219

220+
/// This method may be implemented by targets that want to run passes
221+
/// immediately before legalization.
222+
virtual void addPreLegalizeMachineIR() {}
223+
224+
/// This method should install a legalize pass, which converts the instruction
225+
/// sequence into one that can be selected by the target.
226+
virtual bool addLegalizeMachineIR() { return true; }
227+
220228
/// This method may be implemented by targets that want to run passes
221229
/// immediately before the register bank selection.
222230
virtual void addPreRegBankSelect() {}

‎llvm/include/llvm/InitializePasses.h

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ void initializeMachineCopyPropagationPass(PassRegistry&);
214214
void initializeMachineDominanceFrontierPass(PassRegistry&);
215215
void initializeMachineDominatorTreePass(PassRegistry&);
216216
void initializeMachineFunctionPrinterPassPass(PassRegistry&);
217+
void initializeMachineLegalizePassPass(PassRegistry&);
217218
void initializeMachineLICMPass(PassRegistry&);
218219
void initializeMachineLoopInfoPass(PassRegistry&);
219220
void initializeMachineModuleInfoPass(PassRegistry&);

‎llvm/include/llvm/Target/GenericOpcodes.td

+21
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,27 @@ def G_OR : Instruction {
5757
let isCommutable = 1;
5858
}
5959

60+
//------------------------------------------------------------------------------
61+
// Variadic ops
62+
//------------------------------------------------------------------------------
63+
64+
// Extract multiple registers specified size, starting from blocks given by
65+
// indexes. This will almost certainly be mapped to sub-register COPYs after
66+
// register banks have been selected.
67+
def G_EXTRACT : Instruction {
68+
let OutOperandList = (outs variable_ops);
69+
let InOperandList = (ins variable_ops);
70+
let hasSideEffects = 0;
71+
}
72+
73+
// Combine a sequence of generic vregs into a single larger value (starting at
74+
// bit 0).
75+
def G_SEQUENCE : Instruction {
76+
let OutOperandList = (outs unknown:$dst);
77+
let InOperandList = (ins variable_ops);
78+
let hasSideEffects = 0;
79+
}
80+
6081
//------------------------------------------------------------------------------
6182
// Branches.
6283
//------------------------------------------------------------------------------

‎llvm/include/llvm/Target/TargetOpcodes.def

+8
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ HANDLE_TARGET_OPCODE(G_OR)
172172
/// stack-based object.
173173
HANDLE_TARGET_OPCODE(G_FRAME_INDEX)
174174

175+
/// Generic instruction to extract blocks of bits from the register given
176+
/// (typically a sub-register COPY after instruction selection).
177+
HANDLE_TARGET_OPCODE(G_EXTRACT)
178+
179+
/// Generic instruction to paste a variable number of components together into a
180+
/// larger register.
181+
HANDLE_TARGET_OPCODE(G_SEQUENCE)
182+
175183
/// Generic BRANCH instruction. This is an unconditional branch.
176184
HANDLE_TARGET_OPCODE(G_BR)
177185

‎llvm/include/llvm/Target/TargetSubtargetInfo.h

+5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class CallLowering;
2727
class DataLayout;
2828
class MachineFunction;
2929
class MachineInstr;
30+
class MachineLegalizer;
3031
class RegisterBankInfo;
3132
class SDep;
3233
class SUnit;
@@ -94,6 +95,10 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
9495
return nullptr;
9596
}
9697

98+
virtual const MachineLegalizer *getMachineLegalizer() const {
99+
return nullptr;
100+
}
101+
97102
/// getRegisterInfo - If register information is available, return it. If
98103
/// not, return null.
99104
///

‎llvm/lib/CodeGen/GlobalISel/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
set(GLOBAL_ISEL_FILES
33
IRTranslator.cpp
44
MachineIRBuilder.cpp
5+
MachineLegalizeHelper.cpp
6+
MachineLegalizePass.cpp
57
MachineLegalizer.cpp
68
RegBankSelect.cpp
79
RegisterBank.cpp

‎llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ void llvm::initializeGlobalISel(PassRegistry &Registry) {
2525

2626
void llvm::initializeGlobalISel(PassRegistry &Registry) {
2727
initializeIRTranslatorPass(Registry);
28+
initializeMachineLegalizePassPass(Registry);
2829
initializeRegBankSelectPass(Registry);
2930
}
3031
#endif // LLVM_BUILD_GLOBAL_ISEL

‎llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,35 @@ MachineInstr *MachineIRBuilder::buildFrameIndex(LLT Ty, unsigned Res, int Idx) {
110110
MIB.addImm(Idx);
111111
return NewMI;
112112
}
113+
114+
MachineInstr *MachineIRBuilder::buildAdd(LLT Ty, unsigned Res, unsigned Op0,
115+
unsigned Op1) {
116+
return buildInstr(TargetOpcode::G_ADD, Ty, Res, Op0, Op1);
117+
}
118+
119+
MachineInstr *MachineIRBuilder::buildExtract(LLT Ty, ArrayRef<unsigned> Results,
120+
unsigned Src,
121+
ArrayRef<unsigned> Indexes) {
122+
assert(Results.size() == Indexes.size() && "inconsistent number of regs");
123+
124+
MachineInstr *NewMI = buildInstr(TargetOpcode::G_EXTRACT, Ty);
125+
auto MIB = MachineInstrBuilder(getMF(), NewMI);
126+
for (auto Res : Results)
127+
MIB.addReg(Res, RegState::Define);
128+
129+
MIB.addReg(Src);
130+
131+
for (auto Idx : Indexes)
132+
MIB.addImm(Idx);
133+
return NewMI;
134+
}
135+
136+
MachineInstr *MachineIRBuilder::buildSequence(LLT Ty, unsigned Res,
137+
ArrayRef<unsigned> Ops) {
138+
MachineInstr *NewMI = buildInstr(TargetOpcode::G_SEQUENCE, Ty);
139+
auto MIB = MachineInstrBuilder(getMF(), NewMI);
140+
MIB.addReg(Res, RegState::Define);
141+
for (auto Op : Ops)
142+
MIB.addReg(Op);
143+
return NewMI;
144+
}

0 commit comments

Comments
 (0)
Please sign in to comment.