mersenneforum.org  

Go Back   mersenneforum.org > Factoring Projects > Cunningham Tables

Reply
 
Thread Tools
Old 2010-10-02, 11:31   #23
R.D. Silverman
 
R.D. Silverman's Avatar
 
Nov 2003

746010 Posts
Default

Quote:
Originally Posted by R.D. Silverman View Post
I found the following in an Intel development manual:

"As discussed in section 2.3, some compilers do not implicitly recognize the RDTSC and CPUID function in inline
assembly code. Compilers like Microsoft® Visual C++® 5.0 normally "guarantee" that any register affected by an
inline assembly code section will not affect the C code around it. When overriding the compiler by using the emit
statements, however, the compiler does not know those instructions are overwriting registers (RDTSC overwrites
EAX and EDX, and CPUID overwrites EAX, EBX, ECX, and EDX). Thus, the compiler may not properly store away
the affected registers, so this must be done manually by the programmer by pushing them onto the stack.
There are a few cases where this will not matter. If the code being time measured is a stand-alone section of code,
completely surrounded by the calls to RDTSC, then the register overwriting cannot affect the code around it. If the
measured code section is written in assembly, and the variables are actually used inside of this section, the compiler
will handle the stack allocation itself. Finally, it will not matter if affecting the correctness of the code around the
measured section is not an issue while cycle testing."

Note however, that I did a workaround such that the compiler does NOT
in-line the clock sample code, but instead calls a subroutine. The emitted
code is still mis-using the edx register a few lines later. It seems certain
that the clock sample subroutine is not restoring the edx register when it
returns.
One possible (ugly!) workaround might be:

saved_edx_value = save_edx();
stime = get_time();
restored_edx_value(saved_edx_value);

where save_edx and restore_edx_value are simple hand-coded _asm
routines.

But this is such a kludge!

A better way is to rewrite get_time() in a way such that the compiler
restores the edx register when it exits. I am unsure how to do that.

Here is the current code:

/************************************************************************/
/* */
/* Routine to access the clock. On Pentium prectime returns ticks */
/* */
/************************************************************************/

double get_time()

{ /* start of get_time */

return((double)prectime());

} /* end of get_time */



__int64 prectime(void)
{
__int64 t;
unsigned int a,b;
unsigned int *c = (unsigned int *)&t;
_asm
{
_emit 0x0f;
_emit 0x31;
mov a,eax;
mov b,edx;
}

c[0]=a;
c[1]=b;
return t;
}
R.D. Silverman is offline   Reply With Quote
Old 2010-10-02, 11:37   #24
R.D. Silverman
 
R.D. Silverman's Avatar
 
Nov 2003

22·5·373 Posts
Default

Quote:
Originally Posted by R.D. Silverman View Post
One possible (ugly!) workaround might be:

saved_edx_value = save_edx();
stime = get_time();
restored_edx_value(saved_edx_value);

where save_edx and restore_edx_value are simple hand-coded _asm
routines.

But this is such a kludge!

A better way is to rewrite get_time() in a way such that the compiler
restores the edx register when it exits. I am unsure how to do that.

Here is the current code:

/************************************************************************/
/* */
/* Routine to access the clock. On Pentium prectime returns ticks */
/* */
/************************************************************************/

double get_time()

{ /* start of get_time */

return((double)prectime());

} /* end of get_time */



__int64 prectime(void)
{
__int64 t;
unsigned int a,b;
unsigned int *c = (unsigned int *)&t;
_asm
{
_emit 0x0f;
_emit 0x31;
mov a,eax;
mov b,edx;
}

c[0]=a;
c[1]=b;
return t;
}
I suppose that I could manually insert code into prectime that saves/restores
the edx register via:

__int64 t;
unsigned int a,b,tmp;
unsigned int *c = (unsigned int *)&t;
_asm
{
mov tmp, edx
_emit 0x0f;
_emit 0x31;
mov a,eax;
mov b,edx;
mov edx,tmp
}

Yech!
R.D. Silverman is offline   Reply With Quote
Old 2010-10-02, 14:18   #25
axn
 
axn's Avatar
 
Jun 2003

13D416 Posts
Default

Quote:
Originally Posted by R.D. Silverman View Post
I suppose that I could manually insert code into prectime that saves/restores
the edx register via:

