2017-02-17 01:00:09 +01:00
|
|
|
//===- Attributes.cpp - Implement AttributesList --------------------------===//
|
2008-01-03 00:42:30 +01:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2013-01-28 22:55:20 +01:00
|
|
|
// \file
|
2018-05-01 17:54:18 +02:00
|
|
|
// This file implements the Attribute, AttributeImpl, AttrBuilder,
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
// AttributeListImpl, and AttributeList classes.
|
2008-01-03 00:42:30 +01:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 13:49:48 +02:00
|
|
|
#include "llvm/IR/Attributes.h"
|
2012-12-20 02:36:59 +01:00
|
|
|
#include "AttributeImpl.h"
|
2012-09-26 23:07:29 +02:00
|
|
|
#include "LLVMContextImpl.h"
|
2017-02-17 01:00:09 +01:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
|
|
#include "llvm/ADT/Optional.h"
|
2014-04-12 18:15:53 +02:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2017-06-06 13:49:48 +02:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2017-02-17 01:00:09 +01:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
2018-04-30 16:59:11 +02:00
|
|
|
#include "llvm/Config/llvm-config.h"
|
2017-02-17 01:00:09 +01:00
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/Type.h"
|
2017-02-17 01:00:09 +01:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2010-01-05 02:29:58 +01:00
|
|
|
#include "llvm/Support/Debug.h"
|
2017-02-17 01:00:09 +01:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/MathExtras.h"
|
2009-08-23 13:37:21 +02:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2013-01-24 01:06:56 +01:00
|
|
|
#include <algorithm>
|
2017-02-17 01:00:09 +01:00
|
|
|
#include <cassert>
|
2017-05-15 23:57:41 +02:00
|
|
|
#include <climits>
|
|
|
|
#include <cstddef>
|
2017-02-17 01:00:09 +01:00
|
|
|
#include <cstdint>
|
|
|
|
#include <limits>
|
|
|
|
#include <string>
|
|
|
|
#include <tuple>
|
|
|
|
#include <utility>
|
|
|
|
|
2008-01-03 00:42:30 +01:00
|
|
|
using namespace llvm;
|
|
|
|
|
2008-03-12 18:45:29 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
2013-01-29 01:48:16 +01:00
|
|
|
// Attribute Construction Methods
|
2008-03-12 18:45:29 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
2008-01-14 20:52:09 +01:00
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
// allocsize has two integer arguments, but because they're both 32 bits, we can
|
|
|
|
// pack them into one 64-bit value, at the cost of making said value
|
|
|
|
// nonsensical.
|
|
|
|
//
|
|
|
|
// In order to do this, we need to reserve one value of the second (optional)
|
|
|
|
// allocsize argument to signify "not present."
|
2016-08-25 03:05:08 +02:00
|
|
|
static const unsigned AllocSizeNumElemsNotPresent = -1;
|
2016-04-12 03:05:35 +02:00
|
|
|
|
|
|
|
static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
|
|
|
|
const Optional<unsigned> &NumElemsArg) {
|
|
|
|
assert((!NumElemsArg.hasValue() ||
|
|
|
|
*NumElemsArg != AllocSizeNumElemsNotPresent) &&
|
|
|
|
"Attempting to pack a reserved value");
|
|
|
|
|
|
|
|
return uint64_t(ElemSizeArg) << 32 |
|
|
|
|
NumElemsArg.getValueOr(AllocSizeNumElemsNotPresent);
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::pair<unsigned, Optional<unsigned>>
|
|
|
|
unpackAllocSizeArgs(uint64_t Num) {
|
|
|
|
unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
|
|
|
|
unsigned ElemSizeArg = Num >> 32;
|
|
|
|
|
|
|
|
Optional<unsigned> NumElemsArg;
|
|
|
|
if (NumElems != AllocSizeNumElemsNotPresent)
|
|
|
|
NumElemsArg = NumElems;
|
|
|
|
return std::make_pair(ElemSizeArg, NumElemsArg);
|
|
|
|
}
|
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
|
|
|
|
uint64_t Val) {
|
2012-10-08 23:47:17 +02:00
|
|
|
LLVMContextImpl *pImpl = Context.pImpl;
|
|
|
|
FoldingSetNodeID ID;
|
2013-02-05 23:37:24 +01:00
|
|
|
ID.AddInteger(Kind);
|
2014-09-04 01:38:05 +02:00
|
|
|
if (Val) ID.AddInteger(Val);
|
2012-10-08 23:47:17 +02:00
|
|
|
|
|
|
|
void *InsertPoint;
|
2012-12-20 02:36:59 +01:00
|
|
|
AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
|
2012-10-08 23:47:17 +02:00
|
|
|
|
|
|
|
if (!PA) {
|
|
|
|
// If we didn't find any existing attributes of the same shape then create a
|
|
|
|
// new one and insert it.
|
2014-09-04 01:38:05 +02:00
|
|
|
if (!Val)
|
|
|
|
PA = new EnumAttributeImpl(Kind);
|
|
|
|
else
|
|
|
|
PA = new IntAttributeImpl(Kind, Val);
|
2012-10-08 23:47:17 +02:00
|
|
|
pImpl->AttrsSet.InsertNode(PA, InsertPoint);
|
|
|
|
}
|
|
|
|
|
2013-02-05 09:09:32 +01:00
|
|
|
// Return the Attribute that we found or created.
|
2012-12-19 08:18:57 +01:00
|
|
|
return Attribute(PA);
|
2012-10-08 23:47:17 +02:00
|
|
|
}
|
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
|
|
|
|
LLVMContextImpl *pImpl = Context.pImpl;
|
|
|
|
FoldingSetNodeID ID;
|
|
|
|
ID.AddString(Kind);
|
|
|
|
if (!Val.empty()) ID.AddString(Val);
|
|
|
|
|
|
|
|
void *InsertPoint;
|
|
|
|
AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
|
|
|
|
|
|
|
|
if (!PA) {
|
|
|
|
// If we didn't find any existing attributes of the same shape then create a
|
|
|
|
// new one and insert it.
|
2013-07-11 14:13:16 +02:00
|
|
|
PA = new StringAttributeImpl(Kind, Val);
|
2013-02-05 23:37:24 +01:00
|
|
|
pImpl->AttrsSet.InsertNode(PA, InsertPoint);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the Attribute that we found or created.
|
|
|
|
return Attribute(PA);
|
2013-02-01 00:16:25 +01:00
|
|
|
}
|
|
|
|
|
2013-01-27 23:43:04 +01:00
|
|
|
Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) {
|
2013-02-01 00:16:25 +01:00
|
|
|
assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
|
|
|
|
assert(Align <= 0x40000000 && "Alignment too large.");
|
2013-02-05 23:37:24 +01:00
|
|
|
return get(Context, Alignment, Align);
|
2013-01-27 23:43:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Attribute Attribute::getWithStackAlignment(LLVMContext &Context,
|
|
|
|
uint64_t Align) {
|
2013-02-01 00:16:25 +01:00
|
|
|
assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
|
|
|
|
assert(Align <= 0x100 && "Alignment too large.");
|
2013-02-05 23:37:24 +01:00
|
|
|
return get(Context, StackAlignment, Align);
|
2013-01-27 23:43:04 +01:00
|
|
|
}
|
|
|
|
|
2014-07-18 17:51:28 +02:00
|
|
|
Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
|
|
|
|
uint64_t Bytes) {
|
|
|
|
assert(Bytes && "Bytes must be non-zero.");
|
|
|
|
return get(Context, Dereferenceable, Bytes);
|
|
|
|
}
|
|
|
|
|
2015-04-16 22:29:50 +02:00
|
|
|
Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
|
|
|
|
uint64_t Bytes) {
|
|
|
|
assert(Bytes && "Bytes must be non-zero.");
|
|
|
|
return get(Context, DereferenceableOrNull, Bytes);
|
|
|
|
}
|
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
Attribute
|
|
|
|
Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
|
|
|
|
const Optional<unsigned> &NumElemsArg) {
|
|
|
|
assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
|
|
|
|
"Invalid allocsize arguments -- given allocsize(0, 0)");
|
|
|
|
return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
|
|
|
|
}
|
|
|
|
|
2013-01-29 01:48:16 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Attribute Accessor Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
bool Attribute::isEnumAttribute() const {
|
|
|
|
return pImpl && pImpl->isEnumAttribute();
|
2012-10-05 08:44:41 +02:00
|
|
|
}
|
|
|
|
|
2014-07-18 08:51:55 +02:00
|
|
|
bool Attribute::isIntAttribute() const {
|
|
|
|
return pImpl && pImpl->isIntAttribute();
|
2013-01-29 21:45:34 +01:00
|
|
|
}
|
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
bool Attribute::isStringAttribute() const {
|
|
|
|
return pImpl && pImpl->isStringAttribute();
|
|
|
|
}
|
|
|
|
|
|
|
|
Attribute::AttrKind Attribute::getKindAsEnum() const {
|
2013-07-25 02:34:29 +02:00
|
|
|
if (!pImpl) return None;
|
2014-07-18 08:51:55 +02:00
|
|
|
assert((isEnumAttribute() || isIntAttribute()) &&
|
2013-02-05 23:37:24 +01:00
|
|
|
"Invalid attribute type to get the kind as an enum!");
|
2015-12-16 06:21:02 +01:00
|
|
|
return pImpl->getKindAsEnum();
|
2013-02-05 23:37:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t Attribute::getValueAsInt() const {
|
2013-07-25 02:34:29 +02:00
|
|
|
if (!pImpl) return 0;
|
2014-07-18 08:51:55 +02:00
|
|
|
assert(isIntAttribute() &&
|
|
|
|
"Expected the attribute to be an integer attribute!");
|
2015-12-16 06:21:02 +01:00
|
|
|
return pImpl->getValueAsInt();
|
2013-02-05 23:37:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
StringRef Attribute::getKindAsString() const {
|
2018-03-30 02:47:31 +02:00
|
|
|
if (!pImpl) return {};
|
2013-02-05 23:37:24 +01:00
|
|
|
assert(isStringAttribute() &&
|
|
|
|
"Invalid attribute type to get the kind as a string!");
|
2015-12-16 06:21:02 +01:00
|
|
|
return pImpl->getKindAsString();
|
2013-02-05 23:37:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
StringRef Attribute::getValueAsString() const {
|
2018-03-30 02:47:31 +02:00
|
|
|
if (!pImpl) return {};
|
2013-02-05 23:37:24 +01:00
|
|
|
assert(isStringAttribute() &&
|
|
|
|
"Invalid attribute type to get the value as a string!");
|
2015-12-16 06:21:02 +01:00
|
|
|
return pImpl->getValueAsString();
|
2013-02-05 23:37:24 +01:00
|
|
|
}
|
|
|
|
|
2013-02-06 00:48:36 +01:00
|
|
|
bool Attribute::hasAttribute(AttrKind Kind) const {
|
|
|
|
return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Attribute::hasAttribute(StringRef Kind) const {
|
|
|
|
if (!isStringAttribute()) return false;
|
|
|
|
return pImpl && pImpl->hasAttribute(Kind);
|
2013-01-29 21:45:34 +01:00
|
|
|
}
|
|
|
|
|
2012-12-19 08:18:57 +01:00
|
|
|
unsigned Attribute::getAlignment() const {
|
2013-02-01 02:04:27 +01:00
|
|
|
assert(hasAttribute(Attribute::Alignment) &&
|
|
|
|
"Trying to get alignment from non-alignment attribute!");
|
2013-02-05 23:37:24 +01:00
|
|
|
return pImpl->getValueAsInt();
|
2012-10-05 08:44:41 +02:00
|
|
|
}
|
|
|
|
|
2012-12-19 08:18:57 +01:00
|
|
|
unsigned Attribute::getStackAlignment() const {
|
2013-02-01 02:04:27 +01:00
|
|
|
assert(hasAttribute(Attribute::StackAlignment) &&
|
|
|
|
"Trying to get alignment from non-alignment attribute!");
|
2013-02-05 23:37:24 +01:00
|
|
|
return pImpl->getValueAsInt();
|
2012-10-05 08:44:41 +02:00
|
|
|
}
|
|
|
|
|
2014-07-18 17:51:28 +02:00
|
|
|
uint64_t Attribute::getDereferenceableBytes() const {
|
|
|
|
assert(hasAttribute(Attribute::Dereferenceable) &&
|
|
|
|
"Trying to get dereferenceable bytes from "
|
|
|
|
"non-dereferenceable attribute!");
|
|
|
|
return pImpl->getValueAsInt();
|
|
|
|
}
|
|
|
|
|
2015-04-16 22:29:50 +02:00
|
|
|
uint64_t Attribute::getDereferenceableOrNullBytes() const {
|
|
|
|
assert(hasAttribute(Attribute::DereferenceableOrNull) &&
|
|
|
|
"Trying to get dereferenceable bytes from "
|
|
|
|
"non-dereferenceable attribute!");
|
|
|
|
return pImpl->getValueAsInt();
|
|
|
|
}
|
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
|
|
|
|
assert(hasAttribute(Attribute::AllocSize) &&
|
|
|
|
"Trying to get allocsize args from non-allocsize attribute");
|
|
|
|
return unpackAllocSizeArgs(pImpl->getValueAsInt());
|
|
|
|
}
|
|
|
|
|
2013-02-11 09:43:33 +01:00
|
|
|
std::string Attribute::getAsString(bool InAttrGrp) const {
|
2018-03-30 02:47:31 +02:00
|
|
|
if (!pImpl) return {};
|
2013-01-31 21:59:05 +01:00
|
|
|
|
2013-02-26 07:58:09 +01:00
|
|
|
if (hasAttribute(Attribute::SanitizeAddress))
|
|
|
|
return "sanitize_address";
|
2017-12-09 01:21:41 +01:00
|
|
|
if (hasAttribute(Attribute::SanitizeHWAddress))
|
|
|
|
return "sanitize_hwaddress";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::AlwaysInline))
|
|
|
|
return "alwaysinline";
|
2015-07-11 12:30:36 +02:00
|
|
|
if (hasAttribute(Attribute::ArgMemOnly))
|
|
|
|
return "argmemonly";
|
2013-06-27 02:25:01 +02:00
|
|
|
if (hasAttribute(Attribute::Builtin))
|
|
|
|
return "builtin";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::ByVal))
|
|
|
|
return "byval";
|
2015-05-27 01:48:40 +02:00
|
|
|
if (hasAttribute(Attribute::Convergent))
|
|
|
|
return "convergent";
|
2016-04-01 23:41:15 +02:00
|
|
|
if (hasAttribute(Attribute::SwiftError))
|
|
|
|
return "swifterror";
|
2016-03-29 19:37:21 +02:00
|
|
|
if (hasAttribute(Attribute::SwiftSelf))
|
|
|
|
return "swiftself";
|
2015-12-16 17:16:19 +01:00
|
|
|
if (hasAttribute(Attribute::InaccessibleMemOnly))
|
|
|
|
return "inaccessiblememonly";
|
|
|
|
if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly))
|
|
|
|
return "inaccessiblemem_or_argmemonly";
|
2013-12-19 03:14:12 +01:00
|
|
|
if (hasAttribute(Attribute::InAlloca))
|
|
|
|
return "inalloca";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::InlineHint))
|
|
|
|
return "inlinehint";
|
2012-12-19 08:18:57 +01:00
|
|
|
if (hasAttribute(Attribute::InReg))
|
2013-01-29 04:20:31 +01:00
|
|
|
return "inreg";
|
2014-06-05 21:29:43 +02:00
|
|
|
if (hasAttribute(Attribute::JumpTable))
|
|
|
|
return "jumptable";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::MinSize))
|
|
|
|
return "minsize";
|
|
|
|
if (hasAttribute(Attribute::Naked))
|
|
|
|
return "naked";
|
|
|
|
if (hasAttribute(Attribute::Nest))
|
|
|
|
return "nest";
|
2012-12-19 08:18:57 +01:00
|
|
|
if (hasAttribute(Attribute::NoAlias))
|
2013-01-29 04:20:31 +01:00
|
|
|
return "noalias";
|
2013-02-22 01:12:35 +01:00
|
|
|
if (hasAttribute(Attribute::NoBuiltin))
|
|
|
|
return "nobuiltin";
|
2012-12-19 08:18:57 +01:00
|
|
|
if (hasAttribute(Attribute::NoCapture))
|
2013-01-29 04:20:31 +01:00
|
|
|
return "nocapture";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::NoDuplicate))
|
|
|
|
return "noduplicate";
|
|
|
|
if (hasAttribute(Attribute::NoImplicitFloat))
|
|
|
|
return "noimplicitfloat";
|
|
|
|
if (hasAttribute(Attribute::NoInline))
|
|
|
|
return "noinline";
|
|
|
|
if (hasAttribute(Attribute::NonLazyBind))
|
|
|
|
return "nonlazybind";
|
2014-05-20 03:23:40 +02:00
|
|
|
if (hasAttribute(Attribute::NonNull))
|
|
|
|
return "nonnull";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::NoRedZone))
|
|
|
|
return "noredzone";
|
|
|
|
if (hasAttribute(Attribute::NoReturn))
|
|
|
|
return "noreturn";
|
2018-03-17 14:29:46 +01:00
|
|
|
if (hasAttribute(Attribute::NoCfCheck))
|
|
|
|
return "nocf_check";
|
2015-11-06 11:32:53 +01:00
|
|
|
if (hasAttribute(Attribute::NoRecurse))
|
|
|
|
return "norecurse";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::NoUnwind))
|
|
|
|
return "nounwind";
|
[SimplifyCFG] Create attribute for fuzzing-specific optimizations.
Summary:
When building with libFuzzer, converting control flow to selects or
obscuring the original operands of CMPs reduces the effectiveness of
libFuzzer's heuristics.
This patch provides an attribute to disable or modify certain optimizations
for optimal fuzzing signal.
Provides a less aggressive alternative to https://reviews.llvm.org/D44057.
Reviewers: vitalybuka, davide, arsenm, hfinkel
Reviewed By: vitalybuka
Subscribers: junbuml, mehdi_amini, wdng, javed.absar, hiraditya, llvm-commits, kcc
Differential Revision: https://reviews.llvm.org/D44232
llvm-svn: 328214
2018-03-22 18:07:51 +01:00
|
|
|
if (hasAttribute(Attribute::OptForFuzzing))
|
|
|
|
return "optforfuzzing";
|
2013-08-23 13:53:55 +02:00
|
|
|
if (hasAttribute(Attribute::OptimizeNone))
|
|
|
|
return "optnone";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::OptimizeForSize))
|
|
|
|
return "optsize";
|
2012-12-19 08:18:57 +01:00
|
|
|
if (hasAttribute(Attribute::ReadNone))
|
2013-01-29 04:20:31 +01:00
|
|
|
return "readnone";
|
2012-12-19 08:18:57 +01:00
|
|
|
if (hasAttribute(Attribute::ReadOnly))
|
2013-01-29 04:20:31 +01:00
|
|
|
return "readonly";
|
2016-07-04 10:01:29 +02:00
|
|
|
if (hasAttribute(Attribute::WriteOnly))
|
|
|
|
return "writeonly";
|
2013-04-20 07:14:40 +02:00
|
|
|
if (hasAttribute(Attribute::Returned))
|
|
|
|
return "returned";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::ReturnsTwice))
|
|
|
|
return "returns_twice";
|
|
|
|
if (hasAttribute(Attribute::SExt))
|
|
|
|
return "signext";
|
2018-09-04 14:38:00 +02:00
|
|
|
if (hasAttribute(Attribute::SpeculativeLoadHardening))
|
|
|
|
return "speculative_load_hardening";
|
2017-04-28 22:25:27 +02:00
|
|
|
if (hasAttribute(Attribute::Speculatable))
|
|
|
|
return "speculatable";
|
2012-12-19 08:18:57 +01:00
|
|
|
if (hasAttribute(Attribute::StackProtect))
|
2013-01-29 04:20:31 +01:00
|
|
|
return "ssp";
|
2012-12-19 08:18:57 +01:00
|
|
|
if (hasAttribute(Attribute::StackProtectReq))
|
2013-01-29 04:20:31 +01:00
|
|
|
return "sspreq";
|
2013-01-23 07:41:41 +01:00
|
|
|
if (hasAttribute(Attribute::StackProtectStrong))
|
2013-01-29 04:20:31 +01:00
|
|
|
return "sspstrong";
|
Protection against stack-based memory corruption errors using SafeStack
This patch adds the safe stack instrumentation pass to LLVM, which separates
the program stack into a safe stack, which stores return addresses, register
spills, and local variables that are statically verified to be accessed
in a safe way, and the unsafe stack, which stores everything else. Such
separation makes it much harder for an attacker to corrupt objects on the
safe stack, including function pointers stored in spilled registers and
return addresses. You can find more information about the safe stack, as
well as other parts of or control-flow hijack protection technique in our
OSDI paper on code-pointer integrity (http://dslab.epfl.ch/pubs/cpi.pdf)
and our project website (http://levee.epfl.ch).
The overhead of our implementation of the safe stack is very close to zero
(0.01% on the Phoronix benchmarks). This is lower than the overhead of
stack cookies, which are supported by LLVM and are commonly used today,
yet the security guarantees of the safe stack are strictly stronger than
stack cookies. In some cases, the safe stack improves performance due to
better cache locality.
Our current implementation of the safe stack is stable and robust, we
used it to recompile multiple projects on Linux including Chromium, and
we also recompiled the entire FreeBSD user-space system and more than 100
packages. We ran unit tests on the FreeBSD system and many of the packages
and observed no errors caused by the safe stack. The safe stack is also fully
binary compatible with non-instrumented code and can be applied to parts of
a program selectively.
This patch is our implementation of the safe stack on top of LLVM. The
patches make the following changes:
- Add the safestack function attribute, similar to the ssp, sspstrong and
sspreq attributes.
- Add the SafeStack instrumentation pass that applies the safe stack to all
functions that have the safestack attribute. This pass moves all unsafe local
variables to the unsafe stack with a separate stack pointer, whereas all
safe variables remain on the regular stack that is managed by LLVM as usual.
- Invoke the pass as the last stage before code generation (at the same time
the existing cookie-based stack protector pass is invoked).
- Add unit tests for the safe stack.
Original patch by Volodymyr Kuznetsov and others at the Dependable Systems
Lab at EPFL; updates and upstreaming by myself.
Differential Revision: http://reviews.llvm.org/D6094
llvm-svn: 239761
2015-06-15 23:07:11 +02:00
|
|
|
if (hasAttribute(Attribute::SafeStack))
|
|
|
|
return "safestack";
|
2018-04-03 22:10:40 +02:00
|
|
|
if (hasAttribute(Attribute::ShadowCallStack))
|
|
|
|
return "shadowcallstack";
|
2017-08-14 23:15:13 +02:00
|
|
|
if (hasAttribute(Attribute::StrictFP))
|
|
|
|
return "strictfp";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::StructRet))
|
|
|
|
return "sret";
|
2013-02-26 07:58:09 +01:00
|
|
|
if (hasAttribute(Attribute::SanitizeThread))
|
|
|
|
return "sanitize_thread";
|
|
|
|
if (hasAttribute(Attribute::SanitizeMemory))
|
|
|
|
return "sanitize_memory";
|
2013-01-31 21:59:05 +01:00
|
|
|
if (hasAttribute(Attribute::UWTable))
|
|
|
|
return "uwtable";
|
|
|
|
if (hasAttribute(Attribute::ZExt))
|
|
|
|
return "zeroext";
|
2013-05-24 14:26:52 +02:00
|
|
|
if (hasAttribute(Attribute::Cold))
|
|
|
|
return "cold";
|
2013-01-31 21:59:05 +01:00
|
|
|
|
|
|
|
// FIXME: These should be output like this:
|
|
|
|
//
|
|
|
|
// align=4
|
|
|
|
// alignstack=8
|
|
|
|
//
|
2013-02-05 23:37:24 +01:00
|
|
|
if (hasAttribute(Attribute::Alignment)) {
|
2013-01-29 04:20:31 +01:00
|
|
|
std::string Result;
|
2013-02-11 09:43:33 +01:00
|
|
|
Result += "align";
|
|
|
|
Result += (InAttrGrp) ? "=" : " ";
|
2013-02-05 23:37:24 +01:00
|
|
|
Result += utostr(getValueAsInt());
|
2013-01-29 04:20:31 +01:00
|
|
|
return Result;
|
2010-02-12 01:31:15 +01:00
|
|
|
}
|
2013-02-11 09:43:33 +01:00
|
|
|
|
2015-04-16 22:29:50 +02:00
|
|
|
auto AttrWithBytesToString = [&](const char *Name) {
|
2013-01-29 04:20:31 +01:00
|
|
|
std::string Result;
|
2015-04-16 22:29:50 +02:00
|
|
|
Result += Name;
|
2013-02-11 09:43:33 +01:00
|
|
|
if (InAttrGrp) {
|
|
|
|
Result += "=";
|
|
|
|
Result += utostr(getValueAsInt());
|
|
|
|
} else {
|
|
|
|
Result += "(";
|
|
|
|
Result += utostr(getValueAsInt());
|
|
|
|
Result += ")";
|
|
|
|
}
|
2013-01-29 04:20:31 +01:00
|
|
|
return Result;
|
2015-04-16 22:29:50 +02:00
|
|
|
};
|
2013-01-31 21:59:05 +01:00
|
|
|
|
2015-04-16 22:29:50 +02:00
|
|
|
if (hasAttribute(Attribute::StackAlignment))
|
|
|
|
return AttrWithBytesToString("alignstack");
|
|
|
|
|
|
|
|
if (hasAttribute(Attribute::Dereferenceable))
|
|
|
|
return AttrWithBytesToString("dereferenceable");
|
|
|
|
|
|
|
|
if (hasAttribute(Attribute::DereferenceableOrNull))
|
|
|
|
return AttrWithBytesToString("dereferenceable_or_null");
|
2014-07-18 17:51:28 +02:00
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
if (hasAttribute(Attribute::AllocSize)) {
|
|
|
|
unsigned ElemSize;
|
|
|
|
Optional<unsigned> NumElems;
|
|
|
|
std::tie(ElemSize, NumElems) = getAllocSizeArgs();
|
|
|
|
|
|
|
|
std::string Result = "allocsize(";
|
|
|
|
Result += utostr(ElemSize);
|
|
|
|
if (NumElems.hasValue()) {
|
|
|
|
Result += ',';
|
|
|
|
Result += utostr(*NumElems);
|
|
|
|
}
|
|
|
|
Result += ')';
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2013-01-31 21:59:05 +01:00
|
|
|
// Convert target-dependent attributes to strings of the form:
|
|
|
|
//
|
|
|
|
// "kind"
|
|
|
|
// "kind" = "value"
|
|
|
|
//
|
2013-02-05 23:37:24 +01:00
|
|
|
if (isStringAttribute()) {
|
2013-01-31 21:59:05 +01:00
|
|
|
std::string Result;
|
2015-03-30 17:42:36 +02:00
|
|
|
Result += (Twine('"') + getKindAsString() + Twine('"')).str();
|
2013-01-31 21:59:05 +01:00
|
|
|
|
[IR] Properly handle escape characters in Attribute::getAsString()
If an attribute name has special characters such as '\01', it is not
properly printed in LLVM assembly language format. Since the format
expects the special characters are printed as it is, it has to contain
escape characters to make it printable.
Before:
attributes #0 = { ... "counting-function"="^A__gnu_mcount_nc" ...
After:
attributes #0 = { ... "counting-function"="\01__gnu_mcount_nc" ...
Reviewers: hfinkel, rengolin, rjmccall, compnerd
Subscribers: nemanjai, mcrosier, hans, shenhan, majnemer, llvm-commits
Differential Revision: https://reviews.llvm.org/D23792
llvm-svn: 280357
2016-09-01 13:44:06 +02:00
|
|
|
std::string AttrVal = pImpl->getValueAsString();
|
|
|
|
if (AttrVal.empty()) return Result;
|
|
|
|
|
|
|
|
// Since some attribute strings contain special characters that cannot be
|
|
|
|
// printable, those have to be escaped to make the attribute value printable
|
|
|
|
// as is. e.g. "\01__gnu_mcount_nc"
|
|
|
|
{
|
|
|
|
raw_string_ostream OS(Result);
|
|
|
|
OS << "=\"";
|
2018-05-31 19:01:42 +02:00
|
|
|
printEscapedString(AttrVal, OS);
|
[IR] Properly handle escape characters in Attribute::getAsString()
If an attribute name has special characters such as '\01', it is not
properly printed in LLVM assembly language format. Since the format
expects the special characters are printed as it is, it has to contain
escape characters to make it printable.
Before:
attributes #0 = { ... "counting-function"="^A__gnu_mcount_nc" ...
After:
attributes #0 = { ... "counting-function"="\01__gnu_mcount_nc" ...
Reviewers: hfinkel, rengolin, rjmccall, compnerd
Subscribers: nemanjai, mcrosier, hans, shenhan, majnemer, llvm-commits
Differential Revision: https://reviews.llvm.org/D23792
llvm-svn: 280357
2016-09-01 13:44:06 +02:00
|
|
|
OS << "\"";
|
|
|
|
}
|
2013-02-01 02:04:27 +01:00
|
|
|
return Result;
|
2013-01-31 21:59:05 +01:00
|
|
|
}
|
2013-01-29 04:20:31 +01:00
|
|
|
|
|
|
|
llvm_unreachable("Unknown attribute");
|
2008-01-03 00:42:30 +01:00
|
|
|
}
|
|
|
|
|
2013-01-29 01:34:06 +01:00
|
|
|
bool Attribute::operator<(Attribute A) const {
|
|
|
|
if (!pImpl && !A.pImpl) return false;
|
|
|
|
if (!pImpl) return true;
|
|
|
|
if (!A.pImpl) return false;
|
|
|
|
return *pImpl < *A.pImpl;
|
2012-10-09 01:27:46 +02:00
|
|
|
}
|
|
|
|
|
2012-09-26 23:07:29 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AttributeImpl Definition
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-07-03 00:05:40 +02:00
|
|
|
// Pin the vtables to this file.
|
2017-02-17 01:00:09 +01:00
|
|
|
AttributeImpl::~AttributeImpl() = default;
|
|
|
|
|
2013-11-19 01:57:56 +01:00
|
|
|
void EnumAttributeImpl::anchor() {}
|
2017-02-17 01:00:09 +01:00
|
|
|
|
2014-07-18 08:51:55 +02:00
|
|
|
void IntAttributeImpl::anchor() {}
|
2017-02-17 01:00:09 +01:00
|
|
|
|
2013-11-19 01:57:56 +01:00
|
|
|
void StringAttributeImpl::anchor() {}
|
2013-11-18 10:31:53 +01:00
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
|
|
|
|
if (isStringAttribute()) return false;
|
|
|
|
return getKindAsEnum() == A;
|
2012-12-30 02:38:39 +01:00
|
|
|
}
|
2013-01-24 01:06:56 +01:00
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
bool AttributeImpl::hasAttribute(StringRef Kind) const {
|
|
|
|
if (!isStringAttribute()) return false;
|
|
|
|
return getKindAsString() == Kind;
|
2013-01-04 21:54:35 +01:00
|
|
|
}
|
2012-12-30 02:38:39 +01:00
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
|
2014-07-18 08:51:55 +02:00
|
|
|
assert(isEnumAttribute() || isIntAttribute());
|
2013-07-11 14:13:16 +02:00
|
|
|
return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
|
2013-02-05 23:37:24 +01:00
|
|
|
}
|
2013-02-01 02:04:27 +01:00
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
uint64_t AttributeImpl::getValueAsInt() const {
|
2014-07-18 08:51:55 +02:00
|
|
|
assert(isIntAttribute());
|
|
|
|
return static_cast<const IntAttributeImpl *>(this)->getValue();
|
2013-02-05 23:37:24 +01:00
|
|
|
}
|
2013-01-24 01:06:56 +01:00
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
StringRef AttributeImpl::getKindAsString() const {
|
2013-07-11 14:13:16 +02:00
|
|
|
assert(isStringAttribute());
|
|
|
|
return static_cast<const StringAttributeImpl *>(this)->getStringKind();
|
2013-02-05 23:37:24 +01:00
|
|
|
}
|
2013-01-24 01:06:56 +01:00
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
StringRef AttributeImpl::getValueAsString() const {
|
2013-07-11 14:13:16 +02:00
|
|
|
assert(isStringAttribute());
|
|
|
|
return static_cast<const StringAttributeImpl *>(this)->getStringValue();
|
2013-02-05 23:37:24 +01:00
|
|
|
}
|
2013-01-24 01:06:56 +01:00
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
bool AttributeImpl::operator<(const AttributeImpl &AI) const {
|
|
|
|
// This sorts the attributes with Attribute::AttrKinds coming first (sorted
|
|
|
|
// relative to their enum value) and then strings.
|
2013-02-15 06:25:26 +01:00
|
|
|
if (isEnumAttribute()) {
|
|
|
|
if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum();
|
2014-07-18 08:51:55 +02:00
|
|
|
if (AI.isIntAttribute()) return true;
|
2013-02-15 06:25:26 +01:00
|
|
|
if (AI.isStringAttribute()) return true;
|
2013-02-15 05:15:55 +01:00
|
|
|
}
|
|
|
|
|
2014-07-18 08:51:55 +02:00
|
|
|
if (isIntAttribute()) {
|
2013-02-15 06:25:26 +01:00
|
|
|
if (AI.isEnumAttribute()) return false;
|
2016-04-05 01:06:05 +02:00
|
|
|
if (AI.isIntAttribute()) {
|
|
|
|
if (getKindAsEnum() == AI.getKindAsEnum())
|
|
|
|
return getValueAsInt() < AI.getValueAsInt();
|
|
|
|
return getKindAsEnum() < AI.getKindAsEnum();
|
|
|
|
}
|
2013-02-15 06:25:26 +01:00
|
|
|
if (AI.isStringAttribute()) return true;
|
2013-02-05 23:37:24 +01:00
|
|
|
}
|
2013-01-24 01:06:56 +01:00
|
|
|
|
2013-02-15 06:25:26 +01:00
|
|
|
if (AI.isEnumAttribute()) return false;
|
2014-07-18 08:51:55 +02:00
|
|
|
if (AI.isIntAttribute()) return false;
|
2013-02-15 06:25:26 +01:00
|
|
|
if (getKindAsString() == AI.getKindAsString())
|
|
|
|
return getValueAsString() < AI.getValueAsString();
|
|
|
|
return getKindAsString() < AI.getKindAsString();
|
2013-01-24 01:06:56 +01:00
|
|
|
}
|
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AttributeSet Definition
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
|
|
|
|
return AttributeSet(AttributeSetNode::get(C, B));
|
|
|
|
}
|
|
|
|
|
|
|
|
AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
|
|
|
|
return AttributeSet(AttributeSetNode::get(C, Attrs));
|
|
|
|
}
|
|
|
|
|
2017-05-11 14:28:08 +02:00
|
|
|
AttributeSet AttributeSet::addAttribute(LLVMContext &C,
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
Attribute::AttrKind Kind) const {
|
2017-05-11 14:28:08 +02:00
|
|
|
if (hasAttribute(Kind)) return *this;
|
|
|
|
AttrBuilder B;
|
|
|
|
B.addAttribute(Kind);
|
|
|
|
return addAttributes(C, AttributeSet::get(C, B));
|
|
|
|
}
|
|
|
|
|
|
|
|
AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
StringRef Value) const {
|
2017-05-11 14:28:08 +02:00
|
|
|
AttrBuilder B;
|
|
|
|
B.addAttribute(Kind, Value);
|
|
|
|
return addAttributes(C, AttributeSet::get(C, B));
|
|
|
|
}
|
|
|
|
|
|
|
|
AttributeSet AttributeSet::addAttributes(LLVMContext &C,
|
|
|
|
const AttributeSet AS) const {
|
|
|
|
if (!hasAttributes())
|
|
|
|
return AS;
|
|
|
|
|
|
|
|
if (!AS.hasAttributes())
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
AttrBuilder B(AS);
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this)
|
2017-05-11 14:28:08 +02:00
|
|
|
B.addAttribute(I);
|
|
|
|
|
|
|
|
return get(C, B);
|
|
|
|
}
|
|
|
|
|
|
|
|
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
|
|
|
|
Attribute::AttrKind Kind) const {
|
|
|
|
if (!hasAttribute(Kind)) return *this;
|
2018-01-17 20:15:21 +01:00
|
|
|
AttrBuilder B(*this);
|
|
|
|
B.removeAttribute(Kind);
|
|
|
|
return get(C, B);
|
2017-05-11 14:28:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
|
|
|
|
StringRef Kind) const {
|
|
|
|
if (!hasAttribute(Kind)) return *this;
|
2018-01-17 20:15:21 +01:00
|
|
|
AttrBuilder B(*this);
|
|
|
|
B.removeAttribute(Kind);
|
|
|
|
return get(C, B);
|
2017-05-11 14:28:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
|
|
|
|
const AttrBuilder &Attrs) const {
|
|
|
|
AttrBuilder B(*this);
|
|
|
|
B.remove(Attrs);
|
|
|
|
return get(C, B);
|
|
|
|
}
|
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
unsigned AttributeSet::getNumAttributes() const {
|
|
|
|
return SetNode ? SetNode->getNumAttributes() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
|
2017-05-15 23:57:41 +02:00
|
|
|
return SetNode ? SetNode->hasAttribute(Kind) : false;
|
2017-04-12 02:38:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool AttributeSet::hasAttribute(StringRef Kind) const {
|
2017-05-15 23:57:41 +02:00
|
|
|
return SetNode ? SetNode->hasAttribute(Kind) : false;
|
2017-04-12 02:38:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
|
|
|
|
return SetNode ? SetNode->getAttribute(Kind) : Attribute();
|
|
|
|
}
|
|
|
|
|
|
|
|
Attribute AttributeSet::getAttribute(StringRef Kind) const {
|
|
|
|
return SetNode ? SetNode->getAttribute(Kind) : Attribute();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned AttributeSet::getAlignment() const {
|
|
|
|
return SetNode ? SetNode->getAlignment() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned AttributeSet::getStackAlignment() const {
|
|
|
|
return SetNode ? SetNode->getStackAlignment() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t AttributeSet::getDereferenceableBytes() const {
|
|
|
|
return SetNode ? SetNode->getDereferenceableBytes() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
|
|
|
|
return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
|
2017-04-13 01:57:37 +02:00
|
|
|
return SetNode ? SetNode->getAllocSizeArgs()
|
|
|
|
: std::pair<unsigned, Optional<unsigned>>(0, 0);
|
2017-04-12 02:38:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string AttributeSet::getAsString(bool InAttrGrp) const {
|
|
|
|
return SetNode ? SetNode->getAsString(InAttrGrp) : "";
|
|
|
|
}
|
|
|
|
|
|
|
|
AttributeSet::iterator AttributeSet::begin() const {
|
|
|
|
return SetNode ? SetNode->begin() : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
AttributeSet::iterator AttributeSet::end() const {
|
|
|
|
return SetNode ? SetNode->end() : nullptr;
|
|
|
|
}
|
|
|
|
|
2017-10-15 16:32:27 +02:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
2017-05-11 14:28:08 +02:00
|
|
|
LLVM_DUMP_METHOD void AttributeSet::dump() const {
|
|
|
|
dbgs() << "AS =\n";
|
|
|
|
dbgs() << " { ";
|
|
|
|
dbgs() << getAsString(true) << " }\n";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-01-24 01:06:56 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AttributeSetNode Definition
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-04-11 01:46:08 +02:00
|
|
|
AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
|
2017-04-12 02:38:00 +02:00
|
|
|
: AvailableAttrs(0), NumAttrs(Attrs.size()) {
|
2017-04-11 01:46:08 +02:00
|
|
|
// There's memory after the node where we can store the entries in.
|
2018-11-17 02:44:25 +01:00
|
|
|
llvm::copy(Attrs, getTrailingObjects<Attribute>());
|
2017-04-11 01:46:08 +02:00
|
|
|
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this) {
|
2017-04-11 01:46:08 +02:00
|
|
|
if (!I.isStringAttribute()) {
|
|
|
|
AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-24 01:06:56 +01:00
|
|
|
AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
|
|
|
|
ArrayRef<Attribute> Attrs) {
|
|
|
|
if (Attrs.empty())
|
2014-04-09 08:08:46 +02:00
|
|
|
return nullptr;
|
2013-01-24 01:06:56 +01:00
|
|
|
|
|
|
|
// Otherwise, build a key to look up the existing attributes.
|
|
|
|
LLVMContextImpl *pImpl = C.pImpl;
|
|
|
|
FoldingSetNodeID ID;
|
|
|
|
|
|
|
|
SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 04:13:45 +02:00
|
|
|
llvm::sort(SortedAttrs);
|
2013-01-24 01:06:56 +01:00
|
|
|
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto Attr : SortedAttrs)
|
2015-12-16 06:21:02 +01:00
|
|
|
Attr.Profile(ID);
|
2013-01-24 01:06:56 +01:00
|
|
|
|
|
|
|
void *InsertPoint;
|
|
|
|
AttributeSetNode *PA =
|
|
|
|
pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
|
|
|
|
|
|
|
|
// If we didn't find any existing attributes of the same shape then create a
|
|
|
|
// new one and insert it.
|
|
|
|
if (!PA) {
|
2013-07-11 14:13:16 +02:00
|
|
|
// Coallocate entries after the AttributeSetNode itself.
|
2015-08-06 00:57:34 +02:00
|
|
|
void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
|
2013-07-11 14:13:16 +02:00
|
|
|
PA = new (Mem) AttributeSetNode(SortedAttrs);
|
2013-01-24 01:06:56 +01:00
|
|
|
pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
|
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
// Return the AttributeSetNode that we found or created.
|
2013-01-24 01:06:56 +01:00
|
|
|
return PA;
|
|
|
|
}
|
|
|
|
|
2017-04-11 01:31:05 +02:00
|
|
|
AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
|
|
|
|
// Add target-independent attributes.
|
|
|
|
SmallVector<Attribute, 8> Attrs;
|
|
|
|
for (Attribute::AttrKind Kind = Attribute::None;
|
|
|
|
Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {
|
|
|
|
if (!B.contains(Kind))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Attribute Attr;
|
|
|
|
switch (Kind) {
|
|
|
|
case Attribute::Alignment:
|
|
|
|
Attr = Attribute::getWithAlignment(C, B.getAlignment());
|
|
|
|
break;
|
|
|
|
case Attribute::StackAlignment:
|
|
|
|
Attr = Attribute::getWithStackAlignment(C, B.getStackAlignment());
|
|
|
|
break;
|
|
|
|
case Attribute::Dereferenceable:
|
|
|
|
Attr = Attribute::getWithDereferenceableBytes(
|
|
|
|
C, B.getDereferenceableBytes());
|
|
|
|
break;
|
|
|
|
case Attribute::DereferenceableOrNull:
|
|
|
|
Attr = Attribute::getWithDereferenceableOrNullBytes(
|
|
|
|
C, B.getDereferenceableOrNullBytes());
|
|
|
|
break;
|
|
|
|
case Attribute::AllocSize: {
|
|
|
|
auto A = B.getAllocSizeArgs();
|
|
|
|
Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
Attr = Attribute::get(C, Kind);
|
|
|
|
}
|
|
|
|
Attrs.push_back(Attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add target-dependent (string) attributes.
|
|
|
|
for (const auto &TDA : B.td_attrs())
|
|
|
|
Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second));
|
|
|
|
|
|
|
|
return get(C, Attrs);
|
|
|
|
}
|
|
|
|
|
2013-02-13 09:42:21 +01:00
|
|
|
bool AttributeSetNode::hasAttribute(StringRef Kind) const {
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this)
|
2016-06-26 16:10:56 +02:00
|
|
|
if (I.hasAttribute(Kind))
|
2013-02-13 09:42:21 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
|
2016-01-29 23:25:13 +01:00
|
|
|
if (hasAttribute(Kind)) {
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this)
|
2016-06-26 16:10:56 +02:00
|
|
|
if (I.hasAttribute(Kind))
|
|
|
|
return I;
|
2016-01-29 23:25:13 +01:00
|
|
|
}
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
2013-02-13 09:42:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this)
|
2016-06-26 16:10:56 +02:00
|
|
|
if (I.hasAttribute(Kind))
|
|
|
|
return I;
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
2013-02-13 09:42:21 +01:00
|
|
|
}
|
|
|
|
|
2013-01-29 04:20:31 +01:00
|
|
|
unsigned AttributeSetNode::getAlignment() const {
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this)
|
2016-06-26 16:10:56 +02:00
|
|
|
if (I.hasAttribute(Attribute::Alignment))
|
|
|
|
return I.getAlignment();
|
2013-01-29 04:20:31 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned AttributeSetNode::getStackAlignment() const {
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this)
|
2016-06-26 16:10:56 +02:00
|
|
|
if (I.hasAttribute(Attribute::StackAlignment))
|
|
|
|
return I.getStackAlignment();
|
2013-01-29 04:20:31 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-07-18 17:51:28 +02:00
|
|
|
uint64_t AttributeSetNode::getDereferenceableBytes() const {
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this)
|
2016-06-26 16:10:56 +02:00
|
|
|
if (I.hasAttribute(Attribute::Dereferenceable))
|
|
|
|
return I.getDereferenceableBytes();
|
2014-07-18 17:51:28 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-05-06 19:41:54 +02:00
|
|
|
uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this)
|
2016-06-26 16:10:56 +02:00
|
|
|
if (I.hasAttribute(Attribute::DereferenceableOrNull))
|
|
|
|
return I.getDereferenceableOrNullBytes();
|
2015-05-06 19:41:54 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
std::pair<unsigned, Optional<unsigned>>
|
|
|
|
AttributeSetNode::getAllocSizeArgs() const {
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : *this)
|
2016-06-26 16:10:56 +02:00
|
|
|
if (I.hasAttribute(Attribute::AllocSize))
|
|
|
|
return I.getAllocSizeArgs();
|
2016-04-12 03:05:35 +02:00
|
|
|
return std::make_pair(0, 0);
|
|
|
|
}
|
|
|
|
|
2013-05-01 15:07:03 +02:00
|
|
|
std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
|
2013-04-19 13:43:21 +02:00
|
|
|
std::string Str;
|
2013-07-11 14:13:16 +02:00
|
|
|
for (iterator I = begin(), E = end(); I != E; ++I) {
|
|
|
|
if (I != begin())
|
2013-05-01 15:07:03 +02:00
|
|
|
Str += ' ';
|
|
|
|
Str += I->getAsString(InAttrGrp);
|
2013-01-29 04:20:31 +01:00
|
|
|
}
|
|
|
|
return Str;
|
|
|
|
}
|
|
|
|
|
2008-03-12 18:45:29 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
// AttributeListImpl Definition
|
2008-03-12 18:45:29 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-10-11 03:40:38 +02:00
|
|
|
/// Map from AttributeList index to the internal array index. Adding one happens
|
|
|
|
/// to work, but it relies on unsigned integer wrapping. MSVC warns about
|
|
|
|
/// unsigned wrapping in constexpr functions, so write out the conditional. LLVM
|
|
|
|
/// folds it to add anyway.
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
static constexpr unsigned attrIdxToArrayIdx(unsigned Index) {
|
2017-10-11 03:40:38 +02:00
|
|
|
return Index == AttributeList::FunctionIndex ? 0 : Index + 1;
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
AttributeListImpl::AttributeListImpl(LLVMContext &C,
|
|
|
|
ArrayRef<AttributeSet> Sets)
|
|
|
|
: AvailableFunctionAttrs(0), Context(C), NumAttrSets(Sets.size()) {
|
|
|
|
assert(!Sets.empty() && "pointless AttributeListImpl");
|
2017-04-11 02:16:00 +02:00
|
|
|
|
|
|
|
// There's memory after the node where we can store the entries in.
|
2018-11-17 02:44:25 +01:00
|
|
|
llvm::copy(Sets, getTrailingObjects<AttributeSet>());
|
2017-04-11 02:16:00 +02:00
|
|
|
|
|
|
|
// Initialize AvailableFunctionAttrs summary bitset.
|
2017-04-13 00:22:01 +02:00
|
|
|
static_assert(Attribute::EndAttrKinds <=
|
|
|
|
sizeof(AvailableFunctionAttrs) * CHAR_BIT,
|
|
|
|
"Too many attributes");
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U,
|
|
|
|
"function should be stored in slot 0");
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto I : Sets[0]) {
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
if (!I.isStringAttribute())
|
|
|
|
AvailableFunctionAttrs |= 1ULL << I.getKindAsEnum();
|
2017-04-11 02:16:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
Profile(ID, makeArrayRef(begin(), end()));
|
2017-04-11 02:16:00 +02:00
|
|
|
}
|
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
void AttributeListImpl::Profile(FoldingSetNodeID &ID,
|
|
|
|
ArrayRef<AttributeSet> Sets) {
|
|
|
|
for (const auto &Set : Sets)
|
|
|
|
ID.AddPointer(Set.SetNode);
|
2017-04-11 02:16:00 +02:00
|
|
|
}
|
|
|
|
|
2017-10-15 16:32:27 +02:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
|
|
|
|
AttributeList(const_cast<AttributeListImpl *>(this)).dump();
|
2013-08-03 00:34:30 +02:00
|
|
|
}
|
2017-01-28 03:02:38 +01:00
|
|
|
#endif
|
2013-08-03 00:34:30 +02:00
|
|
|
|
2013-01-27 13:50:02 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
// AttributeList Construction and Mutation Methods
|
2013-01-27 13:50:02 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
AttributeList AttributeList::getImpl(LLVMContext &C,
|
|
|
|
ArrayRef<AttributeSet> AttrSets) {
|
|
|
|
assert(!AttrSets.empty() && "pointless AttributeListImpl");
|
2017-04-11 01:31:05 +02:00
|
|
|
|
2013-01-29 01:34:06 +01:00
|
|
|
LLVMContextImpl *pImpl = C.pImpl;
|
|
|
|
FoldingSetNodeID ID;
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
AttributeListImpl::Profile(ID, AttrSets);
|
2012-10-16 08:01:44 +02:00
|
|
|
|
2012-11-20 06:09:20 +01:00
|
|
|
void *InsertPoint;
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeListImpl *PA =
|
|
|
|
pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
|
2012-10-16 08:01:44 +02:00
|
|
|
|
2008-01-03 00:42:30 +01:00
|
|
|
// If we didn't find any existing attributes of the same shape then
|
|
|
|
// create a new one and insert it.
|
2012-11-20 06:09:20 +01:00
|
|
|
if (!PA) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
// Coallocate entries after the AttributeListImpl itself.
|
2015-08-06 00:57:34 +02:00
|
|
|
void *Mem = ::operator new(
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()));
|
|
|
|
PA = new (Mem) AttributeListImpl(C, AttrSets);
|
2012-11-20 06:09:20 +01:00
|
|
|
pImpl->AttrsLists.InsertNode(PA, InsertPoint);
|
2008-01-03 00:42:30 +01:00
|
|
|
}
|
2012-10-16 08:01:44 +02:00
|
|
|
|
2008-09-25 23:00:45 +02:00
|
|
|
// Return the AttributesList that we found or created.
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
return AttributeList(PA);
|
2008-01-03 00:42:30 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList
|
|
|
|
AttributeList::get(LLVMContext &C,
|
|
|
|
ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
|
2013-01-28 22:55:20 +01:00
|
|
|
// If there are no attributes then return a null AttributesList pointer.
|
|
|
|
if (Attrs.empty())
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
2013-01-28 22:55:20 +01:00
|
|
|
|
2016-01-03 20:43:40 +01:00
|
|
|
assert(std::is_sorted(Attrs.begin(), Attrs.end(),
|
|
|
|
[](const std::pair<unsigned, Attribute> &LHS,
|
|
|
|
const std::pair<unsigned, Attribute> &RHS) {
|
|
|
|
return LHS.first < RHS.first;
|
|
|
|
}) && "Misordered Attributes list!");
|
2018-03-30 02:47:31 +02:00
|
|
|
assert(llvm::none_of(Attrs,
|
|
|
|
[](const std::pair<unsigned, Attribute> &Pair) {
|
|
|
|
return Pair.second.hasAttribute(Attribute::None);
|
|
|
|
}) &&
|
2016-08-11 23:15:00 +02:00
|
|
|
"Pointless attribute!");
|
2013-01-28 22:55:20 +01:00
|
|
|
|
2013-01-28 23:33:39 +01:00
|
|
|
// Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
|
2013-01-28 22:55:20 +01:00
|
|
|
// list.
|
2017-04-12 02:38:00 +02:00
|
|
|
SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
|
2017-02-17 01:00:09 +01:00
|
|
|
for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
|
2013-01-28 22:55:20 +01:00
|
|
|
E = Attrs.end(); I != E; ) {
|
2013-01-28 23:33:39 +01:00
|
|
|
unsigned Index = I->first;
|
2013-01-28 22:55:20 +01:00
|
|
|
SmallVector<Attribute, 4> AttrVec;
|
2013-01-29 16:18:16 +01:00
|
|
|
while (I != E && I->first == Index) {
|
2013-01-28 22:55:20 +01:00
|
|
|
AttrVec.push_back(I->second);
|
|
|
|
++I;
|
|
|
|
}
|
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
|
2013-01-28 22:55:20 +01:00
|
|
|
}
|
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
return get(C, AttrPairVec);
|
2013-01-28 22:55:20 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList
|
|
|
|
AttributeList::get(LLVMContext &C,
|
2017-04-12 02:38:00 +02:00
|
|
|
ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
|
2013-01-28 22:55:20 +01:00
|
|
|
// If there are no attributes then return a null AttributesList pointer.
|
|
|
|
if (Attrs.empty())
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
2013-01-28 22:55:20 +01:00
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
assert(std::is_sorted(Attrs.begin(), Attrs.end(),
|
|
|
|
[](const std::pair<unsigned, AttributeSet> &LHS,
|
|
|
|
const std::pair<unsigned, AttributeSet> &RHS) {
|
|
|
|
return LHS.first < RHS.first;
|
|
|
|
}) &&
|
|
|
|
"Misordered Attributes list!");
|
2018-03-30 02:47:31 +02:00
|
|
|
assert(llvm::none_of(Attrs,
|
|
|
|
[](const std::pair<unsigned, AttributeSet> &Pair) {
|
|
|
|
return !Pair.second.hasAttributes();
|
|
|
|
}) &&
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
"Pointless attribute!");
|
|
|
|
|
|
|
|
unsigned MaxIndex = Attrs.back().first;
|
2018-04-16 19:05:01 +02:00
|
|
|
// If the MaxIndex is FunctionIndex and there are other indices in front
|
|
|
|
// of it, we need to use the largest of those to get the right size.
|
|
|
|
if (MaxIndex == FunctionIndex && Attrs.size() > 1)
|
|
|
|
MaxIndex = Attrs[Attrs.size() - 2].first;
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
|
|
|
|
SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto Pair : Attrs)
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
|
|
|
|
|
|
|
|
return getImpl(C, AttrVec);
|
2013-01-28 22:55:20 +01:00
|
|
|
}
|
|
|
|
|
2017-04-13 02:58:09 +02:00
|
|
|
AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
|
|
|
|
AttributeSet RetAttrs,
|
|
|
|
ArrayRef<AttributeSet> ArgAttrs) {
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
// Scan from the end to find the last argument with attributes. Most
|
|
|
|
// arguments don't have attributes, so it's nice if we can have fewer unique
|
|
|
|
// AttributeListImpls by dropping empty attribute sets at the end of the list.
|
|
|
|
unsigned NumSets = 0;
|
|
|
|
for (size_t I = ArgAttrs.size(); I != 0; --I) {
|
|
|
|
if (ArgAttrs[I - 1].hasAttributes()) {
|
|
|
|
NumSets = I + 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NumSets == 0) {
|
|
|
|
// Check function and return attributes if we didn't have argument
|
|
|
|
// attributes.
|
|
|
|
if (RetAttrs.hasAttributes())
|
|
|
|
NumSets = 2;
|
|
|
|
else if (FnAttrs.hasAttributes())
|
|
|
|
NumSets = 1;
|
2017-04-11 01:31:05 +02:00
|
|
|
}
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
|
|
|
|
// If all attribute sets were empty, we can use the empty attribute list.
|
|
|
|
if (NumSets == 0)
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
|
|
|
|
SmallVector<AttributeSet, 8> AttrSets;
|
|
|
|
AttrSets.reserve(NumSets);
|
|
|
|
// If we have any attributes, we always have function attributes.
|
|
|
|
AttrSets.push_back(FnAttrs);
|
|
|
|
if (NumSets > 1)
|
|
|
|
AttrSets.push_back(RetAttrs);
|
|
|
|
if (NumSets > 2) {
|
|
|
|
// Drop the empty argument attribute sets at the end.
|
|
|
|
ArgAttrs = ArgAttrs.take_front(NumSets - 2);
|
|
|
|
AttrSets.insert(AttrSets.end(), ArgAttrs.begin(), ArgAttrs.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
return getImpl(C, AttrSets);
|
2017-04-11 01:31:05 +02:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
|
|
|
|
const AttrBuilder &B) {
|
2013-01-21 23:44:49 +01:00
|
|
|
if (!B.hasAttributes())
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
Index = attrIdxToArrayIdx(Index);
|
|
|
|
SmallVector<AttributeSet, 8> AttrSets(Index + 1);
|
|
|
|
AttrSets[Index] = AttributeSet::get(C, B);
|
|
|
|
return getImpl(C, AttrSets);
|
2013-01-05 02:36:54 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
|
|
|
|
ArrayRef<Attribute::AttrKind> Kinds) {
|
2013-01-28 23:33:39 +01:00
|
|
|
SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto K : Kinds)
|
2016-08-11 23:15:00 +02:00
|
|
|
Attrs.emplace_back(Index, Attribute::get(C, K));
|
2013-01-28 22:55:20 +01:00
|
|
|
return get(C, Attrs);
|
2013-01-23 07:14:59 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
|
|
|
|
ArrayRef<StringRef> Kinds) {
|
2016-06-15 19:50:39 +02:00
|
|
|
SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto K : Kinds)
|
2016-08-11 23:15:00 +02:00
|
|
|
Attrs.emplace_back(Index, Attribute::get(C, K));
|
2016-06-15 19:50:39 +02:00
|
|
|
return get(C, Attrs);
|
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList AttributeList::get(LLVMContext &C,
|
|
|
|
ArrayRef<AttributeList> Attrs) {
|
|
|
|
if (Attrs.empty())
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
if (Attrs.size() == 1)
|
|
|
|
return Attrs[0];
|
|
|
|
|
|
|
|
unsigned MaxSize = 0;
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto List : Attrs)
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
MaxSize = std::max(MaxSize, List.getNumAttrSets());
|
|
|
|
|
2017-05-31 16:24:06 +02:00
|
|
|
// If every list was empty, there is no point in merging the lists.
|
|
|
|
if (MaxSize == 0)
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
2017-05-31 16:24:06 +02:00
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
|
|
|
|
for (unsigned I = 0; I < MaxSize; ++I) {
|
|
|
|
AttrBuilder CurBuilder;
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto List : Attrs)
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
CurBuilder.merge(List.getAttributes(I - 1));
|
|
|
|
NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
|
2013-01-26 00:09:36 +01:00
|
|
|
}
|
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
return getImpl(C, NewAttrSets);
|
2008-01-03 00:42:30 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
|
|
|
|
Attribute::AttrKind Kind) const {
|
2016-06-14 22:27:35 +02:00
|
|
|
if (hasAttribute(Index, Kind)) return *this;
|
2017-05-03 00:07:37 +02:00
|
|
|
AttrBuilder B;
|
|
|
|
B.addAttribute(Kind);
|
|
|
|
return addAttributes(C, Index, B);
|
2013-03-13 21:20:08 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
|
|
|
|
StringRef Kind,
|
|
|
|
StringRef Value) const {
|
2017-02-17 01:00:09 +01:00
|
|
|
AttrBuilder B;
|
2013-07-25 20:34:24 +02:00
|
|
|
B.addAttribute(Kind, Value);
|
2017-05-03 00:07:37 +02:00
|
|
|
return addAttributes(C, Index, B);
|
2013-07-25 20:34:24 +02:00
|
|
|
}
|
|
|
|
|
2017-05-31 21:23:09 +02:00
|
|
|
AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
Attribute A) const {
|
2017-05-31 21:23:09 +02:00
|
|
|
AttrBuilder B;
|
|
|
|
B.addAttribute(A);
|
|
|
|
return addAttributes(C, Index, B);
|
2015-12-02 07:58:49 +01:00
|
|
|
}
|
|
|
|
|
2017-04-11 01:31:05 +02:00
|
|
|
AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
|
2017-04-19 03:51:13 +02:00
|
|
|
const AttrBuilder &B) const {
|
|
|
|
if (!B.hasAttributes())
|
2017-04-11 01:31:05 +02:00
|
|
|
return *this;
|
|
|
|
|
2017-04-19 00:10:18 +02:00
|
|
|
if (!pImpl)
|
2017-04-19 03:51:13 +02:00
|
|
|
return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
|
2017-04-19 00:10:18 +02:00
|
|
|
|
2008-02-20 00:51:49 +01:00
|
|
|
#ifndef NDEBUG
|
2013-01-28 06:23:28 +01:00
|
|
|
// FIXME it is not obvious how this should work for alignment. For now, say
|
|
|
|
// we can't change a known alignment.
|
2017-05-20 00:23:47 +02:00
|
|
|
unsigned OldAlign = getAttributes(Index).getAlignment();
|
2017-04-19 03:51:13 +02:00
|
|
|
unsigned NewAlign = B.getAlignment();
|
2008-02-20 13:07:57 +01:00
|
|
|
assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
|
2008-02-20 00:51:49 +01:00
|
|
|
"Attempt to change alignment!");
|
|
|
|
#endif
|
2012-10-16 08:01:44 +02:00
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
Index = attrIdxToArrayIdx(Index);
|
|
|
|
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
|
|
|
|
if (Index >= AttrSets.size())
|
|
|
|
AttrSets.resize(Index + 1);
|
2017-04-11 01:31:05 +02:00
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
AttrBuilder Merged(AttrSets[Index]);
|
|
|
|
Merged.merge(B);
|
|
|
|
AttrSets[Index] = AttributeSet::get(C, Merged);
|
2012-10-16 08:01:44 +02:00
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
return getImpl(C, AttrSets);
|
2017-04-11 01:31:05 +02:00
|
|
|
}
|
|
|
|
|
2017-05-31 21:23:09 +02:00
|
|
|
AttributeList AttributeList::addParamAttribute(LLVMContext &C,
|
|
|
|
ArrayRef<unsigned> ArgNos,
|
|
|
|
Attribute A) const {
|
|
|
|
assert(std::is_sorted(ArgNos.begin(), ArgNos.end()));
|
|
|
|
|
|
|
|
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
|
|
|
|
unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
|
|
|
|
if (MaxIndex >= AttrSets.size())
|
|
|
|
AttrSets.resize(MaxIndex + 1);
|
|
|
|
|
|
|
|
for (unsigned ArgNo : ArgNos) {
|
|
|
|
unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
|
|
|
|
AttrBuilder B(AttrSets[Index]);
|
|
|
|
B.addAttribute(A);
|
|
|
|
AttrSets[Index] = AttributeSet::get(C, B);
|
|
|
|
}
|
|
|
|
|
|
|
|
return getImpl(C, AttrSets);
|
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
|
|
|
|
Attribute::AttrKind Kind) const {
|
2016-06-14 22:27:35 +02:00
|
|
|
if (!hasAttribute(Index, Kind)) return *this;
|
2018-01-17 20:15:21 +01:00
|
|
|
|
|
|
|
Index = attrIdxToArrayIdx(Index);
|
|
|
|
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
|
|
|
|
assert(Index < AttrSets.size());
|
|
|
|
|
|
|
|
AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
|
|
|
|
|
|
|
|
return getImpl(C, AttrSets);
|
2013-01-23 01:45:55 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
|
|
|
|
StringRef Kind) const {
|
2016-06-15 19:50:39 +02:00
|
|
|
if (!hasAttribute(Index, Kind)) return *this;
|
2018-01-17 20:15:21 +01:00
|
|
|
|
|
|
|
Index = attrIdxToArrayIdx(Index);
|
|
|
|
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
|
|
|
|
assert(Index < AttrSets.size());
|
|
|
|
|
|
|
|
AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
|
|
|
|
|
|
|
|
return getImpl(C, AttrSets);
|
2008-01-03 00:42:30 +01:00
|
|
|
}
|
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
AttributeList
|
|
|
|
AttributeList::removeAttributes(LLVMContext &C, unsigned Index,
|
|
|
|
const AttrBuilder &AttrsToRemove) const {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
if (!pImpl)
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
2015-05-07 01:19:43 +02:00
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
Index = attrIdxToArrayIdx(Index);
|
|
|
|
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
|
|
|
|
if (Index >= AttrSets.size())
|
|
|
|
AttrSets.resize(Index + 1);
|
2015-05-07 01:19:43 +02:00
|
|
|
|
2018-01-17 20:15:21 +01:00
|
|
|
AttrSets[Index] = AttrSets[Index].removeAttributes(C, AttrsToRemove);
|
2015-05-07 01:19:43 +02:00
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
return getImpl(C, AttrSets);
|
2015-05-07 01:19:43 +02:00
|
|
|
}
|
|
|
|
|
2017-04-11 01:31:05 +02:00
|
|
|
AttributeList AttributeList::removeAttributes(LLVMContext &C,
|
|
|
|
unsigned WithoutIndex) const {
|
|
|
|
if (!pImpl)
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
|
|
|
|
if (WithoutIndex >= getNumAttrSets())
|
|
|
|
return *this;
|
|
|
|
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
|
|
|
|
AttrSets[WithoutIndex] = AttributeSet();
|
|
|
|
return getImpl(C, AttrSets);
|
2017-04-11 01:31:05 +02:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList AttributeList::addDereferenceableAttr(LLVMContext &C,
|
|
|
|
unsigned Index,
|
|
|
|
uint64_t Bytes) const {
|
2017-02-17 01:00:09 +01:00
|
|
|
AttrBuilder B;
|
2015-02-14 20:37:54 +01:00
|
|
|
B.addDereferenceableAttr(Bytes);
|
2017-05-03 00:07:37 +02:00
|
|
|
return addAttributes(C, Index, B);
|
2015-02-14 20:37:54 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList
|
|
|
|
AttributeList::addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
|
|
|
|
uint64_t Bytes) const {
|
2017-02-17 01:00:09 +01:00
|
|
|
AttrBuilder B;
|
2015-04-16 22:29:50 +02:00
|
|
|
B.addDereferenceableOrNullAttr(Bytes);
|
2017-05-03 00:07:37 +02:00
|
|
|
return addAttributes(C, Index, B);
|
2015-04-16 22:29:50 +02:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList
|
|
|
|
AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index,
|
|
|
|
unsigned ElemSizeArg,
|
|
|
|
const Optional<unsigned> &NumElemsArg) {
|
2017-02-17 01:00:09 +01:00
|
|
|
AttrBuilder B;
|
2016-04-12 03:05:35 +02:00
|
|
|
B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
|
2017-05-03 00:07:37 +02:00
|
|
|
return addAttributes(C, Index, B);
|
2016-04-12 03:05:35 +02:00
|
|
|
}
|
|
|
|
|
2013-01-29 01:34:06 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
// AttributeList Accessor Methods
|
2013-01-29 01:34:06 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); }
|
2013-02-10 06:00:40 +01:00
|
|
|
|
2017-04-14 01:12:13 +02:00
|
|
|
AttributeSet AttributeList::getParamAttributes(unsigned ArgNo) const {
|
2017-05-03 20:17:31 +02:00
|
|
|
return getAttributes(ArgNo + FirstArgIndex);
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
AttributeSet AttributeList::getRetAttributes() const {
|
2017-04-11 01:31:05 +02:00
|
|
|
return getAttributes(ReturnIndex);
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
AttributeSet AttributeList::getFnAttributes() const {
|
2017-04-11 01:31:05 +02:00
|
|
|
return getAttributes(FunctionIndex);
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
bool AttributeList::hasAttribute(unsigned Index,
|
|
|
|
Attribute::AttrKind Kind) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).hasAttribute(Kind);
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
bool AttributeList::hasAttribute(unsigned Index, StringRef Kind) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).hasAttribute(Kind);
|
2013-02-13 09:42:21 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
bool AttributeList::hasAttributes(unsigned Index) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).hasAttributes();
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
bool AttributeList::hasFnAttribute(Attribute::AttrKind Kind) const {
|
2016-01-29 23:25:19 +01:00
|
|
|
return pImpl && pImpl->hasFnAttribute(Kind);
|
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
bool AttributeList::hasFnAttribute(StringRef Kind) const {
|
|
|
|
return hasAttribute(AttributeList::FunctionIndex, Kind);
|
2016-09-09 06:50:38 +02:00
|
|
|
}
|
|
|
|
|
2017-04-14 01:12:13 +02:00
|
|
|
bool AttributeList::hasParamAttribute(unsigned ArgNo,
|
|
|
|
Attribute::AttrKind Kind) const {
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
return hasAttribute(ArgNo + FirstArgIndex, Kind);
|
2017-04-14 01:12:13 +02:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
|
|
|
|
unsigned *Index) const {
|
2014-04-09 08:08:46 +02:00
|
|
|
if (!pImpl) return false;
|
2013-01-29 01:34:06 +01:00
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
for (unsigned I = index_begin(), E = index_end(); I != E; ++I) {
|
|
|
|
if (hasAttribute(I, Attr)) {
|
|
|
|
if (Index)
|
|
|
|
*Index = I;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2013-01-29 01:34:06 +01:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
Attribute AttributeList::getAttribute(unsigned Index,
|
|
|
|
Attribute::AttrKind Kind) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).getAttribute(Kind);
|
2013-02-13 09:42:21 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
Attribute AttributeList::getAttribute(unsigned Index, StringRef Kind) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).getAttribute(Kind);
|
2013-02-13 09:42:21 +01:00
|
|
|
}
|
|
|
|
|
2017-04-28 22:34:27 +02:00
|
|
|
unsigned AttributeList::getRetAlignment() const {
|
|
|
|
return getAttributes(ReturnIndex).getAlignment();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned AttributeList::getParamAlignment(unsigned ArgNo) const {
|
2017-05-03 20:17:31 +02:00
|
|
|
return getAttributes(ArgNo + FirstArgIndex).getAlignment();
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
unsigned AttributeList::getStackAlignment(unsigned Index) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).getStackAlignment();
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
uint64_t AttributeList::getDereferenceableBytes(unsigned Index) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).getDereferenceableBytes();
|
2014-07-18 17:51:28 +02:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
uint64_t AttributeList::getDereferenceableOrNullBytes(unsigned Index) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).getDereferenceableOrNullBytes();
|
2015-05-06 19:41:54 +02:00
|
|
|
}
|
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
std::pair<unsigned, Optional<unsigned>>
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttributeList::getAllocSizeArgs(unsigned Index) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).getAllocSizeArgs();
|
2016-04-12 03:05:35 +02:00
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
|
2017-04-12 02:38:00 +02:00
|
|
|
return getAttributes(Index).getAsString(InAttrGrp);
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
AttributeSet AttributeList::getAttributes(unsigned Index) const {
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
Index = attrIdxToArrayIdx(Index);
|
|
|
|
if (!pImpl || Index >= getNumAttrSets())
|
2018-03-30 02:47:31 +02:00
|
|
|
return {};
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
return pImpl->begin()[Index];
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
AttributeList::iterator AttributeList::begin() const {
|
|
|
|
return pImpl ? pImpl->begin() : nullptr;
|
2013-02-01 00:53:05 +01:00
|
|
|
}
|
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
AttributeList::iterator AttributeList::end() const {
|
|
|
|
return pImpl ? pImpl->end() : nullptr;
|
2013-02-01 00:53:05 +01:00
|
|
|
}
|
|
|
|
|
2013-01-29 01:34:06 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
// AttributeList Introspection Methods
|
2013-01-29 01:34:06 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
unsigned AttributeList::getNumAttrSets() const {
|
|
|
|
return pImpl ? pImpl->NumAttrSets : 0;
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
2017-10-15 16:32:27 +02:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
LLVM_DUMP_METHOD void AttributeList::dump() const {
|
2013-01-28 01:21:34 +01:00
|
|
|
dbgs() << "PAL[\n";
|
2013-01-29 01:34:06 +01:00
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
for (unsigned i = index_begin(), e = index_end(); i != e; ++i) {
|
|
|
|
if (getAttributes(i).hasAttributes())
|
|
|
|
dbgs() << " { " << i << " => " << getAsString(i) << " }\n";
|
2008-03-12 18:45:29 +01:00
|
|
|
}
|
2012-10-16 08:01:44 +02:00
|
|
|
|
2010-01-05 02:29:58 +01:00
|
|
|
dbgs() << "]\n";
|
2008-01-06 19:27:01 +01:00
|
|
|
}
|
2017-01-28 03:02:38 +01:00
|
|
|
#endif
|
2013-01-26 00:09:36 +01:00
|
|
|
|
2013-01-29 01:34:06 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AttrBuilder Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
// FIXME: Remove this ctor, use AttributeSet.
|
2017-04-12 02:38:00 +02:00
|
|
|
AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) {
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
AttributeSet AS = AL.getAttributes(Index);
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto &A : AS)
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
addAttribute(A);
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
2017-04-12 02:38:00 +02:00
|
|
|
AttrBuilder::AttrBuilder(AttributeSet AS) {
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto &A : AS)
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-23 19:01:48 +02:00
|
|
|
addAttribute(A);
|
2017-04-11 01:31:05 +02:00
|
|
|
}
|
|
|
|
|
2013-01-29 01:34:06 +01:00
|
|
|
void AttrBuilder::clear() {
|
2013-02-18 13:09:51 +01:00
|
|
|
Attrs.reset();
|
2015-09-04 00:27:42 +02:00
|
|
|
TargetDepAttrs.clear();
|
2015-04-16 22:29:50 +02:00
|
|
|
Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;
|
2016-04-12 03:05:35 +02:00
|
|
|
AllocSizeArgs = 0;
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
|
2013-02-18 13:09:51 +01:00
|
|
|
assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
|
2013-02-01 00:16:25 +01:00
|
|
|
assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment &&
|
2016-04-12 03:05:35 +02:00
|
|
|
Val != Attribute::Dereferenceable && Val != Attribute::AllocSize &&
|
2014-07-18 17:51:28 +02:00
|
|
|
"Adding integer attribute without adding a value!");
|
2013-02-18 13:09:51 +01:00
|
|
|
Attrs[Val] = true;
|
2013-01-29 01:34:06 +01:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-02-01 00:38:01 +01:00
|
|
|
AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
|
2013-02-10 11:13:23 +01:00
|
|
|
if (Attr.isStringAttribute()) {
|
|
|
|
addAttribute(Attr.getKindAsString(), Attr.getValueAsString());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
Attribute::AttrKind Kind = Attr.getKindAsEnum();
|
2013-02-18 13:09:51 +01:00
|
|
|
Attrs[Kind] = true;
|
2013-01-29 01:34:06 +01:00
|
|
|
|
2013-02-05 23:37:24 +01:00
|
|
|
if (Kind == Attribute::Alignment)
|
2013-01-29 01:34:06 +01:00
|
|
|
Alignment = Attr.getAlignment();
|
2013-02-05 23:37:24 +01:00
|
|
|
else if (Kind == Attribute::StackAlignment)
|
2013-01-29 01:34:06 +01:00
|
|
|
StackAlignment = Attr.getStackAlignment();
|
2014-07-18 17:51:28 +02:00
|
|
|
else if (Kind == Attribute::Dereferenceable)
|
|
|
|
DerefBytes = Attr.getDereferenceableBytes();
|
2015-04-16 22:29:50 +02:00
|
|
|
else if (Kind == Attribute::DereferenceableOrNull)
|
|
|
|
DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
|
2016-04-12 03:05:35 +02:00
|
|
|
else if (Kind == Attribute::AllocSize)
|
|
|
|
AllocSizeArgs = Attr.getValueAsInt();
|
2013-01-29 01:34:06 +01:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-02-05 09:09:32 +01:00
|
|
|
AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
|
|
|
|
TargetDepAttrs[A] = V;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-02-01 00:38:01 +01:00
|
|
|
AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
|
2013-02-18 13:09:51 +01:00
|
|
|
assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
|
|
|
|
Attrs[Val] = false;
|
2013-02-01 00:38:01 +01:00
|
|
|
|
|
|
|
if (Val == Attribute::Alignment)
|
|
|
|
Alignment = 0;
|
|
|
|
else if (Val == Attribute::StackAlignment)
|
|
|
|
StackAlignment = 0;
|
2014-07-18 17:51:28 +02:00
|
|
|
else if (Val == Attribute::Dereferenceable)
|
|
|
|
DerefBytes = 0;
|
2015-04-16 22:29:50 +02:00
|
|
|
else if (Val == Attribute::DereferenceableOrNull)
|
|
|
|
DerefOrNullBytes = 0;
|
2016-04-12 03:05:35 +02:00
|
|
|
else if (Val == Attribute::AllocSize)
|
|
|
|
AllocSizeArgs = 0;
|
2013-02-01 00:38:01 +01:00
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) {
|
2017-04-28 20:37:16 +02:00
|
|
|
remove(A.getAttributes(Index));
|
2013-01-29 01:34:06 +01:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-02-05 09:09:32 +01:00
|
|
|
AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
|
2018-03-30 02:47:31 +02:00
|
|
|
auto I = TargetDepAttrs.find(A);
|
2013-02-05 09:09:32 +01:00
|
|
|
if (I != TargetDepAttrs.end())
|
|
|
|
TargetDepAttrs.erase(I);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
|
|
|
|
return unpackAllocSizeArgs(AllocSizeArgs);
|
|
|
|
}
|
|
|
|
|
2013-01-29 01:34:06 +01:00
|
|
|
AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) {
|
|
|
|
if (Align == 0) return *this;
|
|
|
|
|
|
|
|
assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
|
|
|
|
assert(Align <= 0x40000000 && "Alignment too large.");
|
|
|
|
|
2013-02-18 13:09:51 +01:00
|
|
|
Attrs[Attribute::Alignment] = true;
|
2013-01-29 01:34:06 +01:00
|
|
|
Alignment = Align;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) {
|
|
|
|
// Default alignment, allow the target to define how to align it.
|
|
|
|
if (Align == 0) return *this;
|
|
|
|
|
|
|
|
assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
|
|
|
|
assert(Align <= 0x100 && "Alignment too large.");
|
|
|
|
|
2013-02-18 13:09:51 +01:00
|
|
|
Attrs[Attribute::StackAlignment] = true;
|
2013-01-29 01:34:06 +01:00
|
|
|
StackAlignment = Align;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-07-18 17:51:28 +02:00
|
|
|
AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
|
|
|
|
if (Bytes == 0) return *this;
|
|
|
|
|
|
|
|
Attrs[Attribute::Dereferenceable] = true;
|
|
|
|
DerefBytes = Bytes;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-04-16 22:29:50 +02:00
|
|
|
AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
|
|
|
|
if (Bytes == 0)
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
Attrs[Attribute::DereferenceableOrNull] = true;
|
|
|
|
DerefOrNullBytes = Bytes;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
|
|
|
|
const Optional<unsigned> &NumElems) {
|
|
|
|
return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
|
|
|
|
}
|
|
|
|
|
|
|
|
AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
|
|
|
|
// (0, 0) is our "not present" value, so we need to check for it here.
|
|
|
|
assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
|
|
|
|
|
|
|
|
Attrs[Attribute::AllocSize] = true;
|
|
|
|
// Reuse existing machinery to store this as a single 64-bit integer so we can
|
|
|
|
// save a few bytes over using a pair<unsigned, Optional<unsigned>>.
|
|
|
|
AllocSizeArgs = RawArgs;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-02-06 02:16:00 +01:00
|
|
|
AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
|
|
|
|
// FIXME: What if both have alignments, but they don't match?!
|
|
|
|
if (!Alignment)
|
|
|
|
Alignment = B.Alignment;
|
|
|
|
|
|
|
|
if (!StackAlignment)
|
|
|
|
StackAlignment = B.StackAlignment;
|
|
|
|
|
2014-07-18 17:51:28 +02:00
|
|
|
if (!DerefBytes)
|
|
|
|
DerefBytes = B.DerefBytes;
|
|
|
|
|
2015-05-07 01:19:43 +02:00
|
|
|
if (!DerefOrNullBytes)
|
|
|
|
DerefOrNullBytes = B.DerefOrNullBytes;
|
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
if (!AllocSizeArgs)
|
|
|
|
AllocSizeArgs = B.AllocSizeArgs;
|
|
|
|
|
2013-02-16 20:13:18 +01:00
|
|
|
Attrs |= B.Attrs;
|
2013-02-06 02:16:00 +01:00
|
|
|
|
2015-05-07 01:19:43 +02:00
|
|
|
for (auto I : B.td_attrs())
|
|
|
|
TargetDepAttrs[I.first] = I.second;
|
2013-02-06 02:16:00 +01:00
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-05-07 01:19:43 +02:00
|
|
|
AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
|
|
|
|
// FIXME: What if both have alignments, but they don't match?!
|
|
|
|
if (B.Alignment)
|
|
|
|
Alignment = 0;
|
|
|
|
|
|
|
|
if (B.StackAlignment)
|
|
|
|
StackAlignment = 0;
|
|
|
|
|
|
|
|
if (B.DerefBytes)
|
|
|
|
DerefBytes = 0;
|
|
|
|
|
|
|
|
if (B.DerefOrNullBytes)
|
|
|
|
DerefOrNullBytes = 0;
|
|
|
|
|
2016-04-12 03:05:35 +02:00
|
|
|
if (B.AllocSizeArgs)
|
|
|
|
AllocSizeArgs = 0;
|
|
|
|
|
2015-05-07 01:19:43 +02:00
|
|
|
Attrs &= ~B.Attrs;
|
|
|
|
|
|
|
|
for (auto I : B.td_attrs())
|
|
|
|
TargetDepAttrs.erase(I.first);
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AttrBuilder::overlaps(const AttrBuilder &B) const {
|
|
|
|
// First check if any of the target independent attributes overlap.
|
|
|
|
if ((Attrs & B.Attrs).any())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Then check if any target dependent ones do.
|
2017-02-22 07:34:04 +01:00
|
|
|
for (const auto &I : td_attrs())
|
2015-05-07 01:19:43 +02:00
|
|
|
if (B.contains(I.first))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-02-06 02:33:42 +01:00
|
|
|
bool AttrBuilder::contains(StringRef A) const {
|
|
|
|
return TargetDepAttrs.find(A) != TargetDepAttrs.end();
|
|
|
|
}
|
|
|
|
|
2013-01-29 01:34:06 +01:00
|
|
|
bool AttrBuilder::hasAttributes() const {
|
2013-02-18 13:09:51 +01:00
|
|
|
return !Attrs.none() || !TargetDepAttrs.empty();
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
2017-04-28 20:37:16 +02:00
|
|
|
bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const {
|
|
|
|
AttributeSet AS = AL.getAttributes(Index);
|
2013-02-02 01:42:06 +01:00
|
|
|
|
2018-03-30 02:47:31 +02:00
|
|
|
for (const auto Attr : AS) {
|
2014-07-18 08:51:55 +02:00
|
|
|
if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
|
2017-04-28 20:37:16 +02:00
|
|
|
if (contains(Attr.getKindAsEnum()))
|
2013-02-12 08:56:49 +01:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
assert(Attr.isStringAttribute() && "Invalid attribute kind!");
|
2017-04-28 20:37:16 +02:00
|
|
|
return contains(Attr.getKindAsString());
|
2013-02-12 08:56:49 +01:00
|
|
|
}
|
|
|
|
}
|
2013-02-02 01:42:06 +01:00
|
|
|
|
|
|
|
return false;
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool AttrBuilder::hasAlignmentAttr() const {
|
|
|
|
return Alignment != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AttrBuilder::operator==(const AttrBuilder &B) {
|
2013-02-16 20:13:18 +01:00
|
|
|
if (Attrs != B.Attrs)
|
|
|
|
return false;
|
2013-02-06 02:33:42 +01:00
|
|
|
|
|
|
|
for (td_const_iterator I = TargetDepAttrs.begin(),
|
|
|
|
E = TargetDepAttrs.end(); I != E; ++I)
|
|
|
|
if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end())
|
|
|
|
return false;
|
|
|
|
|
2014-07-18 17:51:28 +02:00
|
|
|
return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
|
|
|
|
DerefBytes == B.DerefBytes;
|
2013-01-29 01:34:06 +01:00
|
|
|
}
|
|
|
|
|
2013-01-26 00:09:36 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AttributeFuncs Function Defintions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Which attributes cannot be applied to a type.
|
2015-08-02 00:20:21 +02:00
|
|
|
AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
|
2013-01-26 00:09:36 +01:00
|
|
|
AttrBuilder Incompatible;
|
|
|
|
|
|
|
|
if (!Ty->isIntegerTy())
|
|
|
|
// Attribute that only apply to integers.
|
|
|
|
Incompatible.addAttribute(Attribute::SExt)
|
|
|
|
.addAttribute(Attribute::ZExt);
|
|
|
|
|
|
|
|
if (!Ty->isPointerTy())
|
|
|
|
// Attribute that only apply to pointers.
|
|
|
|
Incompatible.addAttribute(Attribute::ByVal)
|
|
|
|
.addAttribute(Attribute::Nest)
|
|
|
|
.addAttribute(Attribute::NoAlias)
|
|
|
|
.addAttribute(Attribute::NoCapture)
|
2014-05-20 03:23:40 +02:00
|
|
|
.addAttribute(Attribute::NonNull)
|
2014-07-18 17:51:28 +02:00
|
|
|
.addDereferenceableAttr(1) // the int here is ignored
|
2015-04-16 22:29:50 +02:00
|
|
|
.addDereferenceableOrNullAttr(1) // the int here is ignored
|
2013-07-06 02:29:58 +02:00
|
|
|
.addAttribute(Attribute::ReadNone)
|
|
|
|
.addAttribute(Attribute::ReadOnly)
|
2013-12-19 03:14:12 +01:00
|
|
|
.addAttribute(Attribute::StructRet)
|
|
|
|
.addAttribute(Attribute::InAlloca);
|
2013-01-26 00:09:36 +01:00
|
|
|
|
2015-05-07 01:19:56 +02:00
|
|
|
return Incompatible;
|
2013-01-26 00:09:36 +01:00
|
|
|
}
|
2015-12-23 00:57:37 +01:00
|
|
|
|
|
|
|
template<typename AttrClass>
|
|
|
|
static bool isEqual(const Function &Caller, const Function &Callee) {
|
|
|
|
return Caller.getFnAttribute(AttrClass::getKind()) ==
|
|
|
|
Callee.getFnAttribute(AttrClass::getKind());
|
|
|
|
}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Compute the logical AND of the attributes of the caller and the
|
2015-12-23 00:57:37 +01:00
|
|
|
/// callee.
|
|
|
|
///
|
|
|
|
/// This function sets the caller's attribute to false if the callee's attribute
|
|
|
|
/// is false.
|
|
|
|
template<typename AttrClass>
|
|
|
|
static void setAND(Function &Caller, const Function &Callee) {
|
|
|
|
if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
|
|
|
|
!AttrClass::isSet(Callee, AttrClass::getKind()))
|
|
|
|
AttrClass::set(Caller, AttrClass::getKind(), false);
|
|
|
|
}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Compute the logical OR of the attributes of the caller and the
|
2015-12-23 00:57:37 +01:00
|
|
|
/// callee.
|
|
|
|
///
|
|
|
|
/// This function sets the caller's attribute to true if the callee's attribute
|
|
|
|
/// is true.
|
|
|
|
template<typename AttrClass>
|
|
|
|
static void setOR(Function &Caller, const Function &Callee) {
|
|
|
|
if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
|
|
|
|
AttrClass::isSet(Callee, AttrClass::getKind()))
|
|
|
|
AttrClass::set(Caller, AttrClass::getKind(), true);
|
|
|
|
}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// If the inlined function had a higher stack protection level than the
|
2015-12-23 00:57:37 +01:00
|
|
|
/// calling function, then bump up the caller's stack protection level.
|
|
|
|
static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
|
|
|
|
// If upgrading the SSP attribute, clear out the old SSP Attributes first.
|
|
|
|
// Having multiple SSP attributes doesn't actually hurt, but it adds useless
|
|
|
|
// clutter to the IR.
|
2017-05-03 00:07:37 +02:00
|
|
|
AttrBuilder OldSSPAttr;
|
|
|
|
OldSSPAttr.addAttribute(Attribute::StackProtect)
|
|
|
|
.addAttribute(Attribute::StackProtectStrong)
|
|
|
|
.addAttribute(Attribute::StackProtectReq);
|
2015-12-23 00:57:37 +01:00
|
|
|
|
2016-04-12 00:27:48 +02:00
|
|
|
if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr);
|
2015-12-23 00:57:37 +01:00
|
|
|
Caller.addFnAttr(Attribute::StackProtectReq);
|
|
|
|
} else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
|
|
|
|
!Caller.hasFnAttribute(Attribute::StackProtectReq)) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-21 17:57:19 +01:00
|
|
|
Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr);
|
2015-12-23 00:57:37 +01:00
|
|
|
Caller.addFnAttr(Attribute::StackProtectStrong);
|
|
|
|
} else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
|
|
|
|
!Caller.hasFnAttribute(Attribute::StackProtectReq) &&
|
|
|
|
!Caller.hasFnAttribute(Attribute::StackProtectStrong))
|
|
|
|
Caller.addFnAttr(Attribute::StackProtect);
|
|
|
|
}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// If the inlined function required stack probes, then ensure that
|
2017-06-21 20:46:50 +02:00
|
|
|
/// the calling function has those too.
|
|
|
|
static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
|
2017-06-23 01:22:36 +02:00
|
|
|
if (!Caller.hasFnAttribute("probe-stack") &&
|
|
|
|
Callee.hasFnAttribute("probe-stack")) {
|
|
|
|
Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// If the inlined function defines the size of guard region
|
2017-06-23 01:22:36 +02:00
|
|
|
/// on the stack, then ensure that the calling function defines a guard region
|
|
|
|
/// that is no larger.
|
|
|
|
static void
|
|
|
|
adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
|
|
|
|
if (Callee.hasFnAttribute("stack-probe-size")) {
|
|
|
|
uint64_t CalleeStackProbeSize;
|
|
|
|
Callee.getFnAttribute("stack-probe-size")
|
|
|
|
.getValueAsString()
|
|
|
|
.getAsInteger(0, CalleeStackProbeSize);
|
|
|
|
if (Caller.hasFnAttribute("stack-probe-size")) {
|
|
|
|
uint64_t CallerStackProbeSize;
|
|
|
|
Caller.getFnAttribute("stack-probe-size")
|
|
|
|
.getValueAsString()
|
|
|
|
.getAsInteger(0, CallerStackProbeSize);
|
|
|
|
if (CallerStackProbeSize > CalleeStackProbeSize) {
|
|
|
|
Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size"));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size"));
|
|
|
|
}
|
|
|
|
}
|
2017-06-21 20:46:50 +02:00
|
|
|
}
|
|
|
|
|
2018-07-24 20:49:00 +02:00
|
|
|
/// If the inlined function defines a min legal vector width, then ensure
|
2018-11-29 08:27:38 +01:00
|
|
|
/// the calling function has the same or larger min legal vector width. If the
|
|
|
|
/// caller has the attribute, but the callee doesn't, we need to remove the
|
|
|
|
/// attribute from the caller since we can't make any guarantees about the
|
|
|
|
/// caller's requirements.
|
|
|
|
/// This function is called after the inlining decision has been made so we have
|
|
|
|
/// to merge the attribute this way. Heuristics that would use
|
2018-07-24 20:49:00 +02:00
|
|
|
/// min-legal-vector-width to determine inline compatibility would need to be
|
|
|
|
/// handled as part of inline cost analysis.
|
|
|
|
static void
|
|
|
|
adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
|
2018-11-29 08:27:38 +01:00
|
|
|
if (Caller.hasFnAttribute("min-legal-vector-width")) {
|
|
|
|
if (Callee.hasFnAttribute("min-legal-vector-width")) {
|
2018-07-24 20:49:00 +02:00
|
|
|
uint64_t CallerVectorWidth;
|
|
|
|
Caller.getFnAttribute("min-legal-vector-width")
|
|
|
|
.getValueAsString()
|
|
|
|
.getAsInteger(0, CallerVectorWidth);
|
2018-11-29 08:27:38 +01:00
|
|
|
uint64_t CalleeVectorWidth;
|
|
|
|
Callee.getFnAttribute("min-legal-vector-width")
|
|
|
|
.getValueAsString()
|
|
|
|
.getAsInteger(0, CalleeVectorWidth);
|
|
|
|
if (CallerVectorWidth < CalleeVectorWidth)
|
2018-07-24 20:49:00 +02:00
|
|
|
Caller.addFnAttr(Callee.getFnAttribute("min-legal-vector-width"));
|
|
|
|
} else {
|
2018-11-29 08:27:38 +01:00
|
|
|
// If the callee doesn't have the attribute then we don't know anything
|
|
|
|
// and must drop the attribute from the caller.
|
|
|
|
Caller.removeFnAttr("min-legal-vector-width");
|
2018-07-24 20:49:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-30 21:33:53 +02:00
|
|
|
/// If the inlined function has "null-pointer-is-valid=true" attribute,
|
|
|
|
/// set this attribute in the caller post inlining.
|
|
|
|
static void
|
|
|
|
adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
|
|
|
|
if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
|
|
|
|
Caller.addFnAttr(Callee.getFnAttribute("null-pointer-is-valid"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-23 00:57:37 +01:00
|
|
|
#define GET_ATTR_COMPAT_FUNC
|
|
|
|
#include "AttributesCompatFunc.inc"
|
|
|
|
|
|
|
|
bool AttributeFuncs::areInlineCompatible(const Function &Caller,
|
|
|
|
const Function &Callee) {
|
|
|
|
return hasCompatibleFnAttrs(Caller, Callee);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
|
|
|
|
const Function &Callee) {
|
|
|
|
mergeFnAttrs(Caller, Callee);
|
|
|
|
}
|