Skip to content

Commit 41c072e

Browse files
committedMar 12, 2015
Add infrastructure for support of multiple memory constraints.
Summary: The operand flag word for ISD::INLINEASM nodes now contains a 15-bit memory constraint ID when the operand kind is Kind_Mem. This constraint ID is a numeric equivalent to the constraint code string and is converted with a target specific hook in TargetLowering. This patch maps all memory constraints to InlineAsm::Constraint_m so there is no functional change at this point. It just proves that using these previously unused bits in the encoding of the flag word doesn't break anything. The next patch will make each target preserve the current mapping of everything to Constraint_m for itself while changing the target independent implementation of the hook to return Constraint_Unknown appropriately. Each target will then be adapted in separate patches to use appropriate Constraint_* values. Reviewers: hfinkel Reviewed By: hfinkel Subscribers: hfinkel, jholewinski, llvm-commits Differential Revision: http://reviews.llvm.org/D8171 llvm-svn: 232027
1 parent 656e184 commit 41c072e

18 files changed

+107
-44
lines changed
 

‎llvm/include/llvm/CodeGen/SelectionDAGISel.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ class SelectionDAGISel : public MachineFunctionPass {
8080
virtual SDNode *Select(SDNode *N) = 0;
8181

8282
/// SelectInlineAsmMemoryOperand - Select the specified address as a target
83-
/// addressing mode, according to the specified constraint code. If this does
83+
/// addressing mode, according to the specified constraint. If this does
8484
/// not match or is not implemented, return true. The resultant operands
8585
/// (which will appear in the machine instruction) should be added to the
8686
/// OutOps vector.
8787
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
88-
char ConstraintCode,
88+
unsigned ConstraintID,
8989
std::vector<SDValue> &OutOps) {
9090
return true;
9191
}

‎llvm/include/llvm/IR/InlineAsm.h

+38
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,19 @@ class InlineAsm : public Value {
189189

190190
// These are helper methods for dealing with flags in the INLINEASM SDNode
191191
// in the backend.
192+
//
193+
// The encoding of the flag word is currently:
194+
// Bits 2-0 - A Kind_* value indicating the kind of the operand.
195+
// Bits 15-3 - The number of SDNode operands associated with this inline
196+
// assembly operand.
197+
// If bits 2-0 are Kind_Mem:
198+
// Bit 31 - 0
199+
// Bit 30-16 - A Constraint_* value indicating the original constraint
200+
// code.
201+
// Else if bit 31 is set:
202+
// Bit 30-16 - The operand number that this operand must match.
203+
// Else if bit 31 is clear:
204+
// Bit 30-16 - The register class ID to use for the operand.
192205

193206
enum : uint32_t {
194207
// Fixed operands on an INLINEASM SDNode.
@@ -220,6 +233,17 @@ class InlineAsm : public Value {
220233
Kind_Imm = 5, // Immediate.
221234
Kind_Mem = 6, // Memory operand, "m".
222235

236+
// Memory constraint codes.
237+
// These could be tablegenerated but there's little need to do that since
238+
// there's plenty of space in the encoding to support the union of all
239+
// constraint codes for all targets.
240+
Constraint_Unknown = 0,
241+
Constraint_m,
242+
Constraint_o, // Unused at the moment since Constraint_m is always used.
243+
Constraint_v, // Unused at the moment since Constraint_m is always used.
244+
Constraints_Max = Constraint_v,
245+
Constraints_ShiftAmount = 16,
246+
223247
Flag_MatchingOperand = 0x80000000
224248
};
225249

@@ -252,6 +276,15 @@ class InlineAsm : public Value {
252276
return InputFlag | (RC << 16);
253277
}
254278

279+
/// Augment an existing flag word returned by getFlagWord with the constraint
280+
/// code for a memory constraint.
281+
static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) {
282+
assert(Constraint <= 0x7fff && "Too large a memory constraint ID");
283+
assert(Constraint <= Constraints_Max && "Unknown constraint ID");
284+
assert((InputFlag & ~0xffff) == 0 && "High bits already contain data");
285+
return InputFlag | (Constraint << Constraints_ShiftAmount);
286+
}
287+
255288
static unsigned getKind(unsigned Flags) {
256289
return Flags & 7;
257290
}
@@ -266,6 +299,11 @@ class InlineAsm : public Value {
266299
return getKind(Flag) == Kind_Clobber;
267300
}
268301

302+
static unsigned getMemoryConstraintID(unsigned Flag) {
303+
assert(isMemKind(Flag));
304+
return (Flag >> Constraints_ShiftAmount) & 0x7fff;
305+
}
306+
269307
/// getNumOperandRegisters - Extract the number of registers field from the
270308
/// inline asm operand flag.
271309
static unsigned getNumOperandRegisters(unsigned Flag) {

‎llvm/include/llvm/Target/TargetLowering.h

+7
Original file line numberDiff line numberDiff line change
@@ -2625,6 +2625,13 @@ class TargetLowering : public TargetLoweringBase {
26252625
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
26262626
const std::string &Constraint, MVT VT) const;
26272627

2628+
virtual unsigned
2629+
getInlineAsmMemConstraint(const std::string &ConstraintCode) const {
2630+
// FIXME: This currently maps all constraints to the the same code.
2631+
// This will be corrected once all targets are updated.
2632+
return InlineAsm::Constraint_m;
2633+
}
2634+
26282635
/// Try to replace an X constraint, which matches anything, with another that
26292636
/// has more specific requirements based on the type of the corresponding
26302637
/// operand. This returns null if there is no replacement to make.

‎llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -6598,8 +6598,14 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
65986598
// Memory output, or 'other' output (e.g. 'X' constraint).
65996599
assert(OpInfo.isIndirect && "Memory output must be indirect operand");
66006600

6601+
unsigned ConstraintID =
6602+
TLI.getInlineAsmMemConstraint(OpInfo.ConstraintCode);
6603+
assert(ConstraintID != InlineAsm::Constraint_Unknown &&
6604+
"Failed to convert memory constraint code to constraint id.");
6605+
66016606
// Add information to the INLINEASM node to know about this output.
66026607
unsigned OpFlags = InlineAsm::getFlagWord(InlineAsm::Kind_Mem, 1);
6608+
OpFlags = InlineAsm::getFlagWordForMem(OpFlags, ConstraintID);
66036609
AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlags, MVT::i32));
66046610
AsmNodeOperands.push_back(OpInfo.CallOperand);
66056611
break;
@@ -6743,8 +6749,14 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
67436749
assert(InOperandVal.getValueType() == TLI.getPointerTy() &&
67446750
"Memory operands expect pointer values");
67456751

