Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2020-11

Might need some help with this one

18 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

J. Gareth Moreton

Hi everyone,

So a couple of people have reported that -O2 sometimes produces bad code under x86_64.  So far it seems isolated to that CPU.

https://bugs.freepascal.org/view.php?id=38129

After my own investigations with the attached code, the problem still occurs even if the peephole optimizer is disabled, and the uninitialised register is being allocated within conditional code that is not always executed, rather than before or after it.

Anyone with any tips on where to dig next (register allocator, node converter etc.) would be most appreciated!

Gareth aka. Kit

P.S. Also, there seems to be a strange, unrelated glitch.  If I rename the file to "break.pp" and change the program name to "break" (from breakp), the compiled binary doesn't seem to write output (or it immediately exits - can't tell yet).  I'm not sure if this is because of the program name being the same as an instruction or what.

This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

Bart
to J. Gareth Moreton
PM J. Gareth Moreton wrote 5 lines
P.S. Also, there seems to be a strange, unrelated glitch. If I rename the file to "break.pp" and change the program name to "break" (from breakp), the compiled binary doesn't seem to write output (or it immediately exits - can't tell yet). I'm not sure if this is because of the program name being the same as an instruction or what.

Isn't break a reserved word?

Bart

Reply by email

J. Gareth Moreton
to Bart

Technically it isn't a reserved word, or at least not a keyword. Either way the compiler allows it, but the result is peculiar.  It probably shouldn't be allowed in that case.

Gareth aka. Kit

Bart wrote 10 lines
On Thu, Nov 26, 2020 at 4:34 PM J. Gareth Moreton via fpc-devel wrote: > P.S. Also, there seems to be a strange, unrelated glitch. If I rename > the file to "break.pp" and change the program name to "break" (from > breakp), the compiled binary doesn't seem to write output (or it > immediately exits - can't tell yet). I'm not sure if this is because of > the program name being the same as an instruction or what. Isn't break a reserved word?
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

Bart
to J. Gareth Moreton

On Thu, Nov 26, 2020 at 5:00 PM J. Gareth Moreton via fpc-devel wrote:

program break;
{$apptype console}
begin
  writeln('I am Break');
end.

Compiles with fpc 3.2.0 and Delphi 7.
Outputs nothing at all with both compilers....

If I run it inside GDB
Delphi 7 of fpc:
Starting program: C:\Users\Bart\LazarusProjecten\bugs\breakprog/break.exe [New Thread 6888.0x26fc]
[New Thread 6888.0x1ea0]
[New Thread 6888.0x6bc]
[New Thread 6888.0x25b0]
I am Break

Program exited normally.

Bart

Reply by email

Bart
to Bart
PM Bart wrote 24 lines
program break; {$apptype console} begin writeln('I am Break'); end. Compiles with fpc 3.2.0 and Delphi 7. Outputs nothing at all with both compilers.... If I run it inside GDB Delphi 7 of fpc: Starting program: C:\Users\Bart\LazarusProjecten\bugs\breakprog/break.exe [New Thread 6888.0x26fc] [New Thread 6888.0x1ea0] [New Thread 6888.0x6bc] [New Thread 6888.0x25b0] I am Break Program exited normally. -- Bart
  assign(F, 'break.txt');
  rewrite(F);
  writeln(F,'Writing to file...');
  close(F);

Does not create a file (if the program is called break). Unless you run it in GDB, then it does.

Curious...

If you rename the executable (so after compilation/building) it runs as expected.
So it is Windows that does this .....

Bart

Reply by email

J. Gareth Moreton
to Bart: On Thu, Nov 26, 2020 at 5:00 PM J. Gareth Moreton via fpc-devel program break; {$apptype…

That is very peculiar, especially given that Delphi has the same problem!  I wonder what's causing that.

Going back to the problem at hand though... seems we have bad code being generated in places on x86_64, but it's not in the peephole optimizer for once!

Gareth aka. Kit

Bart wrote 25 lines
On Thu, Nov 26, 2020 at 5:00 PM J. Gareth Moreton via fpc-devel wrote: program break; {$apptype console} begin writeln('I am Break'); end. Compiles with fpc 3.2.0 and Delphi 7. Outputs nothing at all with both compilers.... If I run it inside GDB Delphi 7 of fpc: Starting program: C:\Users\Bart\LazarusProjecten\bugs\breakprog/break.exe [New Thread 6888.0x26fc] [New Thread 6888.0x1ea0] [New Thread 6888.0x6bc] [New Thread 6888.0x25b0] I am Break Program exited normally.
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

Jonas Maebe
to J. Gareth Moreton: So a couple of people have reported that -O2 sometimes produces bad code under x86_64. …
J. Gareth Moreton wrote 5 lines
P.S. Also, there seems to be a strange, unrelated glitch.  If I rename the file to "break.pp" and change the program name to "break" (from breakp), the compiled binary doesn't seem to write output (or it immediately exits - can't tell yet).  I'm not sure if this is because of the program name being the same as an instruction or what.

