Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

Porting VAX MACRO Code to OpenVMS Alpha


Previous Contents Index

4.2.2 Changing the Compiler's Branch Prediction

The compiler provides two directives, .BRANCH_LIKELY and .BRANCH_UNLIKELY, to change its assumptions about branch prediction. The directive .BRANCH_LIKELY is for use with forward conditional branches when the probability of the branch is large, say 75 percent or more. The directive .BRANCH_UNLIKELY is for use with backward conditional branches when the probability of the branch is less than 25 percent.

These directives should only be used in performance-sensitive code. Furthermore, you should be more cautious when adding .BRANCH_UNLIKELY, because it introduces an additional branch indirection for the case when the branch is actually taken. That is, the branch is changed to a forward branch to a branch instruction, which in turn branches to the original branch target.

There is no directive to tell the compiler not to follow an unconditional branch. However, if you want the compiler to generate code that does not follow the branch, you can change the unconditional branch to be a conditional branch that you know will always be taken. For example, if you know that in the current code section R3 always contains the address of a data structure, you could change a BRB instruction to a TSTL R3 followed by a BNEQ instruction. This branch will always be taken, but the compiler will fall through and continue code generation with the next instruction. This will always cause a mispredicted branch when executed, but may be useful in some situations.

4.2.3 How to Use .BRANCH_LIKELY

If your code has forward conditional branches that you know will most likely be taken, you can instruct the compiler to generate code using that assumption by inserting the directive .BRANCH_LIKELY immediately before the branch instruction. For example:


MOVL    (R0),R1          ; Get structure 
.BRANCH_LIKELY 
BNEQ    10$              ; Structure exists 
  . 
 (Code to deal with missing structure, which is too large for 
  the compiler to automatically change the branch prediction) 
  . 
10$: 

The compiler will follow the branch and will modify the code flow as described in the previous example, moving all the code that deals with the missing structure out of line to the end of the module.

4.2.4 How to Use .BRANCH_UNLIKELY

If your code has backward conditional branches which you know will most likely not be taken, you can instruct the compiler to generate code using that assumption by inserting the directive .BRANCH_UNLIKELY immediately before the branch instruction. For example:


        MOVL    #QUEUE,R0               ;Get queue header 
10$:    MOVL    (R0),R0                 ;Get entry from queue 
        BEQL    20$                     ;Forward branch assumed unlikely 
        .                               ;by default 
        .                               ;Process queue entry 
        . 
        TSTL    (R0)                    ;More than one entry (known to be 
        .BRANCH_UNLIKELY                ;unlikely) 
        BNEQ    10$                     ;This branch made into forward 
20$:                                    ;conditional branch 

The .BRANCH_UNLIKELY directive is used here because the Alpha hardware would predict a backward branch to 10$ as likely to be taken. The programmer knows it is a rare case, so the directive is used to change the branch to a forward branch, which is predicted not taken.

There is an unconditional branch instruction at the forward branch destination which branches back to the original destination. Again, this code fragment is moved to a point beyond the normal routine exit point. The code that would be generated by the previous VAX MACRO code follows:


        LDQ     R0, 48(R27)             ;Get address of QUEUE from linkage sect. 
10$:    LDL     R0, (R0)                ;Get entry from QUEUE 
        BEQ     R0, 20$ 
        . 
        .                               ;Process queue entry 
        . 
        LDL     R22, (R0)               ;Load temporary register with (R0) 
        BNE     R22,$L1                 ;Conditional forward branch predicted 
20$:                                    ;not taken by Alpha hardware 
        . 
        . 
        . 
        (routine exit) 
 
$L1:    BR      10$                     ;Branch to original destination 

4.2.5 Forward Jumps into Loops

Because of the way that the compiler follows the code flow, a particular case that may not compile well is a forward unconditional branch into a loop. The code generated for this case usually splits the loop into two widely separated pieces. For example, consider the following macro coding construct:


        (Allocate a data block and set up initial pointer) 
        BRB     20$ 
10$:    (Move block pointer to next section to be moved) 
 
20$:    (Move block of data) 
        (Test - is there more to move?) 
        (Yes, branch to 10$) 
 
        (Remainder of routine) 

The macro compiler will follow the BRB instruction when generating the code flow and will then fall through the subsequent conditional branch to 10$. However, because the code at 10$ was skipped over by the BRB instruction, it will not be generated until after the end of the routine. This will convert the conditional branch into a forward branch instead of a backward branch. The generated code layout will look like the following:


        (Allocate a data block and set up initial pointer) 
