Skip to content

Commit da61cb0

Browse files
committed
[Attributes] Make attribute addition behavior consistent
Currently, the behavior when adding an attribute with the same key as an existing attribute is inconsistent, depending on the type of the attribute and the method used to add it. When going through AttrBuilder::addAttribute(), the new attribute always overwrites the old one. When going through AttrBuilder::merge() the new attribute overwrites the existing one if it is a string attribute, but keeps the existing one for int and type attributes. One particular API also asserts that you can't overwrite an align attribute, but does not handle any of the other int, type or string attributes. This patch makes the behavior consistent by always overwriting with the new attribute, which is the behavior I would intuitively expect. Two tests are affected, which now make a different (but equally valid) choice. Those tests could be improved by taking the maximum deref bytes, but I haven't bothered with that, since this is testing a degenerate case -- the important bit is that it doesn't crash. Differential Revision: https://reviews.llvm.org/D117552
1 parent d544a89 commit da61cb0

File tree

4 files changed

+10
-21
lines changed

4 files changed

+10
-21
lines changed

llvm/include/llvm/IR/Attributes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,8 @@ class AttrBuilder {
10481048
return removeAttribute(A.getKindAsEnum());
10491049
}
10501050

1051-
/// Add the attributes from the builder.
1051+
/// Add the attributes from the builder. Attributes in the passed builder
1052+
/// overwrite attributes in this builder if they have the same key.
10521053
AttrBuilder &merge(const AttrBuilder &B);
10531054

10541055
/// Remove the attributes from the builder.

llvm/lib/IR/Attributes.cpp

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -627,11 +627,9 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C,
627627
if (!AS.hasAttributes())
628628
return *this;
629629

630-
AttrBuilder B(C, AS);
631-
for (const auto &I : *this)
632-
B.addAttribute(I);
633-
634-
return get(C, B);
630+
AttrBuilder B(C, *this);
631+
B.merge(AttrBuilder(C, AS));
632+
return get(C, B);
635633
}
636634

637635
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
@@ -1250,15 +1248,6 @@ AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
12501248
if (!pImpl)
12511249
return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
12521250

1253-
#ifndef NDEBUG
1254-
// FIXME it is not obvious how this should work for alignment. For now, say
1255-
// we can't change a known alignment.
1256-
const MaybeAlign OldAlign = getAttributes(Index).getAlignment();
1257-
const MaybeAlign NewAlign = B.getAlignment();
1258-
assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
1259-
"Attempt to change alignment!");
1260-
#endif
1261-
12621251
AttrBuilder Merged(C, getAttributes(Index));
12631252
Merged.merge(B);
12641253
return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
@@ -1744,13 +1733,12 @@ AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
17441733
}
17451734

17461735
AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1747-
// FIXME: What if both have an int/type attribute, but they don't match?!
17481736
for (unsigned Index = 0; Index < Attribute::NumIntAttrKinds; ++Index)
1749-
if (!IntAttrs[Index])
1737+
if (B.IntAttrs[Index])
17501738
IntAttrs[Index] = B.IntAttrs[Index];
17511739

17521740
for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index)
1753-
if (!TypeAttrs[Index])
1741+
if (B.TypeAttrs[Index])
17541742
TypeAttrs[Index] = B.TypeAttrs[Index];
17551743

17561744
Attrs |= B.Attrs;

llvm/test/Transforms/Inline/ret_attr_update.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ define i8* @test5(i8* %ptr, i64 %x) {
142142

143143
; deref attributes have different values on the callee and the call feeding into
144144
; the return.
145-
; AttrBuilder chooses the already existing value and does not overwrite it.
145+
; AttrBuilder overwrites the existing value.
146146
define internal i8* @callee6(i8* %p) alwaysinline {
147147
%r = call dereferenceable_or_null(16) i8* @foo(i8* %p)
148148
%v = call i8* @baz(i8* %p)
@@ -153,7 +153,7 @@ define internal i8* @callee6(i8* %p) alwaysinline {
153153
define i8* @test6(i8* %ptr, i64 %x) {
154154
; CHECK-LABEL: @test6(
155155
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 [[X:%.*]]
156-
; CHECK-NEXT: [[R_I:%.*]] = call dereferenceable_or_null(16) i8* @foo(i8* [[GEP]])
156+
; CHECK-NEXT: [[R_I:%.*]] = call dereferenceable_or_null(12) i8* @foo(i8* [[GEP]])
157157
; CHECK-NEXT: [[V_I:%.*]] = call i8* @baz(i8* [[GEP]])
158158
; CHECK-NEXT: ret i8* [[R_I]]
159159
;

llvm/test/Transforms/InstCombine/deref-alloc-fns.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ define noalias i8* @memalign_unknown_align(i64 %align) {
134134

135135
define noalias i8* @malloc_constant_size2() {
136136
; CHECK-LABEL: @malloc_constant_size2(
137-
; CHECK-NEXT: [[CALL:%.*]] = tail call noalias dereferenceable_or_null(80) i8* @malloc(i64 40)
137+
; CHECK-NEXT: [[CALL:%.*]] = tail call noalias dereferenceable_or_null(40) i8* @malloc(i64 40)
138138
; CHECK-NEXT: ret i8* [[CALL]]
139139
;
140140
%call = tail call noalias dereferenceable_or_null(80) i8* @malloc(i64 40)

0 commit comments

Comments
 (0)