"break" is probably a command that's recognised by the cmd shell. Try to execute the program as .\break or break.exe

Jonas

Reply by email

J. Gareth Moreton
to Jonas Maebe

Hah, that's the reason! Thanks Jonas.  Crisis averted.

Now for the original problem...

Gareth aka. Kit

Jonas Maebe wrote 15 lines
On 26/11/2020 16:34, J. Gareth Moreton via fpc-devel wrote: > P.S. Also, there seems to be a strange, unrelated glitch.  If I rename > the file to "break.pp" and change the program name to "break" (from > breakp), the compiled binary doesn't seem to write output (or it > immediately exits - can't tell yet).  I'm not sure if this is because of > the program name being the same as an instruction or what. "break" is probably a command that's recognised by the cmd shell. Try to execute the program as .\break or break.exe Jonas _______________________________________________ fpc-devel maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

Yuriy Sydorov
to J. Gareth Moreton: So a couple of people have reported that -O2 sometimes produces bad code under x86_64. …

Hi,

J. Gareth Moreton wrote 12 lines
Hi everyone, So a couple of people have reported that -O2 sometimes produces bad code under x86_64.  So far it seems isolated to that CPU. https://bugs.freepascal.org/view.php?id=38129 After my own investigations with the attached code, the problem still occurs even if the peephole optimizer is disabled, and the uninitialised register is being allocated within conditional code that is not always executed, rather than before or after it. Anyone with any tips on where to dig next (register allocator, node converter etc.) would be most appreciated!

First compile with the "-Ooregvar -alr -sr" switches. You will get the assembler output with imaginary registers and notes about register allocations and de-allocations. Inspect if all is correct at this stage. If not then the a code generator of some node is buggy.

Then compile with "-Ooregvar -alr". If the issue is present only at this stage, then the bug is in the register allocator.

Yuriy.

Reply by email

Bart
to Jonas Maebe: "break" is probably a command that's recognised by the cmd shell. Try to execute the…
PM Jonas Maebe wrote
"break" is probably a command that's recognised by the cmd shell.

Yes it is:
C:\Users\Bart>help break
Sets or Clears Extended CTRL+C checking on DOS system

This is present for Compatibility with DOS systems. It has no effect under Windows.

If Command Extensions are enabled, and running on the Windows platform, then the BREAK command will enter a hard coded breakpoint if being debugged by a debugger.

Try to execute the program as .\break or break.exe

Makes no difference whatsoever.
It does run, because you can set ExitCode and query errorlevel after execution.

Bart

Reply by email

J. Gareth Moreton
to Yuriy Sydorov: First compile with the "-Ooregvar -alr -sr" switches. You will get the assembler output…

Okay, so I have to specify "-MObjfpc -Sh" to get it to compile due to what the code uses, and the bug still requires the use of -O2 to appear.  However... "fpc -MObjfpc -Sh -O2 -Ooregvar -alr -sr breakp.pp" produces a bad binary.

I removed the register comments so it's clearer:

    ...
# [11] pChar(result)[i] := BarSym[(progress >= (0.75 + i) / divs) or (i = int32(divs) - 1) and (progress >= 1)];
    cvtsi2ssl    %ireg16d,%mreg34ms
    movaps    %mreg34ms,%mreg35ms
    addss    _$BREAKP$_Ld1(%rip),%mreg35ms
    movl    %ireg18d,%ireg28d
    andl    $4294967295,%ireg28d
    cvtsi2ssq    %ireg28q,%mreg37ms
    movaps    %mreg35ms,%mreg38ms
    divss    %mreg37ms,%mreg38ms
    comiss    %mreg32ms,%mreg38ms
    jp    .Lj12
    jbe    .Lj10 <---- Register %ireg27q not initialised if this instruction branches to .Lj10
.Lj12:
    jmp    .Lj11
.Lj11:
    movl    %ireg18d,%ireg29d
    movslq    %ireg29d,%ireg30q
    subq    $1,%ireg30q
    movslq    %ireg16d,%ireg31q
    movq    %ireg31q,%ireg27q <---- Problem register: %ireg27q     cmpq    %ireg27q,%ireg30q
    je    .Lj14
    jmp    .Lj15
