@@ -520,9 +520,61 @@ bool StatelessToStateful::pointerIsFromKernelArgument(Value &ptr) {
520520 return false ;
521521}
522522
523- bool StatelessToStateful::pointerIsPositiveOffsetFromKernelArgument (
524- Function *F, Value *V, Value *&offset, unsigned int &argNumber, bool ignoreSyncBuffer,
525- std::optional<llvm::Align> OriginalInstructionAlignment) {
523+ static alignment_t determinePointerAlignment (Value *Ptr, const DataLayout &DL, AssumptionCache *AC,
524+ Instruction *InsertionPt) {
525+ alignment_t BestAlign = 1 ;
526+
527+ // 1) Examine uses: look for loads/stores (which may carry explicit
528+ // alignment) or a GEP that reveals an ABI alignment from its element
529+ // type.
530+ for (User *U : Ptr->users ()) {
531+ if (auto *LI = dyn_cast<LoadInst>(U)) {
532+ // Load has an explicit alignment.
533+ alignment_t LdAlign = LI->getAlign ().value ();
534+ if (LdAlign > BestAlign)
535+ BestAlign = LdAlign;
536+ } else if (auto *SI = dyn_cast<StoreInst>(U)) {
537+ // Store sets alignment only if the pointer we store into is Ptr.
538+ if (SI->getPointerOperand () == Ptr) {
539+ alignment_t StAlign = SI->getAlign ().value ();
540+ if (StAlign > BestAlign)
541+ BestAlign = StAlign;
542+ }
543+ } else if (auto *GEP = dyn_cast<GetElementPtrInst>(U)) {
544+ // If the GEP's source element type is sized, we can guess an ABI
545+ // alignment.
546+ Type *BaseTy = GEP->getSourceElementType ();
547+ if (BaseTy && BaseTy->isSized ()) {
548+ alignment_t GEPAlign = DL.getABITypeAlign (BaseTy).value ();
549+ if (GEPAlign > BestAlign)
550+ BestAlign = GEPAlign;
551+ }
552+ }
553+ }
554+
555+ // 2) If this pointer is actually a function parameter, see if it has an
556+ // alignment attribute.
557+ if (auto *Arg = dyn_cast<Argument>(Ptr)) {
558+ if (Arg->hasAttribute (llvm::Attribute::Alignment)) {
559+ if (MaybeAlign ArgAlign = Arg->getParamAlign ()) {
560+ alignment_t ArgAlignOrOne = ArgAlign.valueOrOne ().value ();
561+ if (ArgAlignOrOne > BestAlign)
562+ BestAlign = ArgAlignOrOne;
563+ }
564+ }
565+ }
566+
567+ // 3) Fallback: use LLVM's built-in assumption-based alignment analysis
568+ // (based on a.o. llvm.assume intrinsics).
569+ Align Known = getKnownAlignment (Ptr, DL, InsertionPt, AC);
570+ if (Known > BestAlign)
571+ BestAlign = Known.value ();
572+
573+ return BestAlign;
574+ }
575+
576+ bool StatelessToStateful::pointerIsPositiveOffsetFromKernelArgument (Function *F, Value *V, Value *&offset,
577+ unsigned int &argNumber, bool ignoreSyncBuffer) {
526578 const DataLayout *DL = &F->getParent ()->getDataLayout ();
527579
528580 AssumptionCache *AC = getAC (F);
@@ -572,20 +624,9 @@ bool StatelessToStateful::pointerIsPositiveOffsetFromKernelArgument(
572624 // guarantted to be DW-aligned.)
573625 //
574626 // Note that implicit arg is always aligned.
575- bool isAlignedPointee = false ;
576-
577- if (arg->isImplicitArg ()) {
578- isAlignedPointee = true ;
579- } else {
580- auto knownAlignment = getKnownAlignment ((Value *)arg->getArg (), *DL, F->getEntryBlock ().getFirstNonPHI (), AC);
581-
582- if (knownAlignment >= 4 ) {
583- isAlignedPointee = true ;
584- } else if (OriginalInstructionAlignment.has_value () &&
585- IGC::isStatefulAddrSpace (V->getType ()->getPointerAddressSpace ())) {
586- isAlignedPointee = OriginalInstructionAlignment.value () >= 4 ;
587- }
588- }
627+ bool isAlignedPointee = arg->isImplicitArg ()
628+ ? true
629+ : determinePointerAlignment (base, *DL, AC, F->getEntryBlock ().getFirstNonPHI ()) >= 4 ;
589630
590631 // If m_hasBufferOffsetArg is true, the offset argument is added to
591632 // the final offset to make it definitely positive. Thus skip checking
@@ -614,7 +655,6 @@ bool StatelessToStateful::pointerIsPositiveOffsetFromKernelArgument(
614655 updateArgInfo (arg, gepProducesPositivePointer);
615656 }
616657 }
617-
618658 if ((m_hasBufferOffsetArg || (gepProducesPositivePointer && isAlignedPointee)) &&
619659 getOffsetFromGEP (F, GEPs, argNumber, arg->isImplicitArg (), offset)) {
620660 return true ;
@@ -880,14 +920,12 @@ void StatelessToStateful::promote() {
880920 resAllocMD->uavsNumType += m_promotionMap.size ();
881921}
882922
883- void StatelessToStateful::addToPromotionMap (Instruction &I, Value *Ptr,
884- std::optional<llvm::Align> OriginalInstructionAlignment = std::nullopt ) {
923+ void StatelessToStateful::addToPromotionMap (Instruction &I, Value *Ptr) {
885924 Value *offset = nullptr ;
886925 unsigned baseArgNumber = 0 ;
887926
888- bool isPromotable =
889- m_promotionMap.size () < maxPromotionCount &&
890- pointerIsPositiveOffsetFromKernelArgument (m_F, Ptr, offset, baseArgNumber, true , OriginalInstructionAlignment);
927+ bool isPromotable = m_promotionMap.size () < maxPromotionCount &&
928+ pointerIsPositiveOffsetFromKernelArgument (m_F, Ptr, offset, baseArgNumber, true );
891929
892930 if (isPromotable) {
893931 InstructionInfo II (&I, Ptr, offset);
@@ -986,7 +1024,7 @@ void StatelessToStateful::visitCallInst(CallInst &I) {
9861024
9871025void StatelessToStateful::visitLoadInst (LoadInst &I) {
9881026 Value *ptr = I.getPointerOperand ();
989- addToPromotionMap (I, ptr, I. getAlign () );
1027+ addToPromotionMap (I, ptr);
9901028
9911029 // check if there's non-kernel-arg load/store
9921030 if (IGC_IS_FLAG_ENABLED (DumpHasNonKernelArgLdSt) && ptr != nullptr && !pointerIsFromKernelArgument (*ptr)) {
@@ -998,7 +1036,7 @@ void StatelessToStateful::visitLoadInst(LoadInst &I) {
9981036
9991037void StatelessToStateful::visitStoreInst (StoreInst &I) {
10001038 Value *ptr = I.getPointerOperand ();
1001- addToPromotionMap (I, ptr, I. getAlign () );
1039+ addToPromotionMap (I, ptr);
10021040
10031041 if (IGC_IS_FLAG_ENABLED (DumpHasNonKernelArgLdSt) && ptr != nullptr && !pointerIsFromKernelArgument (*ptr)) {
10041042 ModuleMetaData *modMD = getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData ();
0 commit comments