Skip to content

Commit 1dfc473

Browse files
committed
Revert "[Attributor][NFC] Encode IRPositions in the bits of a single pointer"
A dependent patch has been reverted [0]. Until it goes back in this one has to stay out. [0] ebdb893 This reverts commit d254b50.
1 parent 8f766e3 commit 1dfc473

File tree

3 files changed

+107
-198
lines changed

3 files changed

+107
-198
lines changed

llvm/include/llvm/Transforms/IPO/Attributor.h

Lines changed: 70 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -153,24 +153,29 @@ enum class DepClassTy {
153153
/// are floating values that do not have a corresponding attribute list
154154
/// position.
155155
struct IRPosition {
156+
virtual ~IRPosition() {}
156157

157158
/// The positions we distinguish in the IR.
158-
enum Kind : char {
159-
IRP_INVALID, ///< An invalid position.
160-
IRP_FLOAT, ///< A position that is not associated with a spot suitable
161-
///< for attributes. This could be any value or instruction.
162-
IRP_RETURNED, ///< An attribute for the function return value.
163-
IRP_CALL_SITE_RETURNED, ///< An attribute for a call site return value.
164-
IRP_FUNCTION, ///< An attribute for a function (scope).
165-
IRP_CALL_SITE, ///< An attribute for a call site (function scope).
166-
IRP_ARGUMENT, ///< An attribute for a function argument.
167-
IRP_CALL_SITE_ARGUMENT, ///< An attribute for a call site argument.
159+
///
160+
/// The values are chosen such that the KindOrArgNo member has a value >= 0
161+
/// if it is an argument or call site argument while a value < 0 indicates the
162+
/// respective kind of that value.
163+
enum Kind : int {
164+
IRP_INVALID = -6, ///< An invalid position.
165+
IRP_FLOAT = -5, ///< A position that is not associated with a spot suitable
166+
///< for attributes. This could be any value or instruction.
167+
IRP_RETURNED = -4, ///< An attribute for the function return value.
168+
IRP_CALL_SITE_RETURNED = -3, ///< An attribute for a call site return value.
169+
IRP_FUNCTION = -2, ///< An attribute for a function (scope).
170+
IRP_CALL_SITE = -1, ///< An attribute for a call site (function scope).
171+
IRP_ARGUMENT = 0, ///< An attribute for a function argument.
172+
IRP_CALL_SITE_ARGUMENT = 1, ///< An attribute for a call site argument.
168173
};
169174

170175
/// Default constructor available to create invalid positions implicitly. All
171176
/// other positions need to be created explicitly through the appropriate
172177
/// static member function.
173-
IRPosition() : Enc(nullptr, ENC_VALUE) { verify(); }
178+
IRPosition() : AnchorVal(nullptr), KindOrArgNo(IRP_INVALID) { verify(); }
174179

175180
/// Create a position describing the value of \p V.
176181
static const IRPosition value(const Value &V) {
@@ -193,7 +198,7 @@ struct IRPosition {
193198

194199
/// Create a position describing the argument \p Arg.
195200
static const IRPosition argument(const Argument &Arg) {
196-
return IRPosition(const_cast<Argument &>(Arg), IRP_ARGUMENT);
201+
return IRPosition(const_cast<Argument &>(Arg), Kind(Arg.getArgNo()));
197202
}
198203

199204
/// Create a position describing the function scope of \p CB.
@@ -209,8 +214,7 @@ struct IRPosition {
209214
/// Create a position describing the argument of \p CB at position \p ArgNo.
210215
static const IRPosition callsite_argument(const CallBase &CB,
211216
unsigned ArgNo) {
212-
return IRPosition(const_cast<Use &>(CB.getArgOperandUse(ArgNo)),
213-
IRP_CALL_SITE_ARGUMENT);
217+
return IRPosition(const_cast<CallBase &>(CB), Kind(ArgNo));
214218
}
215219

216220
/// Create a position describing the argument of \p ACS at position \p ArgNo.
@@ -238,7 +242,9 @@ struct IRPosition {
238242
return IRPosition::function(*IRP.getAssociatedFunction());
239243
}
240244

241-
bool operator==(const IRPosition &RHS) const { return Enc == RHS.Enc; }
245+
bool operator==(const IRPosition &RHS) const {
246+
return (AnchorVal == RHS.AnchorVal) && (KindOrArgNo == RHS.KindOrArgNo);
247+
}
242248
bool operator!=(const IRPosition &RHS) const { return !(*this == RHS); }
243249

244250
/// Return the value this abstract attribute is anchored with.
@@ -248,21 +254,16 @@ struct IRPosition {
248254
/// far, only the case for call site arguments as the value is not sufficient
249255
/// to pinpoint them. Instead, we can use the call site as an anchor.
250256
Value &getAnchorValue() const {
251-
switch (getEncodingBits()) {
252-
case ENC_VALUE:
253-
case ENC_RETURNED_VALUE:
254-
case ENC_FLOATING_FUNCTION:
255-
return *getAsValuePtr();
256-
case ENC_CALL_SITE_ARGUMENT_USE:
257-
return *(getAsUsePtr()->getUser());
258-
default:
259-
llvm_unreachable("Unkown encoding!");
260-
};
257+
assert(KindOrArgNo != IRP_INVALID &&
258+
"Invalid position does not have an anchor value!");
259+
return *AnchorVal;
261260
}
262261

263262
/// Return the associated function, if any.
264263
Function *getAssociatedFunction() const {
265-
if (auto *CB = dyn_cast<CallBase>(&getAnchorValue()))
264+
assert(KindOrArgNo != IRP_INVALID &&
265+
"Invalid position does not have an anchor scope!");
266+
if (auto *CB = dyn_cast<CallBase>(AnchorVal))
266267
return CB->getCalledFunction();
267268
return getAnchorScope();
268269
}
@@ -311,33 +312,26 @@ struct IRPosition {
311312

312313
/// Return the value this abstract attribute is associated with.
313314
Value &getAssociatedValue() const {
314-
if (getArgNo() < 0 || isa<Argument>(&getAnchorValue()))
315-
return getAnchorValue();
316-
assert(isa<CallBase>(&getAnchorValue()) && "Expected a call base!");
317-
return *cast<CallBase>(&getAnchorValue())->getArgOperand(getArgNo());
315+
assert(KindOrArgNo != IRP_INVALID &&
316+
"Invalid position does not have an associated value!");
317+
if (getArgNo() < 0 || isa<Argument>(AnchorVal))
318+
return *AnchorVal;
319+
assert(isa<CallBase>(AnchorVal) && "Expected a call base!");
320+
return *cast<CallBase>(AnchorVal)->getArgOperand(getArgNo());
318321
}
319322

320323
/// Return the type this abstract attribute is associated with.
321324
Type *getAssociatedType() const {
325+
assert(KindOrArgNo != IRP_INVALID &&
326+
"Invalid position does not have an associated type!");
322327
if (getPositionKind() == IRPosition::IRP_RETURNED)
323328
return getAssociatedFunction()->getReturnType();
324329
return getAssociatedValue().getType();
325330
}
326331

327332
/// Return the argument number of the associated value if it is an argument or
328333
/// call site argument, otherwise a negative value.
329-
int getArgNo() const {
330-
switch (getPositionKind()) {
331-
case IRPosition::IRP_ARGUMENT:
332-
return cast<Argument>(getAsValuePtr())->getArgNo();
333-
case IRPosition::IRP_CALL_SITE_ARGUMENT: {
334-
Use &U = *getAsUsePtr();
335-
return cast<CallBase>(U.getUser())->getArgOperandNo(&U);
336-
}
337-
default:
338-
return -1;
339-
}
340-
}
334+
int getArgNo() const { return KindOrArgNo; }
341335

342336
/// Return the index in the attribute list for this position.
343337
unsigned getAttrIdx() const {
@@ -353,31 +347,27 @@ struct IRPosition {
353347
return AttributeList::ReturnIndex;
354348
case IRPosition::IRP_ARGUMENT:
355349
case IRPosition::IRP_CALL_SITE_ARGUMENT:
356-
return getArgNo() + AttributeList::FirstArgIndex;
350+
return KindOrArgNo + AttributeList::FirstArgIndex;
357351
}
358352
llvm_unreachable(
359353
"There is no attribute index for a floating or invalid position!");
360354
}
361355

362356
/// Return the associated position kind.
363357
Kind getPositionKind() const {
364-
char EncodingBits = getEncodingBits();
365-
if (EncodingBits == ENC_CALL_SITE_ARGUMENT_USE)
366-
return IRP_CALL_SITE_ARGUMENT;
367-
if (EncodingBits == ENC_FLOATING_FUNCTION)
368-
return IRP_FLOAT;
369-
370-
Value *V = getAsValuePtr();
371-
if (!V)
372-
return IRP_INVALID;
373-
if (isa<Argument>(V))
358+
if (getArgNo() >= 0) {
359+
assert(((isa<Argument>(getAnchorValue()) &&
360+
isa<Argument>(getAssociatedValue())) ||
361+
isa<CallBase>(getAnchorValue())) &&
362+
"Expected argument or call base due to argument number!");
363+
if (isa<CallBase>(getAnchorValue()))
364+
return IRP_CALL_SITE_ARGUMENT;
374365
return IRP_ARGUMENT;
375-
if (isa<Function>(V))
376-
return isReturnPosition(EncodingBits) ? IRP_RETURNED : IRP_FUNCTION;
377-
if (isa<CallBase>(V))
378-
return isReturnPosition(EncodingBits) ? IRP_CALL_SITE_RETURNED
379-
: IRP_CALL_SITE;
380-
return IRP_FLOAT;
366+
}
367+
368+
assert(KindOrArgNo < 0 &&
369+
"Expected (call site) arguments to never reach this point!");
370+
return Kind(KindOrArgNo);
381371
}
382372

383373
/// TODO: Figure out if the attribute related helper functions should live
@@ -445,52 +435,14 @@ struct IRPosition {
445435
static const IRPosition TombstoneKey;
446436
///}
447437

448-
/// Conversion into a void * to allow reuse of pointer hashing.
449-
operator void *() const { return Enc.getOpaqueValue(); }
450-
451438
private:
452439
/// Private constructor for special values only!
453-
explicit IRPosition(void *Ptr) { Enc.setFromOpaqueValue(Ptr); }
440+
explicit IRPosition(int KindOrArgNo)
441+
: AnchorVal(0), KindOrArgNo(KindOrArgNo) {}
454442

455443
/// IRPosition anchored at \p AnchorVal with kind/argument numbet \p PK.
456-
explicit IRPosition(Value &AnchorVal, Kind PK) {
457-
switch (PK) {
458-
case IRPosition::IRP_INVALID:
459-
llvm_unreachable("Cannot create invalid IRP with an anchor value!");
460-
break;
461-
case IRPosition::IRP_FLOAT:
462-
// Special case for floating functions.
463-
if (isa<Function>(AnchorVal))
464-
Enc = {&AnchorVal, ENC_FLOATING_FUNCTION};
465-
else
466-
Enc = {&AnchorVal, ENC_VALUE};
467-
break;
468-
case IRPosition::IRP_FUNCTION:
469-
case IRPosition::IRP_CALL_SITE:
470-
Enc = {&AnchorVal, ENC_VALUE};
471-
break;
472-
case IRPosition::IRP_RETURNED:
473-
case IRPosition::IRP_CALL_SITE_RETURNED:
474-
Enc = {&AnchorVal, ENC_RETURNED_VALUE};
475-
break;
476-
case IRPosition::IRP_ARGUMENT:
477-
Enc = {&AnchorVal, ENC_VALUE};
478-
break;
479-
case IRPosition::IRP_CALL_SITE_ARGUMENT:
480-
llvm_unreachable(
481-
"Cannot create call site argument IRP with an anchor value!");
482-
break;
483-
}
484-
verify();
485-
}
486-
487-
/// IRPosition for the use \p U. The position kind \p PK needs to be
488-
/// IRP_CALL_SITE_ARGUMENT, the anchor value is the user, the associated value
489-
/// the used value.
490-
explicit IRPosition(Use &U, Kind PK) {
491-
assert(PK == IRP_CALL_SITE_ARGUMENT &&
492-
"Use constructor is for call site arguments only!");
493-
Enc = {&U, ENC_CALL_SITE_ARGUMENT_USE};
444+
explicit IRPosition(Value &AnchorVal, Kind PK)
445+
: AnchorVal(&AnchorVal), KindOrArgNo(PK) {
494446
verify();
495447
}
496448

@@ -507,65 +459,30 @@ struct IRPosition {
507459
SmallVectorImpl<Attribute> &Attrs,
508460
Attributor &A) const;
509461

510-
/// Return the underlying pointer as Value *, valid for all positions but
511-
/// IRP_CALL_SITE_ARGUMENT.
512-
Value *getAsValuePtr() const {
513-
assert(getEncodingBits() != ENC_CALL_SITE_ARGUMENT_USE &&
514-
"Not a value pointer!");
515-
return reinterpret_cast<Value *>(Enc.getPointer());
516-
}
517-
518-
/// Return the underlying pointer as Use *, valid only for
519-
/// IRP_CALL_SITE_ARGUMENT positions.
520-
Use *getAsUsePtr() const {
521-
assert(getEncodingBits() == ENC_CALL_SITE_ARGUMENT_USE &&
522-
"Not a value pointer!");
523-
return reinterpret_cast<Use *>(Enc.getPointer());
524-
}
525-
526-
/// Return true if \p EncodingBits describe a returned or call site returned
527-
/// position.
528-
static bool isReturnPosition(char EncodingBits) {
529-
return EncodingBits == ENC_RETURNED_VALUE;
530-
}
531-
532-
/// Return true if the encoding bits describe a returned or call site returned
533-
/// position.
534-
bool isReturnPosition() const { return isReturnPosition(getEncodingBits()); }
535-
536-
/// The encoding of the IRPosition is a combination of a pointer and two
537-
/// encoding bits. The values of the encoding bits are defined in the enum
538-
/// below. The pointer is either a Value* (for the first three encoding bit
539-
/// combinations) or Use* (for ENC_CALL_SITE_ARGUMENT_USE).
540-
///
541-
///{
542-
enum {
543-
ENC_VALUE = 0b00,
544-
ENC_RETURNED_VALUE = 0b01,
545-
ENC_FLOATING_FUNCTION = 0b10,
546-
ENC_CALL_SITE_ARGUMENT_USE = 0b11,
547-
};
548-
549-
// Reserve the maximal amount of bits so there is no need to mask out the
550-
// remaining ones. We will not encode anything else in the pointer anyway.
551-
static constexpr int NumEncodingBits =
552-
PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
553-
static_assert(NumEncodingBits >= 2, "At least two bits are required!");
554-
555-
/// The pointer with the encoding bits.
556-
PointerIntPair<void *, NumEncodingBits, char> Enc;
557-
///}
558-
559-
/// Return the encoding bits.
560-
char getEncodingBits() const { return Enc.getInt(); }
462+
protected:
463+
/// The value this position is anchored at.
464+
Value *AnchorVal;
465+
466+
/// If AnchorVal is Argument or CallBase then this number should be
467+
/// non-negative and it denotes the argument or call site argument index
468+
/// respectively. Otherwise, it denotes the kind of this IRPosition according
469+
/// to Kind above.
470+
int KindOrArgNo;
561471
};
562472

563473
/// Helper that allows IRPosition as a key in a DenseMap.
564-
template <> struct DenseMapInfo<IRPosition> : DenseMapInfo<void *> {
474+
template <> struct DenseMapInfo<IRPosition> {
565475
static inline IRPosition getEmptyKey() { return IRPosition::EmptyKey; }
566476
static inline IRPosition getTombstoneKey() {
567477
return IRPosition::TombstoneKey;
568478
}
479+
static unsigned getHashValue(const IRPosition &IRP) {
480+
return (DenseMapInfo<Value *>::getHashValue(&IRP.getAnchorValue()) << 4) ^
481+
(unsigned(IRP.getArgNo()));
482+
}
483+
static bool isEqual(const IRPosition &LHS, const IRPosition &RHS) {
484+
return LHS == RHS;
485+
}
569486
};
570487

571488
/// A visitor class for IR positions.

0 commit comments

Comments
 (0)