https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/133557
Fixes #131825 >From 9867ba4e47993357adf1f833f2ba816e277656fc Mon Sep 17 00:00:00 2001 From: Matt Arsenault <matthew.arsena...@amd.com> Date: Sat, 29 Mar 2025 09:32:55 +0700 Subject: [PATCH] llvm-reduce: Try to preserve instruction metadata as argument attributes Fixes #131825 --- llvm/include/llvm/IR/Attributes.h | 6 ++ llvm/lib/IR/Attributes.cpp | 32 ++++++++ ...operands-to-args-metadata-to-attributes.ll | 77 +++++++++++++++++++ .../deltas/ReduceOperandsToArgs.cpp | 11 ++- 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 llvm/test/tools/llvm-reduce/reduce-operands-to-args-metadata-to-attributes.ll diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h index d6533b9bcbea1..5252f26f398d2 100644 --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -42,6 +42,7 @@ class ConstantRangeList; class FoldingSetNodeID; class Function; class LLVMContext; +class Instruction; class Type; class raw_ostream; enum FPClassTest : unsigned; @@ -1285,6 +1286,11 @@ class AttrBuilder { /// Add initializes attribute. AttrBuilder &addInitializesAttr(const ConstantRangeList &CRL); + /// Add 0 or more parameter attributes which are equivalent to metadata + /// attached to \p I. e.g. !align -> align. This assumes the argument type is + /// the same as the original instruction and the attribute is compatible. + AttrBuilder &addFromEquivalentMetadata(const Instruction &I); + ArrayRef<Attribute> attrs() const { return Attrs; } bool operator==(const AttrBuilder &B) const; diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 8da1dfe914818..8cb8b0d927afd 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -2291,6 +2291,38 @@ AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) { return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef()); } +AttrBuilder &AttrBuilder::addFromEquivalentMetadata(const Instruction &I) { + if (const MDNode *NonNull = I.getMetadata(LLVMContext::MD_nonnull)) + addAttribute(Attribute::NonNull); + + if (const MDNode *NoUndef = I.getMetadata(LLVMContext::MD_noundef)) + addAttribute(Attribute::NoUndef); + + if (const MDNode *Align = I.getMetadata(LLVMContext::MD_align)) { + ConstantInt *CI = mdconst::extract<ConstantInt>(Align->getOperand(0)); + addAlignmentAttr(CI->getZExtValue()); + } + + if (const MDNode *Dereferenceable = + I.getMetadata(LLVMContext::MD_dereferenceable)) { + ConstantInt *CI = + mdconst::extract<ConstantInt>(Dereferenceable->getOperand(0)); + addDereferenceableAttr(CI->getZExtValue()); + } + + if (const MDNode *DereferenceableOrNull = + I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) { + ConstantInt *CI = + mdconst::extract<ConstantInt>(DereferenceableOrNull->getOperand(0)); + addDereferenceableAttr(CI->getZExtValue()); + } + + if (const MDNode *Range = I.getMetadata(LLVMContext::MD_range)) + addRangeAttr(getConstantRangeFromMetadata(*Range)); + + return *this; +} + AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { // TODO: Could make this O(n) as we're merging two sorted lists. for (const auto &I : B.attrs()) diff --git a/llvm/test/tools/llvm-reduce/reduce-operands-to-args-metadata-to-attributes.ll b/llvm/test/tools/llvm-reduce/reduce-operands-to-args-metadata-to-attributes.ll new file mode 100644 index 0000000000000..913ba9d3218fd --- /dev/null +++ b/llvm/test/tools/llvm-reduce/reduce-operands-to-args-metadata-to-attributes.ll @@ -0,0 +1,77 @@ +; Check that equivalent parameter attributes are introduced when +; moving instructions with metadata to arguments. + +; RUN: llvm-reduce %s -o %t --abort-on-invalid-reduction --delta-passes=operands-to-args --test FileCheck --test-arg %s --test-arg --check-prefix=INTERESTING --test-arg --input-file +; RUN: FileCheck --input-file %t --check-prefix=REDUCED %s + +; INTERESTING-LABEL: define ptr @use_nonnull( +; REDUCED-LABEL: define ptr @use_nonnull(ptr nonnull %nonnull) { +define ptr @use_nonnull() { + %nonnull = load ptr, ptr null, !nonnull !0 + ret ptr %nonnull +} + +; INTERESTING-LABEL: define void @use_noundef( +; REDUCED-LABEL: define void @use_noundef(ptr noundef %noundef, <2 x ptr> noundef %noundef_vec) { +define void @use_noundef() { + %noundef = load ptr, ptr null, !noundef !0 + %noundef_vec = load <2 x ptr>, ptr null, !noundef !0 + store ptr %noundef, ptr null + store <2 x ptr> %noundef_vec, ptr null + ret void +} + +; INTERESTING-LABEL: define ptr @use_align( +; REDUCED-LABEL: define ptr @use_align(ptr align 16 %align) { +define ptr @use_align() { + %align = load ptr, ptr null, !align !1 + ret ptr %align +} + +; INTERESTING-LABEL: define ptr @use_dereferenceable( +; REDUCED-LABEL: define ptr @use_dereferenceable(ptr dereferenceable(12345) %deref) { +define ptr @use_dereferenceable() { + %deref = load ptr, ptr null, !dereferenceable !2 + ret ptr %deref +} + +; INTERESTING-LABEL: define ptr @use_dereferenceable_or_null( +; REDUCED-LABEL: define ptr @use_dereferenceable_or_null(ptr dereferenceable(77777) %deref) { +define ptr @use_dereferenceable_or_null() { + %deref = load ptr, ptr null, !dereferenceable_or_null !3 + ret ptr %deref +} + +; INTERESTING-LABEL: define void @use_range( +; REDUCED-LABEL: define void @use_range(i32 range(i32 8, 25) %simple_range, i32 range(i32 8, 420) %disjoint_range, i32 range(i32 42, 0) %wrapping_range, <2 x i32> range(i32 8, 25) %vector_range) { +define void @use_range() { + %simple_range = load i32, ptr null, !range !4 + %disjoint_range = load i32, ptr null, !range !5 + %wrapping_range = load i32, ptr null, !range !6 + %vector_range = load <2 x i32>, ptr null, !range !4 + store i32 %simple_range, ptr null + store i32 %disjoint_range, ptr null + store i32 %wrapping_range, ptr null + store <2 x i32> %vector_range, ptr null + ret void +} + +; INTERESTING-LABEL: define void @use_noundef_range( +; REDUCED-LABEL: define void @use_noundef_range(i32 noundef range(i32 8, 25) %load, <2 x i32> noundef range(i32 8, 25) %load_vec) { +define void @use_noundef_range() { + %load = load i32, ptr null, !range !4, !noundef !0 + %load_vec = load <2 x i32>, ptr null, !range !4, !noundef !0 + store i32 %load, ptr null + store <2 x i32> %load_vec, ptr null + ret void +} + + + +!0 = !{} +!1 = !{i64 16} +!2 = !{i64 12345} +!3 = !{i64 77777} +!4 = !{i32 8, i32 25} +!5 = !{i32 8, i32 25, i32 69, i32 420} +!6 = !{i32 42, i32 0} diff --git a/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp b/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp index 6b1958e24c932..a652f892414df 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp @@ -160,6 +160,8 @@ static void substituteOperandWithArgument(Function *OldF, VMap[&OldArg] = &NewArg; // Add mapping to VMap } + LLVMContext &Ctx = OldF->getContext(); + // Adjust the new parameters. ValueToValueMapTy OldValMap; for (auto Z : zip_first(UniqueValues, drop_begin(NewF->args(), ArgOffset))) { @@ -176,9 +178,16 @@ static void substituteOperandWithArgument(Function *OldF, // Replace the actual operands. for (Use *Op : OpsToReplace) { - Value *NewArg = OldValMap.lookup(Op->get()); + Argument *NewArg = cast<Argument>(OldValMap.lookup(Op->get())); auto *NewUser = cast<Instruction>(VMap.lookup(Op->getUser())); + // Try to preserve any information contained metadata annotations as the + // equivalent parameter attributes if possible. + if (auto *MDSrcInst = dyn_cast<Instruction>(Op)) { + AttrBuilder AB(Ctx); + NewArg->addAttrs(AB.addFromEquivalentMetadata(*MDSrcInst)); + } + if (PHINode *NewPhi = dyn_cast<PHINode>(NewUser)) { PHINode *OldPhi = cast<PHINode>(Op->getUser()); BasicBlock *OldBB = OldPhi->getIncomingBlock(*Op); _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits