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 > > >