@@ -2094,6 +2094,58 @@ Value *llvm::addRuntimeChecks(
20942094 return MemoryRuntimeCheck;
20952095}
20962096
2097+ Value *llvm::addSafeEltsRuntimeChecks (Instruction *Loc,
2098+ ArrayRef<PointerDiffInfo> Checks,
2099+ SCEVExpander &Expander, ElementCount VF) {
2100+ IRBuilder ChkBuilder (Loc->getContext (),
2101+ InstSimplifyFolder (Loc->getDataLayout ()));
2102+ ChkBuilder.SetInsertPoint (Loc);
2103+ Value *MemoryRuntimeCheck = nullptr ;
2104+
2105+ // Map to keep track of created compares, The key is the pair of operands for
2106+ // the compare, to allow detecting and re-using redundant compares.
2107+ DenseMap<std::pair<Value *, Value *>, Value *> SeenCompares;
2108+ Value *AliasLaneMask = nullptr ;
2109+ for (const auto &[SrcStart, SinkStart, AccessSize, NeedsFreeze,
2110+ WriteAfterRead] : Checks) {
2111+ Type *Ty = SinkStart->getType ();
2112+ Value *Sink = Expander.expandCodeFor (SinkStart, Ty, Loc);
2113+ Value *Src = Expander.expandCodeFor (SrcStart, Ty, Loc);
2114+ if (SeenCompares.lookup ({Sink, Src}))
2115+ continue ;
2116+
2117+ unsigned IntOpc = WriteAfterRead ? Intrinsic::loop_dependence_war_mask
2118+ : Intrinsic::loop_dependence_raw_mask;
2119+ Value *SourceAsPtr = ChkBuilder.CreateCast (Instruction::IntToPtr, Src,
2120+ ChkBuilder.getPtrTy ());
2121+ Value *SinkAsPtr = ChkBuilder.CreateCast (Instruction::IntToPtr, Sink,
2122+ ChkBuilder.getPtrTy ());
2123+ Value *M = ChkBuilder.CreateIntrinsic (
2124+ IntOpc, {VectorType::get (ChkBuilder.getInt1Ty (), VF)},
2125+ {SourceAsPtr, SinkAsPtr, ChkBuilder.getInt64 (AccessSize)}, nullptr ,
2126+ " alias.lane.mask" );
2127+ SeenCompares.insert ({{Sink, Src}, M});
2128+ if (AliasLaneMask)
2129+ M = ChkBuilder.CreateAnd (AliasLaneMask, M);
2130+ else
2131+ AliasLaneMask = M;
2132+ }
2133+ assert (AliasLaneMask && " Expected an alias lane mask to have been created." );
2134+ auto *VecVT = VectorType::get (ChkBuilder.getInt1Ty (), VF);
2135+ // Extend to an i8 since i1 is too small to add with
2136+ Value *PopCount = ChkBuilder.CreateCast (
2137+ Instruction::ZExt, AliasLaneMask,
2138+ VectorType::get (ChkBuilder.getInt8Ty (), VecVT->getElementCount ()));
2139+
2140+ PopCount =
2141+ ChkBuilder.CreateUnaryIntrinsic (Intrinsic::vector_reduce_add, PopCount);
2142+ PopCount = ChkBuilder.CreateCast (Instruction::ZExt, PopCount,
2143+ ChkBuilder.getInt64Ty ());
2144+ MemoryRuntimeCheck = ChkBuilder.CreateICmpUGT (
2145+ PopCount, ConstantInt::get (ChkBuilder.getInt64Ty (), 0 ));
2146+ return MemoryRuntimeCheck;
2147+ }
2148+
20972149Value *llvm::addDiffRuntimeChecks (
20982150 Instruction *Loc, ArrayRef<PointerDiffInfo> Checks, SCEVExpander &Expander,
20992151 function_ref<Value *(IRBuilderBase &, unsigned )> GetVF, unsigned IC) {
@@ -2108,7 +2160,8 @@ Value *llvm::addDiffRuntimeChecks(
21082160 // Map to keep track of created compares, The key is the pair of operands for
21092161 // the compare, to allow detecting and re-using redundant compares.
21102162 DenseMap<std::pair<Value *, Value *>, Value *> SeenCompares;
2111- for (const auto &[SrcStart, SinkStart, AccessSize, NeedsFreeze] : Checks) {
2163+ for (const auto &[SrcStart, SinkStart, AccessSize, NeedsFreeze,
2164+ WriteAfterRead] : Checks) {
21122165 Type *Ty = SinkStart->getType ();
21132166 // Compute VF * IC * AccessSize.
21142167 auto *VFTimesICTimesSize =
@@ -2117,8 +2170,8 @@ Value *llvm::addDiffRuntimeChecks(
21172170 Value *Diff =
21182171 Expander.expandCodeFor (SE.getMinusSCEV (SinkStart, SrcStart), Ty, Loc);
21192172
2120- // Check if the same compare has already been created earlier. In that case,
2121- // there is no need to check it again.
2173+ // Check if the same compare has already been created earlier. In that
2174+ // case, there is no need to check it again.
21222175 Value *IsConflict = SeenCompares.lookup ({Diff, VFTimesICTimesSize});
21232176 if (IsConflict)
21242177 continue ;
0 commit comments