.Lj14:
    comiss    _$BREAKP$_Ld2(%rip),%mreg32ms
    jp    .Lj17
    jae    .Lj16
.Lj17:
    jmp    .Lj15
.Lj16:
    jmp    .Lj10
.Lj15:
    jmp    .Lj13
.Lj10:
    movq    $1,%ireg32q
    jmp    .Lj18
.Lj13:
    movq    $0,%ireg32q
.Lj18:
    movq    (%ireg17q),%ireg33q
    cmpq    $0,%ireg33q
    jne    .Lj19
    leaq    FPC_EMPTYCHAR(%rip),%ireg33q
.Lj19:
    leaq
TC_$P$BREAKP$_$BAR$SINGLE$LONGWORD$$ANSISTRING_$$_BARSYM(%rip),%ireg34q     movb    (%ireg34q,%ireg32q,1),%ireg35l
    movb    %ireg35l,(%ireg33q,%ireg27q,1) <---- Problem register: %ireg27q     cmpl    %ireg25d,%ireg16d
    jge    .Lj9
    jmp    .Lj7
.Lj9:
.Lj6:
    ...

The problem register is %ireg27q - it's not being initialised if "jbe .Lj10" branches.  By your explanation, it seems that the code generator is buggy on one of the nodes.  Thanks for the tips in isolating where it could be.  To help out, I've attached the node dump file for the test program.

Gareth aka. Kit

Yuriy Sydorov wrote 31 lines
Hi, On 26.11.2020 17:34, J. Gareth Moreton via fpc-devel wrote: > Hi everyone, > > So a couple of people have reported that -O2 sometimes produces bad > code under x86_64.  So far it seems isolated to that CPU. > > https://bugs.freepascal.org/view.php?id=38129 > > After my own investigations with the attached code, the problem still > occurs even if the peephole optimizer is disabled, and the > uninitialised register is being allocated within conditional code > that is not always executed, rather than before or after it. > > Anyone with any tips on where to dig next (register allocator, node > converter etc.) would be most appreciated! First compile with the "-Ooregvar -alr -sr" switches. You will get the assembler output with imaginary registers and notes about register allocations and de-allocations. Inspect if all is correct at this stage. If not then the a code generator of some node is buggy. Then compile with "-Ooregvar -alr". If the issue is present only at this stage, then the bug is in the register allocator. Yuriy. _______________________________________________ fpc-devel maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

Tomas Hajny
to Bart: On Thu, Nov 26, 2020 at 6:52 PM Jonas Maebe via fpc-devel Yes it is: C:\Users\Bart>help…
Bart wrote 21 lines
On Thu, Nov 26, 2020 at 6:52 PM Jonas Maebe via fpc-devel wrote: > "break" is probably a command that's recognised by the cmd shell. Yes it is: C:\Users\Bart>help break Sets or Clears Extended CTRL+C checking on DOS system This is present for Compatibility with DOS systems. It has no effect under Windows. If Command Extensions are enabled, and running on the Windows platform, then the BREAK command will enter a hard coded breakpoint if being debugged by a debugger. > Try to > execute the program as .\break or break.exe Makes no difference whatsoever. It does run, because you can set ExitCode and query errorlevel after execution.

Typing 'break.exe' in cmd.exe _does_ make a difference here (it executes as expected unlike when typing just 'break'). And obviously running break.exe using some other 'shell' (e.g. your preferred OFM ;-) ) works as well.

Tomas

Reply by email

Bart
to Tomas Hajny
PM Tomas Hajny wrote
Typing 'break.exe' in cmd.exe _does_ make a difference here (it executes as expected unlike when typing just 'break'). And obviously running break.exe using some other 'shell' (e.g. your preferred OFM ;-) ) works as well.

Well, at my machine it did not.
I also called it from a batchfile (as break.exe) to see if I could catch the errorlevel (I let it crash with a division by zero). The errorlevel is set, but absolutely no output to screen or pipe.

Bart

Reply by email

Tomas Hajny
to Bart
Bart wrote 14 lines
On Thu, Nov 26, 2020 at 11:10 PM Tomas Hajny via fpc-devel wrote: > Typing 'break.exe' in cmd.exe _does_ make a difference here (it > executes > as expected unlike when typing just 'break'). And obviously running > break.exe using some other 'shell' (e.g. your preferred OFM ;-) ) > works > as well. Well, at my machine it did not. I also called it from a batchfile (as break.exe) to see if I could catch the errorlevel (I let it crash with a division by zero). The errorlevel is set, but absolutely no output to screen or pipe.

Understood. Haven't I already mentioned something about MS approach towards compatibility here recently? :/

