Skip to content

llvm-reduce: Try to preserve instruction metadata as argument attributes #133557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions llvm/include/llvm/IR/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class ConstantRangeList;
class FoldingSetNodeID;
class Function;
class LLVMContext;
class Instruction;
class Type;
class raw_ostream;
enum FPClassTest : unsigned;
Expand Down Expand Up @@ -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;
Expand Down
32 changes: 32 additions & 0 deletions llvm/lib/IR/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
Original file line number Diff line number Diff line change
@@ -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}
11 changes: 10 additions & 1 deletion llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,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))) {
Expand All @@ -175,9 +177,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);
Expand Down
Loading