From: meissner@osf.org (Michael Meissner)
Newsgroups: comp.lang.c,comp.sys.sun.misc
Subject: Re: sun cc optimization failure
Date: 4 Sep 92 21:10:04 GMT
Organization: Open Software Foundation

In article <61124@aurs01.UUCP> throop@aurs01.UUCP (Wayne Throop) writes:

| -   #include <stdio.h>
| ->> main() {
| ->>        int i,j,ax;
| ->>        ax = 0;
| ->>        for(i=0;i<3;i++){
| ->>                j = ax * i;
| ->>                puts("in for loop");
| ->>        }
| -          return 0;
| ->> }
| ->> when compiled with cc (sun os 4.1 on sparc 1+), the
| ->> code runs thru the loop three times. when comiled with
| ->> the -O flag it only runs once. 
| -> If you look at the assembler output of the compiler using the following
| 
| Out of curiosity, I ran this through the three compilers I had
| available for the MIPS architecture (decstation) machine I have here.  

Here is the code that GCC 2.2.2+ generated with -O3 -funroll-loops:

	.file	1 "foo.c"
	.set	nobopt

 # GNU C 2.2.2 [AL 1.1, MM 24] DECstation running ultrix compiled by CC

 # Cc1 defaults:

 # Cc1 arguments (-G value = 8, Cpu = default, ISA = 1):
 # -mgpopt -fno-builtin -quiet -dumpbase -O3 -funroll-loops -o

gcc2_compiled.:
	.rdata
	.align	2
$LC0:
	.ascii	"in for loop\000"
	.text
	.align	2
	.globl	main

	.text

	.loc	1 2
	.ent	main
main:
	.frame	$sp,24,$31		# vars= 0, regs= 1/0, args = 16, extra= 0
	.mask	0x80000000,-8
	.fmask	0x00000000,0
	subu	$sp,$sp,24
	sw	$31,16($sp)
	jal	__main
	la	$4,$LC0
	jal	puts
	la	$4,$LC0
	jal	puts
	la	$4,$LC0
	jal	puts
	.set	noreorder
	lw	$31,16($sp)
	move	$2,$0
	j	$31
	addu	$sp,$sp,24
	.set	reorder
	.end	main

| In general, this older gcc does significantly more frame-and-stack
| pointer twiddling, both in this loop and in the prolog and postlog
| code and the like, compared to the MIPS-based compilers.  

If you had specified -O2 rather than -O (and used the OSF version of
GCC 1.39) it would have.  The omit frame pointer code that I put into
1.39 took several iterations to get right, so I didn't want users code
to stop working unless they asked for it.  The last revision of 1.39 I
produced within OSF (not released outside of OSF thought) did turn
omit frame pointer on with -O, and one of the library routines had a
construct that had never come up in compiling other things like the
kernel or compiler with it.

| (2.0 may do better.)

It does.  The frame pointer is automatically omitted with normal -O
optimizations, as well as some low level scheduling.

| But the thing that struck me was, why didn't the optimizer just
| 
|         la      $4,$LABEL
|         jal     puts
|         jal     puts
|         jal     puts
| 
| (or some variation on this theme) as it "should" have?  

It can't do the la just once, because $4 is not caller preserved.

| ( Maybe there are RISCish slot-filling considerations that prevent it... 
|   but I really think the compilers just don't do simple loop unrolling,
|   even when they've already demolished the innards of the loop anyhows. )

Or maybe in the general case, it can cause side effects with register
allocation, and may make you run out of registers sooner (which can
make the loop even slower).
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142

You are in a twisty little passage of standards, all conflicting.
Newsgroups: comp.lang.c