[llvm] 121cac0 - [noalias.decl] Look through llvm.experimental.noalias.scope.decl
Jeroen Dobbelaere via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 19 11:12:48 PST 2021
Author: Jeroen Dobbelaere
Date: 2021-01-19T20:09:42+01:00
New Revision: 121cac01e8f8afe6ed2bb0b8ffe92f323776a716
URL: https://github.com/llvm/llvm-project/commit/121cac01e8f8afe6ed2bb0b8ffe92f323776a716
DIFF: https://github.com/llvm/llvm-project/commit/121cac01e8f8afe6ed2bb0b8ffe92f323776a716.diff
LOG: [noalias.decl] Look through llvm.experimental.noalias.scope.decl
Just like llvm.assume, there are a lot of cases where we can just ignore llvm.experimental.noalias.scope.decl.
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D93042
Added:
llvm/test/Analysis/BasicAA/noalias-scope-decl.ll
llvm/test/Analysis/MemorySSA/noalias-scope-decl.ll
llvm/test/Transforms/EarlyCSE/noalias-scope-decl.ll
llvm/test/Transforms/LoopVectorize/noalias-scope-decl.ll
Modified:
llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
llvm/include/llvm/Analysis/VectorUtils.h
llvm/lib/Analysis/AliasSetTracker.cpp
llvm/lib/Analysis/MemorySSA.cpp
llvm/lib/Analysis/ValueTracking.cpp
llvm/lib/Analysis/VectorUtils.cpp
llvm/lib/CodeGen/Analysis.cpp
llvm/lib/Transforms/Scalar/EarlyCSE.cpp
llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
llvm/test/Analysis/AliasSet/intrinsics.ll
llvm/test/Analysis/CostModel/X86/free-intrinsics.ll
llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll
llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index 47de99b02d97..1e9201430168 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -557,6 +557,7 @@ class TargetTransformInfoImplBase {
case Intrinsic::is_constant:
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end:
+ case Intrinsic::experimental_noalias_scope_decl:
case Intrinsic::objectsize:
case Intrinsic::ptr_annotation:
case Intrinsic::var_annotation:
diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h
index ce3cb22dcd6e..26cb0e456ed4 100644
--- a/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/llvm/include/llvm/Analysis/VectorUtils.h
@@ -304,7 +304,7 @@ typedef unsigned ID;
/// the incoming type is void, we return void. If the EC represents a
/// scalar, we return the scalar type.
inline Type *ToVectorTy(Type *Scalar, ElementCount EC) {
- if (Scalar->isVoidTy() || EC.isScalar())
+ if (Scalar->isVoidTy() || Scalar->isMetadataTy() || EC.isScalar())
return Scalar;
return VectorType::get(Scalar, EC);
}
diff --git a/llvm/lib/Analysis/AliasSetTracker.cpp b/llvm/lib/Analysis/AliasSetTracker.cpp
index 9b21fbf4c9b7..486b4d99dfae 100644
--- a/llvm/lib/Analysis/AliasSetTracker.cpp
+++ b/llvm/lib/Analysis/AliasSetTracker.cpp
@@ -438,6 +438,7 @@ void AliasSetTracker::addUnknown(Instruction *Inst) {
break;
// FIXME: Add lifetime/invariant intrinsics (See: PR30807).
case Intrinsic::assume:
+ case Intrinsic::experimental_noalias_scope_decl:
case Intrinsic::sideeffect:
case Intrinsic::pseudoprobe:
return;
diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp
index f0d27e0b2c6b..52dca7d378e1 100644
--- a/llvm/lib/Analysis/MemorySSA.cpp
+++ b/llvm/lib/Analysis/MemorySSA.cpp
@@ -285,6 +285,7 @@ instructionClobbersQuery(const MemoryDef *MD, const MemoryLocation &UseLoc,
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
case Intrinsic::assume:
+ case Intrinsic::experimental_noalias_scope_decl:
return {false, NoAlias};
case Intrinsic::dbg_addr:
case Intrinsic::dbg_declare:
@@ -1767,9 +1768,15 @@ MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I,
// dependencies here.
// FIXME: Replace this special casing with a more accurate modelling of
// assume's control dependency.
- if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
- if (II->getIntrinsicID() == Intrinsic::assume)
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
+ switch (II->getIntrinsicID()) {
+ default:
+ break;
+ case Intrinsic::assume:
+ case Intrinsic::experimental_noalias_scope_decl:
return nullptr;
+ }
+ }
// Using a nonstandard AA pipelines might leave us with unexpected modref
// results for I, so add a check to not model instructions that may not read
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 7f8f101d42af..4f0c7057089b 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -536,6 +536,7 @@ bool llvm::isAssumeLikeIntrinsic(const Instruction *I) {
case Intrinsic::invariant_end:
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end:
+ case Intrinsic::experimental_noalias_scope_decl:
case Intrinsic::objectsize:
case Intrinsic::ptr_annotation:
case Intrinsic::var_annotation:
diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp
index 1de17aac5170..9a4c96b6f7c2 100644
--- a/llvm/lib/Analysis/VectorUtils.cpp
+++ b/llvm/lib/Analysis/VectorUtils.cpp
@@ -125,6 +125,7 @@ Intrinsic::ID llvm::getVectorIntrinsicIDForCall(const CallInst *CI,
if (isTriviallyVectorizable(ID) || ID == Intrinsic::lifetime_start ||
ID == Intrinsic::lifetime_end || ID == Intrinsic::assume ||
+ ID == Intrinsic::experimental_noalias_scope_decl ||
ID == Intrinsic::sideeffect || ID == Intrinsic::pseudoprobe)
return ID;
return Intrinsic::not_intrinsic;
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index 48b69c8bc203..67eb079afb49 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -530,11 +530,12 @@ bool llvm::isInTailCallPosition(const CallBase &Call, const TargetMachine &TM) {
// Pseudo probe intrinsics do not block tail call optimization either.
if (isa<PseudoProbeInst>(BBI))
continue;
- // A lifetime end or assume intrinsic should not stop tail call
- // optimization.
+ // A lifetime end, assume or noalias.decl intrinsic should not stop tail
+ // call optimization.
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(BBI))
if (II->getIntrinsicID() == Intrinsic::lifetime_end ||
- II->getIntrinsicID() == Intrinsic::assume)
+ II->getIntrinsicID() == Intrinsic::assume ||
+ II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl)
continue;
if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() ||
!isSafeToSpeculativelyExecute(&*BBI))
diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index f005f69519f7..180a82917fa9 100644
--- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -1232,6 +1232,14 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
continue;
}
+ // Likewise, noalias intrinsics don't actually write.
+ if (match(&Inst,
+ m_Intrinsic<Intrinsic::experimental_noalias_scope_decl>())) {
+ LLVM_DEBUG(dbgs() << "EarlyCSE skipping noalias intrinsic: " << Inst
+ << '\n');
+ continue;
+ }
+
// Skip sideeffect intrinsics, for the same reason as assume intrinsics.
if (match(&Inst, m_Intrinsic<Intrinsic::sideeffect>())) {
LLVM_DEBUG(dbgs() << "EarlyCSE skipping sideeffect: " << Inst << '\n');
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index e3e522958c3a..2b873954f88b 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -944,6 +944,13 @@ bool LoopVectorizationLegality::blockCanBePredicated(
continue;
}
+ // Do not let llvm.experimental.noalias.scope.decl block the vectorization.
+ // TODO: there might be cases that it should block the vectorization. Let's
+ // ignore those for now.
+ if (match(&I, m_Intrinsic<Intrinsic::experimental_noalias_scope_decl>())) {
+ continue;
+ }
+
// We might be able to hoist the load.
if (I.mayReadFromMemory()) {
auto *LI = dyn_cast<LoadInst>(&I);
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 50e4ef01b616..865881bb429b 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -2868,6 +2868,13 @@ void InnerLoopVectorizer::scalarizeInstruction(Instruction *Instr, VPUser &User,
VPTransformState &State) {
assert(!Instr->getType()->isAggregateType() && "Can't handle vectors");
+ // llvm.experimental.noalias.scope.decl intrinsics must only be duplicated for
+ // the first lane and part.
+ if (auto *II = dyn_cast<IntrinsicInst>(Instr))
+ if (Instance.Lane != 0 || Instance.Part != 0)
+ if (II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl)
+ return;
+
setDebugLocFromInst(Builder, Instr);
// Does this instruction return a value ?
@@ -8225,7 +8232,8 @@ VPWidenCallRecipe *VPRecipeBuilder::tryToWidenCall(CallInst *CI, VFRange &Range,
Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
if (ID && (ID == Intrinsic::assume || ID == Intrinsic::lifetime_end ||
ID == Intrinsic::lifetime_start || ID == Intrinsic::sideeffect ||
- ID == Intrinsic::pseudoprobe))
+ ID == Intrinsic::pseudoprobe ||
+ ID == Intrinsic::experimental_noalias_scope_decl))
return nullptr;
auto willWiden = [&](ElementCount VF) -> bool {
diff --git a/llvm/test/Analysis/AliasSet/intrinsics.ll b/llvm/test/Analysis/AliasSet/intrinsics.ll
index 12c1a91e7b80..6aeb56ba596e 100644
--- a/llvm/test/Analysis/AliasSet/intrinsics.ll
+++ b/llvm/test/Analysis/AliasSet/intrinsics.ll
@@ -61,5 +61,25 @@ entry:
ret void
}
+; CHECK: Alias sets for function 'test5':
+; CHECK: Alias Set Tracker: 2 alias sets for 2 pointer values.
+; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, LocationSize::precise(1))
+; CHECK-NOT: 1 Unknown instruction
+; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %b, LocationSize::precise(1))
+define void @test5() {
+entry:
+ %a = alloca i8, align 1
+ %b = alloca i8, align 1
+ store i8 1, i8* %a, align 1
+ call void @llvm.experimental.noalias.scope.decl(metadata !0)
+ store i8 1, i8* %b, align 1
+ ret void
+}
+
declare void @llvm.assume(i1)
declare void @llvm.experimental.guard(i1, ...)
+declare void @llvm.experimental.noalias.scope.decl(metadata)
+
+!0 = !{ !1 }
+!1 = distinct !{ !1, !2, !"test5: var" }
+!2 = distinct !{ !2, !"test5" }
diff --git a/llvm/test/Analysis/BasicAA/noalias-scope-decl.ll b/llvm/test/Analysis/BasicAA/noalias-scope-decl.ll
new file mode 100644
index 000000000000..1f4b302d1868
--- /dev/null
+++ b/llvm/test/Analysis/BasicAA/noalias-scope-decl.ll
@@ -0,0 +1,28 @@
+; RUN: opt < %s -basic-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) #0
+declare void @llvm.experimental.noalias.scope.decl(metadata)
+
+define void @test1(i8* %P, i8* %Q) nounwind ssp {
+ tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
+ tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
+ ret void
+
+; CHECK-LABEL: Function: test1:
+
+; CHECK: MayAlias: i8* %P, i8* %Q
+; CHECK: NoModRef: Ptr: i8* %P <-> tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK: NoModRef: Ptr: i8* %Q <-> tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK: Both ModRef: Ptr: i8* %P <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
+; CHECK: Both ModRef: Ptr: i8* %Q <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
+; CHECK: NoModRef: tail call void @llvm.experimental.noalias.scope.decl(metadata !0) <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
+; CHECK: NoModRef: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <-> tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
+}
+
+
+attributes #0 = { nounwind }
+
+!0 = !{ !1 }
+!1 = distinct !{ !1, !2, !"test1: var" }
+!2 = distinct !{ !2, !"test1" }
diff --git a/llvm/test/Analysis/CostModel/X86/free-intrinsics.ll b/llvm/test/Analysis/CostModel/X86/free-intrinsics.ll
index 1a693c582f14..9870d9ae6229 100644
--- a/llvm/test/Analysis/CostModel/X86/free-intrinsics.ll
+++ b/llvm/test/Analysis/CostModel/X86/free-intrinsics.ll
@@ -6,6 +6,7 @@ define i32 @trivially_free() {
; CHECK-SIZE-LABEL: 'trivially_free'
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
+; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !0)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.sideeffect()
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = call {}* @llvm.invariant.start.p0i8(i64 1, i8* undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.invariant.end.p0i8({}* undef, i64 1, i8* undef)
@@ -22,6 +23,7 @@ define i32 @trivially_free() {
; CHECK-THROUGHPUT-LABEL: 'trivially_free'
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
+; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !0)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.sideeffect()
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = call {}* @llvm.invariant.start.p0i8(i64 1, i8* undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.invariant.end.p0i8({}* undef, i64 1, i8* undef)
@@ -37,6 +39,7 @@ define i32 @trivially_free() {
;
%a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
call void @llvm.assume(i1 undef)
+ call void @llvm.experimental.noalias.scope.decl(metadata !4)
call void @llvm.sideeffect()
call void @llvm.dbg.declare(metadata i8** undef, metadata !0, metadata !DIExpression())
call void @llvm.dbg.value(metadata i64 undef, i64 undef, metadata !DIExpression(), metadata !DIExpression())
@@ -56,6 +59,7 @@ define i32 @trivially_free() {
declare i32 @llvm.annotation.i32(i32, i8*, i8*, i32)
declare void @llvm.assume(i1)
+declare void @llvm.experimental.noalias.scope.decl(metadata)
declare void @llvm.sideeffect()
declare void @llvm.dbg.declare(metadata, metadata, metadata)
declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
@@ -76,3 +80,6 @@ declare void @llvm.var.annotation(i8*, i8*, i8*, i32, i8*)
!1 = distinct !DISubprogram(name: "dummy", line: 79, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true)
!2 = !DILabel(scope: !1, name: "label", file: !3, line: 7)
!3 = !DIFile(filename: "debug-label.c", directory: "./")
+!4 = !{ !4 }
+!5 = distinct !{ !5, !6, !"foo: var" }
+!6 = distinct !{ !6, !"foo" }
diff --git a/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll b/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll
index 787bb373cb86..b6b884c7c30a 100644
--- a/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll
+++ b/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll
@@ -8,6 +8,7 @@ define i32 @trivially_free() {
; CHECK-SIZE-LABEL: 'trivially_free'
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
+; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !0)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.sideeffect()
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = call {}* @llvm.invariant.start.p0i8(i64 1, i8* undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.invariant.end.p0i8({}* undef, i64 1, i8* undef)
@@ -24,6 +25,7 @@ define i32 @trivially_free() {
; CHECK-THROUGHPUT-LABEL: 'trivially_free'
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
+; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !0)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.sideeffect()
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = call {}* @llvm.invariant.start.p0i8(i64 1, i8* undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.invariant.end.p0i8({}* undef, i64 1, i8* undef)
@@ -39,6 +41,7 @@ define i32 @trivially_free() {
;
%a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
call void @llvm.assume(i1 undef)
+ call void @llvm.experimental.noalias.scope.decl(metadata !4)
call void @llvm.sideeffect()
call void @llvm.dbg.declare(metadata i8** undef, metadata !0, metadata !DIExpression())
call void @llvm.dbg.value(metadata i64 undef, i64 undef, metadata !DIExpression(), metadata !DIExpression())
@@ -58,6 +61,7 @@ define i32 @trivially_free() {
declare i32 @llvm.annotation.i32(i32, i8*, i8*, i32)
declare void @llvm.assume(i1)
+declare void @llvm.experimental.noalias.scope.decl(metadata)
declare void @llvm.sideeffect()
declare void @llvm.dbg.declare(metadata, metadata, metadata)
declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
@@ -78,3 +82,6 @@ declare void @llvm.var.annotation(i8*, i8*, i8*, i32, i8*)
!1 = distinct !DISubprogram(name: "dummy", line: 79, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true)
!2 = !DILabel(scope: !1, name: "label", file: !3, line: 7)
!3 = !DIFile(filename: "debug-label.c", directory: "./")
+!4 = !{ !4 }
+!5 = distinct !{ !5, !6, !"foo: var" }
+!6 = distinct !{ !6, !"foo" }
diff --git a/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll b/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll
index 6f31249ca771..fb5221b93b1a 100644
--- a/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll
+++ b/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll
@@ -6,6 +6,7 @@ define i32 @trivially_free() {
; CHECK-SIZE-LABEL: 'trivially_free'
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
+; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !0)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.sideeffect()
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = call {}* @llvm.invariant.start.p0i8(i64 1, i8* undef)
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.invariant.end.p0i8({}* undef, i64 1, i8* undef)
@@ -22,6 +23,7 @@ define i32 @trivially_free() {
; CHECK-THROUGHPUT-LABEL: 'trivially_free'
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.assume(i1 undef)
+; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.experimental.noalias.scope.decl(metadata !0)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.sideeffect()
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = call {}* @llvm.invariant.start.p0i8(i64 1, i8* undef)
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.invariant.end.p0i8({}* undef, i64 1, i8* undef)
@@ -37,6 +39,7 @@ define i32 @trivially_free() {
;
%a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
call void @llvm.assume(i1 undef)
+ call void @llvm.experimental.noalias.scope.decl(metadata !4)
call void @llvm.sideeffect()
call void @llvm.dbg.declare(metadata i8** undef, metadata !0, metadata !DIExpression())
call void @llvm.dbg.value(metadata i64 undef, i64 undef, metadata !DIExpression(), metadata !DIExpression())
@@ -56,6 +59,7 @@ define i32 @trivially_free() {
declare i32 @llvm.annotation.i32(i32, i8*, i8*, i32)
declare void @llvm.assume(i1)
+declare void @llvm.experimental.noalias.scope.decl(metadata)
declare void @llvm.sideeffect()
declare void @llvm.dbg.declare(metadata, metadata, metadata)
declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
@@ -76,3 +80,6 @@ declare void @llvm.var.annotation(i8*, i8*, i8*, i32, i8*)
!1 = distinct !DISubprogram(name: "dummy", line: 79, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true)
!2 = !DILabel(scope: !1, name: "label", file: !3, line: 7)
!3 = !DIFile(filename: "debug-label.c", directory: "./")
+!4 = !{ !4 }
+!5 = distinct !{ !5, !6, !"foo: var" }
+!6 = distinct !{ !6, !"foo" }
diff --git a/llvm/test/Analysis/MemorySSA/noalias-scope-decl.ll b/llvm/test/Analysis/MemorySSA/noalias-scope-decl.ll
new file mode 100644
index 000000000000..85bc32d6727b
--- /dev/null
+++ b/llvm/test/Analysis/MemorySSA/noalias-scope-decl.ll
@@ -0,0 +1,24 @@
+; RUN: opt -basic-aa -memoryssa -enable-new-pm=0 -analyze < %s 2>&1 | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s
+;
+; Ensures that llvm.experimental.noalias.scope.decl is treated as not reading or writing memory.
+
+declare void @llvm.experimental.noalias.scope.decl(metadata)
+
+define i32 @foo(i32* %a, i32* %b, i1 %c) {
+; CHECK: 1 = MemoryDef(liveOnEntry)
+; CHECK-NEXT: store i32 4
+ store i32 4, i32* %a, align 4
+; CHECK-NOT: MemoryDef
+; CHECK: call void @llvm.experimental.noalias.scope.decl
+ call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK: MemoryUse(1)
+; CHECK-NEXT: %1 = load i32
+ %1 = load i32, i32* %a, align 4
+ ret i32 %1
+}
+
+
+!0 = !{ !1 }
+!1 = distinct !{ !1, !2, !"foo: var" }
+!2 = distinct !{ !2, !"foo" }
diff --git a/llvm/test/Transforms/EarlyCSE/noalias-scope-decl.ll b/llvm/test/Transforms/EarlyCSE/noalias-scope-decl.ll
new file mode 100644
index 000000000000..6b441c27aad6
--- /dev/null
+++ b/llvm/test/Transforms/EarlyCSE/noalias-scope-decl.ll
@@ -0,0 +1,38 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S < %s -early-cse -earlycse-debug-hash | FileCheck %s
+
+; Store-to-load forwarding across a @llvm.experimental.noalias.scope.decl.
+
+define float @s2l(float* %p) {
+; CHECK-LABEL: @s2l(
+; CHECK-NEXT: store float 0.000000e+00, float* [[P:%.*]], align 4
+; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ store float 0.0, float* %p
+ call void @llvm.experimental.noalias.scope.decl(metadata !0)
+ %t = load float, float* %p
+ ret float %t
+}
+
+; Redundant load elimination across a @llvm.experimental.noalias.scope.decl.
+
+define float @rle(float* %p) {
+; CHECK-LABEL: @rle(
+; CHECK-NEXT: [[R:%.*]] = load float, float* [[P:%.*]], align 4
+; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK-NEXT: [[T:%.*]] = fadd float [[R]], [[R]]
+; CHECK-NEXT: ret float [[T]]
+;
+ %r = load float, float* %p
+ call void @llvm.experimental.noalias.scope.decl(metadata !0)
+ %s = load float, float* %p
+ %t = fadd float %r, %s
+ ret float %t
+}
+
+declare void @llvm.experimental.noalias.scope.decl(metadata)
+
+!0 = !{ !1 }
+!1 = distinct !{ !1, !2 }
+!2 = distinct !{ !2 }
diff --git a/llvm/test/Transforms/LoopVectorize/noalias-scope-decl.ll b/llvm/test/Transforms/LoopVectorize/noalias-scope-decl.ll
new file mode 100644
index 000000000000..140fc219c1d3
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/noalias-scope-decl.ll
@@ -0,0 +1,140 @@
+; RUN: opt < %s -loop-vectorize -force-vector-width=4 -force-vector-interleave=2 -S | FileCheck %s
+
+define void @test1(float* noalias nocapture %a, float* noalias nocapture readonly %b) {
+entry:
+ br label %for.body
+
+; CHECK-LABEL: @test1
+; CHECK: vector.body:
+; CHECK: @llvm.experimental.noalias.scope.decl
+; CHECK-NOT: @llvm.experimental.noalias.scope.decl
+; CHECK: for.body:
+; CHECK: @llvm.experimental.noalias.scope.decl
+; CHECK-NOT: @llvm.experimental.noalias.scope.decl
+; CHECK: ret void
+
+for.body: ; preds = %for.body, %entry
+ %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+ %arrayidx = getelementptr inbounds float, float* %b, i64 %indvars.iv
+ %0 = load float, float* %arrayidx, align 4
+ %cmp1 = fcmp ogt float %0, 1.000000e+02
+ tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
+ %add = fadd float %0, 1.000000e+00
+ %arrayidx5 = getelementptr inbounds float, float* %a, i64 %indvars.iv
+ store float %add, float* %arrayidx5, align 4
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %exitcond = icmp eq i64 %indvars.iv, 1599
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body
+ ret void
+}
+
+declare void @llvm.experimental.noalias.scope.decl(metadata)
+
+%struct.data = type { float*, float* }
+
+define void @test2(%struct.data* nocapture readonly %d) {
+entry:
+ %b = getelementptr inbounds %struct.data, %struct.data* %d, i64 0, i32 1
+ %0 = load float*, float** %b, align 8
+ %ptrint = ptrtoint float* %0 to i64
+ %maskedptr = and i64 %ptrint, 31
+ %maskcond = icmp eq i64 %maskedptr, 0
+ %a = getelementptr inbounds %struct.data, %struct.data* %d, i64 0, i32 0
+ %1 = load float*, float** %a, align 8
+ %ptrint2 = ptrtoint float* %1 to i64
+ %maskedptr3 = and i64 %ptrint2, 31
+ %maskcond4 = icmp eq i64 %maskedptr3, 0
+ br label %for.body
+
+; CHECK-LABEL: @test2
+; CHECK: vector.body:
+; CHECK: @llvm.experimental.noalias.scope.decl(metadata [[SCOPE0_LIST:!.*]])
+; CHECK: @llvm.experimental.noalias.scope.decl(metadata [[SCOPE4_LIST:!.*]])
+; CHECK-NOT: @llvm.experimental.noalias.scope.decl
+; CHECK: for.body:
+; CHECK: @llvm.experimental.noalias.scope.decl(metadata [[SCOPE0_LIST]])
+; CHECK: @llvm.experimental.noalias.scope.decl(metadata [[SCOPE4_LIST]])
+; CHECK-NOT: @llvm.experimental.noalias.scope.decl
+; CHECK: ret void
+
+for.body: ; preds = %for.body, %entry
+ %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
+ tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
+ %arrayidx = getelementptr inbounds float, float* %0, i64 %indvars.iv
+ %2 = load float, float* %arrayidx, align 4
+ %add = fadd float %2, 1.000000e+00
+ tail call void @llvm.experimental.noalias.scope.decl(metadata !4)
+ %arrayidx5 = getelementptr inbounds float, float* %1, i64 %indvars.iv
+ store float %add, float* %arrayidx5, align 4
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %exitcond = icmp eq i64 %indvars.iv, 1599
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body
+ ret void
+}
+
+define void @predicated_noalias_scope_decl(float* noalias nocapture readonly %a, float* noalias nocapture %b, i32 %n) {
+
+; Check that the vector.body still contains a llvm.experimental.noalias.scope.decl
+
+; CHECK-LABEL: @predicated_noalias_scope_decl(
+; CHECK: vector.body:
+; CHECK: call void @llvm.experimental.noalias.scope.decl
+; CHECK-NOT: @llvm.experimental.noalias.scope.decl
+; CHECK: scalar.ph:
+; CHECK-NOT: @llvm.experimental.noalias.scope.decl
+; CHECK: if.else:
+; CHECK: call void @llvm.experimental.noalias.scope.decl
+; CHECK-NOT: @llvm.experimental.noalias.scope.decl
+; CHECK: }
+
+entry:
+ %cmp15 = icmp eq i32 %n, 0
+ br i1 %cmp15, label %for.cond.cleanup, label %for.body.preheader
+
+for.body.preheader: ; preds = %entry
+ %0 = zext i32 %n to i64
+ br label %for.body
+
+for.cond.cleanup.loopexit: ; preds = %if.end5
+ br label %for.cond.cleanup
+
+for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry
+ ret void
+
+for.body: ; preds = %for.body.preheader, %if.end5
+ %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %if.end5 ]
+ %cmp1 = icmp ult i64 %indvars.iv, 495616
+ br i1 %cmp1, label %if.end5, label %if.else
+
+if.else: ; preds = %for.body
+ %cmp2 = icmp ult i64 %indvars.iv, 991232
+ tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
+ br label %if.end5
+
+if.end5: ; preds = %for.body, %if.else
+ %x.0 = phi float [ 4.200000e+01, %if.else ], [ 2.300000e+01, %for.body ]
+ %arrayidx = getelementptr inbounds float, float* %a, i64 %indvars.iv
+ %1 = load float, float* %arrayidx, align 4
+ %mul = fmul float %x.0, %1
+ %arrayidx7 = getelementptr inbounds float, float* %b, i64 %indvars.iv
+ store float %mul, float* %arrayidx7, align 4
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %cmp = icmp eq i64 %indvars.iv.next, %0
+ br i1 %cmp, label %for.cond.cleanup.loopexit, label %for.body
+}
+
+!0 = !{ !1 }
+!1 = distinct !{ !1, !2 }
+!2 = distinct !{ !2 }
+!3 = distinct !{ !3, !2 }
+!4 = !{ !3 }
+
+; CHECK: [[SCOPE0_LIST]] = !{[[SCOPE0:!.*]]}
+; CHECK: [[SCOPE0]] = distinct !{[[SCOPE0]], [[SCOPE0_DOM:!.*]]}
+; CHECK: [[SCOPE0_DOM]] = distinct !{[[SCOPE0_DOM]]}
+; CHECK: [[SCOPE4_LIST]] = !{[[SCOPE4:!.*]]}
+; CHECK: [[SCOPE4]] = distinct !{[[SCOPE4]], [[SCOPE0_DOM]]}
More information about the llvm-commits
mailing list