The official example of MemorySSA shows different behaviour in LLVM 11

Hi, I’m a beginner of LLVM and trying to learn MemorySSA. I explored the Homepage of MemorySSA, and different behavior shows up when I print the Memory SSA of the official example. I used opt memoryssa.ll -passes='print<memoryssa>' -disable-output -o /dev/null to print the SSA form and below is the outcome.

MemorySSA for function: foo                    
define void @foo() {                           
entry:                                          
  %p1 = alloca i8, align 1  
  %p2 = alloca i8, align 1
  %p3 = alloca i8, align 1
; 1 = MemoryDef(liveOnEntry)           
  store i8 0, i8* %p3, align 1
  br label %while.cond
                
while.cond:                                       ; preds = %if.end, %entry
; 6 = MemoryPhi({entry,1},{if.end,4})
  br i1 undef, label %if.then, label %if.else
    
if.then:                                          ; preds = %while.cond
; 2 = MemoryDef(6)          
  store i8 0, i8* %p1, align 1
  br label %if.end
                              
if.else:                                          ; preds = %while.cond
; 3 = MemoryDef(6)
  store i8 1, i8* %p2, align 1
  br label %if.end          
                            
if.end:                                           ; preds = %if.else, %if.then
; 5 = MemoryPhi({if.then,2},{if.else,3})
; MemoryUse(5) MayAlias         
  %0 = load i8, i8* %p1, align 1
; 4 = MemoryDef(5)
  store i8 2, i8* %p2, align 1
; MemoryUse(4) MayAlias     
  %1 = load i8, i8* %p3, align 1
  br label %while.cond      
}

Everything is good exept the statement %1 = load i8, i8* %p3, align 1. The corresponding MemoryAccess is MemoryUse(4) but it should be MemoryUse(1) in term of the homepage of MemorySSA.

did I miss something? My llvm version is 11.0.0.

If anyone has the same outcome, please let me know.

Ok, first of all, hopefully it’s clear that MemoryUse(4) is not wrong. It’s just less precise. If you assume that pointers %p1, %p2, %p3 all alias, then MemoryUse(4) makes sense. The reason that we expect it to be MemoryUse(1) is because we expect it should be trivial for the compiler to realize that these pointers don’t in fact alias since they’re just some allocas declared at the top of the function.

That said, I think that by default, no alias analysis so even the most trivial alias queries can’t
be resolved to NoAlias. But if you put e.g., -aa-pipeline='basic-aa', you should see the expected result (in fact, you should be able to do it in Godbolt but for some reason Discourse does not let me post a link to Godbolt…)

Moral of the story: Don’t forget that MemorySSA is heavily based on alias analysis :slight_smile:

Best,
Stefanos

1 Like

Thanks! Adding some AAs works for me.

I just didn’t realize the missing of AA. By default, AAManager::run() returns a AAResults without any AA; while AAResultsWrapperPass::runOnFunction() returns a AAResults with a number of AAs. This leads to the different MemorySSA initial values when using the new manager approach and the lagacy manager one.

Anyway, thanks again. I should be more careful with it :slight_smile:

1 Like