@@ -14,6 +14,7 @@ SPDX-License-Identifier: MIT
1414#include " common/LLVMWarningsPush.hpp"
1515#include " llvm/Config/llvm-config.h"
1616#include " llvm/IR/GetElementPtrTypeIterator.h"
17+ #include < llvm/IR/ConstantRange.h>
1718#include < llvm/IR/InstIterator.h>
1819#include < llvm/IR/Intrinsics.h>
1920#include < llvm/Support/KnownBits.h>
@@ -2993,4 +2994,71 @@ bool AllowRemovingUnusedImplicitLocalIDs(const CodeGenContext *ctx) {
29932994 return ctx->platform .isCoreChildOf (IGFX_XE2_HPG_CORE );
29942995}
29952996
2997+ ExtractBoundsResult ExtractBounds (llvm::Use &U, llvm::AssumptionCache &AC , llvm::Instruction *CtxI,
2998+ bool peelLaunder /* = true*/ ) {
2999+ IGC_ASSERT_MESSAGE (U.get () && U.get ()->getType ()->isIntegerTy (), " Expecting an integer operand" );
3000+
3001+ ExtractBoundsResult Result;
3002+ llvm::Value *V = U.get ();
3003+ std::optional<llvm::ConstantRange> CRFromErasedLaunder;
3004+ Result.SourceValue = V;
3005+
3006+ if (peelLaunder) {
3007+ auto *MaybeLaunder = llvm::dyn_cast<GenIntrinsicInst>(V);
3008+ const bool IsLaunder = MaybeLaunder && MaybeLaunder->isGenIntrinsic (GenISAIntrinsic::GenISA_launder);
3009+ if (IsLaunder) {
3010+ llvm::Value *Operand = MaybeLaunder->getOperand (0 );
3011+ Result.SourceValue = Operand;
3012+ auto *OperandTy = llvm::dyn_cast<llvm::IntegerType>(Operand->getType ());
3013+ if (!OperandTy || OperandTy->getBitWidth () > 64 )
3014+ return Result;
3015+
3016+ if (auto *Constant = llvm::dyn_cast<llvm::ConstantInt>(Operand)) {
3017+ MaybeLaunder->replaceAllUsesWith (Operand);
3018+ MaybeLaunder->eraseFromParent ();
3019+ const uint64_t Lo = Constant->getZExtValue ();
3020+ Result.Bounds = std::make_pair (Lo, Lo + 1 );
3021+ return Result;
3022+ }
3023+
3024+ U.set (Operand);
3025+
3026+ if (MaybeLaunder->user_empty ()) {
3027+ CRFromErasedLaunder = llvm::computeConstantRange (MaybeLaunder, /* ForSigned=*/ false ,
3028+ /* UseInstrInfo=*/ true , &AC , CtxI,
3029+ /* DT=*/ nullptr , /* Depth=*/ 0 );
3030+ MaybeLaunder->eraseFromParent ();
3031+ V = nullptr ;
3032+ }
3033+ }
3034+ }
3035+
3036+ auto *Ty = llvm::dyn_cast<llvm::IntegerType>(Result.SourceValue ->getType ());
3037+ if (!Ty || Ty->getBitWidth () > 64 || !CtxI)
3038+ return Result;
3039+
3040+ const llvm::DataLayout &DL = CtxI->getModule ()->getDataLayout ();
3041+
3042+ llvm::ConstantRange CRFromOperand = llvm::computeConstantRange (
3043+ Result.SourceValue , /* ForSigned=*/ false , /* UseInstrInfo=*/ true , &AC , CtxI, /* DT=*/ nullptr , /* Depth=*/ 0 );
3044+ llvm::KnownBits KB = IGCLLVM::computeKnownBits (Result.SourceValue , DL , &AC , CtxI);
3045+ llvm::ConstantRange Combined = CRFromOperand.intersectWith (llvm::ConstantRange::fromKnownBits (KB , false ));
3046+
3047+ if (CRFromErasedLaunder.has_value ()) {
3048+ Combined = Combined.intersectWith (*CRFromErasedLaunder);
3049+ } else if (V && V != Result.SourceValue ) {
3050+ llvm::ConstantRange CRFromV = llvm::computeConstantRange (V, /* ForSigned=*/ false , /* UseInstrInfo=*/ true , &AC , CtxI,
3051+ /* DT=*/ nullptr , /* Depth=*/ 0 );
3052+ Combined = Combined.intersectWith (CRFromV);
3053+ }
3054+
3055+ if (!Combined.isFullSet ()) {
3056+ const uint64_t Lo = Combined.getUnsignedMin ().getZExtValue ();
3057+ const uint64_t Hi = Combined.getUnsignedMax ().getZExtValue () + 1 ;
3058+ Result.Bounds = std::make_pair (Lo, Hi);
3059+ }
3060+
3061+ return Result;
3062+ }
3063+
29963064} // namespace IGC
0 commit comments