[LLVMdev] Adding option to LLVM opt to disable a specific pass from command line

2,354 views
Skip to first unread message

Seb

unread,
Dec 7, 2011, 5:07:02 AM12/7/11
to llv...@cs.uiuc.edu
Hi all,

I would like to add an option for LLVM 'opt' to disable a specific optimization pass from command line.

The idea is to have something like:

opt -O2 -disable-pass=[passname,...]

Do you think it could be useful ? How should I proceed to develop it and commit changes to LLVM trunk ?
Thanks for your advices and recommandations.
Best Regards
Seb

Devang Patel

unread,
Dec 7, 2011, 12:51:40 PM12/7/11
to Seb, llv...@cs.uiuc.edu
Hello,

On Dec 7, 2011, at 2:07 AM, Seb wrote:

> Hi all,
>
> I would like to add an option for LLVM 'opt' to disable a specific optimization pass from command line.
>
> The idea is to have something like:
>
> opt -O2 -disable-pass=[passname,...]
>
> Do you think it could be useful ?

I have few questions :

- Why (and when) would you us this ?
- Some of the passes are executed multiple times, how would you select which invocation to disable ? Or would you disable all invocation of such passes ?
- Some passes are required by another passes. In such cases PassManager will insist on running them, which may conflict with the user request from command line. Who wins?
- Why not update the list passes run as part of -O2 (use --debug-pass=Arguments to get it) to remove selected passes and run opt <my list of passes> ... ?


> How should I proceed to develop it and commit changes to LLVM trunk ?
> Thanks for your advices and recommandations.
> Best Regards
> Seb


-
Devang

_______________________________________________
LLVM Developers mailing list
LLV...@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

Seb

unread,
Dec 8, 2011, 4:20:08 AM12/8/11
to Devang Patel, llv...@cs.uiuc.edu
Hello Devang,

answers are interleaved

2011/12/7 Devang Patel <dpa...@apple.com>

Hello,

On Dec 7, 2011, at 2:07 AM, Seb wrote:

> Hi all,
>
> I would like to add an option for LLVM 'opt' to disable a specific optimization pass from command line.
>
> The idea is to have something like:
>
> opt -O2 -disable-pass=[passname,...]
>
> Do you think it could be useful ?

I have few questions :

- Why (and when) would you us this ?

I woudl use this to selectively disable passes in opt that are either redundant with passes performed by the fron-end I'm working on our exhibit a BUG in opt. For instance, I figured out that loop-idiom pass has a BUG in LLVM 2.9, a llvm.memcpy is generated for an overlapping memory region and then x86 backend reorder loads/store thus generating a BUG.

So my use would be to disable all loop-idiom invocations.
 
- Some of the passes are executed multiple times, how would you select which invocation to disable ? Or would you disable all invocation of such passes ?

By default I guess I would like to disable all invocation of such passes. We could also imagine to have an option -disable-pass=[pass_name:inv_num, ...] to deal with multiple invocation.

- Some passes are required by another passes. In such cases PassManager will insist on running them, which may conflict with the user request from command line. Who wins?

How to I know that a pass  is required by another ?
Let's say give priority to pass manager and issue a warning like like
'option -disable-pass=<pass_name> ignored because required by pass <other_pass>.'

- Why not update the list passes run as part of -O2 (use --debug-pass=Arguments to get it) to remove selected passes and run opt <my list of passes> ... ?

 
 I also thought about this but it can lead to long command lines and source of errors.

Roel Jordans

unread,
Dec 8, 2011, 5:36:22 AM12/8/11
to llv...@cs.uiuc.edu
Hello,

> - Some passes are required by another passes. In such cases
> PassManager will insist on running them, which may conflict with the
> user request from command line. Who wins?
>
>
> How to I know that a pass is required by another ?
> Let's say give priority to pass manager and issue a warning like like
> 'option -disable-pass=<pass_name> ignored because required by pass
> <other_pass>.'
>

I would opt for disabling dependent passes as well, and providing a
warning that they have been disabled implicitly (possibly giving the
disabled pass that caused this effect).

