[llvm-dev] [LAA] RtCheck on pointers of different address spaces.

Stefanos Baziotis via llvm-dev llvm-dev at lists.llvm.org
Sun Jul 26 05:39:29 PDT 2020


Hi,

There are a lot of things going on here, but given this:

>  The crash occurs with the pointers 1 & 4 which are from AS1 and AS2
respectively.

and the trace, I'm not sure how that can happen. `groupChecks()` will only
try to group pointers that
are on the same alias set (because it will only try to group pointers that
are in the same Eq class
in DepCands, which if you see its construction in `processMemAccesses()`,
won't put two pointers
from different alias sets in the same Eq Class because _theoretically_, two
such pointers can't
share an underlying object).

Do maybe have a simplified but complete IR ? Is that a possibility?

Kind regards,
Stefanos Baziotis

Στις Κυρ, 26 Ιουλ 2020 στις 1:06 μ.μ., ο/η Devadasan, Christudasan via
llvm-dev <llvm-dev at lists.llvm.org> έγραψε:

> Hello,
>
>
>
> I Have a question related to the RT check on pointers during Loop Access
> Analysis pass.
>
>
>
> There is a testcase with loop code that consist of 4 different memory
> operations referring two global objects of different address spaces.
>
> One from global constant (address space 4, addr_size = 64) and the other
> from local, LDS (address space 3, addr_size= 32).
>
> (Details of various address spaces available for AMDGPU backend:
> https://llvm.org/docs/AMDGPUUsage.html#address-spaces)
>
>
>
> With upstream compiler, the testcase fails with a crash (given at the end
> of the e-mail) in the opt while trying to generate the RT check for these
> pointers. Precisely, with two pointers of different address spaces.
>
> The operand type check fails while trying to insert a ‘AddExpr’ SCEV node
> as their effective type differs for these pointers (One with 32-bit and the
> other with 64-bit)
>
>
>
> *Question: Is this intended to try for the RtCheck on pointers from
> different address spaces? *
>
>                    The comments given in the code snippet (below) hints
> they aren’t.
>
>
>
> Code snippet from LoopAccessAnalysis.cpp:
>
>
> -----------------------------------------------------------------------------------------------------------------------
>
>   bool AccessAnalysis::canCheckPtrAtRT(...) {
>
>                   ----------
>
>   // If the pointers that we would use for the bounds comparison have
> different
>
>   // address spaces, assume the values aren't directly comparable, so we
> can't
>
>   // use them for the runtime check. We also have to assume they could
>
>   // overlap. In the future there should be metadata for whether address
> spaces
>
>   // are disjoint.
>
>   unsigned NumPointers = RtCheck.Pointers.size();
>
>   for (unsigned i = 0; i < NumPointers; ++i) {
>
>    for (unsigned j = i + 1; j < NumPointers; ++j) {
>
>       // Only need to check pointers between two different dependency sets.
>
>           if (RtCheck.Pointers[i].DependencySetId ==
>
>           RtCheck.Pointers[j].DependencySetId)
>
>        continue;
>
>       // Only need to check pointers in the same alias set.
>
>       if (RtCheck.Pointers[i].AliasSetId != RtCheck.Pointers[j].AliasSetId)
>
>         continue;
>
>
>
>       Value *PtrI = RtCheck.Pointers[i].PointerValue;
>
>       Value *PtrJ = RtCheck.Pointers[j].PointerValue;
>
>
>
>       unsigned ASi = PtrI->getType()->getPointerAddressSpace();
>
>       unsigned ASj = PtrJ->getType()->getPointerAddressSpace();
>
>       if (ASi != ASj) {
>
>         LLVM_DEBUG(
>
>             dbgs() << "LAA: Runtime check would require comparison between"
>
>                       " different address spaces\n");
>
>         return false;
>
>       }
>
>     }
>
>
> ----------------------------------------------------------------------------------------------------
>
> More details about the objects, the pointers and the memory operations:
>
>
> ----------------------------------------------------------------------------------------------------
>
> %struct_var1 = type { <2 x float> }
>
> %struct_var2 = type { %struct_var1 }
>
> %class_var1 = type { i32, i32, i32, %struct_var2*, i32, i32, i32}
>
> %class_var2 = type { %class_var1, i8, i8*, i32 }
>
>
>
> Objects:
>
> @Obj1 = external protected local_unnamed_addr addrspace(4)
> externally_initialized global %class_var2, align 8
>
> @Obj2 = internal unnamed_addr addrspace(3) constant [4000 x float] undef,
> align 16
>
>
>
> Pointers:
>
> 1.       %struct_var1.cast = bitcast %struct_var1* %struct_var2.gep to
> i64* (write)       // AS1
>
> 2.       %struct_var2.cast = bitcast %struct_var2* %arrayidx74 to i64*
> (read-only)        // AS1
>
> 3.       %arrayidx1705 = getelementptr inbounds [4000 x float], [4000 x
> float] addrspace(3)* @Obj2, i32 0, i32 %add125 (read-only) // AS2
>
> 4.       %arrayidx274 = getelementptr inbounds [4000 x float], [4000 x
> float] addrspace(3)* @Obj2, i32 0, i32 %arg1 (read-only)  // AS2
>
>
>
> While the pointers 1 & 2 belong to one Alias Set (AS1), pointers 3 & 4
> belong to a different set (AS2). It is because, the Global Alias Analysis
> found there is no alias between these two sets of pointers.
>
> The crash occurs with the pointers 1 & 4 which are from AS1 and AS2
> respectively.
>
> The DependenceSetId will be reset to 1 before processing a new AS and the
> pointers in question, ended up having the same DependenceSetId (1), though
> they are from different AS.
>
>
>
>
>            ----------------------------------------------------------------------------------------------------------------------------------------------------------
>
>             The load/store (memory operations) using these pointers in the
> loop. (extracted only the relevant instructions):
>
>
>            ----------------------------------------------------------------------------------------------------------------------------------------------------------
>
>             define protected amdgpu_kernel void @test_func(i32 %arg1, i32
> %arg2) {
>
>               entry:
>
>   *%arrayidx274 = getelementptr inbounds [4000 x float], [4000 x float]
> addrspace(3)* @Obj2, i32 0, i32 %arg1*
>
>           ---------
>
>   br i1 %cmp1, label %header, label %for.end
>
>
>
> header:
>
>   % *struct_var2.ld* = load %struct_var2*, %struct_var2* addrspace(4)*
> getelementptr inbounds (%class_var2, %class_var2 addrspace(4)* @Obj1, i64
> 0, i32 0, i32 3), align 8
>
>   %struct_var2.gep = getelementptr inbounds %struct_var2, %struct_var2*
> %struct_var2.ld, i64 undef, i32 0
>
> *  %struct_var1.cast = bitcast %struct_var1* %struct_var2.gep to i64**
>
>   br label %for.body
>
>
>
> for.body:
>
>           ---------
>
>    %arrayidx74 = getelementptr inbounds %struct_var2, %struct_var2*
> %struct_var2.ld, i64 %idxprom73
>
> *   %struct_var2.cast = bitcast %struct_var2* %arrayidx74 to i64**
>
>    %for.body.ld = load i64, i64* %*struct_var2.cast*, align 8
>
>           ---------
>
>   br i1 %cmp2, label %if.then, label %if.end
>
>
>
> if.then:
>
>   %rem = srem i32 1, %arg2
>
>   %add125 = add nuw nsw i32 %rem, 1
>
> *  %arrayidx1705 = getelementptr inbounds [4000 x float], [4000 x float]
> addrspace(3)* @Obj2, i32 0, i32 %add125*
>
>   %arrayidx1705.ld = load float, float addrspace(3)* %*arrayidx1705*,
> align 4
>
>   %arrayidx274.ld = load float, float addrspace(3)* %*arrayidx274*, align
> 4
>
>           ---------
>
>   br label %if.end
>
>
>
> if.end:
>
>   store i64 %for.body.ld, i64* %*struct_var1.cast*, align 8
>
>           ---------
>
>   br i1 %cmp3, label %for.body, label %for.end
>
>
>
> for.end:
>
>   br exit
>
>
>
> exit:
>
>           }
>
>
>
>
> ----------------------------------------------------------------------------------------------------------------------------------------------------------
>
> The actual crash and the back-trace:
>
>
> ----------------------------------------------------------------------------------------------------------------------------------------------------------
>
> opt: $SRC/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:2165: const
> llvm::SCEV *llvm::ScalarEvolution::getAddExpr(SmallVectorImpl<const
> llvm::SCEV *> &, SCEV::NoWrapFlags, unsigned int): Assertion
> `getEffectiveSCEVType(Ops[i]->getType()) == ETy && "SCEVAddExpr operand
> types don't match!"' failed.
>
> PLEASE submit a bug report to https://bugs.llvm.org/ and include the
> crash backtrace.
>
> Stack dump:
>
> 0.      Program arguments: $Tools/bin/opt -O3 test.ll -o out.ll
>
>
>
> llvm::ScalarEvolution::getAddExpr(llvm::SmallVectorImpl<llvm::SCEV
> const*>&, llvm::SCEV::NoWrapFlags, unsigned int)
> $SRC/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:2164:5
>
> llvm::ScalarEvolution::getAddExpr(llvm::SCEV const*, llvm::SCEV const*,
> llvm::SCEV::NoWrapFlags, unsigned int)
> $SRC/llvm-project/llvm/include/llvm/Analysis/ScalarEvolution.h:526:3
>
> llvm::ScalarEvolution::getMinusSCEV(llvm::SCEV const*, llvm::SCEV const*,
> llvm::SCEV::NoWrapFlags, unsigned int)
> $SRC/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:3833:3
>
> getMinFromExprs(llvm::SCEV const*, llvm::SCEV const*,
> llvm::ScalarEvolution*)
> $SRC/llvm-project/llvm/lib/Analysis/LoopAccessAnalysis.cpp:275:15
>
> llvm::RuntimeCheckingPtrGroup::addPointer(unsigned int)
> $SRC/llvm-project/llvm/lib/Analysis/LoopAccessAnalysis.cpp:292:15
>
> llvm::RuntimePointerChecking::groupChecks(llvm::EquivalenceClasses<llvm::PointerIntPair<llvm::Value*,
> 1u, bool, llvm::PointerLikeTypeTraits<llvm::Value*>,
> llvm::PointerIntPairInfo<llvm::Value*, 1u,
> llvm::PointerLikeTypeTraits<llvm::Value*> > > >&, bool)
> $SRC/llvm-project/llvm/lib/Analysis/LoopAccessAnalysis.cpp:413:13
>
> llvm::RuntimePointerChecking::generateChecks(llvm::EquivalenceClasses<llvm::PointerIntPair<llvm::Value*,
> 1u, bool, llvm::PointerLikeTypeTraits<llvm::Value*>,
> llvm::PointerIntPairInfo<llvm::Value*, 1u,
> llvm::PointerLikeTypeTraits<llvm::Value*> > > >&, bool)
> $SRC/llvm-project/llvm/lib/Analysis/LoopAccessAnalysis.cpp:259:12
>
> (anonymous
> namespace)::AccessAnalysis::canCheckPtrAtRT(llvm::RuntimePointerChecking&,
> llvm::ScalarEvolution*, llvm::Loop*, llvm::DenseMap<llvm::Value const*,
> llvm::Value*, llvm::DenseMapInfo<llvm::Value const*>,
> llvm::detail::DenseMapPair<llvm::Value const*, llvm::Value*> > const&,
> bool) $SRC/llvm-project/llvm/lib/Analysis/LoopAccessAnalysis.cpp:830:3
>
> llvm::LoopAccessInfo::analyzeLoop(llvm::AAResults*, llvm::LoopInfo*,
> llvm::TargetLibraryInfo const*, llvm::DominatorTree*)
> $SRC/llvm-project/llvm/lib/Analysis/LoopAccessAnalysis.cpp:2038:8
>
> llvm::LoopAccessInfo::LoopAccessInfo(llvm::Loop*, llvm::ScalarEvolution*,
> llvm::TargetLibraryInfo const*, llvm::AAResults*, llvm::DominatorTree*,
> llvm::LoopInfo*)
> $SRC/llvm-project/llvm/lib/Analysis/LoopAccessAnalysis.cpp:2222:1
>
> std::_MakeUniq<llvm::LoopAccessInfo>::__single_object
> std::make_unique<llvm::LoopAccessInfo, llvm::Loop*&,
> llvm::ScalarEvolution*&, llvm::TargetLibraryInfo const*&,
> llvm::AAResults*&, llvm::DominatorTree*&, llvm::LoopInfo*&>(llvm::Loop*&,
> llvm::ScalarEvolution*&, llvm::TargetLibraryInfo const*&,
> llvm::AAResults*&, llvm::DominatorTree*&, llvm::LoopInfo*&)
> /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/bits/unique_ptr.h:821:34
>
> llvm::LoopAccessLegacyAnalysis::getInfo(llvm::Loop*)
> $SRC/llvm-project/llvm/lib/Analysis/LoopAccessAnalysis.cpp:2275:5
>
> (anonymous
> namespace)::LoopLoadElimination::runOnFunction(llvm::Function&)::'lambda'(llvm::Loop&)::operator()(llvm::Loop&)
> const
> $SRC/llvm-project/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp:651:53
>
> llvm::LoopAccessInfo const& llvm::function_ref<llvm::LoopAccessInfo const&
> (llvm::Loop&)>::callback_fn<(anonymous
> namespace)::LoopLoadElimination::runOnFunction(llvm::Function&)::'lambda'(llvm::Loop&)>(long,
> llvm::Loop&) $SRC/llvm-project/llvm/include/llvm/ADT/STLExtras.h:185:5
>
> llvm::function_ref<llvm::LoopAccessInfo const&
> (llvm::Loop&)>::operator()(llvm::Loop&) const
> $SRC/llvm-project/llvm/include/llvm/ADT/STLExtras.h:203:5
>
> eliminateLoadsAcrossLoops(llvm::Function&, llvm::LoopInfo&,
> llvm::DominatorTree&, llvm::BlockFrequencyInfo*, llvm::ProfileSummaryInfo*,
> llvm::function_ref<llvm::LoopAccessInfo const& (llvm::Loop&)>)
> $SRC/llvm-project/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp:618:53
>
> (anonymous namespace)::LoopLoadElimination::runOnFunction(llvm::Function&)
> $SRC/llvm-project/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp:649:5
>
> llvm::FPPassManager::runOnFunction(llvm::Function&)
> $SRC/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1587:23
>
> llvm::FPPassManager::runOnModule(llvm::Module&)
> $SRC/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1629:16
>
> (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&)
> $SRC/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1698:23
>
> llvm::legacy::PassManagerImpl::run(llvm::Module&)
> $SRC/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:614:16
>
> llvm::legacy::PassManager::run(llvm::Module&)
> $SRC/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1824:3
>
> main $SRC/llvm-project/llvm/tools/opt/opt.cpp:955:3
>
> __libc_start_main
> /build/glibc-2ORdQG/glibc-2.27/csu/../csu/libc-start.c:344:0
>
> _start ($Tools/bin/opt+0xc98b6a)
>
> Aborted (core dumped)
>
>
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>
>
> Regards,
>
> CD
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200726/48741e5b/attachment.html>


More information about the llvm-dev mailing list