View previous topic :: View next topic |
Author |
Message |
matt.dawson
Joined: 30 Oct 2014 Posts: 4
|
int1 = val&1 optimization possible? |
Posted: Thu Oct 30, 2014 8:14 pm |
|
|
I notice in my code that this compiles to:
.................... int1 b = (crc & 1);
17E4: MOVF 27,W
17E5: ANDLW 01
17E6: MOVWF 77
17E7: CLRF 7A
17E8: BCF 29.0
17E9: BTFSC 77.0
17EA: BSF 29.0
Since I'm doing an &1 on the outside you could just do this:
17E4: MOVF 27,W
17E5: ANDLW 01
17E6: MOVWF 29
PCM Compiler v5.030 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Oct 30, 2014 9:04 pm |
|
|
Post a short, compilable test program that shows the PIC and all variable declarations.
Example:
Code: |
#include <16F886.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
//============================
void main()
{
int8 crc = 0x55;
int1 b = (crc & 1);
while(TRUE);
} |
|
|
|
matt.dawson
Joined: 30 Oct 2014 Posts: 4
|
|
Posted: Thu Oct 30, 2014 10:19 pm |
|
|
That's exactly it.
I've tested this in PCM Compiler v5.030, compiling at optimisation level 9 and it generates the same extra bit clears, tests and sets.
Code: |
#include <16LF1705.h>
void main() {
int8 a = 15;
int1 b = a&1;
for(;;);
}
|
Generates:
Code: |
.................... void main() {
// Removed irrelevant bits here //
0008: MOVLW 0F
0009: MOVWF 21
000A: MOVF 21,W
000B: ANDLW 01
000C: MOVWF 78
000D: BCF 22.0
000E: BTFSC 78.0
000F: BSF 22.0
.................... int8 a = 15;
.................... int1 b = a&1;
.................... for(;;);
0010: GOTO 010
.................... }
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Fri Oct 31, 2014 1:40 am |
|
|
The code is performing a cast automatically.
Think about it. The & solution, would directly work, if and only if b is the bottom bit of the storage location used.
The 'int8' result of the operation 'crc&1', has to be converted to be an 'int1' solution, so it can set any bit in the target. This is what the compiler is doing.
Try the & solution, with b being the second bit in the value. What happens?.
Then look at the compiler's solution. Does it work?.
Then try with b declared as an int8. What does the compiler generate?. |
|
|
matt.dawson
Joined: 30 Oct 2014 Posts: 4
|
|
Posted: Fri Oct 31, 2014 2:32 am |
|
|
Yes I understand why it's done in the generic case.
The case I'm talking about is an optimization for when the last operation in an expression is a constant and of 1.
It isn't hard to detect that in a parser tree.
>> edit
Also in the case where it's 2, it can be done with a shift.
Or 4 with 2 shifts. I'm just suggesting an optimization. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Fri Oct 31, 2014 2:44 am |
|
|
You don't have a constant. You have a variable.
The solution has to be able to cope with anything.
If you declare crc as a constant, the compiler optimises to just setting the bit without any test at all. |
|
|
matt.dawson
Joined: 30 Oct 2014 Posts: 4
|
|
Posted: Fri Oct 31, 2014 2:55 am |
|
|
In "a & 1", 1 is a constant.
Optimized paths don't have to handle everything, they are chosen based upon the specific code written. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Fri Oct 31, 2014 8:31 am |
|
|
Yes, '1' is a constant, but 'a' is not. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Mon Nov 03, 2014 1:29 am |
|
|
as a comment to this, realise that the casting takes place because the operation 'a & 1', is using 8bit arithmetic, and returns an 8bit value.
The compiler operation 'bit_test', instead returns a true/false value, and therefore doesn't involve the cast:
Code: |
int1 b = bit_test(a,0);
000A: BCF 22.0
000B: BTFSC 21.0
000C: BSF 22.0
|
Which will work for any bit in source or destination, and is the most efficient 'general' solution available. |
|
|
|