CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

if vs Ternary vs Direct Assignment

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

if vs Ternary vs Direct Assignment
PostPosted: Tue Apr 30, 2019 9:16 am     Reply with quote

This is just a report, not a complaint or request. But if someone has a suggestion, I am open to other options too.

I have to test a bit in a UINT8 (aka short int or char) and save off the result into a BOOL for use elsewhere. I tried 3 approaches and what I found in the LST file was intriguing.

IF method uses 12 bytes of program memory:
Code:
if(gsPacket.iData[2] & 0x08) gLEDStatus.condensate = true; else gLEDStatus.condensate = false;
02148:  BTFSS  x73.3
0214A:  BRA    2152
0214C:  MOVLW  01
0214E:  MOVWF  xBC
02150:  BRA    2154
02152:  CLRF   xBC

But the "then" portion above only assigns a value to one single variable, so I can easily use...
Ternary method uses 12 bytes of program memory:
Code:
gLEDStatus.condensate = (gsPacket.iData[2] & 0x08) ? true : false;
02154:  BTFSS  x73.3
02156:  BRA    215C
02158:  MOVLW  01
0215A:  BRA    215E
0215C:  MOVLW  00
0215E:  MOVWF  xBC

But the value I am assigning is only true or false, which appears redundant in the ternary operation. It seems simplest to use...
Direct Assignment method uses 14 bytes of program memory:
Code:
gLEDStatus.condensate = ((gsPacket.iData[2] & 0x08) != 0);
02160:  MOVF   x73,W
02162:  ANDLW  08
02164:  BNZ   216A
02166:  MOVLW  00
02168:  BRA    216C
0216A:  MOVLW  01
0216C:  MOVWF  xBC

You can see from the assembly that the three operations accomplish the same goal in three different ways. This is not unexpected. The most fascinating part to me was that the tightest C code produced the largest assembly code. I felt compelled to share this with the community.

-Kyle


Last edited by kda406 on Tue Apr 30, 2019 9:45 am; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 30, 2019 9:29 am     Reply with quote

How about this one ?
Code:

..... gLEDStatus.condensate = bit_test(gsPacket.iData[2], 3);   
00036:  CLRF   05
00038:  BTFSC  08.3
0003A:  INCF   05,F

Test program:
Code:
#include <18F87K22.h>
#fuses NOWDT
#use delay(internal=4M)
#use rs232(UART1, baud=9600, errors)

struct
{
int8 condensate;
}gLEDStatus;

struct
{
int8 iData[10];
}gsPacket;

//==========================
void main()
{
gLEDStatus.condensate = bit_test(gsPacket.iData[2], 3); 

while(TRUE);
}   
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Tue Apr 30, 2019 9:44 am     Reply with quote

Sweet. I generally stick with portable code, but this is fantastic and needs to be included in the thread.
CCS bit_test() uses 6 bytes of program memory:
Code:
gLEDStatus.condensate = bit_test(gsPacket.iData[2],3);
0216E:  CLRF   xBC
02170:  BTFSC  x73.3
02172:  INCF   xBC,F

Thanks PCM programmer for reminding me about this one.
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Tue Apr 30, 2019 10:36 am     Reply with quote

Generally, ternary operations are not optimised in CCS. They don't skip
evaluation of the 'false' route for example, so I'm not surprised that
there is no gain from using these.

However the key point about 'bit_test', is it takes advantage of the processors
instruction set. The PIC has a fixed location 'bit test' instruction. With a
fixed bit, this can be used instead of having to mask out the required bit
and test this. Much more efficient as you have seen.

If you want to be portable, then code a macro, that when compiled on
CCS, uses the bit_test operation, but otherwise generates the mask and
does the logical test this way. Very Happy
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Tue Apr 30, 2019 12:02 pm     Reply with quote

Just for completeness, my tests were with V5.085 compiled for a PIC18F67K40.

Ttelmah you make several great points, and I agree completely on the use of macros for portability. Very Happy
temtronic



Joined: 01 Jul 2010
Posts: 9246
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Apr 30, 2019 5:08 pm     Reply with quote

hmm...

this..
Quote:
02172: INCF xBC,F

wonder why CCS didn't use the BSF instruction ? After all they're testing a bit...seems to me logical to set a bit ?? No saving in time, both are 1 cycle.

just curious...

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Wed May 01, 2019 1:21 am     Reply with quote

I wondered the same. I suspect the reason is so that the status bit for
non zero will be set. Hence if the result is used in the same C instruction
in a test (so where you do an assignment inside a test), this ensures the
status is set without having to test again. BSF, does not update the
status, while INCF does.
pmuldoon



Joined: 26 Sep 2003
Posts: 218
Location: Northern Indiana

View user's profile Send private message

PostPosted: Tue Jun 11, 2019 5:26 am     Reply with quote

Could it be because the operand is an int8 and not an int1?

Just taking a short break from work and stumbled across this cool thread.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group