6752+
unsigned ConstraintID =
6753+
TLI.getInlineAsmMemConstraint(OpInfo.ConstraintCode);
6754+
assert(ConstraintID != InlineAsm::Constraint_Unknown &&
6755+
"Failed to convert memory constraint code to constraint id.");
6756+
67466757
// Add information to the INLINEASM node to know about this input.
67476758
unsigned ResOpType = InlineAsm::getFlagWord(InlineAsm::Kind_Mem, 1);
6759+
ResOpType = InlineAsm::getFlagWordForMem(ResOpType, ConstraintID);
67486760
AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, MVT::i32));
67496761
AsmNodeOperands.push_back(InOperandVal);
67506762
break;

‎llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1781,7 +1781,9 @@ SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) {
17811781
"Memory operand with multiple values?");
17821782
// Otherwise, this is a memory operand. Ask the target to select it.
17831783
std::vector<SDValue> SelOps;
1784-
if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps))
1784+
if (SelectInlineAsmMemoryOperand(InOps[i+1],
1785+
InlineAsm::getMemoryConstraintID(Flags),
1786+
SelOps))
17851787
report_fatal_error("Could not match memory address. Inline asm"
17861788
" failure!");
17871789

‎llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class AArch64DAGToDAGISel : public SelectionDAGISel {
6565
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
6666
/// inline asm expressions.
6767
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
68-
char ConstraintCode,
68+
unsigned ConstraintID,
6969
std::vector<SDValue> &OutOps) override;
7070

7171
SDNode *SelectMLAV64LaneV128(SDNode *N);
@@ -211,8 +211,9 @@ static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc,
211211
}
212212

