1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[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
This commit is contained in:
Jeroen Dobbelaere 2021-01-19 20:04:52 +01:00
parent ccb1095e5c
commit 116cd71f2c
18 changed files with 313 additions and 7 deletions

View File

@ -557,6 +557,7 @@ public:
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:

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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))

View File

@ -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');

View File

@ -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);

View File

@ -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 {

View File

@ -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" }

View File

@ -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" }

View File

@ -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" }

View File

@ -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" }

View File

@ -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" }

View File

@ -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" }

View File

@ -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 }

View File

@ -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]]}