-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[IR] Add new Range attribute using new ConstantRange Attribute type #83171
Changes from 2 commits
3c8ef54
41798a6
f262d44
81ad281
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -1634,6 +1634,23 @@ Currently, only the following parameter attributes are defined: | |||||||||
|
||||||||||
This attribute cannot be applied to return values. | ||||||||||
|
||||||||||
``range(<ty> <a>, <b>)`` | ||||||||||
This attribute expresses the possible range the parameter is in. The value of | ||||||||||
the parameter is in the specified range or is poison. | ||||||||||
The arguments passed to ``range`` has the following properties: | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
- The type must match the scalar type of the parameter. | ||||||||||
- The pair ``a,b`` represents the range ``[a,b)``. | ||||||||||
- Both ``a`` and ``b`` are constants. | ||||||||||
- The range is allowed to wrap. | ||||||||||
- The range should not represent the full or empty set. That is, | ||||||||||
``a!=b``. | ||||||||||
nikic marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
This attribute may only be applied to parameters with integer or vector of | ||||||||||
integer types. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
For vector-typed parameters, the range is applied element-wise. | ||||||||||
|
||||||||||
.. _gc: | ||||||||||
|
||||||||||
Garbage Collector Strategy Names | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -844,6 +844,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { | |
return bitc::ATTR_KIND_CORO_ONLY_DESTROY_WHEN_COMPLETE; | ||
case Attribute::DeadOnUnwind: | ||
return bitc::ATTR_KIND_DEAD_ON_UNWIND; | ||
case Attribute::Range: | ||
return bitc::ATTR_KIND_RANGE; | ||
case Attribute::EndAttrKinds: | ||
llvm_unreachable("Can not encode end-attribute kinds marker."); | ||
case Attribute::None: | ||
|
@@ -856,6 +858,24 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { | |
llvm_unreachable("Trying to encode unknown attribute"); | ||
} | ||
|
||
static void emitSignedInt64(SmallVectorImpl<uint64_t> &Vals, uint64_t V) { | ||
if ((int64_t)V >= 0) | ||
Vals.push_back(V << 1); | ||
else | ||
Vals.push_back((-V << 1) | 1); | ||
} | ||
|
||
static void emitWideAPInt(SmallVectorImpl<uint64_t> &Vals, const APInt &A) { | ||
// We have an arbitrary precision integer value to write whose | ||
// bit width is > 64. However, in canonical unsigned integer | ||
// format it is likely that the high bits are going to be zero. | ||
// So, we only write the number of active words. | ||
unsigned NumWords = A.getActiveWords(); | ||
const uint64_t *RawData = A.getRawData(); | ||
for (unsigned i = 0; i < NumWords; i++) | ||
emitSignedInt64(Vals, RawData[i]); | ||
} | ||
|
||
void ModuleBitcodeWriter::writeAttributeGroupTable() { | ||
const std::vector<ValueEnumerator::IndexAndAttrSet> &AttrGrps = | ||
VE.getAttributeGroups(); | ||
|
@@ -889,13 +909,30 @@ void ModuleBitcodeWriter::writeAttributeGroupTable() { | |
Record.append(Val.begin(), Val.end()); | ||
Record.push_back(0); | ||
} | ||
} else { | ||
assert(Attr.isTypeAttribute()); | ||
} else if (Attr.isTypeAttribute()) { | ||
Type *Ty = Attr.getValueAsType(); | ||
Record.push_back(Ty ? 6 : 5); | ||
Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); | ||
if (Ty) | ||
Record.push_back(VE.getTypeID(Attr.getValueAsType())); | ||
} else { | ||
assert(Attr.isConstantRangeAttribute()); | ||
ConstantRange Range = Attr.getValueAsConstantRange(); | ||
bool WideAPInt = Range.getBitWidth() > 64; | ||
Record.push_back(WideAPInt ? 8 : 7); | ||
Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); | ||
Record.push_back(Range.getBitWidth()); | ||
if (WideAPInt) { | ||
const APInt &Lower = Range.getLower(); | ||
Record.push_back(Lower.getActiveWords()); | ||
emitWideAPInt(Record, Lower); | ||
const APInt &Upper = Range.getUpper(); | ||
Record.push_back(Upper.getActiveWords()); | ||
emitWideAPInt(Record, Upper); | ||
} else { | ||
emitSignedInt64(Record, *Range.getLower().getRawData()); | ||
emitSignedInt64(Record, *Range.getUpper().getRawData()); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to have a ConstantRange encoding that can be reused for other purposes as well. The way this is implemented now this will be a bit hard, as the wide distinction is part of the attribute kind. I have some local changes that also needed this, and these are the implementations I used:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes much nicer to have separat functions was trying to restrict number of used bytes as other types did it. |
||
} | ||
} | ||
|
||
|
@@ -1716,24 +1753,6 @@ void ModuleBitcodeWriter::writeDIGenericSubrange( | |
Record.clear(); | ||
} | ||
|
||
static void emitSignedInt64(SmallVectorImpl<uint64_t> &Vals, uint64_t V) { | ||
if ((int64_t)V >= 0) | ||
Vals.push_back(V << 1); | ||
else | ||
Vals.push_back((-V << 1) | 1); | ||
} | ||
|
||
static void emitWideAPInt(SmallVectorImpl<uint64_t> &Vals, const APInt &A) { | ||
// We have an arbitrary precision integer value to write whose | ||
// bit width is > 64. However, in canonical unsigned integer | ||
// format it is likely that the high bits are going to be zero. | ||
// So, we only write the number of active words. | ||
unsigned NumWords = A.getActiveWords(); | ||
const uint64_t *RawData = A.getRawData(); | ||
for (unsigned i = 0; i < NumWords; i++) | ||
emitSignedInt64(Vals, RawData[i]); | ||
} | ||
|
||
void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N, | ||
SmallVectorImpl<uint64_t> &Record, | ||
unsigned Abbrev) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.