News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Conditional call

Started by Ian_B, February 16, 2006, 07:22:58 AM

Previous topic - Next topic

Ian_B

I have realised I have a lot of occurrences in the app I'm coding of this:

... test for likely non-error condition
conditional jump @F
invoke UnlikelyProc
@@:


This occurs sufficiently that I'm worried about the continual misprediction of the jump, and it's not pretty to code around as this "UnlikelyProc" gets called from a number of different places to handle a specific unlikely error.

So I'm wondering if there's a way to simulate a "conditional call". I'm aware that this is probably bad programming practice, but it would be much more efficient for this situation. What I envisage is the following, in pseudo-code:

... test for unlikely error condition
mov instruction pointer to register (mov doesn't change flags)
conditional jump to UnlikelyLabel (needn't be a proc now)
ReturnPoint1:
next instruction is jump return point of error code

...

... test for unlikely error condition
mov instruction pointer to register (mov doesn't change flags)
conditional jump to UnlikelyLabel (needn't be a proc now)
ReturnPoint2:
next instruction is jump return point of error code

...

UnlikelyLabel:
push reg with instruction pointer
handle unlikely error
pop reg
add reg, some value to handle few opcodes difference
         between ReturnPoint and where pointer was saved
jmp reg to ReturnPoint


Is this feasible? If so, how would it be coded? Otherwise, is there a better way?

EDIT: I don't need this solution now, as I've realised I can handle the error check consistently in a called proc, so I can handle the error easily from within the checking proc instead without losing any efficiency, but I am still curious about the concept.

IanB

Tedd

Playing with the instruction pointer is likely to give worse performance than all of the jumps (execution is actually optimised to handle call-ret pairs.)
This is a case that pops up quite often; the way I tend to do it is have the error handling at the end and then jump to it if required, since it's a forward jump it will be predicted as not taken (which is hopefully the case most of the time.)
Of course, you want the extra fun of returning to where you came from - which I don't think there's any nice clean way to do. Having the CheckAndHandleError function is probably the best - it will be called 'unnecessarily' each time, but it's a constant path so no mispredictions :wink
No snowflake in an avalanche feels responsible.

Ian_B

Quote from: Tedd on February 16, 2006, 12:48:23 PMThis is a case that pops up quite often; the way I tend to do it is have the error handling at the end and then jump to it if required, since it's a forward jump it will be predicted as not taken (which is hopefully the case most of the time.)
Thanks, Tedd. Yeah, you're right. I'm already doing that a lot, my proc ends are quite busy...  :lol

QuoteHaving the CheckAndHandleError function is probably the best - it will be called 'unnecessarily' each time, but it's a constant path so no mispredictions :wink
Well, the call isn't unnecessary, it has to be checked! I just realised that I was using a standard proc I'd written to check for the error condition (a file being present that you might overwrite) and it could be easily rewritten to reverse the test and exit early if there was no error, otherwise jumping internally to nicely encapsulated handling code, as a different function, rather than trying to handle the error on return. Guess I was getting too hung up on "code re-use"...  ::)

IanB

Tedd

Quote from: Ian_B on February 16, 2006, 01:46:54 PM
QuoteHaving the CheckAndHandleError function is probably the best - it will be called 'unnecessarily' each time, but it's a constant path so no mispredictions :wink
Well, the call isn't unnecessary, it has to be checked! I just realised that I was using a standard proc I'd written to check for the error condition (a file being present that you might overwrite) and it could be easily rewritten to reverse the test and exit early if there was no error, otherwise jumping internally to nicely encapsulated handling code, as a different function, rather than trying to handle the error on return. Guess I was getting too hung up on "code re-use"...  ::)
No it's not unnecessary (hence the ''s) I just meant that it's a function call for the sole purpose of fixing a problem which may or may not actually exist. Obviously you must check it at some point, the normal approach being to check and then call if needed (which seems to make more sense to a human mind), rather than calling each time and having the function check it.
Random idea: how about a create_the_file function which does all of the checking, and all you need to give it is the file-name (and anything else?) The errors can then be flagged from the same place each time, they can be placed at the end of the function, and you return to the correct place on return.
For other purposes you'd obviously need another function - it's not usually a good idea to try to cram everything into one function. Encapsulation is nice if you get it right, but a hammer isn't the best tool for every job :lol
No snowflake in an avalanche feels responsible.