[LLVMdev] Strange pointer aliasing behaviour
NAKAMURA Takumi
geek4civic at gmail.com
Fri Jun 18 08:07:19 PDT 2010
FYI,
the case below can be folded with -scev-aa -licm,
to hoist this->_length on former loop.
class LittleList2X {
public:
int _length;
double _data[8];
LittleList2X( int length )
{
_length = length;
int i = 0;
#if 1
for( ; i<_length && i <= 0x1FFFFFFE; i++ )
_data[i] = 0;
#endif
for( ; i<_length; i++ )
_data[i] = 0;
}
};
Rationale: the pass ScalarEvolution discovers range of &_data[i] must be finite.
(impossible when i >= 0x1FFFFFFF on p:32 target)
...Takumi
2010/6/17 Pierre C <lists at peufeu.com>:
>
> I'm hitting a strange pointer aliasing "bug". Here is a test case :
>
> /* SOURCE CODE */
>
> #define little_list_size 8
>
> class LittleList1 {
> public:
> int _length;
> double _data[ little_list_size ];
>
> LittleList1( int length )
> {
> _length = length;
> for( int i=0; i<length; i++ )
> _data[i] = 0;
> }
> };
>
> class LittleList2 {
> public:
> int _length;
> double _data[ little_list_size ];
>
> LittleList2( int length )
> {
> _length = length;
> for( int i=0; i<_length; i++ )
> _data[i] = 0;
> }
> };
>
> int func1()
> {
> LittleList1 l(4);
> return l._length;
> }
>
> int func2()
> {
> LittleList2 l(4);
> return l._length;
> }
>
> /* END SOURCE CODE */
>
> The only difference between the 2 classes is in the constructor, in the
> line :
> for( int i=0; i<_length; i++ )
>
> One has "length" which is a function parameter, the other has "_length"
> which is the class member which was initialized in the same constructor.
>
> Now let's compile and optimize :
>
> llvm-g++ -emit-llvm -Winline -O3 -Iinclude -c test2.cpp -o test2.bc
> opt -S -O3 -print-alias-sets -count-aa test2.bc
>
> Result :
>
> %struct.LittleList1 = type { i32, [8 x double] }
>
> ********
> Here, func1() is perfectly optimized :
> ********
>
> define i32 @_Z5func1v() nounwind readnone {
> entry:
> ret i32 4
> }
>
>
> ********
> func2() should give the exact same result as func1, however ...
>
> Alias Set Tracker: 1 alias sets for 2 pointer values.
> AliasSet[0x0x8ca140,2] may alias, Mod/Ref Pointers: (i32* %0, 4),
> (double* %scevgep.i, 8)
>
> A spurious alias comes up between the 2 fields of the struct (which should
> in theory not happen).
> So, it reloads _length at each iteration, thus no optimization takes place
> and the code below is generated :
>
> ********
>
> define i32 @_Z5func2v() nounwind readnone {
> entry:
> %l = alloca %struct.LittleList1, align 8 ; <%struct.LittleList1*>
> [#uses=2]
> %0 = getelementptr inbounds %struct.LittleList1* %l, i64 0, i32 0 ;
> <i32*> [#uses=2]
> store i32 4, i32* %0, align 8
> br label %bb.i
>
> bb.i: ; preds = %bb.i, %entry
> %indvar.i = phi i64 [ %tmp, %bb.i ], [ 0, %entry ] ; <i64> [#uses=2]
> %tmp = add i64 %indvar.i, 1 ; <i64> [#uses=2]
> %tmp2.i = trunc i64 %tmp to i32 ; <i32> [#uses=1]
> %scevgep.i = getelementptr %struct.LittleList1* %l, i64 0, i32 1, i64
> %indvar.i ; <double*> [#uses=1]
> store double 0.000000e+00, double* %scevgep.i, align 8
> %1 = load i32* %0, align 8 ; <i32> [#uses=2]
> %2 = icmp sgt i32 %1, %tmp2.i ; <i1> [#uses=1]
> br i1 %2, label %bb.i, label %_ZN11LittleList2C1Ei.exit
>
> _ZN11LittleList2C1Ei.exit: ; preds = %bb.i
> ret i32 %1
>
> ********
>
> g++ correctly resolves this alias and both functions are compiled to
> "return 4".
> llvm-gcc (and opt) detect a spurious alias on func2() (all alias passes
> seem to do the same here) which prevents optimizations, and in other cases
> more complex than this simple test, it also prevents loop unrolling and
> many other optimizations.
>
> Can I do something to fix this ?
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
More information about the llvm-dev
mailing list