20$:    (Move block of data) 
        (Test - is there more to move?) 
        (Yes, branch to 10$) 
        . 
        . 
        (Remainder of routine) 
        (Routine exit) 
        . 
        . 
10$:    (Move block pointer to next section to be moved) 
        BRB     20$ 

This results in the loop being very slow because the branch to 10$ is always predicted not taken, and the code flow has to keep going back and forth between the two locations. This situation can be fixed by inserting a .BRANCH_LIKELY directive before the conditional branch back to 10$. This will result in the following code flow:


        (Allocate a data block and set up initial pointer) 
20$:    (Move block of data) 
        (Test - is there more to move?) 
 (No, branch to $L1) 
10$:    (Move block pointer to next section to be moved) 
        BRB     20$ 
$L1: 
        (Remainder of routine) 

4.3 Code Optimization

The MACRO-32 compiler performs several optimizations on the generated code. It performs all of them by default except VAXREGS. You can change these default values with the /OPTIMIZE switch on the command line. The valid options are:

Note

Debugging is simplified if you specify /NOOPTIMIZE, because the optimizations include relocating and rescheduling code. For more information, see Section 2.13.1.

4.3.1 Using the VAXREGS Optimization

To use the VAXREGS optimization, you must ensure that all routines correctly declare their register usage in their .CALL_ENTRY, .JSB_ENTRY, or .JSB32_ENTRY routine declarations. In addition, you must identify any VAX registers that are required or modified by any routines that are called. By default, the compiler assumes that no VAX registers are required as input to any called routine, and that all VAX registers except R0 and R1 are preserved across the call. To declare this usage, use the READ and WRITTEN qualifiers to the compiler directive .SET_REGISTERS. For example:


.SET_REGISTERS  READ=<R3,R4>, WRITTEN=R5 
JSB     DO_SOMETHING_USEFUL 

In this example, the compiler will assume that R3 and R4 are required inputs to the routine DO_SOMETHING_USEFUL, and that R5 is overwritten by the routine. The register usage can be determined by using the input mask of DO_SOMETHING_USEFUL as the READ qualifier, and the combined output and scratch masks as the WRITE qualifier.

Note

Using the VAXREGS qualifier without correct register declaration for both routine entry points and routine calls will produce incorrect code.

4.4 Common-Based Referencing

On an Alpha system, references to data cells generally require two memory references---one reference to load the data cell address from the linkage section and another reference to the data cell itself. If several data cells are located in proximity to one other, and the ADDRESSES optimization is used, the compiler can load a register with a common base address and then reference the individual data cells as offsets from that base address. This eliminates the load of each individual data cell address and is known as common-based referencing.

The compiler performs this optimization automatically for local data psects when the ADDRESSES optimization is turned on. The compiler generates symbols of the form $PSECT_BASEn to use as the base of a local psect.

To use common-based referencing for external data psects, you must create a prefix file which defines symbols as offsets from a common base. The prefix file cannot be used when assembling the module for OpenVMS VAX because the VAX MACRO assembler does not allow symbols to be defined as offsets from external symbols.

4.4.1 Creating a Prefix File for Common-Based Referencing

The following example illustrates the benefits of creating a prefix file to use common-based referencing. It shows:

Consider the following simple code section (CODE.MAR), which refers to data cells in another module (DATA.MAR):


Module DATA.MAR: 
 
        .PSECT  DATA    NOEXE 
BASE:: 
A::     .LONG   1 
B::     .LONG   2 
C::     .LONG   3 
D::     .LONG   4 
        .END 
 
Module CODE.MAR: 
 
        .PSECT CODE     NOWRT 
 
E::     .CALL_ENTRY 
        MOVL    A,R1 
        MOVL    B,R2 
        MOVL    C,R3 
        MOVL    D,R4 
        RET 
        .END 

When compiling CODE.MAR without using common-based referencing, the following code is generated:

In the linkage section:


        .ADDRESS        A 
        .ADDRESS        B 
        .ADDRESS        C 
        .ADDRESS        D 

In the code section (not including the prologue/epilogue code):


        LDQ     R28, 40(R27)            ;Load address of A from linkage section 
        LDQ     R26, 48(R27)            ;Load address of B from linkage section 
        LDQ     R25, 56(R27)            ;Load address of C from linkage section 
        LDQ     R24, 64(R27)            ;Load address of D from linkage section 
        LDL     R1, (R28)               ;Load value of A 
        LDL     R2, (R26)               ;Load value of B 
        LDL     R3, (R25)               ;Load value of C 
        LDL     R4, (R24)               ;Load value of D 

