https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/217905
Perform the definitional fold if the source value is null in the default address space. Co-authored-by: Claude (Claude-Opus-4.8) <[email protected]> >From 9aa97a0cd87c13749d4a63fbde7a0a6ab839521f Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Fri, 21 Aug 2026 12:26:48 +0200 Subject: [PATCH] InstSimplify: Fold nonnull addrspacecast of null to poison Perform the definitional fold if the source value is null in the default address space. Co-authored-by: Claude (Claude-Opus-4.8) <[email protected]> --- .../llvm/Analysis/InstructionSimplify.h | 4 ++ llvm/lib/Analysis/InstructionSimplify.cpp | 22 ++++++ .../InstSimplify/addrspacecast-nonnull.ll | 69 +++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 llvm/test/Transforms/InstSimplify/addrspacecast-nonnull.ll diff --git a/llvm/include/llvm/Analysis/InstructionSimplify.h b/llvm/include/llvm/Analysis/InstructionSimplify.h index 8f5a484ad2d57..61e1c59b59f56 100644 --- a/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -194,6 +194,10 @@ LLVM_ABI Value *simplifyExtractElementInst(Value *Vec, Value *Idx, LLVM_ABI Value *simplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty, const SimplifyQuery &Q); +/// Given operands for an AddrSpaceCastInst, fold the result or return null. +LLVM_ABI Value *simplifyAddrSpaceCastInst(Value *Op, Type *Ty, bool IsNonNull, + const SimplifyQuery &Q); + /// Given operands for an intrinsic, fold the result or return null. Context /// Function is passed as \p CxtF. \p ExBehavior and \p Rounding only apply to /// constrained FP intrinsics. diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index c76f4d2e9f327..b662b6921319d 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -5707,6 +5707,22 @@ Value *llvm::simplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty, return ::simplifyCastInst(CastOpc, Op, Ty, Q, RecursionLimit); } +static Value *simplifyAddrSpaceCastInst(Value *Op, Type *Ty, bool IsNonNull, + const SimplifyQuery &Q, + unsigned MaxRecurse) { + if (IsNonNull && match(Op, m_Zero()) && Q.CxtI && + !NullPointerIsDefined(Q.CxtI->getFunction(), + Op->getType()->getPointerAddressSpace())) + return PoisonValue::get(Ty); + + return ::simplifyCastInst(Instruction::AddrSpaceCast, Op, Ty, Q, MaxRecurse); +} + +Value *llvm::simplifyAddrSpaceCastInst(Value *Op, Type *Ty, bool IsNonNull, + const SimplifyQuery &Q) { + return ::simplifyAddrSpaceCastInst(Op, Ty, IsNonNull, Q, RecursionLimit); +} + /// For the given destination element of a shuffle, peek through shuffles to /// match a root vector source operand that contains that element in the same /// vector lane (ie, the same mask index), so we can eliminate the shuffle(s). @@ -7831,6 +7847,12 @@ static Value *simplifyInstructionWithOperands(Instruction *I, #define HANDLE_CAST_INST(num, opc, clas) case Instruction::opc: #include "llvm/IR/Instruction.def" #undef HANDLE_CAST_INST + if (I->getOpcode() == Instruction::AddrSpaceCast) { + return simplifyAddrSpaceCastInst(NewOps[0], I->getType(), + cast<AddrSpaceCastInst>(I)->hasNonNull(), + Q, MaxRecurse); + } + return simplifyCastInst(I->getOpcode(), NewOps[0], I->getType(), Q, MaxRecurse); case Instruction::Alloca: diff --git a/llvm/test/Transforms/InstSimplify/addrspacecast-nonnull.ll b/llvm/test/Transforms/InstSimplify/addrspacecast-nonnull.ll new file mode 100644 index 0000000000000..819577a802c4f --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/addrspacecast-nonnull.ll @@ -0,0 +1,69 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=instsimplify < %s | FileCheck %s + +; A nonnull addrspacecast of the address space 0 null value is poison. +define ptr addrspace(1) @fold_scalar() { +; CHECK-LABEL: @fold_scalar( +; CHECK-NEXT: ret ptr addrspace(1) poison +; + %c = addrspacecast nonnull ptr null to ptr addrspace(1) + ret ptr addrspace(1) %c +} + +; A splat null vector of address space 0 pointers folds elementwise. +define <2 x ptr addrspace(1)> @fold_vector() { +; CHECK-LABEL: @fold_vector( +; CHECK-NEXT: ret <2 x ptr addrspace(1)> poison +; + %c = addrspacecast nonnull <2 x ptr> zeroinitializer to <2 x ptr addrspace(1)> + ret <2 x ptr addrspace(1)> %c +} + +define <2 x ptr addrspace(1)> @no_fold_splat_poison() { +; CHECK-LABEL: @no_fold_splat_poison( +; CHECK-NEXT: ret <2 x ptr addrspace(1)> <ptr addrspace(1) addrspacecast (ptr null to ptr addrspace(1)), ptr addrspace(1) poison> +; + %c = addrspacecast nonnull <2 x ptr> <ptr null, ptr poison> to <2 x ptr addrspace(1)> + ret <2 x ptr addrspace(1)> %c +} + +; Without the nonnull flag the cast is not poison. +define ptr addrspace(1) @no_fold_without_flag() { +; CHECK-LABEL: @no_fold_without_flag( +; CHECK-NEXT: ret ptr addrspace(1) addrspacecast (ptr null to ptr addrspace(1)) +; + %c = addrspacecast ptr null to ptr addrspace(1) + ret ptr addrspace(1) %c +} + +; A non-null source is not folded. +define ptr addrspace(1) @no_fold_nonzero_src(ptr %p) { +; CHECK-LABEL: @no_fold_nonzero_src( +; CHECK-NEXT: [[C:%.*]] = addrspacecast nonnull ptr [[P:%.*]] to ptr addrspace(1) +; CHECK-NEXT: ret ptr addrspace(1) [[C]] +; + %c = addrspacecast nonnull ptr %p to ptr addrspace(1) + ret ptr addrspace(1) %c +} + +; The null value of a non-zero source address space is not necessarily the zero +; pointer, so casting it is not folded to poison. +define ptr @no_fold_src_as1() { +; CHECK-LABEL: @no_fold_src_as1( +; CHECK-NEXT: ret ptr addrspacecast (ptr addrspace(1) null to ptr) +; + %c = addrspacecast nonnull ptr addrspace(1) null to ptr + ret ptr %c +} + +; When null is a valid address for the function, the source may legitimately be +; the null pointer, so the fold does not apply. +define ptr addrspace(1) @no_fold_null_valid() #0 { +; CHECK-LABEL: @no_fold_null_valid( +; CHECK-NEXT: ret ptr addrspace(1) addrspacecast (ptr null to ptr addrspace(1)) +; + %c = addrspacecast nonnull ptr null to ptr addrspace(1) + ret ptr addrspace(1) %c +} + +attributes #0 = { null_pointer_is_valid } _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
