62
62
#include " llvm/IR/Instruction.h"
63
63
#include " llvm/IR/Instructions.h"
64
64
#include " llvm/IR/IntrinsicInst.h"
65
+ #include " llvm/IR/Intrinsics.h"
65
66
#include " llvm/IR/LLVMContext.h"
66
67
#include " llvm/IR/Metadata.h"
67
68
#include " llvm/IR/Module.h"
@@ -523,9 +524,10 @@ class Slice {
523
524
public:
524
525
Slice () = default ;
525
526
526
- Slice (uint64_t BeginOffset, uint64_t EndOffset, Use *U, bool IsSplittable)
527
+ Slice (uint64_t BeginOffset, uint64_t EndOffset, Use *U, bool IsSplittable,
528
+ Value *ProtectedFieldDisc)
527
529
: BeginOffset(BeginOffset), EndOffset(EndOffset),
528
- UseAndIsSplittable (U, IsSplittable) {}
530
+ UseAndIsSplittable (U, IsSplittable), ProtectedFieldDisc(ProtectedFieldDisc) {}
529
531
530
532
uint64_t beginOffset () const { return BeginOffset; }
531
533
uint64_t endOffset () const { return EndOffset; }
@@ -538,6 +540,10 @@ class Slice {
538
540
bool isDead () const { return getUse () == nullptr ; }
539
541
void kill () { UseAndIsSplittable.setPointer (nullptr ); }
540
542
543
+ // When this access is via an llvm.protected.field.ptr intrinsic, contains
544
+ // the second argument to the intrinsic, the discriminator.
545
+ Value *ProtectedFieldDisc;
546
+
541
547
// / Support for ordering ranges.
542
548
// /
543
549
// / This provides an ordering over ranges such that start offsets are
@@ -631,6 +637,9 @@ class AllocaSlices {
631
637
// / Access the dead users for this alloca.
632
638
ArrayRef<Instruction *> getDeadUsers () const { return DeadUsers; }
633
639
640
+ // / Access the PFP users for this alloca.
641
+ ArrayRef<IntrinsicInst *> getPFPUsers () const { return PFPUsers; }
642
+
634
643
// / Access Uses that should be dropped if the alloca is promotable.
635
644
ArrayRef<Use *> getDeadUsesIfPromotable () const {
636
645
return DeadUseIfPromotable;
@@ -691,6 +700,10 @@ class AllocaSlices {
691
700
// / they come from outside of the allocated space.
692
701
SmallVector<Instruction *, 8 > DeadUsers;
693
702
703
+ // / Users that are llvm.protected.field.ptr intrinsics. These will be RAUW'd
704
+ // / to their first argument if we rewrite the alloca.
705
+ SmallVector<IntrinsicInst *, 0 > PFPUsers;
706
+
694
707
// / Uses which will become dead if can promote the alloca.
695
708
SmallVector<Use *, 8 > DeadUseIfPromotable;
696
709
@@ -1064,7 +1077,8 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
1064
1077
EndOffset = AllocSize;
1065
1078
}
1066
1079
1067
- AS.Slices .push_back (Slice (BeginOffset, EndOffset, U, IsSplittable));
1080
+ AS.Slices .push_back (
1081
+ Slice (BeginOffset, EndOffset, U, IsSplittable, ProtectedFieldDisc));
1068
1082
}
1069
1083
1070
1084
void visitBitCastInst (BitCastInst &BC) {
@@ -1274,6 +1288,9 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
1274
1288
return ;
1275
1289
}
1276
1290
1291
+ if (II.getIntrinsicID () == Intrinsic::protected_field_ptr)
1292
+ AS.PFPUsers .push_back (&II);
1293
+
1277
1294
Base::visitIntrinsicInst (II);
1278
1295
}
1279
1296
@@ -4682,7 +4699,7 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
4682
4699
NewSlices.push_back (
4683
4700
Slice (BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
4684
4701
&PLoad->getOperandUse (PLoad->getPointerOperandIndex ()),
4685
- /* IsSplittable*/ false ));
4702
+ /* IsSplittable*/ false , nullptr ));
4686
4703
LLVM_DEBUG (dbgs () << " new slice [" << NewSlices.back ().beginOffset ()
4687
4704
<< " , " << NewSlices.back ().endOffset ()
4688
4705
<< " ): " << *PLoad << " \n " );
@@ -4838,10 +4855,12 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
4838
4855
LLVMContext::MD_access_group});
4839
4856
4840
4857
// Now build a new slice for the alloca.
4858
+ // ProtectedFieldDisc==nullptr is a lie, but it doesn't matter because we
4859
+ // already determined that all accesses are consistent.
4841
4860
NewSlices.push_back (
4842
4861
Slice (BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
4843
4862
&PStore->getOperandUse (PStore->getPointerOperandIndex ()),
4844
- /* IsSplittable*/ false ));
4863
+ /* IsSplittable*/ false , nullptr ));
4845
4864
LLVM_DEBUG (dbgs () << " new slice [" << NewSlices.back ().beginOffset ()
4846
4865
<< " , " << NewSlices.back ().endOffset ()
4847
4866
<< " ): " << *PStore << " \n " );
@@ -5618,6 +5637,32 @@ SROA::runOnAlloca(AllocaInst &AI) {
5618
5637
return {Changed, CFGChanged};
5619
5638
}
5620
5639
5640
+ for (auto &P : AS.partitions ()) {
5641
+ std::optional<Value *> ProtectedFieldDisc;
5642
+ // For now, we can't split if a field is accessed both via protected
5643
+ // field and not.
5644
+ for (Slice &S : P) {
5645
+ if (auto *II = dyn_cast<IntrinsicInst>(S.getUse ()->getUser ()))
5646
+ if (II->getIntrinsicID () == Intrinsic::lifetime_start ||
5647
+ II->getIntrinsicID () == Intrinsic::lifetime_end)
5648
+ continue ;
5649
+ if (!ProtectedFieldDisc)
5650
+ ProtectedFieldDisc = S.ProtectedFieldDisc ;
5651
+ if (*ProtectedFieldDisc != S.ProtectedFieldDisc )
5652
+ return {Changed, CFGChanged};
5653
+ }
5654
+ for (Slice *S : P.splitSliceTails ()) {
5655
+ if (auto *II = dyn_cast<IntrinsicInst>(S->getUse ()->getUser ()))
5656
+ if (II->getIntrinsicID () == Intrinsic::lifetime_start ||
5657
+ II->getIntrinsicID () == Intrinsic::lifetime_end)
5658
+ continue ;
5659
+ if (!ProtectedFieldDisc)
5660
+ ProtectedFieldDisc = S->ProtectedFieldDisc ;
5661
+ if (*ProtectedFieldDisc != S->ProtectedFieldDisc )
5662
+ return {Changed, CFGChanged};
5663
+ }
5664
+ }
5665
+
5621
5666
// Delete all the dead users of this alloca before splitting and rewriting it.
5622
5667
for (Instruction *DeadUser : AS.getDeadUsers ()) {
5623
5668
// Free up everything used by this instruction.
@@ -5635,6 +5680,12 @@ SROA::runOnAlloca(AllocaInst &AI) {
5635
5680
clobberUse (*DeadOp);
5636
5681
Changed = true ;
5637
5682
}
5683
+ for (IntrinsicInst *PFPUser : AS.getPFPUsers ()) {
5684
+ PFPUser->replaceAllUsesWith (PFPUser->getArgOperand (0 ));
5685
+
5686
+ DeadInsts.push_back (PFPUser);
5687
+ Changed = true ;
5688
+ }
5638
5689
5639
5690
// No slices to split. Leave the dead alloca for a later pass to clean up.
5640
5691
if (AS.begin () == AS.end ())
0 commit comments