llvm.org GIT mirror llvm / b89bfff
[BasicAA] Take attributes into account when requesting modref info for a call site Differential Revision: https://reviews.llvm.org/D29989 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296617 91177308-0d34-0410-b5e6-96231b3b80d8 Igor Laevsky 3 years ago
4 changed file(s) with 80 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
582582 dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
583583 }
584584
585 bool doesNotReadMemory(unsigned OpNo) const {
586 return dataOperandHasImpliedAttr(OpNo + 1, Attribute::WriteOnly) ||
587 dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
588 }
589
585590 /// Return true if the return value is known to be not null.
586591 /// This may be because it has the nonnull attribute, or because at least
587592 /// one byte is dereferenceable and the pointer is in addrspace(0).
748748 // as an argument, and itself doesn't capture it.
749749 if (!isa(Object) && CS.getInstruction() != Object &&
750750 isNonEscapingLocalObject(Object)) {
751 bool PassedAsArg = false;
751
752 // Optimistically assume that call doesn't touch Object and check this
753 // assumption in the following loop.
754 ModRefInfo Result = MRI_NoModRef;
755
752756 unsigned OperandNo = 0;
753757 for (auto CI = CS.data_operands_begin(), CE = CS.data_operands_end();
754758 CI != CE; ++CI, ++OperandNo) {
760764 OperandNo < CS.getNumArgOperands() && !CS.isByValArgument(OperandNo)))
761765 continue;
762766
767 // Call doesn't access memory through this operand, so we don't care
768 // if it aliases with Object.
769 if (CS.doesNotAccessMemory(OperandNo))
770 continue;
771
763772 // If this is a no-capture pointer argument, see if we can tell that it
764 // is impossible to alias the pointer we're checking. If not, we have to
765 // assume that the call could touch the pointer, even though it doesn't
766 // escape.
773 // is impossible to alias the pointer we're checking.
767774 AliasResult AR =
768775 getBestAAResults().alias(MemoryLocation(*CI), MemoryLocation(Object));
769 if (AR) {
770 PassedAsArg = true;
771 break;
776
777 // Operand doesnt alias 'Object', continue looking for other aliases
778 if (AR == NoAlias)
779 continue;
780 // Operand aliases 'Object', but call doesn't modify it. Strengthen
781 // initial assumption and keep looking in case if there are more aliases.
782 if (CS.onlyReadsMemory(OperandNo)) {
783 Result = static_cast(Result | MRI_Ref);
784 continue;
772785 }
773 }
774
775 if (!PassedAsArg)
776 return MRI_NoModRef;
786 // Operand aliases 'Object' but call only writes into it.
787 if (CS.doesNotReadMemory(OperandNo)) {
788 Result = static_cast(Result | MRI_Mod);
789 continue;
790 }
791 // This operand aliases 'Object' and call reads and writes into it.
792 Result = MRI_ModRef;
793 break;
794 }
795
796 // Early return if we improved mod ref information
797 if (Result != MRI_ModRef)
798 return Result;
777799 }
778800
779801 // If the CallSite is to malloc or calloc, we can assume that it doesn't
0 ; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
1
2 declare void @readonly_attr(i8* readonly nocapture)
3 declare void @writeonly_attr(i8* writeonly nocapture)
4 declare void @readnone_attr(i8* readnone nocapture)
5
6 declare void @readonly_func(i8* nocapture) readonly
7 declare void @writeonly_func(i8* nocapture) writeonly
8 declare void @readnone_func(i8* nocapture) readnone
9
10 declare void @read_write(i8* writeonly nocapture, i8* readonly nocapture, i8* readnone nocapture)
11
12 declare void @func()
13
14 define void @test(i8* noalias %p) {
15 entry:
16 call void @readonly_attr(i8* %p)
17 call void @readonly_func(i8* %p)
18
19 call void @writeonly_attr(i8* %p)
20 call void @writeonly_func(i8* %p)
21
22 call void @readnone_attr(i8* %p)
23 call void @readnone_func(i8* %p)
24
25 call void @read_write(i8* %p, i8* %p, i8* %p)
26
27 call void @func() ["deopt" (i8* %p)]
28 call void @writeonly_attr(i8* %p) ["deopt" (i8* %p)]
29
30 ret void
31 }
32
33 ; CHECK: Just Ref: Ptr: i8* %p <-> call void @readonly_attr(i8* %p)
34 ; CHECK: Just Ref: Ptr: i8* %p <-> call void @readonly_func(i8* %p)
35 ; CHECK: Just Mod: Ptr: i8* %p <-> call void @writeonly_attr(i8* %p)
36 ; CHECK: Just Mod: Ptr: i8* %p <-> call void @writeonly_func(i8* %p)
37 ; CHECK: NoModRef: Ptr: i8* %p <-> call void @readnone_attr(i8* %p)
38 ; CHECK: NoModRef: Ptr: i8* %p <-> call void @readnone_func(i8* %p)
39 ; CHECK: Both ModRef: Ptr: i8* %p <-> call void @read_write(i8* %p, i8* %p, i8* %p)
40 ; CHECK: Just Ref: Ptr: i8* %p <-> call void @func() [ "deopt"(i8* %p) ]
41 ; CHECK: Both ModRef: Ptr: i8* %p <-> call void @writeonly_attr(i8* %p) [ "deopt"(i8* %p) ]
None ; XFAIL: *
1 ; RUN: opt -newgvn -S -o - < %s | FileCheck %s
21
32 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"