* Defect in linearization of short circuit &&
@ 2010-02-14 13:39 Jacek Śliwerski
2010-02-14 21:04 ` Jacek Śliwerski
0 siblings, 1 reply; 18+ messages in thread
From: Jacek Śliwerski @ 2010-02-14 13:39 UTC (permalink / raw)
To: linux-sparse
[-- Attachment #1: Type: text/plain, Size: 523 bytes --]
I am attaching a small sample of code that triggers an issue with the
linearization of &&. Consider the condition within the parser_check
function. If st == NULL, then no more checks should be performed; the
execution flow should immediately be directed to the "else" branch.
However, if you output linearized version (e.g. by using "example"
program), you will notice that it only skips the second check.
Could you help me investigate this issue?
I am using the latest sparse version from git.
Thank you!
Jacek
[-- Attachment #2: parser_check.c --]
[-- Type: text/x-csrc, Size: 356 bytes --]
struct st {
int value;
struct st *other;
};
static void
execute_a (struct st *st, int i)
{
}
static void
execute_b (struct st *st)
{
}
static void
parser_check (struct st *st, int i)
{
if (st && st->other && st->value > i && i > 0){
execute_a (st, i);
} else {
execute_b (st);
}
}
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-14 13:39 Defect in linearization of short circuit && Jacek Śliwerski
@ 2010-02-14 21:04 ` Jacek Śliwerski
2010-02-14 23:09 ` Christopher Li
0 siblings, 1 reply; 18+ messages in thread
From: Jacek Śliwerski @ 2010-02-14 21:04 UTC (permalink / raw)
To: linux-sparse
Apparently, the issue is not with the linearization. I noticed that the
condition has been parsed as:
EXPR_BINOP
* EXPR_LOGICAL
* EXPR_LOGICAL
* EXPR_PREOP
* EXPR_PREOP
* EXPR_COMPARE
* EXPR_COMPARE
After replacing EXPR_BINOP with EXPR_LOGICAL in the top node of the
tree, the linearization works just fine. Could someone explain me the
difference between EXPR_BINOP and EXPR_LOGICAL in this context?
Thanks!
Jacek
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-14 21:04 ` Jacek Śliwerski
@ 2010-02-14 23:09 ` Christopher Li
2010-02-15 19:12 ` Jacek Śliwerski
0 siblings, 1 reply; 18+ messages in thread
From: Christopher Li @ 2010-02-14 23:09 UTC (permalink / raw)
To: Jacek Śliwerski; +Cc: linux-sparse
2010/2/14 Jacek Śliwerski <sliwers@googlemail.com>:
> Apparently, the issue is not with the linearization. I noticed that the
> condition has been parsed as:
>
> EXPR_BINOP
> * EXPR_LOGICAL
> * EXPR_LOGICAL
> * EXPR_PREOP
> * EXPR_PREOP
> * EXPR_COMPARE
> * EXPR_COMPARE
>
> After replacing EXPR_BINOP with EXPR_LOGICAL in the top node of the tree,
> the linearization works just fine. Could someone explain me the difference
> between EXPR_BINOP and EXPR_LOGICAL in this context?
EXPR_BINOP used in normal operation require two operands.
e.g. a + b, a | b
Both operands will get evaluated.
EXPR_LOGICAL using for condition branching and it has the short curcit
behavior in mind. e.g. a || b
Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-14 23:09 ` Christopher Li
@ 2010-02-15 19:12 ` Jacek Śliwerski
2010-02-15 19:41 ` Christopher Li
0 siblings, 1 reply; 18+ messages in thread
From: Jacek Śliwerski @ 2010-02-15 19:12 UTC (permalink / raw)
To: Christopher Li; +Cc: linux-sparse
Christopher Li pisze:
>
> EXPR_BINOP used in normal operation require two operands.
> e.g. a + b, a | b
> Both operands will get evaluated.
>
> EXPR_LOGICAL using for condition branching and it has the short curcit
> behavior in mind. e.g. a || b
I found the offending block of code. It is in expand.c, in function
expand_logical:
/*
* If the right side is safe and cheaper than a branch,
* just avoid the branch and turn it into a regular binop
* style SAFELOGICAL.
*/
if (rcost < BRANCH_COST) {
expr->type = EXPR_BINOP;
rcost -= BRANCH_COST - 1;
}
After removing these lines, everything works fine.
But I guess that there must have been a reason to add them in the first
place. I see it checking the cost of the operation, but I don't know
why somebody assumes that it would be safe not to make a branch. Does
anybody know how to fix it without simply removing these lines?
Thanks!
Jacek
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-15 19:12 ` Jacek Śliwerski
@ 2010-02-15 19:41 ` Christopher Li
2010-02-15 20:18 ` Jacek Śliwerski
0 siblings, 1 reply; 18+ messages in thread
From: Christopher Li @ 2010-02-15 19:41 UTC (permalink / raw)
To: Jacek Śliwerski; +Cc: linux-sparse
2010/2/15 Jacek Śliwerski <sliwers@googlemail.com>:
> Christopher Li pisze:
> /*
> * If the right side is safe and cheaper than a branch,
> * just avoid the branch and turn it into a regular binop
> * style SAFELOGICAL.
> */
> if (rcost < BRANCH_COST) {
> expr->type = EXPR_BINOP;
> rcost -= BRANCH_COST - 1;
> }
>
> After removing these lines, everything works fine.
>
> But I guess that there must have been a reason to add them in the first
> place. I see it checking the cost of the operation, but I don't know why
> somebody assumes that it would be safe not to make a branch. Does anybody
> know how to fix it without simply removing these lines?
That is an optimization from Linus. It basically find out the simple variable
case comparing variable and turn it into binary operations and avoiding the
branch. It is cheaper to use "setne" than "cmp; jne; mov;".
It is safe because all the unsafe operations, e.g. dereferencing memory,
should have set the cost high enough to avoid this optimization.
e.g. all local variable dereferencing should be safe, because the address
is in the stack.
Deferencing a pointer is not, so sparse will not optimize it.
Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-15 19:41 ` Christopher Li
@ 2010-02-15 20:18 ` Jacek Śliwerski
2010-02-15 21:11 ` Christopher Li
0 siblings, 1 reply; 18+ messages in thread
From: Jacek Śliwerski @ 2010-02-15 20:18 UTC (permalink / raw)
To: Christopher Li; +Cc: linux-sparse
Christopher Li pisze:
>
> That is an optimization from Linus. It basically find out the simple variable
> case comparing variable and turn it into binary operations and avoiding the
> branch. It is cheaper to use "setne" than "cmp; jne; mov;".
>
> It is safe because all the unsafe operations, e.g. dereferencing memory,
> should have set the cost high enough to avoid this optimization.
> e.g. all local variable dereferencing should be safe, because the address
> is in the stack.
>
> Deferencing a pointer is not, so sparse will not optimize it.
Please, check my case. The condition is:
if (st && st->other && st->value > i && i > 0)...
Obviously, if st is NULL, then the execution should be transferred
immediately to the else branch. But it does not. It skips the second
test and goes directly to the third one: st->value > i. If a compiler
was built with sparse as a frontend, execution of the generated code
would end up with a segmentation fault. And this code is perfectly valid.
So either it is an issue with the costs or it is an issue with the
linearization.
Anyway, I believe that this case is worth fixing.
Jacek
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-15 20:18 ` Jacek Śliwerski
@ 2010-02-15 21:11 ` Christopher Li
2010-02-16 9:28 ` Bernd Petrovitsch
0 siblings, 1 reply; 18+ messages in thread
From: Christopher Li @ 2010-02-15 21:11 UTC (permalink / raw)
To: Jacek Śliwerski; +Cc: linux-sparse
2010/2/15 Jacek Śliwerski <sliwers@googlemail.com>:
>
> Please, check my case. The condition is:
I did, I did not see any thing wrong with it.
>
> if (st && st->other && st->value > i && i > 0)...
>
> Obviously, if st is NULL, then the execution should be transferred
> immediately to the else branch. But it does not. It skips the second test
> and goes directly to the third one: st->value > i. If a compiler was built
> with sparse as a frontend, execution of the generated code would end up with
> a segmentation fault. And this code is perfectly valid.
I totally agree the source code is valid.
I just haven't see the seg fault part.
$ ./test-linearize parser_check.c
parser_check:
.L0x7f4e12de3130:
<entry-point>
br %arg1, .L0x7f4e12de32e0, .L0x7f4e12de3250
.L0x7f4e12de32e0:
load.32 %r3 <- 4[%arg1]
br %r3, .L0x7f4e12de3208, .L0x7f4e12de3250
.L0x7f4e12de3208:
load.32 %r5 <- 0[%arg1]
setgt.32 %r7 <- %r5, %arg2
phisrc.1 %phi1 <- %r7
br .L0x7f4e12de3298
.L0x7f4e12de3250:
phisrc.1 %phi2 <- $0
br .L0x7f4e12de3298
.L0x7f4e12de3298:
phi.1 %r8 <- %phi1, %phi2
setgt.32 %r10 <- %arg2, $0
and-bool.1 %r11 <- %r8, %r10
br %r11, .L0x7f4e12de3178, .L0x7f4e12de31c0
.L0x7f4e12de3178:
call execute_a, %arg1, %arg2
br .L0x7f4e12de3328
.L0x7f4e12de31c0:
call execute_b, %arg1
br .L0x7f4e12de3328
.L0x7f4e12de3328:
ret
In the fast test, the false branch is L0x7f4e12de3250.
Which is doing the (i > 0) part and it is safe to do so.
It skip the two load.32 operation. It will not generate the seg fault.
I still don't see where the is seg fault part. Please let me know if I am
missing some thing obvious.
Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-15 21:11 ` Christopher Li
@ 2010-02-16 9:28 ` Bernd Petrovitsch
2010-02-16 19:02 ` Christopher Li
0 siblings, 1 reply; 18+ messages in thread
From: Bernd Petrovitsch @ 2010-02-16 9:28 UTC (permalink / raw)
To: Christopher Li; +Cc: Jacek Śliwerski, linux-sparse
On Mon, 2010-02-15 at 13:11 -0800, Christopher Li wrote:
> 2010/2/15 Jacek Śliwerski <sliwers@googlemail.com>:
> >
> > Please, check my case. The condition is:
>
> I did, I did not see any thing wrong with it.
>
> >
> > if (st && st->other && st->value > i && i > 0)...
> >
> > Obviously, if st is NULL, then the execution should be transferred
> > immediately to the else branch. But it does not. It skips the second test
> > and goes directly to the third one: st->value > i. If a compiler was built
> > with sparse as a frontend, execution of the generated code would end up with
> > a segmentation fault. And this code is perfectly valid.
>
> I totally agree the source code is valid.
> I just haven't see the seg fault part.
>
> $ ./test-linearize parser_check.c
> parser_check:
> .L0x7f4e12de3130:
> <entry-point>
> br %arg1, .L0x7f4e12de32e0, .L0x7f4e12de3250
I assume this means "if %arg1 == NULL goto .L0x7f4e12de32e0 else goto .L0x7f4e12de3250"
> .L0x7f4e12de32e0:
> load.32 %r3 <- 4[%arg1]
> br %r3, .L0x7f4e12de3208, .L0x7f4e12de3250
>
> .L0x7f4e12de3208:
> load.32 %r5 <- 0[%arg1]
> setgt.32 %r7 <- %r5, %arg2
> phisrc.1 %phi1 <- %r7
> br .L0x7f4e12de3298
>
> .L0x7f4e12de3250:
I assume this is the "i > 0" check.
> phisrc.1 %phi2 <- $0
> br .L0x7f4e12de3298
>
> .L0x7f4e12de3298:
> phi.1 %r8 <- %phi1, %phi2
> setgt.32 %r10 <- %arg2, $0
> and-bool.1 %r11 <- %r8, %r10
> br %r11, .L0x7f4e12de3178, .L0x7f4e12de31c0
>
> .L0x7f4e12de3178:
> call execute_a, %arg1, %arg2
> br .L0x7f4e12de3328
>
> .L0x7f4e12de31c0:
> call execute_b, %arg1
> br .L0x7f4e12de3328
>
> .L0x7f4e12de3328:
> ret
>
> In the fast test, the false branch is L0x7f4e12de3250.
> Which is doing the (i > 0) part and it is safe to do so.
Are saying that he "i >0 " test done while "st == NULL"?
This is actually wrong as it shouldn't be done (independent of the used
variables and especially if the expression has side effects).
> It skip the two load.32 operation. It will not generate the seg fault.
> I still don't see where the is seg fault part. Please let me know if I am
> missing some thing obvious.
Or am I missing something (presumbly) obvious?
Bernd
--
Bernd Petrovitsch Email : bernd@petrovitsch.priv.at
LUGA : http://www.luga.at
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-16 9:28 ` Bernd Petrovitsch
@ 2010-02-16 19:02 ` Christopher Li
2010-02-16 19:10 ` Christopher Li
` (2 more replies)
0 siblings, 3 replies; 18+ messages in thread
From: Christopher Li @ 2010-02-16 19:02 UTC (permalink / raw)
To: Bernd Petrovitsch; +Cc: Jacek Śliwerski, linux-sparse
On Tue, Feb 16, 2010 at 1:28 AM, Bernd Petrovitsch
<bernd@petrovitsch.priv.at> wrote:
>> $ ./test-linearize parser_check.c
>> parser_check:
>> .L0x7f4e12de3130:
>> <entry-point>
>> br %arg1, .L0x7f4e12de32e0, .L0x7f4e12de3250
> I assume this means "if %arg1 == NULL goto .L0x7f4e12de32e0 else goto .L0x7f4e12de3250"
That is right.
> I assume this is the "i > 0" check.
No, this is the not the i > 0 check yet. This is setting the expression value
of the false branch to 0.
>> phisrc.1 %phi2 <- $0
>> br .L0x7f4e12de3298
>>
>> .L0x7f4e12de3298:
>> phi.1 %r8 <- %phi1, %phi2
>> setgt.32 %r10 <- %arg2, $0
This is the "i > 0" check. (%arg2 is "i")
>> and-bool.1 %r11 <- %r8, %r10
>> br %r11, .L0x7f4e12de3178, .L0x7f4e12de31c0
>>
>> .L0x7f4e12de3178:
>> call execute_a, %arg1, %arg2
>> br .L0x7f4e12de3328
>>
>> In the fast test, the false branch is L0x7f4e12de3250.
>> Which is doing the (i > 0) part and it is safe to do so.
> Are saying that he "i >0 " test done while "st == NULL"?
> This is actually wrong as it shouldn't be done (independent of the used
> variables and especially if the expression has side effects).
That is right. "i > 0" is still being tested.
Consider this example. The same source code and be compile into two
different piece of machine code. They produce the exact same result.
The one with this optimization runs faster than the other one. Do you still
thing that is wrong? How about x86 CPU internally re-ordering the instruction,
is that wrong too?
So I think as long as this behavior is *internal* and *correct*. It is fine.
Of course it'd better be faster as well. Otherwise, what is the point.
The goal of the this optimization is trading the branch instruction
with cheaper arithmetic instruction.
For modern CPU, the branch instruction is likely more expensive
than normal arithmetic instruction. In X86, branch instruction *might*
flush the instruction pipe line while arithmetic operation can usually done
in one cycle.
That is why this optimization is using a cost model. If the left hand
side cost is lower than the branch instruction cost, and it is *safe* to
do so. It turn the branch instruction into arithmetic instruction.
However, in this case, the optimization did not consider this expression
is used in the if statement, and if statement has build-in branch instruction
associate with it. So this optimization might not worthy while here.
But for this expression:
a = st && st->foo && st->bar && i > 0;
This optimization might be worth while.
If the optimization produce incorrect result. That is fatal and that
is a serious bug.
I just want to confirm that is no the case here.
Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-16 19:02 ` Christopher Li
@ 2010-02-16 19:10 ` Christopher Li
2010-02-16 19:19 ` Jacek Śliwerski
2010-02-17 11:47 ` Defect in linearization of short circuit && Bernd Petrovitsch
2 siblings, 0 replies; 18+ messages in thread
From: Christopher Li @ 2010-02-16 19:10 UTC (permalink / raw)
To: Bernd Petrovitsch; +Cc: Jacek Śliwerski, linux-sparse
On Tue, Feb 16, 2010 at 11:02 AM, Christopher Li <sparse@chrisli.org> wrote:
> That is why this optimization is using a cost model. If the left hand
Sorry I mean right hand side here.
> side cost is lower than the branch instruction cost, and it is *safe* to
> do so. It turn the branch instruction into arithmetic instruction.
Chris
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-16 19:02 ` Christopher Li
2010-02-16 19:10 ` Christopher Li
@ 2010-02-16 19:19 ` Jacek Śliwerski
2010-02-16 19:36 ` Christopher Li
2010-02-17 11:47 ` Defect in linearization of short circuit && Bernd Petrovitsch
2 siblings, 1 reply; 18+ messages in thread
From: Jacek Śliwerski @ 2010-02-16 19:19 UTC (permalink / raw)
To: Christopher Li; +Cc: linux-sparse
I understand your point and I agree that the optimization might make
sense. The problem is that my version of sparse gives different results.
parser_check:
.L0xb7ef00ac:
<entry-point>
br %arg1, .L0xb7ef019c, ****.L0xb7ef014c****
.L0xb7ef019c:
load.32 %r3 <- 4[%arg1]
br %r3, .L0xb7ef0124, .L0xb7ef014c
.L0xb7ef0124:
phisrc.1 %phi1 <- $0
br .L0xb7ef0174
****.L0xb7ef014c:****
load.32 %r5 <- 0[%arg1]
setgt.32 %r7 <- %r5, %arg2
phisrc.1 %phi2 <- %r7
br .L0xb7ef0174
.L0xb7ef0174:
phi.1 %r8 <- %phi1, %phi2
setgt.32 %r10 <- %arg2, $0
and-bool.1 %r11 <- %r8, %r10
br %r11, .L0xb7ef00d4, .L0xb7ef00fc
.L0xb7ef00d4:
call execute_a, %arg1, %arg2
br .L0xb7ef01c4
.L0xb7ef00fc:
call execute_b, %arg1
br .L0xb7ef01c4
.L0xb7ef01c4:
ret
Above, you can see that the execution will segfault within the label
.L0xb7ef014c, on load 0[%arg1].
So my question is: do you have any code that is not committed to
git.kernel.org?
Jacek
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-16 19:19 ` Jacek Śliwerski
@ 2010-02-16 19:36 ` Christopher Li
2010-02-16 20:11 ` enum warning patch (was Re: Defect in linearization of short circuit &&) Kamil Dudka
0 siblings, 1 reply; 18+ messages in thread
From: Christopher Li @ 2010-02-16 19:36 UTC (permalink / raw)
To: Jacek Śliwerski; +Cc: linux-sparse
2010/2/16 Jacek Śliwerski <sliwers@googlemail.com>:
> So my question is: do you have any code that is not committed to
> git.kernel.org?
I see. II am using the chrisl branch under:
git://git.kernel.org/pub/scm/devel/sparse/chrisl/sparse.git
The change you are missing is this:
http://git.kernel.org/?p=devel/sparse/chrisl/sparse.git;a=commit;h=9cdd3be634aab6fc98a17007d4db26fc050f213c
Sorry about that, I totally forget about it.
BTW, this should really flush into the official tree. Let me just do that.
I am still sitting on the enum warning patch. That is the only thing holding
up another minor release.
Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* enum warning patch (was Re: Defect in linearization of short circuit &&)
2010-02-16 19:36 ` Christopher Li
@ 2010-02-16 20:11 ` Kamil Dudka
2010-02-16 20:18 ` Kamil Dudka
0 siblings, 1 reply; 18+ messages in thread
From: Kamil Dudka @ 2010-02-16 20:11 UTC (permalink / raw)
To: Christopher Li; +Cc: linux-sparse
On Tuesday 16 of February 2010 20:36:21 Christopher Li wrote:
> I am still sitting on the enum warning patch. That is the only thing
> holding up another minor release.
Still trying to save a sizeof(void *) within struct expression?
It makes no sense to me - on my box I am getting the same
sizeof(struct expression)==64 before/after the patch applied.
Kamil
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: enum warning patch (was Re: Defect in linearization of short circuit &&)
2010-02-16 20:11 ` enum warning patch (was Re: Defect in linearization of short circuit &&) Kamil Dudka
@ 2010-02-16 20:18 ` Kamil Dudka
2010-02-16 22:44 ` Christopher Li
0 siblings, 1 reply; 18+ messages in thread
From: Kamil Dudka @ 2010-02-16 20:18 UTC (permalink / raw)
To: Christopher Li; +Cc: linux-sparse
On Tuesday 16 of February 2010 21:11:31 Kamil Dudka wrote:
> It makes no sense to me - on my box I am getting the same
> sizeof(struct expression)==64 before/after the patch applied.
I've just remembered. There was problem on a 32bit system - 32 bytes before
and 36 bytes after the patch applied...
Kamil
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: enum warning patch (was Re: Defect in linearization of short circuit &&)
2010-02-16 20:18 ` Kamil Dudka
@ 2010-02-16 22:44 ` Christopher Li
2010-02-17 14:00 ` Kamil Dudka
0 siblings, 1 reply; 18+ messages in thread
From: Christopher Li @ 2010-02-16 22:44 UTC (permalink / raw)
To: Kamil Dudka; +Cc: linux-sparse
On Tue, Feb 16, 2010 at 12:18 PM, Kamil Dudka <kdudka@redhat.com> wrote:
> I've just remembered. There was problem on a 32bit system - 32 bytes before
> and 36 bytes after the patch applied...
Yes, size is one of the aspect. I am more worry about putting the enum
information
at the wrong place.
It is about the enum type. It should store in the type system. The
expression is one
level above the type system, it contain a ctype there.
I am much happier if that enum information can be reach from the
expr->ctype some how,
which I haven't find out yet.
While you are here. I have a question for you.
Most simple enum declare has very small set of values. So naturally I
might want to use
some thing smaller than int type to store the enum value. I can't find
a good way to play
well with the enum warnings.
If I use "char type" to store it. It trigger warning when you assign to it.
If I use "enum foo_type type:8" to store it, it will use int type
alignment and padding which
defeat the purpose of using a smaller type.
Any suggestion?
Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-16 19:02 ` Christopher Li
2010-02-16 19:10 ` Christopher Li
2010-02-16 19:19 ` Jacek Śliwerski
@ 2010-02-17 11:47 ` Bernd Petrovitsch
2010-02-17 20:22 ` Christopher Li
2 siblings, 1 reply; 18+ messages in thread
From: Bernd Petrovitsch @ 2010-02-17 11:47 UTC (permalink / raw)
To: Christopher Li; +Cc: Jacek Śliwerski, linux-sparse
On Die, 2010-02-16 at 11:02 -0800, Christopher Li wrote:
> On Tue, Feb 16, 2010 at 1:28 AM, Bernd Petrovitsch
> <bernd@petrovitsch.priv.at> wrote:
> >> $ ./test-linearize parser_check.c
> >> parser_check:
> >> .L0x7f4e12de3130:
> >> <entry-point>
> >> br %arg1, .L0x7f4e12de32e0, .L0x7f4e12de3250
> > I assume this means "if %arg1 == NULL goto .L0x7f4e12de32e0 else goto .L0x7f4e12de3250"
>
> That is right.
>
> > I assume this is the "i > 0" check.
>
> No, this is the not the i > 0 check yet. This is setting the expression value
> of the false branch to 0.
>
> >> phisrc.1 %phi2 <- $0
> >> br .L0x7f4e12de3298
> >>
> >> .L0x7f4e12de3298:
> >> phi.1 %r8 <- %phi1, %phi2
> >> setgt.32 %r10 <- %arg2, $0
>
> This is the "i > 0" check. (%arg2 is "i")
>
> >> and-bool.1 %r11 <- %r8, %r10
> >> br %r11, .L0x7f4e12de3178, .L0x7f4e12de31c0
> >>
> >> .L0x7f4e12de3178:
> >> call execute_a, %arg1, %arg2
> >> br .L0x7f4e12de3328
> >>
> >> In the fast test, the false branch is L0x7f4e12de3250.
> >> Which is doing the (i > 0) part and it is safe to do so.
>
> > Are saying that he "i >0 " test done while "st == NULL"?
> > This is actually wrong as it shouldn't be done (independent of the used
> > variables and especially if the expression has side effects).
>
> That is right. "i > 0" is still being tested.
>
> Consider this example. The same source code and be compile into two
> different piece of machine code. They produce the exact same result.
> The one with this optimization runs faster than the other one. Do you still
> thing that is wrong? How about x86 CPU internally re-ordering the instruction,
No. The above is the conceptual point of view as it's the definition
(for the C programming language).
As long as the outside observed behaviour is as if the "i > 0" (in this
example) has never been executed (IOW: any side effect didn't show up),
it's correct.
"Speculative execution" works that way.
> is that wrong too?
As long as the program behaves as if it did not happen, it' correct. So
calculating all conditions in parallel is IMHO fine as long as any
"writeback operation" (which are outside relevant) happen if and only if
the conditions were "true" (in the above example).
> So I think as long as this behavior is *internal* and *correct*. It is fine.
I think we are actually in violent agreement. I got the impression that
this was a general strategy (and not where all parts of the && sequence
are side-effect free).
> Of course it'd better be faster as well. Otherwise, what is the point.
Yup.
> The goal of the this optimization is trading the branch instruction
> with cheaper arithmetic instruction.
>
> For modern CPU, the branch instruction is likely more expensive
> than normal arithmetic instruction. In X86, branch instruction *might*
> flush the instruction pipe line while arithmetic operation can usually done
> in one cycle.
>
> That is why this optimization is using a cost model. If the left hand
> side cost is lower than the branch instruction cost, and it is *safe* to
> do so. It turn the branch instruction into arithmetic instruction.
>
> However, in this case, the optimization did not consider this expression
> is used in the if statement, and if statement has build-in branch instruction
> associate with it. So this optimization might not worthy while here.
>
> But for this expression:
>
> a = st && st->foo && st->bar && i > 0;
>
> This optimization might be worth while.
ACK. But this example has no side effect (assuming no preprocessor
trickery, no "volatile" somewhere relevant, etc.) so it' not
"dangerous".
Above I was talking about the general case.
> If the optimization produce incorrect result. That is fatal and that
> is a serious bug.
> I just want to confirm that is no the case here.
Bernd
--
Bernd Petrovitsch Email : bernd@petrovitsch.priv.at
LUGA : http://www.luga.at
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: enum warning patch (was Re: Defect in linearization of short circuit &&)
2010-02-16 22:44 ` Christopher Li
@ 2010-02-17 14:00 ` Kamil Dudka
0 siblings, 0 replies; 18+ messages in thread
From: Kamil Dudka @ 2010-02-17 14:00 UTC (permalink / raw)
To: Christopher Li; +Cc: linux-sparse
On Tue February 16 2010 23:44:08 Christopher Li wrote:
> Most simple enum declare has very small set of values. So naturally I
> might want to use
> some thing smaller than int type to store the enum value. I can't find
> a good way to play
> well with the enum warnings.
>
> If I use "char type" to store it. It trigger warning when you assign to it.
> If I use "enum foo_type type:8" to store it, it will use int type
> alignment and padding which
> defeat the purpose of using a smaller type.
>
> Any suggestion?
I don't think it's that easy to implement while keeping it enough generic.
You need either a type able to store _any_ enum value, or a kind of type
with variable size to keep it still working. The second seems like quite
a lot of fuss over 4 bytes of memory.
Kamil
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Defect in linearization of short circuit &&
2010-02-17 11:47 ` Defect in linearization of short circuit && Bernd Petrovitsch
@ 2010-02-17 20:22 ` Christopher Li
0 siblings, 0 replies; 18+ messages in thread
From: Christopher Li @ 2010-02-17 20:22 UTC (permalink / raw)
To: Bernd Petrovitsch; +Cc: Jacek Śliwerski, linux-sparse
On Wed, Feb 17, 2010 at 3:47 AM, Bernd Petrovitsch
<bernd@petrovitsch.priv.at> wrote:
>>
>> But for this expression:
>>
>> a = st && st->foo && st->bar && i > 0;
>>
>> This optimization might be worth while.
> ACK. But this example has no side effect (assuming no preprocessor
> trickery, no "volatile" somewhere relevant, etc.) so it' not
> "dangerous".
> Above I was talking about the general case.
Then we are in agreement.
Sparse actually go the extra mile to make sure the expression is
safe. So whenever the expression has side effects or unsafe, it set the cost
of the expression prohibitively high.
E.g:
expand_dereference() return UNSAFE because the expression can segfault.
expand_call() return SIDE_EFFECT.
So if there is a bug cause the some unsafe optimization. We just just fix the
bug instead of disable the optimization.
It is harder to do this optimization in the linearized instructions because
the linearized instruction does not have the expression boundary any more.
Chris
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2010-02-17 20:22 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-14 13:39 Defect in linearization of short circuit && Jacek Śliwerski
2010-02-14 21:04 ` Jacek Śliwerski
2010-02-14 23:09 ` Christopher Li
2010-02-15 19:12 ` Jacek Śliwerski
2010-02-15 19:41 ` Christopher Li
2010-02-15 20:18 ` Jacek Śliwerski
2010-02-15 21:11 ` Christopher Li
2010-02-16 9:28 ` Bernd Petrovitsch
2010-02-16 19:02 ` Christopher Li
2010-02-16 19:10 ` Christopher Li
2010-02-16 19:19 ` Jacek Śliwerski
2010-02-16 19:36 ` Christopher Li
2010-02-16 20:11 ` enum warning patch (was Re: Defect in linearization of short circuit &&) Kamil Dudka
2010-02-16 20:18 ` Kamil Dudka
2010-02-16 22:44 ` Christopher Li
2010-02-17 14:00 ` Kamil Dudka
2010-02-17 11:47 ` Defect in linearization of short circuit && Bernd Petrovitsch
2010-02-17 20:22 ` Christopher Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).