__int64 t;
unsigned int a,b,tmp;
unsigned int *c = (unsigned int *)&t;
_asm
{
mov tmp, edx
_emit 0x0f;
_emit 0x31;
mov a,eax;
mov b,edx;
mov edx,tmp
}

Yech!
Please see my earlier post -- It might not just be the edx register that you need to preserver. eax may also need to be preserved.
axn is online now   Reply With Quote
Old 2010-10-02, 14:24   #26
axn
 
axn's Avatar
 
Jun 2003

22·33·47 Posts
Default

Quote:
Originally Posted by retina View Post
Unlikely because the debug code show the values being loaded from the stack. It would be extremely strange code that places pointers to the data on the stack AND loads eax/edx with pointers to the data and then calls the subroutine. There is no calling standard that defines that behaviour.
Debug code and release code need not have any relation to each other. This is a case where the optimizer is not realizing that eax/edx got clobbered. But without seeing the assembly of how the routine is _called_, it is just speculation.
axn is online now   Reply With Quote
Old 2010-10-02, 14:32   #27
axn
 
axn's Avatar
 
Jun 2003

13D416 Posts
Default

Can you post the code of your get_time function? Are you using opcodes using inline assembly or are you using __rdtsc() intrinsic (http://msdn.microsoft.com/en-us/library/twchhe95.aspx)?

Last fiddled with by axn on 2010-10-02 at 14:34
axn is online now   Reply With Quote
Old 2010-10-02, 16:06   #28
R.D. Silverman
 
R.D. Silverman's Avatar
 
Nov 2003

22·5·373 Posts
Default

Quote:
Originally Posted by axn View Post
Can you post the code of your get_time function? Are you using opcodes using inline assembly or are you using __rdtsc() intrinsic (http://msdn.microsoft.com/en-us/library/twchhe95.aspx)?
?? See #23, #24 in this thread!
R.D. Silverman is offline   Reply With Quote
Old 2010-10-02, 16:07   #29
R.D. Silverman
 
R.D. Silverman's Avatar
 
Nov 2003

1D2416 Posts
Default

Quote:
Originally Posted by R.D. Silverman View Post
?? See #23, #24 in this thread!
BTW, I did an explicit save/restore of eax, edx, and the code
now works fine.

Last fiddled with by R.D. Silverman on 2010-10-02 at 16:08
R.D. Silverman is offline   Reply With Quote
Old 2010-10-02, 18:17   #30
axn
 
axn's Avatar
 
Jun 2003

22·33·47 Posts
Default

Quote:
Originally Posted by R.D. Silverman View Post
BTW, I did an explicit save/restore of eax, edx, and the code
now works fine.
Oops. Didn't realize that was the code. Can you use the __rdtsc intrinsic instead? As in:
Code:
double get_time()
{ /* start of get_time */
  return((double)__rdtsc());
} /* end of get_time */
Does the compiler recognize that eax/edx is getting clobbered in this case and saves it?
axn is online now   Reply With Quote
Old 2010-10-02, 22:12   #31
R.D. Silverman
 
R.D. Silverman's Avatar
 
Nov 2003

164448 Posts
Default

Quote:
Originally Posted by axn View Post
Oops. Didn't realize that was the code. Can you use the __rdtsc intrinsic instead? As in:
Code:
double get_time()
{ /* start of get_time */
  return((double)__rdtsc());
} /* end of get_time */
Does the compiler recognize that eax/edx is getting clobbered in this case and saves it?
I don't know. It is moot at this point.

BTW, when I first wrote this code, the intrinsic did not exist......
R.D. Silverman is offline   Reply With Quote
Reply

Thread Tools


Similar Threads
Thread Thread Starter Forum Replies Last Post
mprime 28.10 compiler warning Explorer09 Software 1 2017-01-23 02:50
GCC/compiler warnings Dubslow Programming 2 2016-02-27 06:55
compiler/assembler optimizations possible? ixfd64 Software 7 2011-02-25 20:05
Linux32 -> Windows64 C compiler? geoff Programming 3 2007-09-26 03:09
/. Video processor compiler tha Hardware 17 2005-10-12 08:10

All times are UTC. The time now is 08:09.


Tue Jul 27 08:09:08 UTC 2021 up 4 days, 2:38, 0 users, load averages: 1.57, 1.61, 1.72

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.

This forum has received and complied with 0 (zero) government requests for information.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation.
A copy of the license is included in the FAQ.