@@ -46,7 +46,8 @@ class LegalizationArtifactCombiner {
46
46
: Builder(B), MRI(MRI), LI(LI) {}
47
47
48
48
bool tryCombineAnyExt (MachineInstr &MI,
49
- SmallVectorImpl<MachineInstr *> &DeadInsts) {
49
+ SmallVectorImpl<MachineInstr *> &DeadInsts,
50
+ SmallVectorImpl<Register> &UpdatedDefs) {
50
51
assert (MI.getOpcode () == TargetOpcode::G_ANYEXT);
51
52
52
53
Builder.setInstr (MI);
@@ -58,6 +59,7 @@ class LegalizationArtifactCombiner {
58
59
if (mi_match (SrcReg, MRI, m_GTrunc (m_Reg (TruncSrc)))) {
59
60
LLVM_DEBUG (dbgs () << " .. Combine MI: " << MI;);
60
61
Builder.buildAnyExtOrTrunc (DstReg, TruncSrc);
62
+ UpdatedDefs.push_back (DstReg);
61
63
markInstAndDefDead (MI, *MRI.getVRegDef (SrcReg), DeadInsts);
62
64
return true ;
63
65
}
@@ -70,6 +72,7 @@ class LegalizationArtifactCombiner {
70
72
m_GSExt (m_Reg (ExtSrc)),
71
73
m_GZExt (m_Reg (ExtSrc)))))) {
72
74
Builder.buildInstr (ExtMI->getOpcode (), {DstReg}, {ExtSrc});
75
+ UpdatedDefs.push_back (DstReg);
73
76
markInstAndDefDead (MI, *ExtMI, DeadInsts);
74
77
return true ;
75
78
}
@@ -83,15 +86,17 @@ class LegalizationArtifactCombiner {
83
86
auto &CstVal = SrcMI->getOperand (1 );
84
87
Builder.buildConstant (
85
88
DstReg, CstVal.getCImm ()->getValue ().sext (DstTy.getSizeInBits ()));
89
+ UpdatedDefs.push_back (DstReg);
86
90
markInstAndDefDead (MI, *SrcMI, DeadInsts);
87
91
return true ;
88
92
}
89
93
}
90
- return tryFoldImplicitDef (MI, DeadInsts);
94
+ return tryFoldImplicitDef (MI, DeadInsts, UpdatedDefs );
91
95
}
92
96
93
97
bool tryCombineZExt (MachineInstr &MI,
94
- SmallVectorImpl<MachineInstr *> &DeadInsts) {
98
+ SmallVectorImpl<MachineInstr *> &DeadInsts,
99
+ SmallVectorImpl<Register> &UpdatedDefs) {
95
100
assert (MI.getOpcode () == TargetOpcode::G_ZEXT);
96
101
97
102
Builder.setInstr (MI);
@@ -124,15 +129,17 @@ class LegalizationArtifactCombiner {
124
129
auto &CstVal = SrcMI->getOperand (1 );
125
130
Builder.buildConstant (
126
131
DstReg, CstVal.getCImm ()->getValue ().zext (DstTy.getSizeInBits ()));
132
+ UpdatedDefs.push_back (DstReg);
127
133
markInstAndDefDead (MI, *SrcMI, DeadInsts);
128
134
return true ;
129
135
}
130
136
}
131
- return tryFoldImplicitDef (MI, DeadInsts);
137
+ return tryFoldImplicitDef (MI, DeadInsts, UpdatedDefs );
132
138
}
133
139
134
140
bool tryCombineSExt (MachineInstr &MI,
135
- SmallVectorImpl<MachineInstr *> &DeadInsts) {
141
+ SmallVectorImpl<MachineInstr *> &DeadInsts,
142
+ SmallVectorImpl<Register> &UpdatedDefs) {
136
143
assert (MI.getOpcode () == TargetOpcode::G_SEXT);
137
144
138
145
Builder.setInstr (MI);
@@ -154,11 +161,12 @@ class LegalizationArtifactCombiner {
154
161
markInstAndDefDead (MI, *MRI.getVRegDef (SrcReg), DeadInsts);
155
162
return true ;
156
163
}
157
- return tryFoldImplicitDef (MI, DeadInsts);
164
+ return tryFoldImplicitDef (MI, DeadInsts, UpdatedDefs );
158
165
}
159
166
160
167
bool tryCombineTrunc (MachineInstr &MI,
161
- SmallVectorImpl<MachineInstr *> &DeadInsts) {
168
+ SmallVectorImpl<MachineInstr *> &DeadInsts,
169
+ SmallVectorImpl<Register> &UpdatedDefs) {
162
170
assert (MI.getOpcode () == TargetOpcode::G_TRUNC);
163
171
164
172
Builder.setInstr (MI);
@@ -174,6 +182,7 @@ class LegalizationArtifactCombiner {
174
182
auto &CstVal = SrcMI->getOperand (1 );
175
183
Builder.buildConstant (
176
184
DstReg, CstVal.getCImm ()->getValue ().trunc (DstTy.getSizeInBits ()));
185
+ UpdatedDefs.push_back (DstReg);
177
186
markInstAndDefDead (MI, *SrcMI, DeadInsts);
178
187
return true ;
179
188
}
@@ -182,10 +191,10 @@ class LegalizationArtifactCombiner {
182
191
return false ;
183
192
}
184
193
185
-
186
194
// / Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
187
195
bool tryFoldImplicitDef (MachineInstr &MI,
188
- SmallVectorImpl<MachineInstr *> &DeadInsts) {
196
+ SmallVectorImpl<MachineInstr *> &DeadInsts,
197
+ SmallVectorImpl<Register> &UpdatedDefs) {
189
198
unsigned Opcode = MI.getOpcode ();
190
199
assert (Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
191
200
Opcode == TargetOpcode::G_SEXT);
@@ -202,13 +211,15 @@ class LegalizationArtifactCombiner {
202
211
return false ;
203
212
LLVM_DEBUG (dbgs () << " .. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;);
204
213
Builder.buildInstr (TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
214
+ UpdatedDefs.push_back (DstReg);
205
215
} else {
206
216
// G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top
207
217
// bits will be 0 for G_ZEXT and 0/1 for the G_SEXT.
208
218
if (isConstantUnsupported (DstTy))
209
219
return false ;
210
220
LLVM_DEBUG (dbgs () << " .. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;);
211
221
Builder.buildConstant (DstReg, 0 );
222
+ UpdatedDefs.push_back (DstReg);
212
223
}
213
224
214
225
markInstAndDefDead (MI, *DefMI, DeadInsts);
@@ -269,7 +280,8 @@ class LegalizationArtifactCombiner {
269
280
}
270
281
271
282
bool tryCombineMerges (MachineInstr &MI,
272
- SmallVectorImpl<MachineInstr *> &DeadInsts) {
283
+ SmallVectorImpl<MachineInstr *> &DeadInsts,
284
+ SmallVectorImpl<Register> &UpdatedDefs) {
273
285
assert (MI.getOpcode () == TargetOpcode::G_UNMERGE_VALUES);
274
286
275
287
unsigned NumDefs = MI.getNumOperands () - 1 ;
@@ -319,8 +331,8 @@ class LegalizationArtifactCombiner {
319
331
SmallVector<Register, 2 > TmpRegs;
320
332
// This is a vector that is being scalarized and casted. Extract to
321
333
// the element type, and do the conversion on the scalars.
322
- LLT MergeEltTy
323
- = MRI.getType (MergeI->getOperand (0 ).getReg ()).getElementType ();
334
+ LLT MergeEltTy =
335
+ MRI.getType (MergeI->getOperand (0 ).getReg ()).getElementType ();
324
336
for (unsigned j = 0 ; j < NumMergeRegs; ++j)
325
337
TmpRegs.push_back (MRI.createGenericVirtualRegister (MergeEltTy));
326
338
@@ -331,6 +343,7 @@ class LegalizationArtifactCombiner {
331
343
} else {
332
344
Builder.buildUnmerge (DstRegs, MergeI->getOperand (Idx + 1 ).getReg ());
333
345
}
346
+ UpdatedDefs.append (DstRegs.begin (), DstRegs.end ());
334
347
}
335
348
336
349
} else if (NumMergeRegs > NumDefs) {
@@ -352,7 +365,9 @@ class LegalizationArtifactCombiner {
352
365
++j, ++Idx)
353
366
Regs.push_back (MergeI->getOperand (Idx).getReg ());
354
367
355
- Builder.buildMerge (MI.getOperand (DefIdx).getReg (), Regs);
368
+ Register DefReg = MI.getOperand (DefIdx).getReg ();
369
+ Builder.buildMerge (DefReg, Regs);
370
+ UpdatedDefs.push_back (DefReg);
356
371
}
357
372
358
373
} else {
@@ -366,8 +381,9 @@ class LegalizationArtifactCombiner {
366
381
367
382
for (unsigned Idx = 0 ; Idx < NumDefs; ++Idx) {
368
383
Register MergeSrc = MergeI->getOperand (Idx + 1 ).getReg ();
369
- Builder.buildInstr (ConvertOp, {MI.getOperand (Idx).getReg ()},
370
- {MergeSrc});
384
+ Register DefReg = MI.getOperand (Idx).getReg ();
385
+ Builder.buildInstr (ConvertOp, {DefReg}, {MergeSrc});
386
+ UpdatedDefs.push_back (DefReg);
371
387
}
372
388
373
389
markInstAndDefDead (MI, *MergeI, DeadInsts);
@@ -378,9 +394,11 @@ class LegalizationArtifactCombiner {
378
394
" Bitcast and the other kinds of conversions should "
379
395
" have happened earlier" );
380
396
381
- for (unsigned Idx = 0 ; Idx < NumDefs; ++Idx)
382
- MRI.replaceRegWith (MI.getOperand (Idx).getReg (),
383
- MergeI->getOperand (Idx + 1 ).getReg ());
397
+ for (unsigned Idx = 0 ; Idx < NumDefs; ++Idx) {
398
+ Register NewDef = MergeI->getOperand (Idx + 1 ).getReg ();
399
+ MRI.replaceRegWith (MI.getOperand (Idx).getReg (), NewDef);
400
+ UpdatedDefs.push_back (NewDef);
401
+ }
384
402
}
385
403
386
404
markInstAndDefDead (MI, *MergeI, DeadInsts);
@@ -399,7 +417,8 @@ class LegalizationArtifactCombiner {
399
417
}
400
418
401
419
bool tryCombineExtract (MachineInstr &MI,
402
- SmallVectorImpl<MachineInstr *> &DeadInsts) {
420
+ SmallVectorImpl<MachineInstr *> &DeadInsts,
421
+ SmallVectorImpl<Register> &UpdatedDefs) {
403
422
assert (MI.getOpcode () == TargetOpcode::G_EXTRACT);
404
423
405
424
// Try to use the source registers from a G_MERGE_VALUES
@@ -414,13 +433,14 @@ class LegalizationArtifactCombiner {
414
433
// for N >= %2.getSizeInBits() / 2
415
434
// %3 = G_EXTRACT %1, (N - %0.getSizeInBits()
416
435
417
- unsigned Src = lookThroughCopyInstrs (MI.getOperand (1 ).getReg ());
418
- MachineInstr *MergeI = MRI.getVRegDef (Src );
436
+ Register SrcReg = lookThroughCopyInstrs (MI.getOperand (1 ).getReg ());
437
+ MachineInstr *MergeI = MRI.getVRegDef (SrcReg );
419
438
if (!MergeI || !isMergeLikeOpcode (MergeI->getOpcode ()))
420
439
return false ;
421
440
422
- LLT DstTy = MRI.getType (MI.getOperand (0 ).getReg ());
423
- LLT SrcTy = MRI.getType (Src);
441
+ Register DstReg = MI.getOperand (0 ).getReg ();
442
+ LLT DstTy = MRI.getType (DstReg);
443
+ LLT SrcTy = MRI.getType (SrcReg);
424
444
425
445
// TODO: Do we need to check if the resulting extract is supported?
426
446
unsigned ExtractDstSize = DstTy.getSizeInBits ();
@@ -438,10 +458,9 @@ class LegalizationArtifactCombiner {
438
458
439
459
// TODO: We could modify MI in place in most cases.
440
460
Builder.setInstr (MI);
441
- Builder.buildExtract (
442
- MI.getOperand (0 ).getReg (),
443
- MergeI->getOperand (MergeSrcIdx + 1 ).getReg (),
444
- Offset - MergeSrcIdx * MergeSrcSize);
461
+ Builder.buildExtract (DstReg, MergeI->getOperand (MergeSrcIdx + 1 ).getReg (),
462
+ Offset - MergeSrcIdx * MergeSrcSize);
463
+ UpdatedDefs.push_back (DstReg);
445
464
markInstAndDefDead (MI, *MergeI, DeadInsts);
446
465
return true ;
447
466
}
@@ -458,33 +477,79 @@ class LegalizationArtifactCombiner {
458
477
// etc, process the dead instructions now if any.
459
478
if (!DeadInsts.empty ())
460
479
deleteMarkedDeadInsts (DeadInsts, WrapperObserver);
480
+
481
+ // Put here every vreg that was redefined in such a way that it's at least
482
+ // possible that one (or more) of its users (immediate or COPY-separated)
483
+ // could become artifact combinable with the new definition (or the
484
+ // instruction reachable from it through a chain of copies if any).
485
+ SmallVector<Register, 4 > UpdatedDefs;
486
+ bool Changed = false ;
461
487
switch (MI.getOpcode ()) {
462
488
default :
463
489
return false ;
464
490
case TargetOpcode::G_ANYEXT:
465
- return tryCombineAnyExt (MI, DeadInsts);
491
+ Changed = tryCombineAnyExt (MI, DeadInsts, UpdatedDefs);
492
+ break ;
466
493
case TargetOpcode::G_ZEXT:
467
- return tryCombineZExt (MI, DeadInsts);
494
+ Changed = tryCombineZExt (MI, DeadInsts, UpdatedDefs);
495
+ break ;
468
496
case TargetOpcode::G_SEXT:
469
- return tryCombineSExt (MI, DeadInsts);
497
+ Changed = tryCombineSExt (MI, DeadInsts, UpdatedDefs);
498
+ break ;
470
499
case TargetOpcode::G_UNMERGE_VALUES:
471
- return tryCombineMerges (MI, DeadInsts);
500
+ Changed = tryCombineMerges (MI, DeadInsts, UpdatedDefs);
501
+ break ;
472
502
case TargetOpcode::G_EXTRACT:
473
- return tryCombineExtract (MI, DeadInsts);
474
- case TargetOpcode::G_TRUNC: {
475
- if (tryCombineTrunc (MI, DeadInsts))
476
- return true ;
477
-
478
- bool Changed = false ;
479
- for (auto &Use : MRI.use_instructions (MI.getOperand (0 ).getReg ()))
480
- Changed |= tryCombineInstruction (Use, DeadInsts, WrapperObserver);
481
- return Changed;
503
+ Changed = tryCombineExtract (MI, DeadInsts, UpdatedDefs);
504
+ break ;
505
+ case TargetOpcode::G_TRUNC:
506
+ Changed = tryCombineTrunc (MI, DeadInsts, UpdatedDefs);
507
+ if (!Changed) {
508
+ // Try to combine truncates away even if they are legal. As all artifact
509
+ // combines at the moment look only "up" the def-use chains, we achieve
510
+ // that by throwing truncates' users (with look through copies) into the
511
+ // ArtifactList again.
512
+ UpdatedDefs.push_back (MI.getOperand (0 ).getReg ());
513
+ }
514
+ break ;
482
515
}
516
+ // If the main loop through the ArtifactList found at least one combinable
517
+ // pair of artifacts, not only combine it away (as done above), but also
518
+ // follow the def-use chain from there to combine everything that can be
519
+ // combined within this def-use chain of artifacts.
520
+ while (!UpdatedDefs.empty ()) {
521
+ Register NewDef = UpdatedDefs.pop_back_val ();
522
+ assert (NewDef.isVirtual () && " Unexpected redefinition of a physreg" );
523
+ for (MachineInstr &Use : MRI.use_instructions (NewDef)) {
524
+ switch (Use.getOpcode ()) {
525
+ // Keep this list in sync with the list of all artifact combines.
526
+ case TargetOpcode::G_ANYEXT:
527
+ case TargetOpcode::G_ZEXT:
528
+ case TargetOpcode::G_SEXT:
529
+ case TargetOpcode::G_UNMERGE_VALUES:
530
+ case TargetOpcode::G_EXTRACT:
531
+ case TargetOpcode::G_TRUNC:
532
+ // Adding Use to ArtifactList.
533
+ WrapperObserver.changedInstr (Use);
534
+ break ;
535
+ case TargetOpcode::COPY: {
536
+ Register Copy = Use.getOperand (0 ).getReg ();
537
+ if (Copy.isVirtual ())
538
+ UpdatedDefs.push_back (Copy);
539
+ break ;
540
+ }
541
+ default :
542
+ // If we do not have an artifact combine for the opcode, there is no
543
+ // point in adding it to the ArtifactList as nothing interesting will
544
+ // be done to it anyway.
545
+ break ;
546
+ }
547
+ }
483
548
}
549
+ return Changed;
484
550
}
485
551
486
552
private:
487
-
488
553
static unsigned getArtifactSrcReg (const MachineInstr &MI) {
489
554
switch (MI.getOpcode ()) {
490
555
case TargetOpcode::COPY:
0 commit comments