@@ -153,24 +153,29 @@ enum class DepClassTy {
153153// / are floating values that do not have a corresponding attribute list
154154// / position.
155155struct 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-
451438private:
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