213213
bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
214-
const SDValue &Op, char ConstraintCode, std::vector<SDValue> &OutOps) {
215-
assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
214+
const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
215+
assert(ConstraintID == InlineAsm::Constraint_m &&
216+
"unexpected asm memory constraint");
216217
// Require the address to be in a register. That is safe for all AArch64
217218
// variants and it is hard to do anything much smarter without knowing
218219
// how the operand is used.

‎llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ class ARMDAGToDAGISel : public SelectionDAGISel {
257257

258258
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
259259
/// inline asm expressions.
260-
bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
260+
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
261261
std::vector<SDValue> &OutOps) override;
262262

263263
// Form pairs of consecutive R, S, D, or Q registers.
@@ -3472,9 +3472,10 @@ SDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){
34723472

34733473

34743474
bool ARMDAGToDAGISel::
3475-
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
3475+
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
34763476
std::vector<SDValue> &OutOps) {
3477-
assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
3477+
assert(ConstraintID == InlineAsm::Constraint_m &&
3478+
"unexpected asm memory constraint");
34783479
// Require the address to be in a register. That is safe for all ARM
34793480
// variants and it is hard to do anything much smarter without knowing
34803481
// how the operand is used.

‎llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class HexagonDAGToDAGISel : public SelectionDAGISel {
9393
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
9494
/// inline asm expressions.
9595
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
96-
char ConstraintCode,
96+
unsigned ConstraintID,
9797
std::vector<SDValue> &OutOps) override;
9898
bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset);
9999

@@ -1405,15 +1405,15 @@ bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr,
14051405

14061406

