News:

;) This forum is the property of Proton software developers

Main Menu

Compilation makes bloated assembler code.

Started by atomix, Feb 10, 2025, 10:45 AM

Previous topic - Next topic

atomix

For Positron 4.0.5.1

Device 18F46K22
Declare Xtal 64

Dim dummy[100] As Byte
Dim cnt        As Word

cnt = 1

If cnt.4 = 1 Then cnt.4 = 0

Asm code:
QuoteF1_000007 equ $ ; in [UNTITLED2.BAS] cnt = 1
    movlb 0x00
    clrf cntH,1
    movlw 1
    movwf cnt,1
F1_000009 equ $ ; in [UNTITLED2.BAS] if cnt.4 = 1 Then cnt.4 = 0
    movf cnt,WREG,1
    btfss WREG,4,0
    bra _lbl__3

    bcf cnt,4,1


For Positron 4.0.5.3

Device 18F46K22
Declare Xtal 64

Dim dummy[100] As Byte
Dim cnt        As Word

cnt = 1

If cnt.4 = 1 Then cnt.4 = 0

Asm code:
QuoteF1_000007 equ $ ; in [UNTITLED2.BAS] cnt = 1
    movlb 0x00
    clrf cntH,1
    movlw 1
    movwf cnt,1
F1_000009 equ $ ; in [UNTITLED2.BAS] if cnt.4 = 1 Then cnt.4 = 0
    movff cnt,WREG
    btfss WREG,4,0
    bra _lbl__3

    bcf cnt,4,1

But it should be like this

Device 18F46K22
Declare Xtal 64

Dim dummy[100] As Byte
Dim cnt        As Word

cnt = 1

If cnt.4 = 1 Then cnt.4 = 0

Asm code:
QuoteF1_000007 equ $ ; in [UNTITLED2.BAS] cnt = 1
    movlb 0x00
    clrf cntH,1
    movlw 1
    movwf cnt,1
F1_000009 equ $ ; in [UNTITLED2.BAS] if cnt.4 = 1 Then cnt.4 = 0
    btfsc cnt,4,1
    bcf cnt,4,1

top204

#1
It is not bloated, it is a safe method of bit testing banked variables, that will always set RAM banks as they should be set.

Because the 100 element array moves other variables out of bankless Access RAM in your code listing above, the compiler needs to use a method that will not jump to a section that has a different RAM bank, that has not been reset before the jump. So it uses a method of setting the BSR (Movlb mnemonic) then loading an SFR in Access RAM, and re-adjusting the BSR SFR before the jump.

If the bit being tested from a variable out of Access RAM is bit-0 or bit-7, the compiler uses a different method of rotating the bit into the Carry flag and jumping based upon its condition, because the STATUS SFR is always in bankless RAM. This is a smaller, and still safe mechanism.

rrcf cnt,W,1
bnc _lbl__3
bcf cnt,4,1


Remember, all comparisons end with a jump of some sort, if a result of the comparison is true or false, and the comparison has no idea where it is jumping too, or what is at the destination.

Comparing bits from variables outside Bankless RAM causes a bit of extra code memory, but works as it should, because the comparison has no idea what it is going to do after the comparison is finished, or where it is going etc... As opposed to just using a single mnemonic, and finding that the RAM bank is totally incorrect when it gets to where it should be.

This is one of the reasons I added the Heap directive so that arrays or Strings are not filling lower RAM, and I made the compiler create all of its Bit variables in Access RAM on 18F devices, and lower RAM on 14-bit core types, so the comparisons can be single Btfss or Btfsc mnemonics on 18F devices, and usually single mnemonics on the fragmented 14-bit core types.

Unfortunately, with the multi-RAM bank mechanism on the 8-bit PIC microcontrollers, it can never be perfect, but is still a lot better than most other compilers that add a Movlb mnemonic, virtually, everywhere a variable is loaded in the assembler code because it has no knowledge of previous RAM banks.

I'll see if I can create a section in the compiler's peephole optimiser to trap 'certain' comparison combinations, but it is a complex process that must take 'all' scenarios into account, otherwise, code will be smaller, but NOT work. :-) So, it has to be done with care and a time of beta testing, otherwise, currently working programs will fail subtly. But it will produce slightly smaller code while failing. LOL.

Many years ago, I did create an optimiser pass that tried to circumvent that type of code, but it is not 100% safe, depending on the high level code listing, and the amount of RAM bank changes needed within a section of it, or what it is jumping too, so I never made it an official mechanism.

The extra optimiser can be enabled with:

Declare Optimise_Bit_Test = On

But use it with care, and monitoring of the assembler code, because it may jump to a section where the RAM bank is different and has not been changed before the jump, but the compiler did not know it would be in a different RAM bank section, because it does not know what variables follow the section it jumps too. In a way, I made the compiler's syntax too flexible for its own good. :-)

Then the code:

If cnt.4 = 1 Then cnt.4 = 0

Will produce the assembler code:

btfsc cnt,4,0
bcf cnt,4,0


atomix

QuoteDeclare Optimise_Bit_Test = On

I am once again convinced that you are the coolest and most talented person I know.

It works just great and excellent!!!  :)

top204

#3
Many thanks Atomix.

Your kind words mean such a lot to me, because I know you are a very good programmer, so you know what I have stated above makes some sense in the "real world". :-)

The Declare Optimise_Bit_Test, can be set to On or Off throughout the program, so if there is a section of code you know that it will be safe, turn it on, then turn it off again when you are not sure.

This is something I cannot place as an "official" part of the compiler because it can cause problems if used as a general Declare at the top of a program listing on some devices, and on some codes listings etc... Unlike the standard optimiser that is always 100% safe on 18F and enhanced 14-bit core devices.