restrict func param losing noalias when inlined

Given some code:

void func (float * restrict a, float *b) {
for (int i =0; i < 100; ++i) {
a[i] = b[i] + 1;
}
}

float * aa;
float * bb;
int main() {
func(aa, bb);
return 0;
}

produces IR that has the llvm.noalias intrinsic along with the !noalias metadata:for both the load and store, however, AA returns MayAlias, I would expect a NoAlias?

This is also an older version of llvm: 6 (yes, I know, sigh).

Thanks,

Ryan

Hi Ryan,

the alias metadata was (and is) broken for various reasons.
he replacement is currently under review, I can point you to it,
however, to be honest, I'm unclear how we are supposed to help
you with LLVM 6 right now.

Cheers,
Johannes

Johannes,

Thanks, I have been following along some of the thread(s) and the phab reviews. The scope of this work is more encompassing than our current needs and I’ve looked at trying to carve a piece out.

It’s not clear to me what purpose the llvm.noalias intrinsic serves right now. Also, if a mem instruction has !noalias metadata, then it should not be aliased, but I must be missing some complexity. For example, if you look at the alias of two memory locations and they are both tagged with noalias MD, that should be safe to NoAlias providing they have no specific !scope tag? I’ve looked at the ScopedNoAliasAA but during the inline no !scope MD is created therefore it’s not marked as NoAlias from that analysis (it returns MayAlias if no scope MD or no noalias MD).

Thanks,

Ryan

Johannes,

Thanks, I have been following along some of the thread(s) and the phab
reviews. The scope of this work is more encompassing than our current needs
and I've looked at trying to carve a piece out.

It's not clear to me what purpose the llvm.noalias intrinsic serves right
now. Also, if a mem instruction has !noalias metadata, then it should not
be aliased, but I must be missing some complexity. For example, if you look
at the alias of two memory locations and they are both tagged with noalias
MD, that should be safe to NoAlias providing they have no specific !scope
tag? I've looked at the ScopedNoAliasAA but during the inline no !scope MD
is created therefore it's not marked as NoAlias from that analysis (it
returns MayAlias if no scope MD or no noalias MD).

`!noalias` metadata needs a scope to be useful, otherwise it is not:

https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata

Though I don't know what the implementation status in 6.0 was.

~ Johannes

As far as I know, the 'llvm.noalias' intrinsic has never been part of the main llvm.

So, you might have applied some of Hal Finkel's patches that introduced them
in an attempt to fix some of the issues with inlining and noalias ?

In that case, the '!alias.scope' is indeed not needed, and the 'llvm.noalias' intrinsic is used to
deduce the 'based on' relationship of a restrict pointer. But those patches have a number
of known issues. The more complete approach (aka 'full restrict support') which is under review now
fixes those issues... but that's on top-of-tree, not on llvm-6.

Greetings,

Jeroen Dobbelaere

Sorry, I didn’t have the IR on the computer I was emailing from earlier.

@aa = global [1000 x float] zeroinitializer, section “.dram0.data”, align 32
@pa = local_unnamed_addr global float* getelementptr inbounds ([1000 x float], [1000 x float]* @aa, i32 0, i32 0), align 4
@bb = global [1000 x float] zeroinitializer, section “.dram0.data”, align 32
@pb = local_unnamed_addr global float* getelementptr inbounds ([1000 x float], [1000 x float]* @bb, i32 0, i32 0), align 4

; Function Attrs: noinline nounwind
define i32 @main() local_unnamed_addr #0 !dbg !6 {
entry:
%0 = load float*, float** @pa, align 4, !dbg !8, !tbaa !9
%1 = load float*, float** @pb, align 4, !dbg !13, !tbaa !9
%2 = tail call float* @llvm.noalias.p0f32(float* %0, metadata !14), !dbg !17
br label %vector.body, !dbg !18

vector.body: ; preds = %vector.body, %entry
%index = phi i32 [ 0, %entry ], [ %index.next, %vector.body ], !dbg !21
%3 = getelementptr inbounds float, float* %1, i32 %index, !dbg !22
%4 = bitcast float* %3 to <8 x float>, !dbg !22
%wide.load = load <8 x float>, <8 x float>
%4, align 4, !dbg !22, !tbaa !23, !noalias !14
%5 = fadd reassoc nnan nsz contract <8 x float> %wide.load, <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>, !dbg !25
%6 = getelementptr inbounds float, float* %2, i32 %index, !dbg !26
%7 = bitcast float* %6 to <8 x float>, !dbg !27
store <8 x float> %5, <8 x float>
%7, align 4, !dbg !27, !tbaa !23, !noalias !14
%index.next = add i32 %index, 8, !dbg !21
%8 = icmp eq i32 %index.next, 1000, !dbg !21
br i1 %8, label %func.exit, label %vector.body, !dbg !18, !llvm.loop !28

func.exit: ; preds = %vector.body
ret i32 0, !dbg !32
}

Ok, maybe Hal will find the time to chime in. :slight_smile:

Adding Jeroen and me back to the explicit recipients, also adding Hal, though, see below.

From: Ryan Taylor <ryta1203@gmail.com>
Date: Tue, Sep 29, 2020 at 10:29 AM
Subject: Re: [llvm-dev] restrict func param losing noalias when inlined
To: Jeroen Dobbelaere <Jeroen.Dobbelaere@synopsys.com>
Cc: Johannes Doerfert <johannesdoerfert@gmail.com>

Ok, maybe Hal will find the time to chime in. :slight_smile:

I'm still unsure what you expect to happen here?
The patches are old and, as Jeroen noted, were never merged.
There were known problems wrt soundness and completeness,
proper restrict support is provided by Jeroen's patch set.

~ Johannes

Yes, I see that, I’m not sure how X86 is getting that info, AA->alias for these MemoryLocation (s) returns MayAlias when inlined and NoAlias when not inlined.

Is there some other interface we should be using to get the AA info? (I would imagine that ModRef would return similar). I was also hoping that this would fall under ScopedNoAliasAA since it’s being inlined, but that doesn’t appear to be the case either, and ScopedNoAliasAA returns MayAlias if there is no !scope and no !noalias.

Thanks,

Ryan