Skip to content

Commit

Permalink
[AttributeSet] Overload AttributeSet::addAttribute to reduce compile
Browse files Browse the repository at this point in the history
time.

The new overloaded function is used when an attribute is added to a
large number of slots of an AttributeSet (for example, to function
parameters). This is much faster than calling AttributeSet::addAttribute
once per slot, because AttributeSet::getImpl (which calls
FoldingSet::FIndNodeOrInsertPos) is called only once per function
instead of once per slot.

With this commit, clang compiles a file which used to take over 22
minutes in just 13 seconds.

rdar://problem/23581000

Differential Revision: http://reviews.llvm.org/D15085

llvm-svn: 254491
  • Loading branch information
ahatanaka committed Dec 2, 2015
1 parent f419a1f commit 237916b
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 17 deletions.
5 changes: 5 additions & 0 deletions llvm/include/llvm/IR/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ class AttributeSet {
AttributeSet addAttribute(LLVMContext &C, unsigned Index,
StringRef Kind, StringRef Value) const;

/// Add an attribute to the attribute set at the given indices. Because
/// attribute sets are immutable, this returns a new set.
AttributeSet addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices,
Attribute A) const;

/// \brief Add attributes to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
AttributeSet addAttributes(LLVMContext &C, unsigned Index,
Expand Down
30 changes: 30 additions & 0 deletions llvm/lib/IR/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,36 @@ AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index,
return addAttributes(C, Index, AttributeSet::get(C, Index, B));
}

AttributeSet AttributeSet::addAttribute(LLVMContext &C,
ArrayRef<unsigned> Indices,
Attribute A) const {
unsigned I = 0, E = pImpl ? pImpl->getNumAttributes() : 0;
auto IdxI = Indices.begin(), IdxE = Indices.end();
SmallVector<AttributeSet, 4> AttrSet;

while (I != E && IdxI != IdxE) {
if (getSlotIndex(I) < *IdxI)
AttrSet.emplace_back(getSlotAttributes(I++));
else if (getSlotIndex(I) > *IdxI)
AttrSet.emplace_back(AttributeSet::get(C, std::make_pair(*IdxI++, A)));
else {
AttrBuilder B(getSlotAttributes(I), *IdxI);
B.addAttribute(A);
AttrSet.emplace_back(AttributeSet::get(C, *IdxI, B));
++I;
++IdxI;
}
}

while (I != E)
AttrSet.emplace_back(getSlotAttributes(I++));

while (IdxI != IdxE)
AttrSet.emplace_back(AttributeSet::get(C, std::make_pair(*IdxI++, A)));

return get(C, AttrSet);
}

AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index,
AttributeSet Attrs) const {
if (!pImpl) return Attrs;
Expand Down
21 changes: 14 additions & 7 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1942,20 +1942,27 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) {
// Mark any parameters that are known to be non-null with the nonnull
// attribute. This is helpful for inlining calls to functions with null
// checks on their arguments.
SmallVector<unsigned, 4> Indices;
unsigned ArgNo = 0;

for (Value *V : CS.args()) {
if (V->getType()->isPointerTy() && !CS.paramHasAttr(ArgNo+1, Attribute::NonNull) &&
isKnownNonNullAt(V, CS.getInstruction(), DT, TLI)) {
AttributeSet AS = CS.getAttributes();
AS = AS.addAttribute(CS.getInstruction()->getContext(), ArgNo+1,
Attribute::NonNull);
CS.setAttributes(AS);
Changed = true;
}
isKnownNonNullAt(V, CS.getInstruction(), DT, TLI))
Indices.push_back(ArgNo + 1);
ArgNo++;
}

assert(ArgNo == CS.arg_size() && "sanity check");

if (!Indices.empty()) {
AttributeSet AS = CS.getAttributes();
LLVMContext &Ctx = CS.getInstruction()->getContext();
AS = AS.addAttribute(Ctx, Indices,
Attribute::get(Ctx, Attribute::NonNull));
CS.setAttributes(AS);
Changed = true;
}

// If the callee is a pointer to a function, attempt to move any casts to the
// arguments of the call/invoke.
Value *Callee = CS.getCalledValue();
Expand Down
24 changes: 14 additions & 10 deletions llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,27 +307,31 @@ bool CorrelatedValuePropagation::processSwitch(SwitchInst *SI) {
/// processCallSite - Infer nonnull attributes for the arguments at the
/// specified callsite.
bool CorrelatedValuePropagation::processCallSite(CallSite CS) {
bool Changed = false;

SmallVector<unsigned, 4> Indices;
unsigned ArgNo = 0;

for (Value *V : CS.args()) {
PointerType *Type = dyn_cast<PointerType>(V->getType());

if (Type && !CS.paramHasAttr(ArgNo + 1, Attribute::NonNull) &&
LVI->getPredicateAt(ICmpInst::ICMP_EQ, V,
ConstantPointerNull::get(Type),
CS.getInstruction()) == LazyValueInfo::False) {
AttributeSet AS = CS.getAttributes();
AS = AS.addAttribute(CS.getInstruction()->getContext(), ArgNo + 1,
Attribute::NonNull);
CS.setAttributes(AS);
Changed = true;
}
CS.getInstruction()) == LazyValueInfo::False)
Indices.push_back(ArgNo + 1);
ArgNo++;
}

assert(ArgNo == CS.arg_size() && "sanity check");

return Changed;
if (Indices.empty())
return false;

AttributeSet AS = CS.getAttributes();
LLVMContext &Ctx = CS.getInstruction()->getContext();
AS = AS.addAttribute(Ctx, Indices, Attribute::get(Ctx, Attribute::NonNull));
CS.setAttributes(AS);

return true;
}

Constant *CorrelatedValuePropagation::getConstantAt(Value *V, Instruction *At) {
Expand Down

0 comments on commit 237916b

Please sign in to comment.