Mikael Holmén via llvm-dev
2015-Aug-07 11:15 UTC
[llvm-dev] load instruction erroneously removed by GVN
Hi, I'm having a problem with GVN removing a load instruction that I think is needed. Dump before GVN: *** IR Dump Before Global Value Numbering *** ; Function Attrs: minsize optsize define i16 @TEST__MAIN(i16 %argc.13.par, i16** %argv.14.par) #0 { %buf.17 = alloca [10 x i16], align 1 %_tmp30 = getelementptr inbounds [10 x i16], [10 x i16]* %buf.17, i16 0, i16 0, !dbg !22 call fastcc void @format_long(i16* %_tmp30, i16 10, i32 10), !dbg !22 %_tmp32 = getelementptr [10 x i16], [10 x i16]* %buf.17, i16 0, i16 0, !dbg !24 %_tmp33 = load i16, i16* %_tmp32, align 1, !dbg !24 call fastcc void @check_i(i16 2, i16 %_tmp33, i16 48), !dbg !24 ret i16 0, !dbg !25 } GVN debug printouts: GVN iteration: 0 GVN removed: %_tmp32 = getelementptr [10 x i16], [10 x i16]* %buf.17, i16 0, i16 0, !dbg !16 GVN removed: %_tmp33 = load i16, i16* %_tmp30, align 1, !dbg !16 GVN iteration: 1 And then the code aftern GVN: *** IR Dump After Global Value Numbering *** ; Function Attrs: minsize optsize define i16 @TEST__MAIN(i16 %argc.13.par, i16** %argv.14.par) #0 { %buf.17 = alloca [10 x i16], align 1 %_tmp30 = getelementptr inbounds [10 x i16], [10 x i16]* %buf.17, i16 0, i16 0, !dbg !22 call fastcc void @format_long(i16* %_tmp30, i16 10, i32 10), !dbg !22 call fastcc void @check_i(i16 2, i16 undef, i16 48), !dbg !24 ret i16 0, !dbg !25 } So GVN has deemed %_tmp33 = load i16, i16* %_tmp32, align 1, !dbg !24 useless, and removed it, replacing %_tmp33 with undef. While examining the load, processLoad does MemDepResult Dep = MD->getDependency(L); [...] Instruction *DepInst = Dep.getInst(); [...] // If this load really doesn't depend on anything, then we must be loading an // undef value. This can happen when loading for a fresh allocation with no // intervening stores, for example. if (isa<AllocaInst>(DepInst) || isMallocLikeFn(DepInst, TLI)) { L->replaceAllUsesWith(UndefValue::get(L->getType())); markInstructionForDeletion(L); ++NumGVNLoad; return true; } The Dep points to the %buf.17 = alloca [10 x i16], align 1 instruction, so of course GVN thinks the load is reading uninitialized memory and thus can be replaced with undef. But between the load and the alloca there is also call fastcc void @format_long(i16* %_tmp30, i16 10, i32 10), !dbg !22 which will use %_tmp30 to write in the alloca'd buffer. Shoulnd't MemoryDependenceAnalysis::getDependency rather return the call? MemoryDependenceAnalysis::getDependency uses MemoryDependenceAnalysis::getPointerDependencyFrom, which does the following analysis at the end: // See if this instruction (e.g. a call or vaarg) mod/ref's the pointer. AliasAnalysis::ModRefResult MR = AA->getModRefInfo(Inst, MemLoc); // If necessary, perform additional analysis. if (MR == AliasAnalysis::ModRef) MR = AA->callCapturesBefore(Inst, MemLoc, DT); switch (MR) { case AliasAnalysis::NoModRef: // If the call has no effect on the queried pointer, just ignore it. continue; case AliasAnalysis::Mod: return MemDepResult::getClobber(Inst); case AliasAnalysis::Ref: // If the call is known to never store to the pointer, and if this is a // load query, we can safely ignore it (scan past it). if (isLoad) continue; default: // Otherwise, there is a potential dependence. Return a clobber. return MemDepResult::getClobber(Inst); } In my case, when analysing the call instruction, MR is first set to ModRef by AA->getModRefInfo(Inst, MemLoc);, but then it is reset to NoModRef by MR = AA->callCapturesBefore(Inst, MemLoc, DT); and thus it fails to recognize the dependency towards the call. Note that the function format_long does not capture the pointer, but it does use it to write at the pointed address. Anyone here knows how this should work? Thanks in advance, Mikael
Caldarale, Charles R via llvm-dev
2015-Aug-07 11:53 UTC
[llvm-dev] load instruction erroneously removed by GVN
> From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] > On Behalf Of Mikael Holmén via llvm-dev > Subject: [llvm-dev] load instruction erroneously removed by GVN> But between the load and the alloca there is also > call fastcc void @format_long(i16* %_tmp30, i16 10, i32 10), !dbg !22 > which will use %_tmp30 to write in the alloca'd buffer.> Shoulnd't MemoryDependenceAnalysis::getDependency rather return the call?Depends. What is the exact declaration of format_long? - Chuck
Mikael Holmén via llvm-dev
2015-Aug-07 12:02 UTC
[llvm-dev] load instruction erroneously removed by GVN
On 08/07/2015 01:53 PM, Caldarale, Charles R wrote:>> From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] >> On Behalf Of Mikael Holmén via llvm-dev >> Subject: [llvm-dev] load instruction erroneously removed by GVN > >> But between the load and the alloca there is also >> call fastcc void @format_long(i16* %_tmp30, i16 10, i32 10), !dbg !22 >> which will use %_tmp30 to write in the alloca'd buffer. > >> Shoulnd't MemoryDependenceAnalysis::getDependency rather return the call? > > Depends. What is the exact declaration of format_long?In the input .ll file it is: ; Function Attrs: minsize optsize define internal i16 @format_long(i16* %res.8.par, i16 %base.9.par, i32 %x.10.par) #3 { which is later changed somewhere in opt to: ; Function Attrs: minsize nounwind optsize define internal fastcc i16 @format_long(i16* %res.8.par, i16 %base.9.par, i32 %x.10.par) #2 { Thanks, Mikael> > - Chuck > > >