By creating a prefix file that defines external data cells as offsets from a common base address, you can cause the compiler to use common-based referencing for external references. A prefix file for this example, which defines A, B, C, and D in terms of BASE, follows:


A = BASE+0 
B = BASE+4 
C = BASE+8 
D = BASE+12 

When compiling CODE.MAR using this prefix file and the ADDRESSES optimization, the following code is generated:

In the linkage section:


.ADDRESS        BASE            ;Base of data psect 

In the code section (not including the prologue/epilogue code):


LDQ     R16, 40(R27)            ;Load address of BASE from linkage section  
LDL     R1, (R16)               ;Load value of A 
LDL     R2, 4(R16)              ;Load value of B 
LDL     R3, 8(R16)              ;Load value of C 
LDL     R4, 12(R16)             ;Load value of D 

In this example, common-based referencing shrinks the size of both the code and the linkage sections and eliminates three memory references. This method of creating a prefix file to enable common-based referencing of external data cells can be useful if you have one large, separate module that defines a data area used by many modules.


Part 2
Reference


Appendix A
Compiler Qualifiers

This appendix describes the invocation format of the MACRO-32 Compiler for OpenVMS Alpha and each of its qualifiers.


MACRO/MIGRATION

Invokes the MACRO-32 Compiler for OpenVMS Alpha to compile one or more VAX MACRO assembly language source files into native OpenVMS Alpha object code.


Format

MACRO/MIGRATION filespec[+...]


Parameters

filespec[+...]

Specifies a VAX MACRO assembly language source file to be compiled. If you specify more than one file, separate the file specifications with plus signs (+). File specifications separated by plus signs are concatenated into one input file and produce a single object file and, if indicated, a listing file.

Note

Unlike the VAX assembler, the MACRO-32 compiler does not support the creation of separate object files when the source files are separated by a comma (,).

You cannot include a wildcard character in a file specification. For each file specification, the compiler command supplies a default file type of MAR.

The compiler creates output files of one version higher than the highest version existing in the target directory.


Description

The qualifiers to the MACRO/MIGRATION command serve as either command (global) qualifiers or positional qualifiers. A command qualifier affects all the files specified in the command. A positional qualifier affects only the file that it qualifies. All MACRO/MIGRATION qualifiers except /LIBRARY are usable as either command or positional qualifiers. The /LIBRARY qualifier is a positional qualifier only.

Many of the qualifiers take one or more arguments. If you specify only one argument, you can omit the parentheses.

The compiler supports most of the standard MACRO qualifiers. Some of these qualifiers have additional options unique to the compiler and some of them are missing one or more VAX MACRO options. The compiler also supports several new qualifiers, unique to the compiler. All of these qualifiers are shown in Table A-1.

Table A-1 Compiler Qualifiers
Standard MACRO Qualifiers New Qualifiers
/DEBUG /FLAG
/DIAGNOSTICS /MACHINE
/DISABLE 1 /OPTIMIZE
/ENABLE 1 /PRESERVE
/LIBRARY /RETRY_COUNT
/LIST /SYMBOLS
/OBJECT /TIE
/SHOW /UNALIGNED
  /WARN


1With additional options unique to the compiler and some VAX MACRO options missing


Qualifiers

/DEBUG=(option[,...])

/NODEBUG

Includes or excludes local symbols in the symbol table or traceback information in the object module. You can specify one or more of the following options:
Option Description
ALL Makes local symbols and traceback information in the object module available to the debugger. This qualifier is equivalent to /ENABLE=(DEBUG,TRACEBACK).
NONE Makes local symbols and traceback information in the object module unavailable to the debugger. This qualifier is equivalent to /DISABLE=(DEBUG,TRACEBACK).
SYMBOLS Makes all local symbols in the object module available and all traceback information unavailable to the debugger. This qualifier is equivalent to /ENABLE=SYMBOLS.
TRACEBACK Makes traceback information in the object module available and local symbols unavailable to the debugger. This qualifier is equivalent to /ENABLE=TRACEBACK.

The default value for /DEBUG is ALL. The /DEBUG qualifier overrides /ENABLE=(DEBUG,TRACEBACK) or /DISABLE=(DEBUG,TRACEBACK), regardless of their order on the command line.

Note

Debugging can be simplified by specifying /NOOPTIMIZE. This qualifier prevents the movement of generated code across source line boundaries.

