开发者

Connection between ternary logic and mux logic?

I'm implementing a computer simulator in C with the challenge not to use conditionals (ie no if/else, switch/case, while/for, etc.). There are a lot of muxes in the hardware I'm simulating, so it would be nice if I could use the conditional ternary logic operators. So, my question: do C compilers create MUX logic from ternary 开发者_JAVA百科logic operators, or do they create branches?

Example:

int a, b, q, r;
/* Ternary logic */
r = q ? a : b;
/* MUX equivalent logic */
r = ( q & a ) | ( (~q) & b )
/* Branch equivalent logic */
if (q) r = a; else r = b;


The ternary operator is equivalent to a branch: i.e. the value not returned is not evaluated.

I don't know how much you are constrained, so note that boolean operators && and || don't evaluate their second argument is the result can be determined from the first.

(And note that you line "MUX" doesn't something very different from the other two expressions: it select bits from a or b depending on the value of corresponding bit in q, it doesn't select a or b depending if q is null or not; Edit: it is worse: you are using !q and not ~q...).


C compilers create branches out of ternary statements.

Using Freescale's Codewarrior IDE, I compiled the following C program:

int a, b, q, r;    
void main(void) {    
  a = 0;    
  b = 1;    
  q = 0;    
  r = q ? a : b;    
..
..    
}

The assembly corresponding to the ternary statement is as follows:

...
LDX    0x1104 ; load val[q] into register x    
BNE    *+4    ; branch to abs addr 0xC016 if val[q]==a    
BRA    *+5    ; branch to abs addr 0xC019 if val[q]!=a
...


Often, branching logic is created, but is very possible to do ternary operation without any kind of branch if you're fine with both values being evaluated. Consider this:

#include <stdio.h>

static inline int isel(int cond, int a, int b)
{
   int mask = cond | (-cond);
   mask >>= 31;
   return (b & mask) | (a & ~mask);
}

int main(void)
{
   printf("1 ? 3 : 4 => %d\n", isel(1, 3, 4));
   printf("0 ? 3 : 4 => %d\n", isel(0, 3, 4));
   printf("-1 ? 3 : 4 => %d\n", isel(-1, 3, 4));
   return 0;
}

This code assumes that right-shifting of signed numbers will sign-extend, and that sizeof(int) == 4. Some processors can do isel() as an assembly instruction. However, both values will be evaluated, which the ternary ?: doesn't do.

Depending on the situation, the compiler will generally try to do the fastest thing, either branching to avoid redundant calculation, or doing this kind of logic if values in the ternary expression are simple.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