14071407
bool HexagonDAGToDAGISel::
1408-
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
1408+
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
14091409
std::vector<SDValue> &OutOps) {
14101410
SDValue Op0, Op1;
14111411

1412-
switch (ConstraintCode) {
1413-
case 'o': // Offsetable.
1414-
case 'v': // Not offsetable.
1412+
switch (ConstraintID) {
1413+
case InlineAsm::Constraint_o: // Offsetable.
1414+
case InlineAsm::Constraint_v: // Not offsetable.
14151415
default: return true;
1416-
case 'm': // Memory.
1416+
case InlineAsm::Constraint_m: // Memory.
14171417
if (!SelectAddr(Op.getNode(), Op, Op0, Op1))
14181418
return true;
14191419
break;

‎llvm/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ namespace {
104104
bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
105105
bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
106106

107-
bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
107+
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
108108
std::vector<SDValue> &OutOps) override;
109109

110110
// Include the pieces autogenerated from the target description.
@@ -280,12 +280,12 @@ bool MSP430DAGToDAGISel::SelectAddr(SDValue N,
280280
}
281281

282282
bool MSP430DAGToDAGISel::
283-
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
283+
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
284284
std::vector<SDValue> &OutOps) {
285285
SDValue Op0, Op1;
286-
switch (ConstraintCode) {
286+
switch (ConstraintID) {
287287
default: return true;
288-
case 'm': // memory
288+
case InlineAsm::Constraint_m: // memory
289289
if (!SelectAddr(Op, Op0, Op1))
290290
return true;
291291
break;

‎llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,10 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
230230
}
231231

232232
bool MipsDAGToDAGISel::
233-
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
233+
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
234234
std::vector<SDValue> &OutOps) {
235-
assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
235+
assert(ConstraintID == InlineAsm::Constraint_m &&
236+
"unexpected asm memory constraint");
236237
OutOps.push_back(Op);
237238
return false;
238239
}

‎llvm/lib/Target/Mips/MipsISelDAGToDAG.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ class MipsDAGToDAGISel : public SelectionDAGISel {
125125
virtual void processFunctionAfterISel(MachineFunction &MF) = 0;
126126

127127
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
128-
char ConstraintCode,
128+
unsigned ConstraintID,
129129
std::vector<SDValue> &OutOps) override;
130130
};
131131
}

‎llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -5044,12 +5044,12 @@ bool NVPTXDAGToDAGISel::ChkMemSDNodeAddressSpace(SDNode *N,
50445044
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
50455045
/// inline asm expressions.
50465046
bool NVPTXDAGToDAGISel::SelectInlineAsmMemoryOperand(
5047-
const SDValue &Op, char ConstraintCode, std::vector<SDValue> &OutOps) {
5047+
const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
50485048
SDValue Op0, Op1;
5049-
switch (ConstraintCode) {
5049+
switch (ConstraintID) {
50505050
default:
50515051
return true;
5052-
case 'm': // memory
5052+
case InlineAsm::Constraint_m: // memory
50535053
if (SelectDirectAddr(Op, Op0)) {
50545054
OutOps.push_back(Op0);
50555055
OutOps.push_back(CurDAG->getTargetConstant(0, MVT::i32));

‎llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class LLVM_LIBRARY_VISIBILITY NVPTXDAGToDAGISel : public SelectionDAGISel {
4848
const NVPTXSubtarget *Subtarget;
4949

5050
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
51-
char ConstraintCode,
51+
unsigned ConstraintID,
5252
std::vector<SDValue> &OutOps) override;
5353
private:
5454
// Include the pieces autogenerated from the target description.

‎llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ namespace {
186186
/// register can be improved, but it is wrong to substitute Reg+Reg for
187187
/// Reg in an asm, because the load or store opcode would have to change.
188188
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
189-
char ConstraintCode,
189+
unsigned ConstraintID,
190190
std::vector<SDValue> &OutOps) override {
191191
// We need to make sure that this one operand does not end up in r0
192192
// (because we might end up lowering this as 0(%op)).

‎llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class SparcDAGToDAGISel : public SelectionDAGISel {
5050
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
5151
/// inline asm expressions.
5252
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
53-
char ConstraintCode,
53+
unsigned ConstraintID,
5454
std::vector<SDValue> &OutOps) override;
5555

5656
const char *getPassName() const override {
@@ -195,12 +195,12 @@ SDNode *SparcDAGToDAGISel::Select(SDNode *N) {
195195
/// inline asm expressions.
196196
bool
197197
SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
198-
char ConstraintCode,
198+
unsigned ConstraintID,
199199
std::vector<SDValue> &OutOps) {
200200
SDValue Op0, Op1;
201-
switch (ConstraintCode) {
201+
switch (ConstraintID) {
202202
default: return true;
203-
case 'm': // memory
203+
case InlineAsm::Constraint_m: // memory
204204
if (!SelectADDRrr(Op, Op0, Op1))
205205
SelectADDRri(Op, Op0, Op1);
206206
break;

‎llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ class SystemZDAGToDAGISel : public SelectionDAGISel {
328328

329329
// Override SelectionDAGISel.
330330
SDNode *Select(SDNode *Node) override;
331-
bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
331+
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
332332
std::vector<SDValue> &OutOps) override;
333333

334334
// Include the pieces autogenerated from the target description.
@@ -1129,9 +1129,10 @@ SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) {
11291129

11301130
bool SystemZDAGToDAGISel::
11311131
SelectInlineAsmMemoryOperand(const SDValue &Op,
1132-
char ConstraintCode,
1132+
unsigned ConstraintID,
11331133
std::vector<SDValue> &OutOps) {
1134-
assert(ConstraintCode == 'm' && "Unexpected constraint code");
1134+
assert(ConstraintID == InlineAsm::Constraint_m &&
1135+
"Unexpected constraint code");
11351136
// Accept addresses with short displacements, which are compatible
11361137
// with Q, R, S and T. But keep the index operand for future expansion.
11371138
SDValue Base, Disp, Index;

‎llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ namespace {
228228
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
229229
/// inline asm expressions.
230230
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
231-
char ConstraintCode,
231+
unsigned ConstraintID,
232232
std::vector<SDValue> &OutOps) override;
233233

234234
void EmitSpecialCodeForMain();
@@ -2814,14 +2814,14 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) {
28142814
}
28152815

28162816
bool X86DAGToDAGISel::
2817-
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
2817+
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
28182818
std::vector<SDValue> &OutOps) {
28192819
SDValue Op0, Op1, Op2, Op3, Op4;
2820-
switch (ConstraintCode) {
2821-
case 'o': // offsetable ??
2822-
case 'v': // not offsetable ??
2820+
switch (ConstraintID) {
2821+
case InlineAsm::Constraint_o: // offsetable ??
2822+
case InlineAsm::Constraint_v: // not offsetable ??
28232823
default: return true;
2824-
case 'm': // memory
2824+
case InlineAsm::Constraint_m: // memory
28252825
if (!SelectAddr(nullptr, Op, Op0, Op1, Op2, Op3, Op4))
28262826
return true;
28272827
break;

‎llvm/lib/Target/XCore/XCoreISelDAGToDAG.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ namespace {
6565
// Complex Pattern Selectors.
6666
bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
6767

68-
bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
68+
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
6969
std::vector<SDValue> &OutOps) override;
7070

7171
const char *getPassName() const override {
@@ -108,12 +108,12 @@ bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base,
108108
}
109109

110110
bool XCoreDAGToDAGISel::
111-
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
111+
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
112112
std::vector<SDValue> &OutOps) {
113113
SDValue Reg;
114-
switch (ConstraintCode) {
114+
switch (ConstraintID) {
115115
default: return true;
116-
case 'm': // Memory.
116+
case InlineAsm::Constraint_m: // Memory.
117117
switch (Op.getOpcode()) {
118118
default: return true;
119119
case XCoreISD::CPRelativeWrapper:

0 commit comments

Comments
 (0)
Please sign in to comment.