24
24
25
25
using namespace llvm ;
26
26
27
- static void legalizeFreeze (Instruction &I,
27
+ static bool legalizeFreeze (Instruction &I,
28
28
SmallVectorImpl<Instruction *> &ToRemove,
29
- DenseMap<Value *, Value *>, bool & ) {
29
+ DenseMap<Value *, Value *>) {
30
30
auto *FI = dyn_cast<FreezeInst>(&I);
31
31
if (!FI)
32
- return ;
32
+ return false ;
33
33
34
34
FI->replaceAllUsesWith (FI->getOperand (0 ));
35
35
ToRemove.push_back (FI);
36
+ return true ;
36
37
}
37
38
38
- static void fixI8UseChain (Instruction &I,
39
+ static bool fixI8UseChain (Instruction &I,
39
40
SmallVectorImpl<Instruction *> &ToRemove,
40
- DenseMap<Value *, Value *> &ReplacedValues, bool & ) {
41
+ DenseMap<Value *, Value *> &ReplacedValues) {
41
42
42
43
auto ProcessOperands = [&](SmallVector<Value *> &NewOperands) {
43
44
Type *InstrType = IntegerType::get (I.getContext (), 32 );
@@ -74,19 +75,19 @@ static void fixI8UseChain(Instruction &I,
74
75
if (Trunc->getDestTy ()->isIntegerTy (8 )) {
75
76
ReplacedValues[Trunc] = Trunc->getOperand (0 );
76
77
ToRemove.push_back (Trunc);
77
- return ;
78
+ return true ;
78
79
}
79
80
}
80
81
81
82
if (auto *Store = dyn_cast<StoreInst>(&I)) {
82
83
if (!Store->getValueOperand ()->getType ()->isIntegerTy (8 ))
83
- return ;
84
+ return false ;
84
85
SmallVector<Value *> NewOperands;
85
86
ProcessOperands (NewOperands);
86
87
Value *NewStore = Builder.CreateStore (NewOperands[0 ], NewOperands[1 ]);
87
88
ReplacedValues[Store] = NewStore;
88
89
ToRemove.push_back (Store);
89
- return ;
90
+ return true ;
90
91
}
91
92
92
93
if (auto *Load = dyn_cast<LoadInst>(&I);
@@ -104,17 +105,17 @@ static void fixI8UseChain(Instruction &I,
104
105
LoadInst *NewLoad = Builder.CreateLoad (ElementType, NewOperands[0 ]);
105
106
ReplacedValues[Load] = NewLoad;
106
107
ToRemove.push_back (Load);
107
- return ;
108
+ return true ;
108
109
}
109
110
110
111
if (auto *Load = dyn_cast<LoadInst>(&I);
111
112
Load && isa<ConstantExpr>(Load->getPointerOperand ())) {
112
113
auto *CE = dyn_cast<ConstantExpr>(Load->getPointerOperand ());
113
114
if (!(CE->getOpcode () == Instruction::GetElementPtr))
114
- return ;
115
+ return false ;
115
116
auto *GEP = dyn_cast<GEPOperator>(CE);
116
117
if (!GEP->getSourceElementType ()->isIntegerTy (8 ))
117
- return ;
118
+ return false ;
118
119
119
120
Type *ElementType = Load->getType ();
120
121
ConstantInt *Offset = dyn_cast<ConstantInt>(GEP->getOperand (1 ));
@@ -143,12 +144,12 @@ static void fixI8UseChain(Instruction &I,
143
144
ReplacedValues[Load] = NewLoad;
144
145
Load->replaceAllUsesWith (NewLoad);
145
146
ToRemove.push_back (Load);
146
- return ;
147
+ return true ;
147
148
}
148
149
149
150
if (auto *BO = dyn_cast<BinaryOperator>(&I)) {
150
151
if (!I.getType ()->isIntegerTy (8 ))
151
- return ;
152
+ return false ;
152
153
SmallVector<Value *> NewOperands;
153
154
ProcessOperands (NewOperands);
154
155
Value *NewInst =
@@ -162,43 +163,43 @@ static void fixI8UseChain(Instruction &I,
162
163
}
163
164
ReplacedValues[BO] = NewInst;
164
165
ToRemove.push_back (BO);
165
- return ;
166
+ return true ;
166
167
}
167
168
168
169
if (auto *Sel = dyn_cast<SelectInst>(&I)) {
169
170
if (!I.getType ()->isIntegerTy (8 ))
170
- return ;
171
+ return false ;
171
172
SmallVector<Value *> NewOperands;
172
173
ProcessOperands (NewOperands);
173
174
Value *NewInst = Builder.CreateSelect (Sel->getCondition (), NewOperands[1 ],
174
175
NewOperands[2 ]);
175
176
ReplacedValues[Sel] = NewInst;
176
177
ToRemove.push_back (Sel);
177
- return ;
178
+ return true ;
178
179
}
179
180
180
181
if (auto *Cmp = dyn_cast<CmpInst>(&I)) {
181
182
if (!Cmp->getOperand (0 )->getType ()->isIntegerTy (8 ))
182
- return ;
183
+ return false ;
183
184
SmallVector<Value *> NewOperands;
184
185
ProcessOperands (NewOperands);
185
186
Value *NewInst =
186
187
Builder.CreateCmp (Cmp->getPredicate (), NewOperands[0 ], NewOperands[1 ]);
187
188
Cmp->replaceAllUsesWith (NewInst);
188
189
ReplacedValues[Cmp] = NewInst;
189
190
ToRemove.push_back (Cmp);
190
- return ;
191
+ return true ;
191
192
}
192
193
193
194
if (auto *Cast = dyn_cast<CastInst>(&I)) {
194
195
if (!Cast->getSrcTy ()->isIntegerTy (8 ))
195
- return ;
196
+ return false ;
196
197
197
198
ToRemove.push_back (Cast);
198
199
auto *Replacement = ReplacedValues[Cast->getOperand (0 )];
199
200
if (Cast->getType () == Replacement->getType ()) {
200
201
Cast->replaceAllUsesWith (Replacement);
201
- return ;
202
+ return true ;
202
203
}
203
204
204
205
Value *AdjustedCast = nullptr ;
@@ -213,7 +214,7 @@ static void fixI8UseChain(Instruction &I,
213
214
if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
214
215
if (!GEP->getType ()->isPointerTy () ||
215
216
!GEP->getSourceElementType ()->isIntegerTy (8 ))
216
- return ;
217
+ return false ;
217
218
218
219
Value *BasePtr = GEP->getPointerOperand ();
219
220
if (ReplacedValues.count (BasePtr))
@@ -248,16 +249,17 @@ static void fixI8UseChain(Instruction &I,
248
249
ReplacedValues[GEP] = NewGEP;
249
250
GEP->replaceAllUsesWith (NewGEP);
250
251
ToRemove.push_back (GEP);
252
+ return true ;
251
253
}
254
+ return false ;
252
255
}
253
256
254
- static void upcastI8AllocasAndUses (Instruction &I,
257
+ static bool upcastI8AllocasAndUses (Instruction &I,
255
258
SmallVectorImpl<Instruction *> &ToRemove,
256
- DenseMap<Value *, Value *> &ReplacedValues,
257
- bool &) {
259
+ DenseMap<Value *, Value *> &ReplacedValues) {
258
260
auto *AI = dyn_cast<AllocaInst>(&I);
259
261
if (!AI || !AI->getAllocatedType ()->isIntegerTy (8 ))
260
- return ;
262
+ return false ;
261
263
262
264
Type *SmallestType = nullptr ;
263
265
@@ -292,19 +294,20 @@ static void upcastI8AllocasAndUses(Instruction &I,
292
294
}
293
295
294
296
if (!SmallestType)
295
- return ; // no valid casts found
297
+ return false ; // no valid casts found
296
298
297
299
// Replace alloca
298
300
IRBuilder<> Builder (AI);
299
301
auto *NewAlloca = Builder.CreateAlloca (SmallestType);
300
302
ReplacedValues[AI] = NewAlloca;
301
303
ToRemove.push_back (AI);
304
+ return true ;
302
305
}
303
306
304
- static void
307
+ static bool
305
308
downcastI64toI32InsertExtractElements (Instruction &I,
306
309
SmallVectorImpl<Instruction *> &ToRemove,
307
- DenseMap<Value *, Value *> &, bool & ) {
310
+ DenseMap<Value *, Value *> &) {
308
311
309
312
if (auto *Extract = dyn_cast<ExtractElementInst>(&I)) {
310
313
Value *Idx = Extract->getIndexOperand ();
@@ -319,6 +322,7 @@ downcastI64toI32InsertExtractElements(Instruction &I,
319
322
320
323
Extract->replaceAllUsesWith (NewExtract);
321
324
ToRemove.push_back (Extract);
325
+ return true ;
322
326
}
323
327
}
324
328
@@ -336,8 +340,10 @@ downcastI64toI32InsertExtractElements(Instruction &I,
336
340
337
341
Insert->replaceAllUsesWith (Insert32Index);
338
342
ToRemove.push_back (Insert);
343
+ return true ;
339
344
}
340
345
}
346
+ return false ;
341
347
}
342
348
343
349
static void emitMemcpyExpansion (IRBuilder<> &Builder, Value *Dst, Value *Src,
@@ -454,17 +460,17 @@ static void emitMemsetExpansion(IRBuilder<> &Builder, Value *Dst, Value *Val,
454
460
// Expands the instruction `I` into corresponding loads and stores if it is a
455
461
// memcpy call. In that case, the call instruction is added to the `ToRemove`
456
462
// vector. `ReplacedValues` is unused.
457
- static void legalizeMemCpy (Instruction &I,
463
+ static bool legalizeMemCpy (Instruction &I,
458
464
SmallVectorImpl<Instruction *> &ToRemove,
459
- DenseMap<Value *, Value *> &ReplacedValues, bool & ) {
465
+ DenseMap<Value *, Value *> &ReplacedValues) {
460
466
461
467
CallInst *CI = dyn_cast<CallInst>(&I);
462
468
if (!CI)
463
- return ;
469
+ return false ;
464
470
465
471
Intrinsic::ID ID = CI->getIntrinsicID ();
466
472
if (ID != Intrinsic::memcpy)
467
- return ;
473
+ return false ;
468
474
469
475
IRBuilder<> Builder (&I);
470
476
Value *Dst = CI->getArgOperand (0 );
@@ -477,19 +483,20 @@ static void legalizeMemCpy(Instruction &I,
477
483
assert (IsVolatile->getZExtValue () == 0 && " Expected IsVolatile to be false" );
478
484
emitMemcpyExpansion (Builder, Dst, Src, Length);
479
485
ToRemove.push_back (CI);
486
+ return true ;
480
487
}
481
488
482
- static void legalizeMemSet (Instruction &I,
489
+ static bool legalizeMemSet (Instruction &I,
483
490
SmallVectorImpl<Instruction *> &ToRemove,
484
- DenseMap<Value *, Value *> &ReplacedValues, bool & ) {
491
+ DenseMap<Value *, Value *> &ReplacedValues) {
485
492
486
493
CallInst *CI = dyn_cast<CallInst>(&I);
487
494
if (!CI)
488
- return ;
495
+ return false ;
489
496
490
497
Intrinsic::ID ID = CI->getIntrinsicID ();
491
498
if (ID != Intrinsic::memset)
492
- return ;
499
+ return false ;
493
500
494
501
IRBuilder<> Builder (&I);
495
502
Value *Dst = CI->getArgOperand (0 );
@@ -498,39 +505,41 @@ static void legalizeMemSet(Instruction &I,
498
505
assert (Size && " Expected Size to be a ConstantInt" );
499
506
emitMemsetExpansion (Builder, Dst, Val, Size, ReplacedValues);
500
507
ToRemove.push_back (CI);
508
+ return true ;
501
509
}
502
510
503
- static void updateFnegToFsub (Instruction &I,
511
+ static bool updateFnegToFsub (Instruction &I,
504
512
SmallVectorImpl<Instruction *> &ToRemove,
505
- DenseMap<Value *, Value *> &, bool & ) {
513
+ DenseMap<Value *, Value *> &) {
506
514
const Intrinsic::ID ID = I.getOpcode ();
507
515
if (ID != Instruction::FNeg)
508
- return ;
516
+ return false ;
509
517
510
518
IRBuilder<> Builder (&I);
511
519
Value *In = I.getOperand (0 );
512
520
Value *Zero = ConstantFP::get (In->getType (), -0.0 );
513
521
I.replaceAllUsesWith (Builder.CreateFSub (Zero, In));
514
522
ToRemove.push_back (&I);
523
+ return true ;
515
524
}
516
525
517
- static void
526
+ static bool
518
527
legalizeGetHighLowi64Bytes (Instruction &I,
519
528
SmallVectorImpl<Instruction *> &ToRemove,
520
- DenseMap<Value *, Value *> &ReplacedValues, bool & ) {
529
+ DenseMap<Value *, Value *> &ReplacedValues) {
521
530
if (auto *BitCast = dyn_cast<BitCastInst>(&I)) {
522
531
if (BitCast->getDestTy () ==
523
532
FixedVectorType::get (Type::getInt32Ty (I.getContext ()), 2 ) &&
524
533
BitCast->getSrcTy ()->isIntegerTy (64 )) {
525
534
ToRemove.push_back (BitCast);
526
535
ReplacedValues[BitCast] = BitCast->getOperand (0 );
527
- return ;
536
+ return true ;
528
537
}
529
538
}
530
539
531
540
if (auto *Extract = dyn_cast<ExtractElementInst>(&I)) {
532
541
if (!dyn_cast<BitCastInst>(Extract->getVectorOperand ()))
533
- return ;
542
+ return false ;
534
543
auto *VecTy = dyn_cast<FixedVectorType>(Extract->getVectorOperandType ());
535
544
if (VecTy && VecTy->getElementType ()->isIntegerTy (32 ) &&
536
545
VecTy->getNumElements () == 2 ) {
@@ -558,14 +567,16 @@ legalizeGetHighLowi64Bytes(Instruction &I,
558
567
}
559
568
ToRemove.push_back (Extract);
560
569
Extract->replaceAllUsesWith (ReplacedValues[Extract]);
570
+ return true ;
561
571
}
562
572
}
563
573
}
574
+ return false ;
564
575
}
565
576
566
- static void legalizeScalarLoadStoreOnArrays (
577
+ static bool legalizeScalarLoadStoreOnArrays (
567
578
Instruction &I, SmallVectorImpl<Instruction *> &ToRemove,
568
- DenseMap<Value *, Value *> &, bool &MadeChange ) {
579
+ DenseMap<Value *, Value *> &) {
569
580
570
581
Value *PtrOp;
571
582
unsigned PtrOpIndex;
@@ -579,25 +590,25 @@ static void legalizeScalarLoadStoreOnArrays(
579
590
PtrOpIndex = SI->getPointerOperandIndex ();
580
591
LoadStoreTy = SI->getValueOperand ()->getType ();
581
592
} else
582
- return ;
593
+ return false ;
583
594
584
595
// If the load/store is not of a single-value type (i.e., scalar or vector)
585
596
// then we do not modify it. It shouldn't be a vector either because the
586
597
// dxil-data-scalarization pass is expected to run before this, but it's not
587
598
// incorrect to apply this transformation to vector load/stores.
588
599
if (!LoadStoreTy->isSingleValueType ())
589
- return ;
600
+ return false ;
590
601
591
602
Type *ArrayTy;
592
603
if (auto *GlobalVarPtrOp = dyn_cast<GlobalVariable>(PtrOp))
593
604
ArrayTy = GlobalVarPtrOp->getValueType ();
594
605
else if (auto *AllocaPtrOp = dyn_cast<AllocaInst>(PtrOp))
595
606
ArrayTy = AllocaPtrOp->getAllocatedType ();
596
607
else
597
- return ;
608
+ return false ;
598
609
599
610
if (!isa<ArrayType>(ArrayTy))
600
- return ;
611
+ return false ;
601
612
602
613
assert (ArrayTy->getArrayElementType () == LoadStoreTy &&
603
614
" Expected array element type to be the same as to the scalar load or "
@@ -607,7 +618,7 @@ static void legalizeScalarLoadStoreOnArrays(
607
618
Value *GEP = GetElementPtrInst::Create (
608
619
ArrayTy, PtrOp, {Zero, Zero}, GEPNoWrapFlags::all (), " " , I.getIterator ());
609
620
I.setOperand (PtrOpIndex, GEP);
610
- MadeChange = true ;
621
+ return true ;
611
622
}
612
623
613
624
namespace {
@@ -624,17 +635,12 @@ class DXILLegalizationPipeline {
624
635
ToRemove.clear ();
625
636
ReplacedValues.clear ();
626
637
for (auto &I : instructions (F)) {
627
- for (auto &LegalizationFn : LegalizationPipeline[Stage]) {
628
- bool PerLegalizationChange = false ;
629
- LegalizationFn (I, ToRemove, ReplacedValues, PerLegalizationChange);
630
- MadeChange |= PerLegalizationChange;
631
- }
638
+ for (auto &LegalizationFn : LegalizationPipeline[Stage])
639
+ MadeChange |= LegalizationFn (I, ToRemove, ReplacedValues);
632
640
}
633
641
634
642
for (auto *Inst : reverse (ToRemove))
635
643
Inst->eraseFromParent ();
636
-
637
- MadeChange |= !ToRemove.empty ();
638
644
}
639
645
return MadeChange;
640
646
}
@@ -643,8 +649,8 @@ class DXILLegalizationPipeline {
643
649
enum LegalizationStage { Stage1 = 0 , Stage2 = 1 , NumStages };
644
650
645
651
using LegalizationFnTy =
646
- std::function<void (Instruction &, SmallVectorImpl<Instruction *> &,
647
- DenseMap<Value *, Value *> &, bool & )>;
652
+ std::function<bool (Instruction &, SmallVectorImpl<Instruction *> &,
653
+ DenseMap<Value *, Value *> &)>;
648
654
649
655
SmallVector<LegalizationFnTy> LegalizationPipeline[NumStages];
650
656
0 commit comments