-------------------
D:\TEMP>cmd
Microsoft Windows [Version 10.0.18363.1082]
(c) 2019 Microsoft Corporation. Všechna práva vyhrazena.

D:\TEMP>break

D:\TEMP>break.exe
I am Break

D:\TEMP>.\break
I am Break

D:\TEMP>
===================

Tomas

Reply by email

Alexander Grotewohl
to Tomas Hajny

"break" is a windows built-in. explains the first attempt.

Alexander Grotewohl https://dcclost.com ________________________________
Earlier message 42 lines
From: fpc-devel on behalf of Tomas Hajny via fpc-devel Sent: Friday, November 27, 2020 11:16:26 AM To: FPC developers' list Cc: Tomas Hajny Subject: Re: [fpc-devel] Might need some help with this one On 2020-11-27 15:34, Bart via fpc-devel wrote: > On Thu, Nov 26, 2020 at 11:10 PM Tomas Hajny via fpc-devel > wrote: > >> Typing 'break.exe' in cmd.exe _does_ make a difference here (it >> executes >> as expected unlike when typing just 'break'). And obviously running >> break.exe using some other 'shell' (e.g. your preferred OFM ;-) ) >> works >> as well. > > Well, at my machine it did not. > I also called it from a batchfile (as break.exe) to see if I could > catch the errorlevel (I let it crash with a division by zero). > The errorlevel is set, but absolutely no output to screen or pipe. Understood. Haven't I already mentioned something about MS approach towards compatibility here recently? :/ ------------------- D:\TEMP>cmd Microsoft Windows [Version 10.0.18363.1082] (c) 2019 Microsoft Corporation. Všechna práva vyhrazena. D:\TEMP>break D:\TEMP>break.exe I am Break D:\TEMP>.\break I am Break D:\TEMP> =================== Tomas

Reply by email

J. Gareth Moreton
to Alexander Grotewohl

Crumbs, this minor aside has blown up more than the original problem!

To get back on topic, it seems there's a bug with one of the node code generators under -O2 and above.  It's not something I've researched that deeply, but I would like to see it fixed.  First though we need to find which node is malfunctioning.

Gareth aka. Kit

Alexander Grotewohl wrote 56 lines
"break" is a windows built-in. explains the first attempt. -- Alexander Grotewohl https://dcclost.com <https://dcclost.com> ------------------------------------------------------------------------ *From:* fpc-devel on behalf of Tomas Hajny via fpc-devel *Sent:* Friday, November 27, 2020 11:16:26 AM *To:* FPC developers' list *Cc:* Tomas Hajny *Subject:* Re: [fpc-devel] Might need some help with this one On 2020-11-27 15:34, Bart via fpc-devel wrote: > On Thu, Nov 26, 2020 at 11:10 PM Tomas Hajny via fpc-devel > wrote: > >> Typing 'break.exe' in cmd.exe _does_ make a difference here (it >> executes >> as expected unlike when typing just 'break'). And obviously running >> break.exe using some other 'shell' (e.g. your preferred OFM ;-) ) >> works >> as well. > > Well, at my machine it did not. > I also called it from a batchfile (as break.exe) to see if I could > catch the errorlevel (I let it crash with a division by zero). > The errorlevel is set, but absolutely no output to screen or pipe. Understood. Haven't I already mentioned something about MS approach towards compatibility here recently? :/ ------------------- D:\TEMP>cmd Microsoft Windows [Version 10.0.18363.1082] (c) 2019 Microsoft Corporation. Všechna práva vyhrazena. D:\TEMP>break D:\TEMP>break.exe I am Break D:\TEMP>.\break I am Break D:\TEMP> =================== Tomas _______________________________________________ fpc-devel maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel <https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel> _______________________________________________ fpc-devel maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

J. Gareth Moreton

(I'm on the Raspberry PI, so I'm posting this via my Webmail, so the e-mail chain may get messed up in the logs. Sorry)

BREAKTHROUGH! This issue is not isolated to x86_64-win64. I have just reproduced it on aarch64- linux.

I'm starting to suspect that i38053, i38055 and i38129 are all related.

Gareth aka. Kit

On Fri 27/11/20 19:47 , "J. Gareth Moreton via fpc-devel" sent:

