[llvm] e60d62b - Utils: Inhibit load/store folding through phis for llvm.protected.field.ptr.
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 3 17:42:52 PST 2025
Author: Peter Collingbourne
Date: 2025-12-03T17:42:48-08:00
New Revision: e60d62b90f83210f43816fb528e6557ab1770683
URL: https://github.com/llvm/llvm-project/commit/e60d62b90f83210f43816fb528e6557ab1770683
DIFF: https://github.com/llvm/llvm-project/commit/e60d62b90f83210f43816fb528e6557ab1770683.diff
LOG: Utils: Inhibit load/store folding through phis for llvm.protected.field.ptr.
Protected pointer field loads/stores should be paired with the intrinsic
to avoid unnecessary address escapes.
Reviewers: nikic
Reviewed By: nikic
Pull Request: https://github.com/llvm/llvm-project/pull/151649
Added:
llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll
Modified:
llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
llvm/lib/Transforms/Utils/Local.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
index 9815644f5f43d..de97b8e60ac65 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -698,8 +698,7 @@ static bool isSafeAndProfitableToSinkLoad(LoadInst *L) {
Instruction *InstCombinerImpl::foldPHIArgLoadIntoPHI(PHINode &PN) {
LoadInst *FirstLI = cast<LoadInst>(PN.getIncomingValue(0));
- // Can't forward swifterror through a phi.
- if (FirstLI->getOperand(0)->isSwiftError())
+ if (!canReplaceOperandWithVariable(FirstLI, 0))
return nullptr;
// FIXME: This is overconservative; this transform is allowed in some cases
@@ -738,8 +737,7 @@ Instruction *InstCombinerImpl::foldPHIArgLoadIntoPHI(PHINode &PN) {
LI->getPointerAddressSpace() != LoadAddrSpace)
return nullptr;
- // Can't forward swifterror through a phi.
- if (LI->getOperand(0)->isSwiftError())
+ if (!canReplaceOperandWithVariable(LI, 0))
return nullptr;
// We can't sink the load if the loaded value could be modified between
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index a03cf6e953e35..f7842a235b20d 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3884,6 +3884,12 @@ bool llvm::canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx) {
if (Op->isSwiftError())
return false;
+ // Protected pointer field loads/stores should be paired with the intrinsic
+ // to avoid unnecessary address escapes.
+ if (auto *II = dyn_cast<IntrinsicInst>(Op))
+ if (II->getIntrinsicID() == Intrinsic::protected_field_ptr)
+ return false;
+
// Cannot replace alloca argument with phi/select.
if (I->isLifetimeStartOrEnd())
return false;
diff --git a/llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll b/llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll
new file mode 100644
index 0000000000000..bf60de446ea91
--- /dev/null
+++ b/llvm/test/Transforms/PhaseOrdering/phi-protected-field-ptr.ll
@@ -0,0 +1,38 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -O2 -S < %s | FileCheck %s
+
+; Test that no optimization run at -O2 moves the loads into the exit block,
+; as this causes unnecessary address escapes with pointer field protection.
+
+define ptr @phi_prot_ptr(i1 %sel, ptr %p1, ptr %p2) {
+; CHECK-LABEL: define ptr @phi_prot_ptr(
+; CHECK-SAME: i1 [[SEL:%.*]], ptr readonly [[P1:%.*]], ptr readonly [[P2:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: br i1 [[SEL]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: [[PROTP1:%.*]] = tail call ptr @llvm.protected.field.ptr.p0(ptr [[P1]], i64 1, i1 true)
+; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[PROTP1]], align 8
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: [[PROTP2:%.*]] = tail call ptr @llvm.protected.field.ptr.p0(ptr [[P2]], i64 2, i1 true)
+; CHECK-NEXT: [[LOAD2:%.*]] = load ptr, ptr [[PROTP2]], align 8
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: [[RETVAL:%.*]] = phi ptr [ [[LOAD1]], %[[T]] ], [ [[LOAD2]], %[[F]] ]
+; CHECK-NEXT: ret ptr [[RETVAL]]
+;
+ br i1 %sel, label %t, label %f
+
+t:
+ %protp1 = call ptr @llvm.protected.field.ptr.p0(ptr %p1, i64 1, i1 true)
+ %load1 = load ptr, ptr %protp1
+ br label %exit
+
+f:
+ %protp2 = call ptr @llvm.protected.field.ptr.p0(ptr %p2, i64 2, i1 true)
+ %load2 = load ptr, ptr %protp2
+ br label %exit
+
+exit:
+ %retval = phi ptr [ %load1, %t ], [ %load2, %f ]
+ ret ptr %retval
+}
More information about the llvm-commits
mailing list