llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-ir Author: Matt Arsenault (arsenm) <details> <summary>Changes</summary> Teach the flag-propagation controls about the nonnull flag on addrspacecast. Co-authored-by: Claude (Claude-Opus-4.8) <noreply@<!-- -->anthropic.com> --- Full diff: https://github.com/llvm/llvm-project/pull/217904.diff 5 Files Affected: - (modified) llvm/lib/IR/Instruction.cpp (+20) - (modified) llvm/lib/IR/Operator.cpp (+4) - (modified) llvm/test/Transforms/EarlyCSE/flags.ll (+44) - (modified) llvm/test/Transforms/SimplifyCFG/HoistCode.ll (+30) - (modified) llvm/unittests/IR/InstructionsTest.cpp (+21) ``````````diff diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 1ac5bd6b636d1..6db2ba780ca65 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -475,6 +475,10 @@ void Instruction::dropPoisonGeneratingFlags() { cast<ICmpInst>(this)->setSameSign(false); break; + case Instruction::AddrSpaceCast: + cast<AddrSpaceCastInst>(this)->setNonNull(false); + break; + case Instruction::Call: { if (auto *II = dyn_cast<IntrinsicInst>(this)) { switch (II->getIntrinsicID()) { @@ -766,6 +770,14 @@ void Instruction::copyIRFlags(const Value *V, bool IncludeWrapFlags) { if (auto *SrcICmp = dyn_cast<ICmpInst>(V)) if (auto *DestICmp = dyn_cast<ICmpInst>(this)) DestICmp->setSameSign(SrcICmp->hasSameSign()); + + if (auto *SrcASC = dyn_cast<AddrSpaceCastInst>(V)) + if (auto *DestASC = dyn_cast<AddrSpaceCastInst>(this)) { + assert(DestASC->getSrcAddressSpace() == SrcASC->getSrcAddressSpace() && + "nonull flag cannot be safely preserved with different source " + "address spaces"); + DestASC->setNonNull(SrcASC->hasNonNull()); + } } void Instruction::andIRFlags(const Value *V) { @@ -811,6 +823,14 @@ void Instruction::andIRFlags(const Value *V) { if (auto *SrcICmp = dyn_cast<ICmpInst>(V)) if (auto *DestICmp = dyn_cast<ICmpInst>(this)) DestICmp->setSameSign(DestICmp->hasSameSign() && SrcICmp->hasSameSign()); + + if (auto *SrcASC = dyn_cast<AddrSpaceCastInst>(V)) + if (auto *DestASC = dyn_cast<AddrSpaceCastInst>(this)) { + assert(DestASC->getSrcAddressSpace() == SrcASC->getSrcAddressSpace() && + "nonull flag cannot be safely preserved with different source " + "address spaces"); + DestASC->setNonNull(DestASC->hasNonNull() && SrcASC->hasNonNull()); + } } const char *Instruction::getOpcodeName(unsigned OpCode) { diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp index 09a719b0f440f..b453b65063595 100644 --- a/llvm/lib/IR/Operator.cpp +++ b/llvm/lib/IR/Operator.cpp @@ -54,6 +54,10 @@ bool Operator::hasPoisonGeneratingFlags() const { return false; case Instruction::ICmp: return cast<ICmpInst>(this)->hasSameSign(); + case Instruction::AddrSpaceCast: + if (auto *ASC = dyn_cast<AddrSpaceCastInst>(this)) + return ASC->hasNonNull(); + return false; case Instruction::Call: if (auto *II = dyn_cast<IntrinsicInst>(this)) { switch (II->getIntrinsicID()) { diff --git a/llvm/test/Transforms/EarlyCSE/flags.ll b/llvm/test/Transforms/EarlyCSE/flags.ll index dcaaacbac639f..ef1ba3792dce3 100644 --- a/llvm/test/Transforms/EarlyCSE/flags.ll +++ b/llvm/test/Transforms/EarlyCSE/flags.ll @@ -112,3 +112,47 @@ define i32 @load_undef_noundef(ptr %p) { %v = load i32, ptr %p, !noundef !{} ret i32 %v } + +define void @addrspacecast_both_nonnull(ptr addrspace(1) %p) { +; CHECK-LABEL: @addrspacecast_both_nonnull( +; CHECK-NEXT: [[C1:%.*]] = addrspacecast nonnull ptr addrspace(1) [[P:%.*]] to ptr +; CHECK-NEXT: call void @use.ptr(i32 0, ptr [[C1]]) +; CHECK-NEXT: call void @use.ptr(i32 1, ptr [[C1]]) +; CHECK-NEXT: ret void +; + %c1 = addrspacecast nonnull ptr addrspace(1) %p to ptr + call void @use.ptr(i32 0, ptr %c1) + %c2 = addrspacecast nonnull ptr addrspace(1) %p to ptr + call void @use.ptr(i32 1, ptr %c2) + ret void +} + +define void @addrspacecast_first_nonnull(ptr addrspace(1) %p) { +; CHECK-LABEL: @addrspacecast_first_nonnull( +; CHECK-NEXT: [[C1:%.*]] = addrspacecast ptr addrspace(1) [[P:%.*]] to ptr +; CHECK-NEXT: call void @use.ptr(i32 0, ptr [[C1]]) +; CHECK-NEXT: call void @use.ptr(i32 1, ptr [[C1]]) +; CHECK-NEXT: ret void +; + %c1 = addrspacecast nonnull ptr addrspace(1) %p to ptr + call void @use.ptr(i32 0, ptr %c1) + %c2 = addrspacecast ptr addrspace(1) %p to ptr + call void @use.ptr(i32 1, ptr %c2) + ret void +} + +define void @addrspacecast_vector_first_nonnull(<2 x ptr addrspace(1)> %p) { +; CHECK-LABEL: @addrspacecast_vector_first_nonnull( +; CHECK-NEXT: [[C1:%.*]] = addrspacecast <2 x ptr addrspace(1)> [[P:%.*]] to <2 x ptr> +; CHECK-NEXT: call void @use.vec(i32 0, <2 x ptr> [[C1]]) +; CHECK-NEXT: call void @use.vec(i32 1, <2 x ptr> [[C1]]) +; CHECK-NEXT: ret void +; + %c1 = addrspacecast nonnull <2 x ptr addrspace(1)> %p to <2 x ptr> + call void @use.vec(i32 0, <2 x ptr> %c1) + %c2 = addrspacecast <2 x ptr addrspace(1)> %p to <2 x ptr> + call void @use.vec(i32 1, <2 x ptr> %c2) + ret void +} + +declare void @use.vec(i32, <2 x ptr>) memory(read) diff --git a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll index f17652cc5e471..5d2bc55652d59 100644 --- a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll +++ b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll @@ -214,6 +214,36 @@ F: ret i16 %z2 } +define ptr @hoist_addrspacecast_flags_preserve(i1 %C, ptr addrspace(1) %p) { +; CHECK-LABEL: @hoist_addrspacecast_flags_preserve( +; CHECK-NEXT: common.ret: +; CHECK-NEXT: [[Z1:%.*]] = addrspacecast nonnull ptr addrspace(1) [[P:%.*]] to ptr +; CHECK-NEXT: ret ptr [[Z1]] +; + br i1 %C, label %T, label %F +T: + %z1 = addrspacecast nonnull ptr addrspace(1) %p to ptr + ret ptr %z1 +F: + %z2 = addrspacecast nonnull ptr addrspace(1) %p to ptr + ret ptr %z2 +} + +define ptr @hoist_addrspacecast_flags_drop(i1 %C, ptr addrspace(1) %p) { +; CHECK-LABEL: @hoist_addrspacecast_flags_drop( +; CHECK-NEXT: common.ret: +; CHECK-NEXT: [[Z1:%.*]] = addrspacecast ptr addrspace(1) [[P:%.*]] to ptr +; CHECK-NEXT: ret ptr [[Z1]] +; + br i1 %C, label %T, label %F +T: + %z1 = addrspacecast ptr addrspace(1) %p to ptr + ret ptr %z1 +F: + %z2 = addrspacecast nonnull ptr addrspace(1) %p to ptr + ret ptr %z2 +} + define ptr @hoist_gep_flags_both_nuw(i1 %C, ptr %p) { ; CHECK-LABEL: @hoist_gep_flags_both_nuw( ; CHECK-NEXT: common.ret: diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp index 6f8dc6a0b9f6f..da17c61608773 100644 --- a/llvm/unittests/IR/InstructionsTest.cpp +++ b/llvm/unittests/IR/InstructionsTest.cpp @@ -861,6 +861,27 @@ TEST_F(ModuleWithFunctionTest, DropPoisonGeneratingFlags) { GI->dropPoisonGeneratingFlags(); ASSERT_FALSE(GI->isInBounds()); } + + { + Value *Ptr = B.CreateIntToPtr(Arg0, B.getPtrTy(1)); + auto *ASC = cast<AddrSpaceCastInst>( + B.CreateAddrSpaceCast(Ptr, B.getPtrTy(), "", /*IsNonNull*/ true)); + EXPECT_TRUE(ASC->hasNonNull()); + EXPECT_TRUE(ASC->hasPoisonGeneratingFlags()); + ASC->dropPoisonGeneratingFlags(); + EXPECT_FALSE(ASC->hasNonNull()); + EXPECT_FALSE(ASC->hasPoisonGeneratingFlags()); + } + + { + // A ConstantExpr addrspacecast is an Operator but not an + // AddrSpaceCastInst; hasPoisonGeneratingFlags() must not assume the + // instruction subclass. + Constant *NullPtr = Constant::getNullValue(B.getPtrTy(1)); + auto *CE = + cast<Operator>(ConstantExpr::getAddrSpaceCast(NullPtr, B.getPtrTy())); + EXPECT_FALSE(CE->hasPoisonGeneratingFlags()); + } } TEST(InstructionsTest, GEPIndices) { `````````` </details> https://github.com/llvm/llvm-project/pull/217904 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
