Gcc/clang -O1 bug

I encountered a gcc/clang -O1 (not -O2) optimization bug that really
shocked me a bit.

In the code below, if the following line is dropped,

val () = ptr_volatile (p_nseq)

then the gcc/clang (with -O1) somehow thinks that the content of nseq is
never modified. As a consequence, the function always returns 0. If -O1
is dropped or changed to -O0, then the compiled code works fine. I also
tried tcc and noticed that it can compile the following code correctly.

This is a shock because the involved code is so simple!

To see what happens, you can try out the code at:

implement
board_dirmax
(
board, pid, dir, i, j
) = let
//
var nseq: int = 0
val p_nseq = addr@nseq
//
fun loop
(
i: int, j: int
) : void = let
//
val pid2 = board[i, j]
//
in
if pid = pid2
then let
val n = $UN.ptr1_get (p_nseq)
val () = $UN.ptr1_set (p_nseq, n + 1)
val (i, j) = dirnext (dir, i, j)
in
loop (i, j)
end // end of [then]
// end of [if]
end // end of [loop]
//
val () = ptr_volatile (p_nseq) // -O1 bug if omitted
val () = try loop (i, j) with ~MatrixSubscriptExn () => ()
//
in
$UN.cast{intGte(0)}(nseq)
end // end of [board_dirmax]

Okay, I made the email setting change.On Saturday, May 17, 2014 4:40:45 AM UTC-4, Sean Leather wrote:

After off-list discussion (my apologies, but see remark at end), Hongwei
shared the generated C for this example. Follow the tmpref188 variable.
It does indeed look like a bug in GCC.

extern atstype_int
_057_home_057_hwxi_057_research_057_Postiats_055_contrib_057_git_057_projects_057_SMALL_057_M_055_N_055_K_055_game_057_Part1_057_game_board_056_dats__board_dirmax
(atstype_ptrk arg0, atstype_int arg1, atstype_boxed arg2, atstype_int arg3
, atstype_int arg4) {
atstype_int tmpret187 ;
atstype_int tmpref188 ;
;
;
atstype_exnconptr tmp270 ;
__patsflab_board_dirmax: # 5637 “game_board_dats.c” (tmpref188 = 0) ;
ATSLIB_056_prelude__ptr_volatile((&(tmpref188))) ;
do {
int flag ;
atsexnframe_ptr frame ;
atsexnframe_ptr *framep ;
frame = alloca(sizeof(atsexnframe_t)) ;
framep = my_atsexnframe_getref() ;
my_atsexnframe_enter(frame, framep) ;
flag = _setjmp (frame->
env) ;
if (flag==0) {
loop_91(arg0, arg1, arg2, (&(tmpref188)), arg3, arg4) ;
my_atsexnframe_leave(framep) ;
}
else {
tmp270 = (framep)->
exn ;
my_atsexnframe_leave(framep) ;
do {
;
__atstmplab23: if (!(((tmp270)==(void
)(&(
ATSLIB_056_prelude__MatrixSubscriptExn))))) {
atsruntime_raise(tmp270) ;
}
__atstmplab24: # 5680 “game_board_dats.c” ;
break ;
}
while (0) ;
}
}
while(0) ;
(tmpret187 = ((atstype_int)tmpref188)) ;
return (tmpret187) ;

}

About the off-list reply, this Google Group is apparently set up to have
recipients post their replies “to the author of the message only”. I
recommend changing the setting to “to the entire group”. On the group
management page, I believe you can set this in Settings → Email options →
Post replies.

Would it be possible for you (or Hongwei) to attach the generated C source as a
separate file? I’d like to have a look at this, but it’s come through a bit
mangled in the email.

-Ian

Quoting Sean Leather (2014-05-17 04:40:45)

signature.asc (836 Bytes)

gcc-4.6.3 was used.On Saturday, May 17, 2014 1:14:40 AM UTC-4, gmhwxi wrote:

I encountered a gcc/clang -O1 (not -O2) optimization bug that really
shocked me a bit.

In the code below, if the following line is dropped,

val () = ptr_volatile (p_nseq)

then the gcc/clang (with -O1) somehow thinks that the content of nseq is
never modified. As a consequence, the function always returns 0. If -O1
is dropped or changed to -O0, then the compiled code works fine. I also
tried tcc and noticed that it can compile the following code correctly.

This is a shock because the involved code is so simple!

To see what happens, you can try out the code at:

https://github.com/githwxi/ATS-Postiats-contrib/tree/master/projects/SMALL/M-N-K-game/Part1

implement
board_dirmax
(
board, pid, dir, i, j
) = let
//
var nseq: int = 0
val p_nseq = addr@nseq
//
fun loop
(
i: int, j: int
) : void = let
//
val pid2 = board[i, j]
//
in
if pid = pid2
then let
val n = $UN.ptr1_get (p_nseq)
val () = $UN.ptr1_set (p_nseq, n + 1)
val (i, j) = dirnext (dir, i, j)
in
loop (i, j)
end // end of [then]
// end of [if]
end // end of [loop]
//
val () = ptr_volatile (p_nseq) // -O1 bug if omitted
val () = try loop (i, j) with ~MatrixSubscriptExn () => ()
//
in
$UN.cast{intGte(0)}(nseq)
end // end of [board_dirmax]

After off-list discussion (my apologies, but see remark at end), Hongwei
shared the generated C for this example. Follow the tmpref188 variable. It
does indeed look like a bug in GCC.

