On Tue, Jul 10, 2012 at 9:46 AM, Jakob Stoklund Olesen <span dir="ltr"><<a href="mailto:stoklund@2pi.dk" target="_blank" class="cremed">stoklund@2pi.dk</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><div class="im"><div>On Jul 10, 2012, at 9:21 AM, Chandler Carruth <<a href="mailto:chandlerc@gmail.com" target="_blank" class="cremed">chandlerc@gmail.com</a>> wrote:</div>
<br><blockquote type="cite"><div class="gmail_extra"><div class="gmail_quote">On Tue, Jul 10, 2012 at 9:13 AM, Jakob Stoklund Olesen <span dir="ltr"><<a href="mailto:stoklund@2pi.dk" target="_blank" class="cremed">stoklund@2pi.dk</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><div></div></div></blockquote>
</div></div></blockquote><br></div><div class="im"><blockquote type="cite"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style="word-wrap:break-word"><div><div>Unfortunately, we can't bail out of register allocation.</div></div></div></blockquote><div><br></div><div>But is there a cheaper algorithm we could fall over to? I don't know the first thing about regalloc, so maybe this doesn't make sense. Just trying to get a feel for whether this is solvable within the backend, or we simply must not produce such inputs.</div>
</div></div></blockquote><div><br></div></div></div>It is not impossible to fall back to RAFast which doesn't compute liveness at all, and so won't have this problem. It's a giant hack that I'd rather not do, though.<div>
<br></div><div>The fundamental problem is that LLVM doesn't have an IR optimizer, it has an IR canonicalizer. In this case, it's probably LICM hoisting a thousand GEPs out of a thousand-block loop, creating the quadratic problem. Normally, CodeGenPrepare would sink those GEPs again, but in this case they are used by PHIs which CGP won't touch.</div>
</div></blockquote><div><br></div><div>As it happens, that's not it. Here is a snippet of the generated code:</div><div><br></div><div>=====</div><div><div>define void @bar(i32* %a) nounwind uwtable address_safety {</div>
<div>  tail call void @llvm.dbg.value(metadata !{i32* %a}, i64 0, metadata !13), !dbg !14</div><div>  %1 = tail call i32 (...)* @foo() nounwind, !dbg !15</div><div>  %2 = getelementptr inbounds i32* %a, i64 2877, !dbg !15</div>
<div>  %3 = ptrtoint i32* %2 to i64, !dbg !15</div><div>  %4 = lshr i64 %3, 3, !dbg !15</div><div>  %5 = or i64 %4, 17592186044416, !dbg !15</div><div>  %6 = inttoptr i64 %5 to i8*, !dbg !15  %7 = load i8* %6, align 1, !dbg !15  %8 = icmp eq i8 %7, 0, !dbg !15</div>
<div>  br i1 %8, label %15, label %9</div><div><br></div><div>; <label>:9                                       ; preds = %0</div><div>  %10 = and i64 %3, 7</div><div>  %11 = add i64 %10, 3</div><div>  %12 = trunc i64 %11 to i8</div>
<div>  %13 = icmp slt i8 %12, %7</div><div>  br i1 %13, label %15, label %14</div><div><br></div><div>; <label>:14                                      ; preds = %9</div><div>  call void @__asan_report_store4(i64 %3) noreturn nounwind, !dbg !15</div>
<div>  unreachable</div><div><br></div><div>; <label>:15                                      ; preds = %9, %0</div><div>  store i32 %1, i32* %2, align 4, !dbg !15, !tbaa !17</div><div>  %16 = tail call i32 (...)* @foo() nounwind, !dbg !20</div>
<div>  %17 = getelementptr inbounds i32* %a, i64 20955, !dbg !20</div><div>  %18 = ptrtoint i32* %17 to i64, !dbg !20</div><div>  %19 = lshr i64 %18, 3, !dbg !20</div><div>  %20 = or i64 %19, 17592186044416, !dbg !20</div>
<div>  %21 = inttoptr i64 %20 to i8*, !dbg !20</div><div>  %22 = load i8* %21, align 1, !dbg !20</div><div>  %23 = icmp eq i8 %22, 0, !dbg !20</div><div>  br i1 %23, label %30, label %24</div><div><br></div><div>; <label>:24                                      ; preds = %15</div>
<div>  %25 = and i64 %18, 7</div><div>  %26 = add i64 %25, 3</div><div>  %27 = trunc i64 %26 to i8</div><div>  %28 = icmp slt i8 %27, %22</div><div>  br i1 %28, label %30, label %29</div><div><br></div><div>; <label>:29                                      ; preds = %24</div>
<div>  call void @__asan_report_store4(i64 %18) noreturn nounwind, !dbg !20</div><div>  unreachable</div></div><div>=====</div><div><br></div><div>The pattern established here repeats.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><div>If you sink those GEPs, I expect the problem will go away.<br></div></div></blockquote><div><br></div><div>I don't see any way to sink the GEPs here... We're not even using them in the two instrumentation basic blocks, we're using the result of ptrtoint on the gep.</div>
<div><br></div><div>My suggestion for a long-term fix is to avoid duplicating these two basic blocks for every store, and instead have a single set of instrumentation blocks that select the questionable value through a phi-node. The only tricky thing is that we'll also need to pass down debug info somehow, as currently it leverages that the debug info is attached to the particular call to the runtime library.</div>
<div><br></div><div><br></div><div>I don't think ASan should be relying on the long term code motion passes -- it should be emitting IR that is tuned for the subsequent passes.</div></div></div>