[llvm] [AArch64][PAC] Select auth+load into LDRAA/LDRAB/LDRA[pre]. (PR #123769)
Daniil Kovalev via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 27 04:03:35 PST 2025
================
@@ -1671,6 +1673,163 @@ bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *N) {
return true;
}
+bool AArch64DAGToDAGISel::tryAuthLoad(SDNode *N) {
+ LoadSDNode *LD = cast<LoadSDNode>(N);
+ EVT VT = LD->getMemoryVT();
+ if (VT != MVT::i64)
+ return false;
+
+ assert(LD->getExtensionType() == ISD::NON_EXTLOAD && "invalid 64bit extload");
+
+ ISD::MemIndexedMode AM = LD->getAddressingMode();
+ if (AM != ISD::PRE_INC && AM != ISD::UNINDEXED)
+ return false;
+ bool IsPre = AM == ISD::PRE_INC;
+
+ SDValue Chain = LD->getChain();
+ SDValue Ptr = LD->getBasePtr();
+
+ SDValue Base = Ptr;
+
+ int64_t OffsetVal = 0;
+ if (IsPre) {
+ OffsetVal = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
+ } else if (CurDAG->isBaseWithConstantOffset(Base)) {
+ // We support both 'base' and 'base + constant offset' modes.
+ ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Base.getOperand(1));
+ if (!RHS)
+ return false;
+ OffsetVal = RHS->getSExtValue();
+ Base = Base.getOperand(0);
+ }
+
+ // The base must be of the form:
+ // (int_ptrauth_auth <signedbase>, <key>, <disc>)
+ // with disc being either a constant int, or:
+ // (int_ptrauth_blend <addrdisc>, <const int disc>)
+ if (Base.getOpcode() != ISD::INTRINSIC_WO_CHAIN)
+ return false;
+
+ unsigned IntID = cast<ConstantSDNode>(Base.getOperand(0))->getZExtValue();
+ if (IntID != Intrinsic::ptrauth_auth)
+ return false;
+
+ unsigned KeyC = cast<ConstantSDNode>(Base.getOperand(2))->getZExtValue();
+ bool IsDKey = KeyC == AArch64PACKey::DA || KeyC == AArch64PACKey::DB;
+ SDValue Disc = Base.getOperand(3);
+
+ Base = Base.getOperand(1);
+
+ bool ZeroDisc = isNullConstant(Disc);
+ SDValue IntDisc, AddrDisc;
+ std::tie(IntDisc, AddrDisc) = extractPtrauthBlendDiscriminators(Disc, CurDAG);
+
+ // If this is an indexed pre-inc load, we obviously need the writeback form.
+ bool needsWriteback = IsPre;
+ // If not, but the base authenticated pointer has any other use, it's
+ // beneficial to use the writeback form, to "writeback" the auth, even if
+ // there is no base+offset addition.
+ if (!Ptr.hasOneUse()) {
+ needsWriteback = true;
+
+ // However, we can only do that if we don't introduce cycles between the
+ // load node and any other user of the pointer computation nodes. That can
+ // happen if the load node uses any of said other users.
+ // In other words: we can only do this transformation if none of the other
+ // uses of the pointer computation to be folded are predecessors of the load
+ // we're folding into.
+ //
+ // Visited is a cache containing nodes that are known predecessors of N.
+ // Worklist is the set of nodes we're looking for predecessors of.
+ // For the first lookup, that only contains the load node N. Each call to
+ // hasPredecessorHelper adds any of the potential predecessors of N to the
+ // Worklist.
+ SmallPtrSet<const SDNode *, 32> Visited;
+ SmallVector<const SDNode *, 16> Worklist;
+ Worklist.push_back(N);
+ for (SDNode *U : Ptr.getNode()->users())
----------------
kovdan01 wrote:
Nit
```suggestion
for (const SDNode *U : Ptr.getNode()->users())
```
https://github.com/llvm/llvm-project/pull/123769
More information about the llvm-commits
mailing list