@@ -648,7 +648,8 @@ class AllocaSlices {
648648 // / Access the dead users for this alloca.
649649 ArrayRef<Instruction *> getDeadUsers () const { return DeadUsers; }
650650
651- // / Access the PFP users for this alloca.
651+ // / Access the users for this alloca that are llvm.protected.field.ptr
652+ // / intrinsics.
652653 ArrayRef<IntrinsicInst *> getPFPUsers () const { return PFPUsers; }
653654
654655 // / Access Uses that should be dropped if the alloca is promotable.
@@ -1043,6 +1044,10 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
10431044 // / Set to de-duplicate dead instructions found in the use walk.
10441045 SmallPtrSet<Instruction *, 4 > VisitedDeadInsts;
10451046
1047+ // When this access is via an llvm.protected.field.ptr intrinsic, contains
1048+ // the second argument to the intrinsic, the discriminator.
1049+ Value *ProtectedFieldDisc = nullptr ;
1050+
10461051public:
10471052 SliceBuilder (const DataLayout &DL, AllocaInst &AI, AllocaSlices &AS)
10481053 : PtrUseVisitor<SliceBuilder>(DL),
@@ -1289,8 +1294,26 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
12891294 return ;
12901295 }
12911296
1292- if (II.getIntrinsicID () == Intrinsic::protected_field_ptr)
1297+ if (II.getIntrinsicID () == Intrinsic::protected_field_ptr) {
1298+ // We only handle loads and stores as users of llvm.protected.field.ptr.
1299+ // Other uses may add items to the worklist, which will cause
1300+ // ProtectedFieldDisc to be tracked incorrectly.
12931301 AS.PFPUsers .push_back (&II);
1302+ ProtectedFieldDisc = II.getArgOperand (1 );
1303+ for (Use &U : II.uses ()) {
1304+ this ->U = &U;
1305+ if (auto *LI = dyn_cast<LoadInst>(U.getUser ()))
1306+ visitLoadInst (*LI);
1307+ else if (auto *SI = dyn_cast<StoreInst>(U.getUser ()))
1308+ visitStoreInst (*SI);
1309+ else
1310+ PI.setAborted (&II);
1311+ if (PI.isAborted ())
1312+ break ;
1313+ }
1314+ ProtectedFieldDisc = nullptr ;
1315+ return ;
1316+ }
12941317
12951318 Base::visitIntrinsicInst (II);
12961319 }
@@ -5896,29 +5919,27 @@ SROA::runOnAlloca(AllocaInst &AI) {
58965919 }
58975920
58985921 for (auto &P : AS.partitions ()) {
5922+ // For now, we can't split if a field is accessed both via protected field
5923+ // and not, because that would mean that we would need to introduce sign and
5924+ // auth operations to convert between the protected and non-protected uses,
5925+ // and this pass doesn't know how to do that. Also, this case is unlikely to
5926+ // occur in normal code.
58995927 std::optional<Value *> ProtectedFieldDisc;
5900- // For now, we can't split if a field is accessed both via protected
5901- // field and not.
5902- for (Slice &S : P) {
5928+ auto SliceHasMismatch = [&](Slice &S) {
59035929 if (auto *II = dyn_cast<IntrinsicInst>(S.getUse ()->getUser ()))
59045930 if (II->getIntrinsicID () == Intrinsic::lifetime_start ||
59055931 II->getIntrinsicID () == Intrinsic::lifetime_end)
5906- continue ;
5932+ return false ;
59075933 if (!ProtectedFieldDisc)
59085934 ProtectedFieldDisc = S.ProtectedFieldDisc ;
5909- if (*ProtectedFieldDisc != S.ProtectedFieldDisc )
5935+ return *ProtectedFieldDisc != S.ProtectedFieldDisc ;
5936+ };
5937+ for (Slice &S : P)
5938+ if (SliceHasMismatch (S))
59105939 return {Changed, CFGChanged};
5911- }
5912- for (Slice *S : P.splitSliceTails ()) {
5913- if (auto *II = dyn_cast<IntrinsicInst>(S->getUse ()->getUser ()))
5914- if (II->getIntrinsicID () == Intrinsic::lifetime_start ||
5915- II->getIntrinsicID () == Intrinsic::lifetime_end)
5916- continue ;
5917- if (!ProtectedFieldDisc)
5918- ProtectedFieldDisc = S->ProtectedFieldDisc ;
5919- if (*ProtectedFieldDisc != S->ProtectedFieldDisc )
5940+ for (Slice *S : P.splitSliceTails ())
5941+ if (SliceHasMismatch (*S))
59205942 return {Changed, CFGChanged};
5921- }
59225943 }
59235944
59245945 // Delete all the dead users of this alloca before splitting and rewriting it.
0 commit comments