Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Common/PredicateExpander.cpp
35290 views
1
//===--------------------- PredicateExpander.cpp --------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
/// \file
9
/// Functionalities used by the Tablegen backends to expand machine predicates.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "PredicateExpander.h"
14
#include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
15
#include "llvm/TableGen/Record.h"
16
17
namespace llvm {
18
19
void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
20
void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
21
22
void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
23
int ImmVal,
24
StringRef FunctionMapper) {
25
if (!FunctionMapper.empty())
26
OS << FunctionMapper << "(";
27
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
28
<< ").getImm()";
29
if (!FunctionMapper.empty())
30
OS << ")";
31
OS << (shouldNegate() ? " != " : " == ") << ImmVal;
32
}
33
34
void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
35
StringRef ImmVal,
36
StringRef FunctionMapper) {
37
if (ImmVal.empty())
38
expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
39
40
if (!FunctionMapper.empty())
41
OS << FunctionMapper << "(";
42
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
43
<< ").getImm()";
44
if (!FunctionMapper.empty())
45
OS << ")";
46
OS << (shouldNegate() ? " != " : " == ") << ImmVal;
47
}
48
49
void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
50
int OpIndex,
51
StringRef FunctionMapper) {
52
if (shouldNegate())
53
OS << "!";
54
if (!FunctionMapper.empty())
55
OS << FunctionMapper << "(";
56
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
57
<< ").getImm()";
58
if (!FunctionMapper.empty())
59
OS << ")";
60
}
61
62
void PredicateExpander::expandCheckImmOperandLT(raw_ostream &OS, int OpIndex,
63
int ImmVal,
64
StringRef FunctionMapper) {
65
if (!FunctionMapper.empty())
66
OS << FunctionMapper << "(";
67
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
68
<< ").getImm()";
69
if (!FunctionMapper.empty())
70
OS << ")";
71
OS << (shouldNegate() ? " >= " : " < ") << ImmVal;
72
}
73
74
void PredicateExpander::expandCheckImmOperandGT(raw_ostream &OS, int OpIndex,
75
int ImmVal,
76
StringRef FunctionMapper) {
77
if (!FunctionMapper.empty())
78
OS << FunctionMapper << "(";
79
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
80
<< ").getImm()";
81
if (!FunctionMapper.empty())
82
OS << ")";
83
OS << (shouldNegate() ? " <= " : " > ") << ImmVal;
84
}
85
86
void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
87
const Record *Reg,
88
StringRef FunctionMapper) {
89
assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
90
91
if (!FunctionMapper.empty())
92
OS << FunctionMapper << "(";
93
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
94
<< ").getReg()";
95
if (!FunctionMapper.empty())
96
OS << ")";
97
OS << (shouldNegate() ? " != " : " == ");
98
const StringRef Str = Reg->getValueAsString("Namespace");
99
if (!Str.empty())
100
OS << Str << "::";
101
OS << Reg->getName();
102
}
103
104
void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
105
int OpIndex,
106
StringRef FunctionMapper) {
107
if (shouldNegate())
108
OS << "!";
109
if (!FunctionMapper.empty())
110
OS << FunctionMapper << "(";
111
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
112
<< ").getReg()";
113
if (!FunctionMapper.empty())
114
OS << ")";
115
}
116
117
void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
118
int OpIndex) {
119
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
120
<< ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
121
}
122
123
void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
124
int Second) {
125
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
126
<< ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
127
<< (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
128
}
129
130
void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
131
OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
132
<< (shouldNegate() ? "!= " : "== ") << NumOps;
133
}
134
135
void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
136
OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
137
<< (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
138
<< "::" << Inst->getName();
139
}
140
141
void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
142
const RecVec &Opcodes) {
143
assert(!Opcodes.empty() && "Expected at least one opcode to check!");
144
bool First = true;
145
146
if (Opcodes.size() == 1) {
147
OS << "( ";
148
expandCheckOpcode(OS, Opcodes[0]);
149
OS << " )";
150
return;
151
}
152
153
OS << '(';
154
increaseIndentLevel();
155
for (const Record *Rec : Opcodes) {
156
OS << '\n';
157
OS.indent(getIndentLevel() * 2);
158
if (!First)
159
OS << (shouldNegate() ? "&& " : "|| ");
160
161
expandCheckOpcode(OS, Rec);
162
First = false;
163
}
164
165
OS << '\n';
166
decreaseIndentLevel();
167
OS.indent(getIndentLevel() * 2);
168
OS << ')';
169
}
170
171
void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
172
const RecVec &Opcodes) {
173
if (shouldExpandForMC())
174
expandFalse(OS);
175
else
176
expandCheckOpcode(OS, Opcodes);
177
}
178
179
void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
180
const RecVec &Sequence,
181
bool IsCheckAll) {
182
assert(!Sequence.empty() && "Found an invalid empty predicate set!");
183
if (Sequence.size() == 1)
184
return expandPredicate(OS, Sequence[0]);
185
186
// Okay, there is more than one predicate in the set.
187
bool First = true;
188
OS << (shouldNegate() ? "!(" : "(");
189
increaseIndentLevel();
190
191
bool OldValue = shouldNegate();
192
setNegatePredicate(false);
193
for (const Record *Rec : Sequence) {
194
OS << '\n';
195
OS.indent(getIndentLevel() * 2);
196
if (!First)
197
OS << (IsCheckAll ? "&& " : "|| ");
198
expandPredicate(OS, Rec);
199
First = false;
200
}
201
OS << '\n';
202
decreaseIndentLevel();
203
OS.indent(getIndentLevel() * 2);
204
OS << ')';
205
setNegatePredicate(OldValue);
206
}
207
208
void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
209
StringRef MethodName) {
210
OS << (shouldNegate() ? "!" : "");
211
OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
212
OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
213
}
214
215
void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
216
OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
217
<< "getOperand(" << OpIndex << ").isReg() ";
218
}
219
220
void PredicateExpander::expandCheckIsVRegOperand(raw_ostream &OS, int OpIndex) {
221
OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
222
<< "getOperand(" << OpIndex << ").getReg().isVirtual()";
223
}
224
225
void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
226
OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
227
<< "getOperand(" << OpIndex << ").isImm() ";
228
}
229
230
void PredicateExpander::expandCheckFunctionPredicateWithTII(
231
raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
232
StringRef TIIPtr) {
233
if (!shouldExpandForMC()) {
234
OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
235
OS << (isByRef() ? "(MI)" : "(*MI)");
236
return;
237
}
238
239
OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
240
}
241
242
void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
243
StringRef MCInstFn,
244
StringRef MachineInstrFn) {
245
OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
246
<< (isByRef() ? "(MI)" : "(*MI)");
247
}
248
249
void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
250
StringRef Code) {
251
if (shouldExpandForMC())
252
return expandFalse(OS);
253
254
OS << '(' << Code << ')';
255
}
256
257
void PredicateExpander::expandReturnStatement(raw_ostream &OS,
258
const Record *Rec) {
259
std::string Buffer;
260
raw_string_ostream SS(Buffer);
261
262
SS << "return ";
263
expandPredicate(SS, Rec);
264
SS << ";";
265
OS << Buffer;
266
}
267
268
void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
269
const Record *Rec) {
270
const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
271
for (const Record *Opcode : Opcodes) {
272
OS.indent(getIndentLevel() * 2);
273
OS << "case " << Opcode->getValueAsString("Namespace")
274
<< "::" << Opcode->getName() << ":\n";
275
}
276
277
increaseIndentLevel();
278
OS.indent(getIndentLevel() * 2);
279
expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
280
decreaseIndentLevel();
281
}
282
283
void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
284
const RecVec &Cases,
285
const Record *Default) {
286
std::string Buffer;
287
raw_string_ostream SS(Buffer);
288
289
SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
290
for (const Record *Rec : Cases) {
291
expandOpcodeSwitchCase(SS, Rec);
292
SS << '\n';
293
}
294
295
// Expand the default case.
296
SS.indent(getIndentLevel() * 2);
297
SS << "default:\n";
298
299
increaseIndentLevel();
300
SS.indent(getIndentLevel() * 2);
301
expandStatement(SS, Default);
302
decreaseIndentLevel();
303
SS << '\n';
304
305
SS.indent(getIndentLevel() * 2);
306
SS << "} // end of switch-stmt";
307
OS << Buffer;
308
}
309
310
void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
311
// Assume that padding has been added by the caller.
312
if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
313
expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
314
Rec->getValueAsDef("DefaultCase"));
315
return;
316
}
317
318
if (Rec->isSubClassOf("MCReturnStatement")) {
319
expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
320
return;
321
}
322
323
llvm_unreachable("No known rules to expand this MCStatement");
324
}
325
326
void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
327
// Assume that padding has been added by the caller.
328
if (Rec->isSubClassOf("MCTrue")) {
329
if (shouldNegate())
330
return expandFalse(OS);
331
return expandTrue(OS);
332
}
333
334
if (Rec->isSubClassOf("MCFalse")) {
335
if (shouldNegate())
336
return expandTrue(OS);
337
return expandFalse(OS);
338
}
339
340
if (Rec->isSubClassOf("CheckNot")) {
341
flipNegatePredicate();
342
expandPredicate(OS, Rec->getValueAsDef("Pred"));
343
flipNegatePredicate();
344
return;
345
}
346
347
if (Rec->isSubClassOf("CheckIsRegOperand"))
348
return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
349
350
if (Rec->isSubClassOf("CheckIsVRegOperand"))
351
return expandCheckIsVRegOperand(OS, Rec->getValueAsInt("OpIndex"));
352
353
if (Rec->isSubClassOf("CheckIsImmOperand"))
354
return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
355
356
if (Rec->isSubClassOf("CheckRegOperand"))
357
return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
358
Rec->getValueAsDef("Reg"),
359
Rec->getValueAsString("FunctionMapper"));
360
361
if (Rec->isSubClassOf("CheckRegOperandSimple"))
362
return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
363
Rec->getValueAsString("FunctionMapper"));
364
365
if (Rec->isSubClassOf("CheckInvalidRegOperand"))
366
return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
367
368
if (Rec->isSubClassOf("CheckImmOperand"))
369
return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
370
Rec->getValueAsInt("ImmVal"),
371
Rec->getValueAsString("FunctionMapper"));
372
373
if (Rec->isSubClassOf("CheckImmOperand_s"))
374
return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
375
Rec->getValueAsString("ImmVal"),
376
Rec->getValueAsString("FunctionMapper"));
377
378
if (Rec->isSubClassOf("CheckImmOperandLT"))
379
return expandCheckImmOperandLT(OS, Rec->getValueAsInt("OpIndex"),
380
Rec->getValueAsInt("ImmVal"),
381
Rec->getValueAsString("FunctionMapper"));
382
383
if (Rec->isSubClassOf("CheckImmOperandGT"))
384
return expandCheckImmOperandGT(OS, Rec->getValueAsInt("OpIndex"),
385
Rec->getValueAsInt("ImmVal"),
386
Rec->getValueAsString("FunctionMapper"));
387
388
if (Rec->isSubClassOf("CheckImmOperandSimple"))
389
return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
390
Rec->getValueAsString("FunctionMapper"));
391
392
if (Rec->isSubClassOf("CheckSameRegOperand"))
393
return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
394
Rec->getValueAsInt("SecondIndex"));
395
396
if (Rec->isSubClassOf("CheckNumOperands"))
397
return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
398
399
if (Rec->isSubClassOf("CheckPseudo"))
400
return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
401
402
if (Rec->isSubClassOf("CheckOpcode"))
403
return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
404
405
if (Rec->isSubClassOf("CheckAll"))
406
return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
407
/* AllOf */ true);
408
409
if (Rec->isSubClassOf("CheckAny"))
410
return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
411
/* AllOf */ false);
412
413
if (Rec->isSubClassOf("CheckFunctionPredicate")) {
414
return expandCheckFunctionPredicate(
415
OS, Rec->getValueAsString("MCInstFnName"),
416
Rec->getValueAsString("MachineInstrFnName"));
417
}
418
419
if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {
420
return expandCheckFunctionPredicateWithTII(
421
OS, Rec->getValueAsString("MCInstFnName"),
422
Rec->getValueAsString("MachineInstrFnName"),
423
Rec->getValueAsString("TIIPtrName"));
424
}
425
426
if (Rec->isSubClassOf("CheckNonPortable"))
427
return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
428
429
if (Rec->isSubClassOf("TIIPredicate"))
430
return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
431
432
llvm_unreachable("No known rules to expand this MCInstPredicate");
433
}
434
435
void STIPredicateExpander::expandHeader(raw_ostream &OS,
436
const STIPredicateFunction &Fn) {
437
const Record *Rec = Fn.getDeclaration();
438
StringRef FunctionName = Rec->getValueAsString("Name");
439
440
OS.indent(getIndentLevel() * 2);
441
OS << "bool ";
442
if (shouldExpandDefinition())
443
OS << getClassPrefix() << "::";
444
OS << FunctionName << "(";
445
if (shouldExpandForMC())
446
OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
447
else
448
OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
449
if (Rec->getValueAsBit("UpdatesOpcodeMask"))
450
OS << ", APInt &Mask";
451
OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
452
if (shouldExpandDefinition()) {
453
OS << "{\n";
454
return;
455
}
456
457
if (Rec->getValueAsBit("OverridesBaseClassMember"))
458
OS << "override";
459
OS << ";\n";
460
}
461
462
void STIPredicateExpander::expandPrologue(raw_ostream &OS,
463
const STIPredicateFunction &Fn) {
464
RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
465
bool UpdatesOpcodeMask =
466
Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
467
468
increaseIndentLevel();
469
unsigned IndentLevel = getIndentLevel();
470
for (const Record *Delegate : Delegates) {
471
OS.indent(IndentLevel * 2);
472
OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
473
if (UpdatesOpcodeMask)
474
OS << ", Mask";
475
if (shouldExpandForMC())
476
OS << ", ProcessorID";
477
OS << "))\n";
478
OS.indent((1 + IndentLevel) * 2);
479
OS << "return true;\n\n";
480
}
481
482
if (shouldExpandForMC())
483
return;
484
485
OS.indent(IndentLevel * 2);
486
OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
487
}
488
489
void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS,
490
const OpcodeGroup &Group,
491
bool ShouldUpdateOpcodeMask) {
492
const OpcodeInfo &OI = Group.getOpcodeInfo();
493
for (const PredicateInfo &PI : OI.getPredicates()) {
494
const APInt &ProcModelMask = PI.ProcModelMask;
495
bool FirstProcID = true;
496
for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
497
if (!ProcModelMask[I])
498
continue;
499
500
if (FirstProcID) {
501
OS.indent(getIndentLevel() * 2);
502
OS << "if (ProcessorID == " << I;
503
} else {
504
OS << " || ProcessorID == " << I;
505
}
506
FirstProcID = false;
507
}
508
509
OS << ") {\n";
510
511
increaseIndentLevel();
512
OS.indent(getIndentLevel() * 2);
513
if (ShouldUpdateOpcodeMask) {
514
if (PI.OperandMask.isZero())
515
OS << "Mask.clearAllBits();\n";
516
else
517
OS << "Mask = " << PI.OperandMask << ";\n";
518
OS.indent(getIndentLevel() * 2);
519
}
520
OS << "return ";
521
expandPredicate(OS, PI.Predicate);
522
OS << ";\n";
523
decreaseIndentLevel();
524
OS.indent(getIndentLevel() * 2);
525
OS << "}\n";
526
}
527
}
528
529
void STIPredicateExpander::expandBody(raw_ostream &OS,
530
const STIPredicateFunction &Fn) {
531
bool UpdatesOpcodeMask =
532
Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
533
534
unsigned IndentLevel = getIndentLevel();
535
OS.indent(IndentLevel * 2);
536
OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
537
OS.indent(IndentLevel * 2);
538
OS << "default:\n";
539
OS.indent(IndentLevel * 2);
540
OS << " break;";
541
542
for (const OpcodeGroup &Group : Fn.getGroups()) {
543
for (const Record *Opcode : Group.getOpcodes()) {
544
OS << '\n';
545
OS.indent(IndentLevel * 2);
546
OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
547
}
548
549
OS << '\n';
550
increaseIndentLevel();
551
expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
552
553
OS.indent(getIndentLevel() * 2);
554
OS << "break;\n";
555
decreaseIndentLevel();
556
}
557
558
OS.indent(IndentLevel * 2);
559
OS << "}\n";
560
}
561
562
void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
563
const STIPredicateFunction &Fn) {
564
OS << '\n';
565
OS.indent(getIndentLevel() * 2);
566
OS << "return ";
567
expandPredicate(OS, Fn.getDefaultReturnPredicate());
568
OS << ";\n";
569
570
decreaseIndentLevel();
571
OS.indent(getIndentLevel() * 2);
572
StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
573
OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
574
}
575
576
void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
577
const STIPredicateFunction &Fn) {
578
const Record *Rec = Fn.getDeclaration();
579
if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
580
return;
581
582
expandHeader(OS, Fn);
583
if (shouldExpandDefinition()) {
584
expandPrologue(OS, Fn);
585
expandBody(OS, Fn);
586
expandEpilogue(OS, Fn);
587
}
588
}
589
590
} // namespace llvm
591
592