extern atstype_int
_057_home_057_hwxi_057_research_057_Postiats_055_contrib_057_git_057_projects_057_SMALL_057_M_055_N_055_K_055_game_057_Part1_057_game_board_056_dats__board_dirmax
(atstype_ptrk arg0, atstype_int arg1, atstype_boxed arg2, atstype_int arg3,atstype_int arg4
) {
atstype_int tmpret187 ;
atstype_int tmpref188 ;
;
;
atstype_exnconptr tmp270 ;
__patsflab_board_dirmax: # 5637 “game_board_dats.c” (tmpref188 = 0) ;
ATSLIB_056_prelude__ptr_volatile((&(tmpref188))) ;
do {
int flag ;
atsexnframe_ptr frame ;
atsexnframe_ptr *framep ;
frame = alloca(sizeof(atsexnframe_t)) ;
framep = my_atsexnframe_getref() ;
my_atsexnframe_enter(frame, framep) ;
flag = _setjmp (frame->
env) ;
if (flag==0) {
loop_91(arg0, arg1, arg2, (&(tmpref188)), arg3, arg4) ;
my_atsexnframe_leave(framep) ;
}
else {
tmp270 = (framep)->
exn ;
my_atsexnframe_leave(framep) ;
do {
;
__atstmplab23: if (!(((tmp270)==(void
)(&(
ATSLIB_056_prelude__MatrixSubscriptExn))))) {
atsruntime_raise(tmp270) ;
}
__atstmplab24: # 5680 “game_board_dats.c” ;
break ;
}
while (0) ;
}
}
while(0) ;
(tmpret187 = ((atstype_int)tmpref188)) ;
return (tmpret187) ;

}

About the off-list reply, this Google Group is apparently set up to have
recipients post their replies “to the author of the message only”. I
recommend changing the setting to “to the entire group”. On the group
management page, I believe you can set this in Settings -> Email options ->
Post replies.

Here it is.

The file is generated using ‘gcc -E’.

The function of interest is the one whose name contains ‘dirmax’.

If you remove the call to ‘ptr_volatile’, then ‘gcc -O1’ may generate buggy
code.

My guess is that the cause of the problem is related to the use of
longjmp/setjmp in the code.

Rich West showed me a bug of gcc the other day involving longjmp/setjmp.
There might be a relation
between these two bugs.On Mon, May 19, 2014 at 2:03 AM, Ian Denhardt i...@zenhack.net wrote:

Would it be possible for you (or Hongwei) to attach the generated C source
as a
separate file? I’d like to have a look at this, but it’s come through a bit
mangled in the email.

-Ian

Quoting Sean Leather (2014-05-17 04:40:45)


After off-list discussion (my apologies, but see remark at end),
Hongwei shared the generated C for this example. Follow
the tmpref188 variable. It does indeed look like a bug in GCC.
extern atstype_int

_057_home_057_hwxi_057_research_057_Postiats_055_contrib_057_git_057_pr

ojects_057_SMALL_057_M_055_N_055_K_055_game_057_Part1_057_game_board_05

6_dats__board_dirmax(atstype_ptrk arg0, atstype_int arg1,
atstype_boxed
arg2, atstype_int arg3, atstype_int arg4) {
atstype_int tmpret187 ;
atstype_int tmpref188 ;
;
;
atstype_exnconptr tmp270 ;
__patsflab_board_dirmax: # 5637 “game_board_dats.c” (tmpref188 =

;
ATSLIB_056_prelude__ptr_volatile((&(tmpref188))) ;
do {
int flag ;
atsexnframe_ptr frame ;
atsexnframe_ptr *framep ;
frame = alloca(sizeof(atsexnframe_t)) ;
framep = my_atsexnframe_getref() ;
my_atsexnframe_enter(frame, framep) ;
flag = _setjmp (frame->
env) ;
if (flag==0) {
loop_91(arg0, arg1, arg2, (&(tmpref188)), arg3, arg4) ;
my_atsexnframe_leave(framep) ;
}
else {
tmp270 = (framep)->
exn ;
my_atsexnframe_leave(framep) ;
do {
;
__atstmplab23: if
(!(((tmp270)==(void
)(&(ATSLIB_056_prelude__MatrixSubscriptExn))))) {
atsruntime_raise(tmp270) ;
}
__atstmplab24: # 5680 “game_board_dats.c” ;
break ;
}
while (0) ;
}
}
while(0) ;
(tmpret187 = ((atstype_int)tmpref188)) ;
return (tmpret187) ;
}
About the off-list reply, this Google Group is apparently set up to
have recipients post their replies �to the author of the message
only�.
I recommend changing the setting to �to the entire group�. On the
group
management page, I believe you can set this in Settings → Email
options → Post replies.


You received this message because you are subscribed to the Google
Groups “ats-lang-users” group.
To unsubscribe from this group and stop receiving emails from it, send
an email to [1]ats-lang-user…@googlegroups.com.
To post to this group, send email to
[2]ats-lan…@googlegroups.com.
To view this discussion on the web visit
[3]
https://groups.google.com/d/msgid/ats-lang-users/2f01e82f-bb89-4999-
a5ff-8095b902f82b%40googlegroups.com.

References

  1. mailto:ats-lang-user...@googlegroups.com
  2. mailto:ats-lan...@googlegroups.com

https://groups.google.com/d/msgid/ats-lang-users/2f01e82f-bb89-4999-a5ff-8095b902f82b%40googlegroups.com?utm_medium=email&utm_source=footer

game_board_dats.c (238 KB)