I think such behavior would make sense if you were disabling passes
because they contain bugs.

Another option would be to differentiate between a strong (disabling
pass + dependents) and weak (disabling pass if no dependents) disable
parameter.

- Roel

David Blaikie

unread,
Dec 8, 2011, 10:58:00 AM12/8/11
to Seb, llv...@cs.uiuc.edu
> For instance, I figured out that loop-idiom pass has a BUG in
> LLVM 2.9, a llvm.memcpy is generated for an overlapping memory region and
> then x86 backend reorder loads/store thus generating a BUG.

Just for the record it seems this is a bug in your frontend, not in
the LLVM backend. The memcpy intrinsic, like the standard memcpy
function, requires that the regions be non-overlapping:
http://llvm.org/docs/LangRef.html#int_memcpy By violating this
contract it's possible you'll encounter all sorts of issues in other
passes too.

- David

Seb

unread,
Dec 9, 2011, 4:03:37 AM12/9/11
to David Blaikie, llv...@cs.uiuc.edu
David,

I think my explanation is not clear, my front-end did NOTt generate 'llvm.memcpy' it generate LL code that after use of LLVM 'opt' get transformed by 'loop-idom' pass into an 'llvm.memcpy' for an overlapping loop:

static void
t0(int n)
{
    int i;
    for (i=0; i<n; i++)
    result[i+1] = result[i];
}

Then 'llc' expanded llvm.memcpy into a sequence of load/store that where performed out-of-order and thus the final code was incorrect.
So to sumarize, BUG was not in my front-end, it was in LLVM 'opt' loop-idom pass, it seems now fixed into 3.0. However I think I would be a good idea to add more control from command line on pass we want to disable.

Best Regards
Seb

2011/12/8 David Blaikie <dbla...@gmail.com>

Joerg Sonnenberger

unread,
Dec 9, 2011, 7:22:54 AM12/9/11
to llv...@cs.uiuc.edu
On Fri, Dec 09, 2011 at 10:03:37AM +0100, Seb wrote:
> I think my explanation is not clear, my front-end did NOTt generate
> 'llvm.memcpy' it generate LL code that after use of LLVM 'opt' get
> transformed by 'loop-idom' pass into an 'llvm.memcpy' for an overlapping
> loop:
>
> static void
> t0(int n)
> {
> int i;
> for (i=0; i<n; i++)
> result[i+1] = result[i];
> }

Do you really want to assign result[0] to everything?

I wonder how much work it is to each the loop-idiom pass to handle this
and the case of reverse indices correctly, if result is char *. E.g.
create either memset or memmove...

Joerg

Seb

unread,
Dec 9, 2011, 8:23:18 AM12/9/11
to llv...@cs.uiuc.edu


2011/12/9 Joerg Sonnenberger <jo...@britannica.bec.de>

On Fri, Dec 09, 2011 at 10:03:37AM +0100, Seb wrote:
> I think my explanation is not clear, my front-end did NOTt generate
> 'llvm.memcpy' it generate LL code that after use of LLVM 'opt' get
> transformed by 'loop-idom' pass into an 'llvm.memcpy' for an overlapping
> loop:
>
> static void
> t0(int n)
> {
>     int i;
>     for (i=0; i<n; i++)
>     result[i+1] = result[i];
> }

Do you really want to assign result[0] to everything?

I wonder how much work it is to each the loop-idiom pass to handle this
and the case of reverse indices correctly, if result is char *. E.g.
create either memset or memmove...

Joerg

 
This thread is not to discuss how relevant this example is. I just would like to know:
a) If people think that adding an option to disable a specific pass is useful.
b) To discuss implementation details (disable all pass invocations, what to do when there are dependencies between passes invocations).
c) If I implement it, what's the process to get my change merge with trunk.

Now for my own purpose, I commented out loop-idiom invocation in LLVM 2.9 sources and it worked well. I just wanted to develop something generic that could benefit LLVM community.

Best Regards
Seb

Seb

