The addition of all these new instructions to the zArchitecture make me
think that it might be wise to develop some ideas on how to determine
which instructions to use. In a very generic sense, there will likely
always be reasons to not follow the guideline in specific cases. So I'll
just throw out a few. Feel free to add new ones, modify mine, or even
say why mine are not good.
1) KISS - when possible, use simply to understand instructions. Just to
be kind to yourself and others who will come later. Don't do the
following, even though it is "neat".
*
* FIND THE MIN OF FIELD1 AND FIELD2
* NOTE THAT FIELD1 & FIELD2 MUST BE ON A HALFWORD BOUNDRY
* AND HAVE AN EVEN LENGTH.
LA R1,FIELD1
LA R3,FIELD2
XR R2,R2
LA R14,L'FIELD1
CFC 0(R14)
* R1 IS UNCHANGED OR POINTS TO THE LESSOR OF THE TWO
*
*
2) Where possible, if you have a choice of two instructions which will
produce the same effective result for your needs, use the one which does
not use or set the condition code. Silly example: if you just want to
load a value from memory, use an L instruction, not an LT instruction.
3) Where possible and understandable, use one instruction instead of
two. Example: if you want to load a value from memory and test it
against zero, then use the LT instruction instead of a L and C (or
LTR).
4) If two instructions do the same thing, use the simpler one. My
example, use LT Rx, instead of ICM Rx,B'1111', .
5) Where possible, use relative addressing instead of base+index. That
is, use the "Branch Relative Condition" in preference to an equivalent
"Branch on Condition". The same with loads and stores.
6) Use immediate instructions for "constants". And by constant, I mean
constant. Like it's loaded into store protected memory. These are
relatively new instructions on z9(?) and above. The negative of them is
that if the constant is used in many places, the code will be bloated
due to have multiple copies of the constant "in-line" in the
instructions. So it might be better to use a normal Load or Load
Relative Long (or Add or Subtract or Multiply or any of the other
immediate instructions) if you are loading the same value in, for
example, 50 different places in your code.
7) Avoid using a just loaded register value immediately. If I understand
what others have said, this can stall the pipeline. Except when it is
too confusing, intermix unrelated instructions.
8) Unroll loops. Or do multiple subscripts in a single execution of the
loop. It bloats the code, but can help execution speed. Most z machines
are not memory constrained for code.
9) Controversial: know how to use "side effects". Example: What is the
"best" way to subtract one from a value in a general register? I'd say
"BCTR Rx,0". But that is not BCTR's normal function. Maybe AHI Rx,-1
really is "better" because it is more obvious what is being done. And,
if a CC is needed, then the BCTR is definitely useless. But if the CC is
not needed, then the BCTR is, IMO, definitely better. Perhaps a list of
"well known" side effects needs to be part of our culture.
10) The fastest instruction is the one not executed. Instead of fancy
code, try to use efficient algorithms. Bubble sorts are so passe! <grin>
A silly example of this was from my z80 days. I coded a bubble sort in
good z80 assembler. And a good heap sort in interpreted BASIC. The BASIC
code ran in significantly less time than the assembler.
--
John McKown
Maranatha! <><