Show quoted text 86 lines
Crumbs, this minor aside has blown up more than the original problem! To get back on topic, it seems there's a bug with one of the node code generators under -O2 and above.  It's not something I've researched that deeply, but I would like to see it fixed.  First though we need to find which node is malfunctioning. Gareth aka. Kit On 27/11/2020 19:43, Alexander Grotewohl via fpc-devel wrote: "break" is a windows built-in. explains the first attempt. -- Alexander Grotewohl https://dcclost.com [1] ------------------------- FROM: fpc-devel on behalf of Tomas Hajny via fpc-devel SENT: Friday, November 27, 2020 11:16:26 AM TO: FPC developers' list CC: Tomas Hajny SUBJECT: Re: [fpc-devel] Might need some help with this one   On 2020-11-27 15:34, Bart via fpc-devel wrote: > On Thu, Nov 26, 2020 at 11:10 PM Tomas Hajny via fpc-devel > wrote: > >> Typing 'break.exe' in cmd.exe _does_ make a difference here (it >> executes >> as expected unlike when typing just 'break'). And obviously running >> break.exe using some other 'shell' (e.g. your preferred OFM ;-) ) >> works >> as well. > > Well, at my machine it did not. > I also called it from a batchfile (as break.exe) to see if I could > catch the errorlevel (I let it crash with a division by zero). > The errorlevel is set, but absolutely no output to screen or pipe. Understood. Haven't I already mentioned something about MS approach towards compatibility here recently? :/ ------------------- D:TEMP>cmd Microsoft Windows [Version 10.0.18363.1082] (c) 2019 Microsoft Corporation. Všechna práva vyhrazena. D:TEMP>break D:TEMP>break.exe I am Break D:TEMP>.break I am Break D:TEMP> =================== Tomas _______________________________________________ fpc-devel maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel [2] _______________________________________________  fpc-devel maillist -   https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel  [3] Virus-free. www.avast.com [4] [5] _______________________________________________ fpc-devel maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel [6] Links: ------ [1] https://dcclost.com [2] https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel [3] https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campai gn=sig-emailheight: 29px; [4] https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campai gn=sig-email[5] http://secureweb.fast.net.uk/#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2 [6] http://secureweb.fast.net.uk/parse.php?redirect=https://lists.freepascal.or g/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

J. Gareth Moreton
to J. Gareth Moreton: Crumbs, this minor aside has blown up more than the original problem! To get back on…

I got a fix.

https://bugs.freepascal.org/view.php?id=38129

It's not perfect because CSE becomes less efficient, but it appears to fix the bug.  Someone with more knowledge of this part of the compiler might be able to improve on it in the future. x86_64-win64 and aarch64-linux tests all pass.  I'm not yet sure if it fixes the -O2 bugs reported on aarch64 specifically - those will have to be tested when this fix (or another one) goes live.

Gareth aka. Kit

J. Gareth Moreton wrote 78 lines
Crumbs, this minor aside has blown up more than the original problem! To get back on topic, it seems there's a bug with one of the node code generators under -O2 and above.  It's not something I've researched that deeply, but I would like to see it fixed. First though we need to find which node is malfunctioning. Gareth aka. Kit On 27/11/2020 19:43, Alexander Grotewohl via fpc-devel wrote: > "break" is a windows built-in. explains the first attempt. > > -- > Alexander Grotewohl > https://dcclost.com <https://dcclost.com> > ------------------------------------------------------------------------ > *From:* fpc-devel on behalf > of Tomas Hajny via fpc-devel > *Sent:* Friday, November 27, 2020 11:16:26 AM > *To:* FPC developers' list > *Cc:* Tomas Hajny > *Subject:* Re: [fpc-devel] Might need some help with this one > On 2020-11-27 15:34, Bart via fpc-devel wrote: > > On Thu, Nov 26, 2020 at 11:10 PM Tomas Hajny via fpc-devel > > wrote: > > > >> Typing 'break.exe' in cmd.exe _does_ make a difference here (it > >> executes > >> as expected unlike when typing just 'break'). And obviously running > >> break.exe using some other 'shell' (e.g. your preferred OFM ;-) ) > >> works > >> as well. > > > > Well, at my machine it did not. > > I also called it from a batchfile (as break.exe) to see if I could > > catch the errorlevel (I let it crash with a division by zero). > > The errorlevel is set, but absolutely no output to screen or pipe. > > Understood. Haven't I already mentioned something about MS approach > towards compatibility here recently? :/ > > ------------------- > D:\TEMP>cmd > Microsoft Windows [Version 10.0.18363.1082] > (c) 2019 Microsoft Corporation. Všechna práva vyhrazena. > > D:\TEMP>break > > D:\TEMP>break.exe > I am Break > > D:\TEMP>.\break > I am Break > > D:\TEMP> > =================== > > Tomas > _______________________________________________ > fpc-devel maillist  - > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel > <https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel> > > _______________________________________________ > fpc-devel maillist > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient> Virus-free. www.avast.com <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient> <#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2> _______________________________________________ fpc-devel maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email