unread,
Dec 9, 2011, 8:38:38 AM12/9/11
to llv...@cs.uiuc.edu
By the way, CLANG 2.9 produce same behavior as my front-end:

Try clang

clang -O2 -S -emit-llvm rec.c -o rec.ll

on following example:

/*--- Recurrence recognition.  */

static int expect[] = {
    1, 1, 1, 1          /* t0:  0 - 3  */
};

extern void check() ;

#define N sizeof(expect) / sizeof(int)

static int result[N];


static void
t0(int n)
{
    int i;
    for (i=0; i<n; i++)
    result[i+1] = result[i];
}

void
test() {
    result[0] = 1;
    t0(3);

    check(result, expect, N);
}

LL file generated is:
; ModuleID = 'ka50.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"

@result = internal global [4 x i32] zeroinitializer, align 16
@expect = internal global [4 x i32] [i32 1, i32 1, i32 1, i32 1], align 16

define void @test() nounwind {
  store i32 1, i32* getelementptr inbounds ([4 x i32]* @result, i64 0, i64 0), align 16, !tbaa !0
  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (i32* getelementptr inbounds ([4 x i32]* @result, i64 0, i64 1) to i8*), i8* bitcast ([4 x i32]* @result to i8*), i64 12, i32 4, i1 false) nounwind
  tail call void (...)* @check(i32* getelementptr inbounds ([4 x i32]* @result, i64 0, i64 0), i32* getelementptr inbounds ([4 x i32]* @expect, i64 0, i64 0), i64 4) nounwind
  ret void
}

declare void @check(...)

Then assembly produced is:

test:                                   # @test
.Leh_func_begin0:
# BB#0:
    pushq    %rbp
.Ltmp0:
    movq    %rsp, %rbp
.Ltmp1:
    movl    $1, result(%rip)
    movl    result+8(%rip), %eax
    movl    %eax, result+12(%rip)
    movq    result(%rip), %rax
    movq    %rax, result+4(%rip)
    movl    $result, %edi
    movl    $expect, %esi
    movl    $4, %edx
    xorb    %al, %al
    callq    check
    popq    %rbp
    ret

As you can see resul+8 is read before being written and thus the problem.
Hope that clarifies the problem.


2011/12/9 Seb <babsl...@gmail.com>

Tom Honermann

unread,
Dec 9, 2011, 10:23:16 AM12/9/11
to Seb, llv...@cs.uiuc.edu
On 12/9/2011 8:23 AM, Seb wrote:
> This thread is not to discuss how relevant this example is. I just would
> like to know:
> a) If people think that adding an option to disable a specific pass is
> useful.

Yes, a peer of mine recently wanted such an option to disable individual
passes in order to 1) narrow in on a bug in one of them that affected
stack back tracing, and 2) provide a workaround for the bug. He didn't
pursue modifying code to remove the passes one at a time and thus the
bug remains hidden.

Tom.

Duncan Sands

unread,
Dec 10, 2011, 9:05:28 AM12/10/11
to llv...@cs.uiuc.edu
Hi Tom,

> On 12/9/2011 8:23 AM, Seb wrote:
>> This thread is not to discuss how relevant this example is. I just would
>> like to know:
>> a) If people think that adding an option to disable a specific pass is
>> useful.
>
> Yes, a peer of mine recently wanted such an option to disable individual
> passes in order to 1) narrow in on a bug in one of them that affected
> stack back tracing, and 2) provide a workaround for the bug. He didn't
> pursue modifying code to remove the passes one at a time and thus the
> bug remains hidden.

you don't have to modify code to reduce the list of passes. Get clang (or
whatever) to produce unoptimized bitcode. Check that running
opt -std-compile-opts
(or opt -O3) or whatever reproduces the problem. Adding -debug-pass=Arguments
will show you the list of passes used. You can then run opt with this explicit
list of passes (rather than -std-compile-opts), and remove passes until you find
the problematic one. Bugpoint can do this for you automatically.

Ciao, Duncan.

Reply all
Reply to author
Forward
0 new messages