[llvm-bugs] [Bug 39240] New: clang/llvm looses restrictness, resulting in wrong code
via llvm-bugs
llvm-bugs at lists.llvm.org
Wed Oct 10 00:38:07 PDT 2018
https://bugs.llvm.org/show_bug.cgi?id=39240
Bug ID: 39240
Summary: clang/llvm looses restrictness, resulting in wrong
code
Product: libraries
Version: trunk
Hardware: PC
OS: Windows NT
Status: NEW
Severity: enhancement
Priority: P
Component: Scalar Optimizations
Assignee: unassignedbugs at nondot.org
Reporter: jeroen.dobbelaere at synopsys.com
CC: llvm-bugs at lists.llvm.org
clang/llvm implements argument restrictness by putting a 'noalias' on the the
restrict argument. When alias analysis traces the base object of a pointer to
two different base objects of which one is marked with 'noalias', it concludes
that these pointers do not alias.
This mapping results in wrong behavior according to the restrict specification:
(or my interpretation of it is wrong ;) ):
6.7.3.1, 4: 'every other lvalue used to access the value of X shall also have
its address based on P.'
where P is the restrict annotated pointer. This means that in following code
*tmp and *pA might alias:
// Assume pA and pB point to the same set of objects X
// restrict rules dictate that all accesses in the scope must happen through
// the restrict pointer (pA) or a pointer based on it.
int foo(int* __restrict pA, int* pB, int* pC) {
int *tmp=pA; // tmp is based on pA
pA=pB; // pB also points into the set of objects X, but, accessing it must
happen through a pointer based on pA
*tmp=42; // tmp points into the set of objects X
*pA=43; // pA points into the set of objects X
*pC=99; // pC does not point into the set of objects X
return *tmp; // fail: needs a load !!! (either 42 or 43)
}
results in:
define dso_local i32 @foo(i32* noalias nocapture, i32* nocapture, i32*
nocapture) local_unnamed_addr #0 {
store i32 42, i32* %0, align 4, !tbaa !2
store i32 43, i32* %1, align 4, !tbaa !2
store i32 99, i32* %2, align 4, !tbaa !2
ret i32 42 ; WRONG! %0 must be reloaded
}
But, clang/llvm assumes that *tmp and *pA will never alias, and propagates the
42.
NOTES:
- gcc has the same issue
- icc has the correct behavior
- for this example, moving the __restrict from pA to the pC argument, results
in equivalent code with the correct behavior.
- llvm + Hal Finkels local restrict patches has the correct behavior, IF the
restrict is made local:
int foo(int* pA_, int* pB, int* pC) {
int* __restrict pA=pA_;
int *tmp=pA; // tmp is based on pA
....
results in:
define dso_local i32 @foo(i32* nocapture %pA_, i32* nocapture %pB, i32*
nocapture %pC) local_unnamed_addr #1 {
entry:
%0 = tail call i32* @llvm.noalias.p0i32(i32* %pA_, metadata !6)
store i32 42, i32* %0, align 4, !tbaa !2, !noalias !6
%1 = tail call i32* @llvm.noalias.p0i32(i32* %pB, metadata !6)
store i32 43, i32* %1, align 4, !tbaa !2, !noalias !6
store i32 99, i32* %pC, align 4, !tbaa !2, !noalias !6
%2 = load i32, i32* %0, align 4, !tbaa !2, !noalias !6
ret i32 %2
}
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20181010/c7f450fe/attachment-0001.html>
More information about the llvm-bugs
mailing list