For more information about debugging, see the OpenVMS Debugger Manual.

/DIAGNOSTICS[=filespec]

/NODIAGNOSTICS (default)

Creates a file containing assembler messages and diagnostic information. If you omit the file specification, the default file name is the same as the source program; the default file type is DIA.

No wildcard characters are allowed in the file specification.

The diagnostics file is reserved for use with Digital layered products, such as the VAX Language-Sensitive Editor (LSE).

/DISABLE=(option[,...])

/NODISABLE

Provides initial settings for the compiler functions that can be controlled by the .DISABLE and .ENABLE MACRO directives.

You can specify one or more of the following functions:
Option Description
DEBUG Excludes local symbol table information in the object file for use with the debugger. If the /DEBUG qualifier is also specified, it overrides /DISABLE=(DEBUG,TRACEBACK) or /ENABLE=(DEBUG,TRACEBACK), regardless of their order on the command line.
FLAGGING Deactivates compiler flagging.
GLOBAL Disables the assumption that undefined symbols are external symbols.
OVERFLOW Deactivates production of overflow trap code for the following opcodes: ADDx, ADWC, INCx, ADAWI, SUBx, SBWC, DECx, MNEGx, MULx, CVTxy (where x is greater than y, for example CVTLB), AOBxx, ACBL, and SOBxx.
QUADWORD Disables support for quadword literal expressions.
SUPPRESSION Prevents the listing of unreferenced symbols in the symbol table.
TRACEBACK Disables the provision of traceback information to the debugger. If the /DEBUG qualifier is also specified, it overrides /DISABLE=(DEBUG,TRACEBACK) or /ENABLE=(DEBUG,TRACEBACK), regardless of their order on the command line.

By default, at compiler activation, FLAGGING, GLOBAL, and SUPPRESSION are enabled, and DEBUG, OVERFLOW, QUADWORD, and TRACEBACK are disabled.

The /NODISABLE qualifier has the same effect as omitting the /DISABLE qualifier. It can also be used to negate the effects of any /DISABLE qualifiers specified earlier in the command line.

Note

If /DISABLE is used two or more times in the command line, the last /DISABLE will override all previous uses of /DISABLE. The options not specified in the final /DISABLE will revert to their default values.

Furthermore, if /ENABLE and /DISABLE are used in the same command line for the same option, /DISABLE will always prevail, regardless of its position in the command line.

Workaround---If you want to disable two or more options, specify them in the following way:


/DISABLE=(xxxx, yyyy) 
 

/ENABLE=(option[,...])

/NOENABLE

Provides initial settings for the compiler functions that can be controlled by the .DISABLE and .ENABLE MACRO directives.

You can specify one or more of the following functions:
Option Description
DEBUG Includes local symbol table information in the object file for use with the debugger. If the /DEBUG qualifier is also specified, it overrides /ENABLE=(DEBUG,TRACEBACK) or /DISABLE=(DEBUG,TRACEBACK), regardless of their order on the command line.
FLAGGING Activates compiler flagging.
GLOBAL Assumes undefined symbols are external symbols.
OVERFLOW Activates production of overflow trap code for the following opcodes: ADDx, ADWC, INCx, ADAWI, SUBx, SBWC, DECx, MNEGx, MULx, CVTxy (where x is greater than y, for example CVTLB), AOBxx, ACBL, and SOBxx.
QUADWORD Provides support for quadword literal expressions.
SUPPRESSION Provides listing of unreferenced symbols in the symbol table.
TRACEBACK Provides traceback information to the debugger. If the /DEBUG qualifier is also specified, it overrides /ENABLE=(DEBUG,TRACEBACK) or /DISABLE=(DEBUG,TRACEBACK), regardless of their order on the command line.

By default, at compiler activation, FLAGGING, GLOBAL, TRACEBACK, and SUPPRESSION are enabled, and DEBUG, OVERFLOW, and QUADWORD are disabled.

The /NOENABLE qualifier has the same effect as not specifying the /ENABLE qualifier. It can also be used to negate the effects of any /ENABLE qualifiers specified earlier in the command line.

Note

For every option of the /ENABLE qualifier, if /ENABLE and /DISABLE are used in the same command line for the same option, /DISABLE will always prevail, regardless of its position in the command line.

You may want to enable an option previously disabled through the use of a symbol. For example, you may have incorporated the following frequently used options into the DCL symbol MAC, as follows:


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
5601PRO_008.HTML