Xref: utzoo comp.lang.c:32464 comp.arch:18367 Path: utzoo!attcan!uunet!snorkelwacker!paperboy!meissner From: meissner@osf.org (Michael Meissner) Newsgroups: comp.lang.c,comp.arch Subject: Re: a style question Message-ID: Date: 2 Oct 90 18:04:11 GMT References: <7341@darkstar.ucsc.edu> <1990Sep30.050655.13212@zoo.toronto.edu> <1990Sep30.172917.2951@Neon.Stanford.EDU> <1990Oct2.151644.1581@phri.nyu.edu> Sender: news@OSF.ORG Organization: Open Software Foundation Lines: 91 In-reply-to: roy@phri.nyu.edu's message of 2 Oct 90 15:16:44 GMT In article <1990Oct2.151644.1581@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes: | Are there actually any machines in which a compare-and-branch for | inequality is any faster or slower than a compare-and-branch for less-than? | It seems to me that either should take one pass through the ALU to do the | comparison and set some flags, so they should both take the same amount of | time. I'm basing my assumption on experience with pdp-11 type machines, | but I find it hard to imagine any other machine being significantly | different. Maybe if you had an asynchronous ALU? Yes, any computer based on the MIPS chipset (MIPS, DECstation, SGI) is faster to do a branch on both equality and inquality, than for the other comparison operators. | The only scenario I could think of would be a RISC machine which | has only two branches; branch-on-equal, and branch-on-less-than. The | compiler could generate an appropriate stream of instructions to simulate | any possible branch condition from just those two, and some streams might | end up being longer than others, but that sounds pretty strange, and very | un-orthogonal. Mips does not have a branch on a < b (unless b is 0). It has a set register to 1 if a < b instruction (& 0 otherwise). Thus to do the branch, you set the scratch register to be the value of a < b, and then do a branch on that register being zero. It does have a direct instruction to branch if two registers are equal or not equal. For example, consider the following program: int i, j, k, l, m, n; void foo(){ if (i < j) k++; if (l == m) n++; } It produces the following code after running it through the compiler and assembler: foo: File 'test-branch.c': 0: int i, j, k, l, m, n; 1: 2: void foo(){ 3: if (i < j) [test-branch.c: 4] 0x0: 8f8e0000 lw r14,0(gp) [test-branch.c: 4] 0x4: 8f8f0000 lw r15,0(gp) [test-branch.c: 4] 0x8: 00000000 nop [test-branch.c: 4] 0xc: 01cf082a slt r1,r14,r15 [test-branch.c: 4] 0x10: 10200005 beq r1,r0,0x28 [test-branch.c: 4] 0x14: 00000000 nop 4: k++; [test-branch.c: 5] 0x18: 8f980000 lw r24,0(gp) [test-branch.c: 5] 0x1c: 00000000 nop [test-branch.c: 5] 0x20: 27190001 addiu r25,r24,1 [test-branch.c: 5] 0x24: af990000 sw r25,0(gp) 5: 6: if (l == m) [test-branch.c: 7] 0x28: 8f880000 lw r8,0(gp) [test-branch.c: 7] 0x2c: 8f890000 lw r9,0(gp) [test-branch.c: 7] 0x30: 00000000 nop [test-branch.c: 7] 0x34: 15090005 bne r8,r9,0x4c [test-branch.c: 7] 0x38: 00000000 nop 7: n++; [test-branch.c: 8] 0x3c: 8f8a0000 lw r10,0(gp) [test-branch.c: 8] 0x40: 00000000 nop [test-branch.c: 8] 0x44: 254b0001 addiu r11,r10,1 [test-branch.c: 8] 0x48: af8b0000 sw r11,0(gp) 8: } [test-branch.c: 9] 0x4c: 03e00008 jr r31 [test-branch.c: 9] 0x50: 00000000 nop 0x54: 00000000 nop 0x58: 00000000 nop 0x5c: 00000000 nop From looking at the way the bits are set down, the blez (branch on less than or equal zero) and bgtz (branch on greater than zero) instructions could have been defined as ble and bgt, since the second register field is required to be 0 (and register $0 is hardwired to 0). I suspect the decision may have been due to chip real estate, and the fact that equality comparisons happen more frequently in real programs. -- Michael Meissner email: meissner@osf.org phone: 617-621-8861 Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142 Do apple growers tell their kids money doesn't grow on bushes?