Index: lib/Analysis/AliasSetTracker.cpp =================================================================== --- lib/Analysis/AliasSetTracker.cpp +++ lib/Analysis/AliasSetTracker.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/IR/Value.h" #include "llvm/Pass.h" #include "llvm/Support/AtomicOrdering.h" @@ -169,7 +170,11 @@ addRef(); UnknownInsts.emplace_back(I); - if (!I->mayWriteToMemory()) { + // Some intrinsics are marked as modifying memory, but don't actually do it. + using namespace PatternMatch; + bool MayWriteMemory = I->mayWriteToMemory() && + !match(I, m_Intrinsic()); + if (!MayWriteMemory) { Alias = SetMayAlias; Access |= RefAccess; return; Index: test/Analysis/AliasSet/intrinsics.ll =================================================================== --- test/Analysis/AliasSet/intrinsics.ll +++ test/Analysis/AliasSet/intrinsics.ll @@ -16,4 +16,50 @@ ret void } +; CHECK: Alias sets for function 'test2': +; CHECK: Alias Set Tracker: 3 alias sets for 2 pointer values. +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %a, 1) +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] may alias, Ref +; CHECK: 1 Unknown instructions: call void (i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ] +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %b, 1) +define void @test2(i32 %c) { +entry: + %a = alloca i8, align 1 + %b = alloca i8, align 1 + store i8 1, i8* %a, align 1 + %cond1 = icmp ne i32 %c, 0 + call void (i1, ...) @llvm.experimental.guard(i1 %cond1)["deopt"()] + store i8 1, i8* %b, align 1 + ret void +} + +; CHECK: Alias sets for function 'test3': +; CHECK: Alias Set Tracker: 1 alias sets for 2 pointer values. +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 3] may alias, Mod/Ref Pointers: (i8* %a, 1), (i8* %b, 1) +; CHECK: 1 Unknown instructions: call void (i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ] +define void @test3(i32 %c, i8* %a, i8* %b) { +entry: + store i8 1, i8* %a, align 1 + %cond1 = icmp ne i32 %c, 0 + call void (i1, ...) @llvm.experimental.guard(i1 %cond1)["deopt"()] + store i8 1, i8* %b, align 1 + ret void +} + +; CHECK: Alias sets for function 'test4': +; CHECK: Alias Set Tracker: 2 alias sets for 2 pointer values. +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 2] may alias, Mod/Ref Pointers: (i8* %a, 1) +; CHECK: 1 Unknown instructions: call void (i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ] +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Pointers: (i8* %b, 1) +define void @test4(i32 %c, i8* %a) { +entry: + %b = alloca i8, align 1 + store i8 1, i8* %a, align 1 + %cond1 = icmp ne i32 %c, 0 + call void (i1, ...) @llvm.experimental.guard(i1 %cond1)["deopt"()] + store i8 1, i8* %b, align 1 + ret void +} + declare void @llvm.assume(i1) +declare void @llvm.experimental.guard(i1, ...) Index: test/Transforms/LICM/hoist-mustexec.ll =================================================================== --- test/Transforms/LICM/hoist-mustexec.ll +++ test/Transforms/LICM/hoist-mustexec.ll @@ -4,6 +4,7 @@ target triple = "x86_64-unknown-linux-gnu" declare void @f() nounwind +declare void @llvm.experimental.guard(i1,...) ; constant fold on first ieration define i32 @test1(i32* noalias nocapture readonly %a) nounwind uwtable { @@ -281,6 +282,31 @@ ret i32 -1 } +define void @test-hoisting-in-presence-of-guards(i1 %c, i32* %p) { + +; CHECK-LABEL: @test-hoisting-in-presence-of-guards +; CHECK: entry: +; CHECK: %a = load i32, i32* %p +; CHECK: %invariant_cond = icmp ne i32 %a, 100 +; CHECK: loop: + +entry: + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %iv.next = add i32 %iv, 1 + %a = load i32, i32* %p + %invariant_cond = icmp ne i32 %a, 100 + call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] + %loop_cond = icmp slt i32 %iv.next, 1000 + br i1 %loop_cond, label %loop, label %exit + +exit: + ret void +} + + declare void @may_throw() inaccessiblememonly ; Test that we can sink a mustexecute load from loop header even in presence of