Repository: llvm/llvm-project
File: llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp (C++)

Code before:

class AMDGPUCodeGenPrepare : public FunctionPass {
public:
  static char ID;
  AMDGPUCodeGenPrepare() : FunctionPass(ID) {}
  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<AssumptionCacheTracker>();
    AU.addRequired<UniformityInfoWrapperPass>();
    AU.addRequired<TargetLibraryInfoWrapperPass>();

    // FIXME: Division expansion needs to preserve the dominator tree.
    if (!ExpandDiv64InIR)
      AU.setPreservesAll();
  }
  bool runOnFunction(Function &F) override;
  StringRef getPassName() const override { return "AMDGPU IR optimizations"; }
};

static bool markDereferenceableCalls(Function &F) {
  if (F.hasFnAttribute("amdgpu-no-implicitarg-ptr"))
    return false;

  bool Changed = false;
  unsigned CodeObjectVersion =
      AMDGPU::getAMDHSACodeObjectVersion(*(F.getParent()));
  uint64_t Bytes = (CodeObjectVersion >= AMDGPU::AMDHSA_COV5) ? 256 : 64;

  for (BasicBlock &BB : F)
    for (Instruction &I : BB)
      if (auto *CI = dyn_cast<CallInst>(&I)) {
        Function *Callee = CI->getCalledFunction();
        if (!Callee)
          continue;

        // Check if this is a call to amdgcn_implicitarg_ptr intrinsic
        Intrinsic::ID IID = Callee->getIntrinsicID();
        if (IID != Intrinsic::amdgcn_implicitarg_ptr)
          continue;

        if (!CI->hasRetAttr(Attribute::Dereferenceable)) {
          CI->addRetAttr(
              Attribute::getWithDereferenceableBytes(CI->getContext(), Bytes));
          Changed = true;
        }
      }

  return Changed;
}
} // end anonymous namespace

bool AMDGPUCodeGenPrepareImpl::run() {

Review comment (bug):
The dereferenceable byte size for code object versions before COV5 is incorrect. According to AMDGPUSubtarget::getImplicitArgNumBytes (line 356 in AMDGPUSubtarget.cpp), the implicit argument structure size for COV4 is 56 bytes, not 64 bytes. This should be changed to match the correct size to avoid potential memory safety issues where the dereferenceable attribute claims more bytes are safely accessible than actually exist.
```suggestion
  uint64_t Bytes = (CodeObjectVersion >= AMDGPU::AMDHSA_COV5) ? 256 : 56;
```

Code after:
    AU.addRequired<AssumptionCacheTracker>();
    AU.addRequired<UniformityInfoWrapperPass>();
    AU.addRequired<TargetLibraryInfoWrapperPass>();

    // FIXME: Division expansion needs to preserve the dominator tree.
    if (!ExpandDiv64InIR)
      AU.setPreservesAll();
  }
  bool runOnFunction(Function &F) override;
  StringRef getPassName() const override { return "AMDGPU IR optimizations"; }
};

} // end anonymous namespace

bool AMDGPUCodeGenPrepareImpl::run() {
  BreakPhiNodesCache.clear();
  bool MadeChange = false;

  // Need to use make_early_inc_range because integer division expansion is
  // handled by Transform/Utils, and it can delete instructions such as the
  // terminator of the BB.
  for (BasicBlock &BB : reverse(F)) {
    for (Instruction &I : make_early_inc_range(reverse(BB))) {
      if (!isInstructionTriviallyDead(&I, TLI))
        MadeChange |= visit(I);
    }
  }

  while (!DeadVals.empty()) {
    if (auto *I = dyn_cast_or_null<Instruction>(DeadVals.pop_back_val()))
      RecursivelyDeleteTriviallyDeadInstructions(I, TLI);
  }

  return MadeChange;
}

bool AMDGPUCodeGenPrepareImpl::isLegalFloatingTy(const Type *Ty) const {
  return Ty->isFloatTy() || Ty->isDoubleTy() ||
         (Ty->isHalfTy() && ST.has16BitInsts());
}

bool AMDGPUCodeGenPrepareImpl::canWidenScalarExtLoad(LoadInst &I) const {
  Type *Ty = I.getType();
  int TySize = DL.getTypeSizeInBits(Ty);
  Align Alignment = DL.getValueOrABITypeAlignment(I.getAlign(), Ty);

  return I.isSimple() && TySize < 32 && Alignment >= 4 && UA.isUniform(&I);
}

unsigned
AMDGPUCodeGenPrepareImpl::numBitsUnsigned(Value *Op,