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:
parent
ccb1095e5c
commit
116cd71f2c
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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');
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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" }
|
||||
|
28
test/Analysis/BasicAA/noalias-scope-decl.ll
Normal file
28
test/Analysis/BasicAA/noalias-scope-decl.ll
Normal 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" }
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
@ -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" }
|
||||
|
24
test/Analysis/MemorySSA/noalias-scope-decl.ll
Normal file
24
test/Analysis/MemorySSA/noalias-scope-decl.ll
Normal 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" }
|
38
test/Transforms/EarlyCSE/noalias-scope-decl.ll
Normal file
38
test/Transforms/EarlyCSE/noalias-scope-decl.ll
Normal 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 }
|
140
test/Transforms/LoopVectorize/noalias-scope-decl.ll
Normal file
140
test/Transforms/LoopVectorize/noalias-scope-decl.ll
Normal 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]]}
|
Loading…
x
Reference in New Issue
Block a user