void WordcodeEmitter::emitPushuint(const uint8_t *pc)
	{
		// FIXME: wrong for 64-bit, we want 32 bits of payload
		pc++;
		uint32_t value = pool->cpool_uint[AvmCore::readU30(pc)];
		if ((value & 0xF0000000U) == 0) {
			CHECK(2);
			*dest++ = NEW_OPCODE(WOP_pushbits);
			*dest++ = (value << 3) | kIntegerType;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
			peep(WOP_pushbits, dest-2);
#endif
		}
		else {
			union {
				double d;
				uint32_t bits[2];
			} v;
			v.d = (double)value;
			CHECK(3);
			*dest++ = NEW_OPCODE(WOP_push_doublebits);
			*dest++ = v.bits[0];
			*dest++ = v.bits[1];
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
			peep(WOP_push_doublebits, dest-3);
#endif
		}
	}
Exemplo n.º 2
0
int main()
{
	  int r,v,c;
  	push(3);
  	peep(&v);
   	printf("The top element is %d\n",v);
  	push(4);
  	push(5);
  	peep(&v);
		pop(*r);
  	peep(stack,&v);
	  printf("The top element is %d\n",v);
  	return 0;
 }
Exemplo n.º 3
0
int main()
{ int val ,option;
  clrscr();
  do
  {
     printf("\n **** Main Menu *****");
     printf("\n 1. Push");
     printf("\n 2.pop");
     printf("\n 3. peep");
     printf("\n 4. display");
     printf("\n*******");
     printf("\n Enter your option");
     scanf("%d",&option);
     switch(option)
     { case 1: printf("\n Enter number to be pushed on to the stack");
	       scanf("%d",&val);
	       push(val);
	       break;
       case 2: pop();
	       break;
       case 3: peep();
	       break;
       case 4: display();
	       break;
       default: printf("\n wroung option");
     }
  }while(option>=1 && option<=4);
  getch();
  return 0;
}
Exemplo n.º 4
0
void main()
{       int n ;
	s:
	clrscr();

	printf("Implementation of stack using linked list :\n\n");
	printf("Select your choice :\n");
	printf("1. Push :\n") ;
	printf("2. Pop :\n")  ;
	printf("3. Peep :\n");
	printf("4. Change :\n");
	printf("5. Display :\n");
	printf("6. Exit :") ;
	scanf("%d",&n) ;
	switch(n)
	{
	  case 1:	push(); getch();goto s;
	  case 2:       pop();  getch();goto s;
	  case 3:       peep(); getch();goto s;
	  case 4:       change(); getch();goto s;
	  case 5:      	display(); getch(); goto s;
	  case 6:	       break;

	}
	getch();


    }
Exemplo n.º 5
0
void main()
{
	int i,j,t;
	struct stack s;
	char post[20],infix[20];
	init(&s);
	push(&s,'5');
	push(&s,'2');
	i=pop(&s);
	j=peep(&s);
	if(s.top!=-1)
	{
		printf("Popped element = %d\n ",i);
		printf("Top element = %d\n ",j);
	}
	printf("Enter the infix expression:\n");
	scanf("%s",infix);
	infixToPostfix(infix,post);
	printf("Postfix statement:\n");
	printf("%s",post);
	/*printf("Enter postfix expression:\n ");
	scanf("%s",post);*/
	t=evaluate(post);
	printf("\nThe result is %d ",t);

}
Exemplo n.º 6
0
void main()
{
 int ch,item,pos;
clrscr();
  do
  {
  clrscr();
  printf("\n\n1. Push");
  printf("\n2. Pop");
  printf("\n3. Peep");
  printf("\n4. change");
  printf("\n5. Disp");
  printf("\n6. Exit");

  printf("\n\nEnter your choice:");
  scanf("%d",&ch);
  switch(ch)
  {
	case 1:
		  printf("\nEnter Item:");
		  scanf("%d",&item);

		  push(item);
		  break;
	case 2:
		  pop();
		  break;
	case 3:
		  printf("\nEnter the pos:");
		  scanf("%d",&pos);

		  peep(pos);
		  break;
	case 4:
		  printf("\nEnter the pos:");
		  scanf("%d",&pos);

		  printf("\nEnter the item:");
		  scanf("%d",&item);

		  change(pos,item);
		  break;

	case 5:
		  disp();
		  break;
	case 6:
		  exit(0);
		  break;

    }

 } while(ch!=6);

getch();
}
Exemplo n.º 7
0
Arquivo: tg.c Projeto: sambuc/netbsd
/*
 * Generate WWV/H 0 or 1 data pulse.
 */
void sec(
	int	code		/* DATA0, DATA1, PI */
	)
{
	/*
	 * The WWV data pulse begins with 5 ms of 1000 Hz follwed by a
	 * guard time of 25 ms. The data pulse is 170, 570 or 770 ms at
	 * 100 Hz corresponding to 0, 1 or position indicator (PI),
	 * respectively. Note the 100-Hz data pulses are transmitted 6
	 * dB below the 1000-Hz sync pulses. Originally the data pulses
	 * were transmited 10 dB below the sync pulses, but the station
	 * engineers increased that to 6 dB because the Heath GC-1000
	 * WWV/H radio clock worked much better.
	 */
	peep(5, tone, HIGH);		/* send seconds tick */
	peep(25, tone, OFF);
	peep(code - 30, 100, LOW);	/* send data */
	peep(1000 - code, 100, OFF);
}
	void WordcodeEmitter::emitPushshort(const uint8_t *pc) 
	{
		CHECK(2);
		pc++;
		*dest++ = NEW_OPCODE(WOP_pushbits);
		*dest++ = (intptr_t)((int16_t)AvmCore::readU30(pc) << 3) | kIntegerType;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(WOP_pushbits, dest-2);
#endif
	}
	void WordcodeEmitter::emitGetscopeobject(const uint8_t *pc) 
	{
		CHECK(2);
		pc++;
		*dest++ = NEW_OPCODE(OP_getscopeobject);
		*dest++ = *pc++;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(OP_getscopeobject, dest-2);
#endif
	}
Exemplo n.º 10
0
	// These take no arguments
	void WordcodeEmitter::emitOp0(const uint8_t *pc, WordOpcode opcode) {
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].width == 1);
#endif // _DEBUG
		(void)pc;
		CHECK(1);
		*dest++ = NEW_OPCODE(opcode);
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-1);
#endif
	}
Exemplo n.º 11
0
	// These take one U30 argument, and the argument is explicitly passed here (result of optimization)
	void WordcodeEmitter::emitOp1(WordOpcode opcode, uint32_t operand)
	{
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].width == 2);
#endif // _DEBUG
		CHECK(2);
		*dest++ = NEW_OPCODE(opcode);
		*dest++ = (intptr_t)(int32_t)operand;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-2);
#endif
	}
Exemplo n.º 12
0
	// These take one U30 argument
	void WordcodeEmitter::emitOp1(const uint8_t *pc, WordOpcode opcode)
	{
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].width == 2);
#endif // _DEBUG
		CHECK(2);
		pc++;
		*dest++ = NEW_OPCODE(opcode);
		*dest++ = (intptr_t)(int32_t)AvmCore::readU30(pc);
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-2);
#endif
	}
Exemplo n.º 13
0
	void WordcodeEmitter::emitOp2(WordOpcode opcode, uint32_t op1, uint32_t op2)
	{
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].width == 3);
#endif
		CHECK(3);
		*dest++ = NEW_OPCODE(opcode);
		*dest++ = (intptr_t)(int32_t)op1;
		*dest++ = (intptr_t)(int32_t)op2;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-3);
#endif
	}
Exemplo n.º 14
0
int main()
{
  stack_t s;
  init(&s);
  push(&s, 10);
  push(&s, 20);
  push(&s, 90);
  display(&s);
  pop(&s);
  display(&s);
  peep(&s);
  display(&s);
  return 0;
}
Exemplo n.º 15
0
void infixToPostfix(char infix[],char postfix[])
{
	struct stack s1;
	int i=0,j=0,r;
	char ch,c;
	init(&s1);
	while(infix[i]!='\0')
	{
		ch=infix[i];
		if(isdigit(ch))
		{
			postfix[j++]=ch;
		}
		else	if(ch==')')
			{
				c=pop(&s1);
				while(c!='(')
				{
					postfix[j++]=c;
					c=pop(&s1);
				}
			}
			else	if(ch=='(')
				{
					push(&s1,ch);
				}
				else
				{
					
					while(!isempty(s1)&&
					priority(ch)<=priority(peep(&s1)) )
					{							
						c=pop(&s1);
						printf("pop operator %c\n",c);
						postfix[j++]=c;

					}
					printf("push operator %c\n",ch);
					push(&s1,ch);
				}
		i++;
	}
	while(!isempty(s1))
	{
		c=pop(&s1);
		postfix[j++]=c;
	}
	postfix[j]='\0';
}	
Exemplo n.º 16
0
	// These take one S24 argument that is PC-relative.  If the offset is negative
	// then the target must be a LABEL instruction, and we can just look it up.
	// Otherwise, we enter the target offset into an ordered list with the current
	// transformed PC and the location to backpatch.
	void WordcodeEmitter::emitRelativeJump(const uint8_t *pc, WordOpcode opcode)
	{
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].jumps);
#endif
		CHECK(2);
		pc++;
		intptr_t offset = (intptr_t)AvmCore::readS24(pc);
		pc += 3;
		*dest++ = NEW_OPCODE(opcode);
		uintptr_t base_offset = uintptr_t(buffer_offset + (dest - buffers->data) + 1);
		emitRelativeOffset(base_offset, pc, offset);
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-2);
		AvmAssert(state == 0);		// Never allow a jump instruction to be in the middle of a match
#endif
	}
Exemplo n.º 17
0
int optimize(ins_t *code) {
  int changed;

  // keep optimizing until there's nothing left
  do {
    changed = 0;
    changed |= fold(code);
    changed |= condense(code);
    changed |= unloop(code);
    changed |= dce(code);
    changed |= peep(code);
  } while (changed);

  peepfinal(code);

  int opt_size;
  for (opt_size = 0; code[opt_size].op != OP_EOF; ++opt_size) {}
  return opt_size;
}
Exemplo n.º 18
0
void main()
{
	int val,ch;
	clrscr();
	do
	{
		printf("\n1> push\n2> pop\n3> peep\n4> duplicate\n5> swap\
		\n6> display\n7> clear\n0> exit");
		printf("\nplease enter the choice");
		scanf("%d",&ch);
		switch(ch)
		{
			case 0:/*----EXIT----*/
				exit();
			case 1:/*----push----*/
				printf("\nplease enter the number\n");
				scanf("%d",&val);
				push(val);
				break;
			case 2:/*----POP----*/
				val=pop();
				printf("\nThe pop-up item/number is %d",val);
				break;
			case 3:/*----peep----*/
				peep();
				break;
			case 4:/*----DUPLICATE----*/
				duplicate();
				break;
			case 5:/*----swap----*/
				swap();
				break;
			case 6:/*----DISPLAY----*/
				display();
				break;
			case 7:/*----CLEAR-----*/
				clear();
				break;
		}
	}while(ch!=0);
getch();
}
Exemplo n.º 19
0
void peep_icode(BOOLEAN branches)
{
    int i;
    BOOLEAN changed;
    golist = oAlloc(sizeof(QUAD*)*(nextLabel - firstLabel));
    scan_gotos(intermed_head);
    scan_abnormal();
    for (i=0; i < blockCount; i++)
        if (blockArray[i])
            blockArray[i]->visiteddfst = FALSE;


    do 
    {
        changed = FALSE;
        for (i=0; i < blockCount; i++)
            if (blockArray[i])
                changed |= peep(blockArray[i], branches);
    } while (changed);
}
//Execution of Main
void main()
{
	
	int choice,flag,count=0;
	clrscr();
	do
	{
	flag=0;
	clrscr();
	printf("Enter Number Accordingly:\n");
	printf("1. Push\n");
	printf("2. Pop\n");
	printf("3. Peep\n");
	printf("4. Traversal\n");
	printf("5. Exit:\n");
	printf("Enter Your Choice:");
	scanf("%d",&choice);
	switch (choice)
	{
		case 1:
		{
			push();
			flag=1;
			count++;
			break;

		}
		case 2:
		{
			pop();
			flag=1;
			count++;
			break;
		}
		case 3:
		{
			peep();
			flag=1;
			count++;
			break;
		}
		case 4:
		{
			display();
			flag=1;
			count++;
			break;
		}
		case 5:
		{
			flag=2;
			break;
		}
		default:
		{
			printf("Enter a Valid Choice");
		}
	}
	}
	while(flag==1);
	if(flag==2)
	{
		printf("\nYou have ran this loop for %d times\n",count);
		printf("\nYou have Exited the Program\n");

	}
	getch();
}
Exemplo n.º 21
0
Arquivo: tg.c Projeto: sambuc/netbsd
/*
 * Main program
 */
int
main(
	int	argc,		/* command line options */
	char	**argv		/* poiniter to list of tokens */
	)
{
	struct timeval tv;	/* system clock at startup */
	audio_info_t info;	/* Sun audio structure */
	struct tm *tm = NULL;	/* structure returned by gmtime */
	char	device[50];	/* audio device */
	char	code[100];	/* timecode */
	int	rval, temp, arg, sw, ptr;
	int	minute, hour, day, year;
	int	i;

	/*
	 * Parse options
	 */
	strlcpy(device, DEVICE, sizeof(device));
	year = 0;
	while ((temp = getopt(argc, argv, "a:dhilsu:v:y:")) != -1) {
		switch (temp) {

		case 'a':	/* specify audio device (/dev/audio) */
			strlcpy(device, optarg, sizeof(device));
			break;

		case 'd':	/* set DST for summer (WWV/H only) */
			dst++;
			break;

		case 'h':	/* select WWVH sync frequency */
			tone = 1200;
			break;

		case 'i':	/* select irig format */
			encode = IRIG;
			break;

		case 'l':	/* set leap warning bit (WWV/H only) */
			leap++;
			break;

		case 's':	/* enable speaker */
			port |= AUDIO_SPEAKER;
			break;

		case 'u':	/* set DUT1 offset (-7 to +7) */
			sscanf(optarg, "%d", &dut1);
			if (dut1 < 0)
				dut1 = abs(dut1);
			else
				dut1 |= 0x8;
			break;

		case 'v':	/* set output level (0-255) */
			sscanf(optarg, "%d", &level);
			break;

		case 'y':	/* set initial date and time */
			sscanf(optarg, "%2d%3d%2d%2d", &year, &day,
			    &hour, &minute);
			utc++;
			break;

		defult:
			printf("invalid option %c\n", temp);
			break;
		}
	}

	/*
	 * Open audio device and set options
	 */
	fd = open("/dev/audio", O_WRONLY);
	if (fd <= 0) {
		printf("audio open %s\n", strerror(errno));
		exit(1);
	}
	rval = ioctl(fd, AUDIO_GETINFO, &info);
	if (rval < 0) {
		printf("audio control %s\n", strerror(errno));
		exit(0);
	}
	info.play.port = port;
	info.play.gain = level;
	info.play.sample_rate = SECOND;
	info.play.channels = 1;
	info.play.precision = 8;
	info.play.encoding = AUDIO_ENCODING_ULAW;
	printf("port %d gain %d rate %d chan %d prec %d encode %d\n",
	    info.play.port, info.play.gain, info.play.sample_rate,
	    info.play.channels, info.play.precision,
	    info.play.encoding);
	ioctl(fd, AUDIO_SETINFO, &info);

 	/*
	 * Unless specified otherwise, read the system clock and
	 * initialize the time.
	 */
	if (!utc) {
		gettimeofday(&tv, NULL);
		tm = gmtime(&tv.tv_sec);
		minute = tm->tm_min;
		hour = tm->tm_hour;
		day = tm->tm_yday + 1;
		year = tm->tm_year % 100;
		second = tm->tm_sec;

		/*
		 * Delay the first second so the generator is accurately
		 * aligned with the system clock within one sample (125
		 * microseconds ).
		 */
		delay(SECOND - tv.tv_usec * 8 / 1000);
	}
	memset(code, 0, sizeof(code));
	switch (encode) {

	/*
	 * For WWV/H and default time, carefully set the signal
	 * generator seconds number to agree with the current time.
	 */ 
	case WWV:
		printf("year %d day %d time %02d:%02d:%02d tone %d\n",
		    year, day, hour, minute, second, tone);
		snprintf(code, sizeof(code), "%01d%03d%02d%02d%01d",
		    year / 10, day, hour, minute, year % 10);
		printf("%s\n", code);
		ptr = 8;
		for (i = 0; i <= second; i++) {
			if (progx[i].sw == DEC)
				ptr--;
		}
		break;

	/*
	 * For IRIG the signal generator runs every second, so requires
	 * no additional alignment.
	 */
	case IRIG:
		printf("sbs %x year %d day %d time %02d:%02d:%02d\n",
		    0, year, day, hour, minute, second);
		break;
	}

	/*
	 * Run the signal generator to generate new timecode strings
	 * once per minute for WWV/H and once per second for IRIG.
	 */
	while(1) {

		/*
		 * Crank the state machine to propagate carries to the
		 * year of century. Note that we delayed up to one
		 * second for alignment after reading the time, so this
		 * is the next second.
		 */
		second = (second + 1) % 60;
		if (second == 0) {
			minute++;
			if (minute >= 60) {
				minute = 0;
				hour++;
			}
			if (hour >= 24) {
				hour = 0;
				day++;
			}

			/*
			 * At year rollover check for leap second.
			 */
			if (day >= (year & 0x3 ? 366 : 367)) {
				if (leap) {
					sec(DATA0);
					printf("\nleap!");
					leap = 0;
				}
				day = 1;
				year++;
			}
			if (encode == WWV) {
				snprintf(code, sizeof(code),
				    "%01d%03d%02d%02d%01d", year / 10,
				    day, hour, minute, year % 10);
				printf("\n%s\n", code);
				ptr = 8;
			}
		}
		if (encode == IRIG) {
			snprintf(code, sizeof(code),
			    "%04x%04d%06d%02d%02d%02d", 0, year, day,
			    hour, minute, second);
			printf("%s\n", code);
			ptr = 19;
		}

		/*
		 * Generate data for the second
		 */
		switch(encode) {

		/*
		 * The IRIG second consists of 20 BCD digits of width-
		 * modulateod pulses at 2, 5 and 8 ms and modulated 50
		 * percent on the 1000-Hz carrier.
		 */
		case IRIG:
			for (i = 0; i < 100; i++) {
				if (i < 10) {
					sw = progz[i].sw;
					arg = progz[i].arg;
				} else {
					sw = progy[i % 10].sw;
					arg = progy[i % 10].arg;
				}
				switch(sw) {

				case COEF:	/* send BCD bit */
					if (code[ptr] & arg) {
						peep(M5, 1000, HIGH);
						peep(M5, 1000, LOW);
						printf("1");
					} else {
						peep(M2, 1000, HIGH);
						peep(M8, 1000, LOW);
						printf("0");
					}
					break;

				case DEC:	/* send IM/PI bit */
					ptr--;
					printf(" ");
					peep(arg, 1000, HIGH);
					peep(10 - arg, 1000, LOW);
					break;

				case MIN:	/* send data bit */
					peep(arg, 1000, HIGH);
					peep(10 - arg, 1000, LOW);
					printf("M ");
					break;
				}
				if (ptr < 0)
					break;
			}
			printf("\n");
			break;

		/*
		 * The WWV/H second consists of 9 BCD digits of width-
		 * modulateod pulses 200, 500 and 800 ms at 100-Hz.
		 */
		case WWV:
			sw = progx[second].sw;
			arg = progx[second].arg;
			switch(sw) {

			case DATA:		/* send data bit */
				sec(arg);
				break;

			case COEF:		/* send BCD bit */
				if (code[ptr] & arg) {
					sec(DATA1);
					printf("1");
				} else {
					sec(DATA0);
					printf("0");
				}
				break;

			case LEAP:		/* send leap bit */
				if (leap) {
					sec(DATA1);
					printf("L ");
				} else {
					sec(DATA0);
					printf("  ");
				}
				break;

			case DEC:		/* send data bit */
				ptr--;
				sec(arg);
				printf(" ");
				break;

			case MIN:		/* send minute sync */
				peep(arg, tone, HIGH);
				peep(1000 - arg, tone, OFF);
				break;

			case DUT1:		/* send DUT1 bits */
				if (dut1 & arg)
					sec(DATA1);
				else
					sec(DATA0);
				break;
				
			case DST1:		/* send DST1 bit */
				ptr--;
				if (dst)
					sec(DATA1);
				else
					sec(DATA0);
				printf(" ");
				break;

			case DST2:		/* send DST2 bit */
				if (dst)
					sec(DATA1);
				else
					sec(DATA0);
				break;
			}
		}
	}
}
Exemplo n.º 22
0
void
regopt(Prog *firstp)
{
	Reg *r, *r1;
	Prog *p;
	Graph *g;
	int i, z;
	uint32 vreg;
	Bits bit;
	ProgInfo info;

	if(first) {
		fmtinstall('Q', Qconv);
		first = 0;
	}
	
	fixjmp(firstp);
	mergetemp(firstp);

	/*
	 * control flow is more complicated in generated go code
	 * than in generated c code.  define pseudo-variables for
	 * registers, so we have complete register usage information.
	 */
	nvar = NREGVAR;
	memset(var, 0, NREGVAR*sizeof var[0]);
	for(i=0; i<NREGVAR; i++) {
		if(regnodes[i] == N)
			regnodes[i] = newname(lookup(regname[i]));
		var[i].node = regnodes[i];
	}

	regbits = RtoB(REGSP)|RtoB(REGLINK)|RtoB(REGPC);
	for(z=0; z<BITS; z++) {
		externs.b[z] = 0;
		params.b[z] = 0;
		consts.b[z] = 0;
		addrs.b[z] = 0;
		ovar.b[z] = 0;
	}

	// build list of return variables
	setoutvar();

	/*
	 * pass 1
	 * build aux data structure
	 * allocate pcs
	 * find use and set of variables
	 */
	g = flowstart(firstp, sizeof(Reg));
	if(g == nil)
		return;
	firstr = (Reg*)g->start;

	for(r = firstr; r != R; r = (Reg*)r->f.link) {
		p = r->f.prog;
		proginfo(&info, p);

		// Avoid making variables for direct-called functions.
		if(p->as == ABL && p->to.type == D_EXTERN)
			continue;

		bit = mkvar(r, &p->from);
		if(info.flags & LeftRead)
			for(z=0; z<BITS; z++)
				r->use1.b[z] |= bit.b[z];
		if(info.flags & LeftAddr)
			setaddrs(bit);

		if(info.flags & RegRead) {	
			if(p->from.type != D_FREG)
				r->use1.b[0] |= RtoB(p->reg);
			else
				r->use1.b[0] |= FtoB(p->reg);
		}

		if(info.flags & (RightAddr | RightRead | RightWrite)) {
			bit = mkvar(r, &p->to);
			if(info.flags & RightAddr)
				setaddrs(bit);
			if(info.flags & RightRead)
				for(z=0; z<BITS; z++)
					r->use2.b[z] |= bit.b[z];
			if(info.flags & RightWrite)
				for(z=0; z<BITS; z++)
					r->set.b[z] |= bit.b[z];
		}
	}
	if(firstr == R)
		return;

	for(i=0; i<nvar; i++) {
		Var *v = var+i;
		if(v->addr) {
			bit = blsh(i);
			for(z=0; z<BITS; z++)
				addrs.b[z] |= bit.b[z];
		}

		if(debug['R'] && debug['v'])
			print("bit=%2d addr=%d et=%-6E w=%-2d s=%N + %lld\n",
				i, v->addr, v->etype, v->width, v->node, v->offset);
	}

	if(debug['R'] && debug['v'])
		dumpit("pass1", &firstr->f, 1);

	/*
	 * pass 2
	 * find looping structure
	 */
	flowrpo(g);

	if(debug['R'] && debug['v'])
		dumpit("pass2", &firstr->f, 1);

	/*
	 * pass 3
	 * iterate propagating usage
	 * 	back until flow graph is complete
	 */
loop1:
	change = 0;
	for(r = firstr; r != R; r = (Reg*)r->f.link)
		r->f.active = 0;
	for(r = firstr; r != R; r = (Reg*)r->f.link)
		if(r->f.prog->as == ARET)
			prop(r, zbits, zbits);
loop11:
	/* pick up unreachable code */
	i = 0;
	for(r = firstr; r != R; r = r1) {
		r1 = (Reg*)r->f.link;
		if(r1 && r1->f.active && !r->f.active) {
			prop(r, zbits, zbits);
			i = 1;
		}
	}
	if(i)
		goto loop11;
	if(change)
		goto loop1;

	if(debug['R'] && debug['v'])
		dumpit("pass3", &firstr->f, 1);


	/*
	 * pass 4
	 * iterate propagating register/variable synchrony
	 * 	forward until graph is complete
	 */
loop2:
	change = 0;
	for(r = firstr; r != R; r = (Reg*)r->f.link)
		r->f.active = 0;
	synch(firstr, zbits);
	if(change)
		goto loop2;

	addsplits();

	if(debug['R'] && debug['v'])
		dumpit("pass4", &firstr->f, 1);

	if(debug['R'] > 1) {
		print("\nprop structure:\n");
		for(r = firstr; r != R; r = (Reg*)r->f.link) {
			print("%d:%P", r->f.loop, r->f.prog);
			for(z=0; z<BITS; z++) {
				bit.b[z] = r->set.b[z] |
					r->refahead.b[z] | r->calahead.b[z] |
					r->refbehind.b[z] | r->calbehind.b[z] |
					r->use1.b[z] | r->use2.b[z];
				bit.b[z] &= ~addrs.b[z];
			}

			if(bany(&bit)) {
				print("\t");
				if(bany(&r->use1))
					print(" u1=%Q", r->use1);
				if(bany(&r->use2))
					print(" u2=%Q", r->use2);
				if(bany(&r->set))
					print(" st=%Q", r->set);
				if(bany(&r->refahead))
					print(" ra=%Q", r->refahead);
				if(bany(&r->calahead))
					print(" ca=%Q", r->calahead);
				if(bany(&r->refbehind))
					print(" rb=%Q", r->refbehind);
				if(bany(&r->calbehind))
					print(" cb=%Q", r->calbehind);
			}
			print("\n");
		}
	}

	/*
	 * pass 4.5
	 * move register pseudo-variables into regu.
	 */
	for(r = firstr; r != R; r = (Reg*)r->f.link) {
		r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS;

		r->set.b[0] &= ~REGBITS;
		r->use1.b[0] &= ~REGBITS;
		r->use2.b[0] &= ~REGBITS;
		r->refbehind.b[0] &= ~REGBITS;
		r->refahead.b[0] &= ~REGBITS;
		r->calbehind.b[0] &= ~REGBITS;
		r->calahead.b[0] &= ~REGBITS;
		r->regdiff.b[0] &= ~REGBITS;
		r->act.b[0] &= ~REGBITS;
	}

	if(debug['R'] && debug['v'])
		dumpit("pass4.5", &firstr->f, 1);

	/*
	 * pass 5
	 * isolate regions
	 * calculate costs (paint1)
	 */
	r = firstr;
	if(r) {
		for(z=0; z<BITS; z++)
			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
		if(bany(&bit) & !r->f.refset) {
			// should never happen - all variables are preset
			if(debug['w'])
				print("%L: used and not set: %Q\n", r->f.prog->lineno, bit);
			r->f.refset = 1;
		}
	}

	for(r = firstr; r != R; r = (Reg*)r->f.link)
		r->act = zbits;
	rgp = region;
	nregion = 0;
	for(r = firstr; r != R; r = (Reg*)r->f.link) {
		for(z=0; z<BITS; z++)
			bit.b[z] = r->set.b[z] &
			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
		if(bany(&bit) && !r->f.refset) {
			if(debug['w'])
				print("%L: set and not used: %Q\n", r->f.prog->lineno, bit);
			r->f.refset = 1;
			excise(&r->f);
		}
		for(z=0; z<BITS; z++)
			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
		while(bany(&bit)) {
			i = bnum(bit);
			rgp->enter = r;
			rgp->varno = i;
			change = 0;
			if(debug['R'] > 1)
				print("\n");
			paint1(r, i);
			bit.b[i/32] &= ~(1L<<(i%32));
			if(change <= 0) {
				if(debug['R'])
					print("%L $%d: %Q\n",
						r->f.prog->lineno, change, blsh(i));
				continue;
			}
			rgp->cost = change;
			nregion++;
			if(nregion >= NRGN) {
				if(debug['R'] > 1)
					print("too many regions\n");
				goto brk;
			}
			rgp++;
		}
	}
brk:
	qsort(region, nregion, sizeof(region[0]), rcmp);

	if(debug['R'] && debug['v'])
		dumpit("pass5", &firstr->f, 1);

	/*
	 * pass 6
	 * determine used registers (paint2)
	 * replace code (paint3)
	 */
	rgp = region;
	for(i=0; i<nregion; i++) {
		bit = blsh(rgp->varno);
		vreg = paint2(rgp->enter, rgp->varno);
		vreg = allreg(vreg, rgp);
		if(debug['R']) {
			if(rgp->regno >= NREG)
				print("%L $%d F%d: %Q\n",
					rgp->enter->f.prog->lineno,
					rgp->cost,
					rgp->regno-NREG,
					bit);
			else
				print("%L $%d R%d: %Q\n",
					rgp->enter->f.prog->lineno,
					rgp->cost,
					rgp->regno,
					bit);
		}
		if(rgp->regno != 0)
			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
		rgp++;
	}

	if(debug['R'] && debug['v'])
		dumpit("pass6", &firstr->f, 1);

	/*
	 * pass 7
	 * peep-hole on basic block
	 */
	if(!debug['R'] || debug['P']) {
		peep(firstp);
	}

	if(debug['R'] && debug['v'])
		dumpit("pass7", &firstr->f, 1);

	/*
	 * last pass
	 * eliminate nops
	 * free aux structures
	 * adjust the stack pointer
	 *	MOVW.W 	R1,-12(R13)			<<- start
	 *	MOVW   	R0,R1
	 *	MOVW   	R1,8(R13)
	 *	MOVW   	$0,R1
	 *	MOVW   	R1,4(R13)
	 *	BL     	,runtime.newproc+0(SB)
	 *	MOVW   	&ft+-32(SP),R7			<<- adjust
	 *	MOVW   	&j+-40(SP),R6			<<- adjust
	 *	MOVW   	autotmp_0003+-24(SP),R5		<<- adjust
	 *	MOVW   	$12(R13),R13			<<- finish
	 */
	vreg = 0;
	for(p = firstp; p != P; p = p->link) {
		while(p->link != P && p->link->as == ANOP)
			p->link = p->link->link;
		if(p->to.type == D_BRANCH)
			while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
				p->to.u.branch = p->to.u.branch->link;
		if(p->as == AMOVW && p->to.reg == 13) {
			if(p->scond & C_WBIT) {
				vreg = -p->to.offset;		// in adjust region
//				print("%P adjusting %d\n", p, vreg);
				continue;
			}
			if(p->from.type == D_CONST && p->to.type == D_REG) {
				if(p->from.offset != vreg)
					print("in and out different\n");
//				print("%P finish %d\n", p, vreg);
				vreg = 0;	// done adjust region
				continue;
			}

//			print("%P %d %d from type\n", p, p->from.type, D_CONST);
//			print("%P %d %d to type\n\n", p, p->to.type, D_REG);
		}

		if(p->as == AMOVW && vreg != 0) {
			if(p->from.sym != S)
			if(p->from.name == D_AUTO || p->from.name == D_PARAM) {
				p->from.offset += vreg;
//				print("%P adjusting from %d %d\n", p, vreg, p->from.type);
			}
			if(p->to.sym != S)
			if(p->to.name == D_AUTO || p->to.name == D_PARAM) {
				p->to.offset += vreg;
//				print("%P adjusting to %d %d\n", p, vreg, p->from.type);
			}
		}
	}

	flowend(g);
}
Exemplo n.º 23
0
void
regopt(Prog *p)
{
	Reg *r, *r1, *r2;
	Prog *p1;
	int i, z;
	int32_t initpc, val, npc;
	uint32_t vreg;
	Bits bit;
	struct
	{
		int32_t	m;
		int32_t	c;
		Reg*	p;
	} log5[6], *lp;

	firstr = R;
	lastr = R;
	nvar = 0;
	regbits = RtoB(D_SP) | RtoB(D_AX);
	for(z=0; z<BITS; z++) {
		externs.b[z] = 0;
		params.b[z] = 0;
		consts.b[z] = 0;
		addrs.b[z] = 0;
	}

	/*
	 * pass 1
	 * build aux data structure
	 * allocate pcs
	 * find use and set of variables
	 */
	val = 5L * 5L * 5L * 5L * 5L;
	lp = log5;
	for(i=0; i<5; i++) {
		lp->m = val;
		lp->c = 0;
		lp->p = R;
		val /= 5L;
		lp++;
	}
	val = 0;
	for(; p != P; p = p->link) {
		switch(p->as) {
		case ADATA:
		case AGLOBL:
		case ANAME:
		case ASIGNAME:
			continue;
		}
		r = rega();
		if(firstr == R) {
			firstr = r;
			lastr = r;
		} else {
			lastr->link = r;
			r->p1 = lastr;
			lastr->s1 = r;
			lastr = r;
		}
		r->prog = p;
		r->pc = val;
		val++;

		lp = log5;
		for(i=0; i<5; i++) {
			lp->c--;
			if(lp->c <= 0) {
				lp->c = lp->m;
				if(lp->p != R)
					lp->p->log5 = r;
				lp->p = r;
				(lp+1)->c = 0;
				break;
			}
			lp++;
		}

		r1 = r->p1;
		if(r1 != R)
		switch(r1->prog->as) {
		case ARET:
		case AJMP:
		case AIRETL:
			r->p1 = R;
			r1->s1 = R;
		}

		bit = mkvar(r, &p->from, p->as==AMOVL);
		if(bany(&bit))
		switch(p->as) {
		/*
		 * funny
		 */
		case ALEAL:
			for(z=0; z<BITS; z++)
				addrs.b[z] |= bit.b[z];
			break;

		/*
		 * left side read
		 */
		default:
			for(z=0; z<BITS; z++)
				r->use1.b[z] |= bit.b[z];
			break;
		}

		bit = mkvar(r, &p->to, 0);
		if(bany(&bit))
		switch(p->as) {
		default:
			diag(Z, "reg: unknown op: %A", p->as);
			break;

		/*
		 * right side read
		 */
		case ACMPB:
		case ACMPL:
		case ACMPW:
			for(z=0; z<BITS; z++)
				r->use2.b[z] |= bit.b[z];
			break;

		/*
		 * right side write
		 */
		case ANOP:
		case AMOVL:
		case AMOVB:
		case AMOVW:
		case AMOVBLSX:
		case AMOVBLZX:
		case AMOVWLSX:
		case AMOVWLZX:
			for(z=0; z<BITS; z++)
				r->set.b[z] |= bit.b[z];
			break;

		/*
		 * right side read+write
		 */
		case AADDB:
		case AADDL:
		case AADDW:
		case AANDB:
		case AANDL:
		case AANDW:
		case ASUBB:
		case ASUBL:
		case ASUBW:
		case AORB:
		case AORL:
		case AORW:
		case AXORB:
		case AXORL:
		case AXORW:
		case ASALB:
		case ASALL:
		case ASALW:
		case ASARB:
		case ASARL:
		case ASARW:
		case AROLB:
		case AROLL:
		case AROLW:
		case ARORB:
		case ARORL:
		case ARORW:
		case ASHLB:
		case ASHLL:
		case ASHLW:
		case ASHRB:
		case ASHRL:
		case ASHRW:
		case AIMULL:
		case AIMULW:
		case ANEGL:
		case ANOTL:
		case AADCL:
		case ASBBL:
			for(z=0; z<BITS; z++) {
				r->set.b[z] |= bit.b[z];
				r->use2.b[z] |= bit.b[z];
			}
			break;

		/*
		 * funny
		 */
		case AFMOVDP:
		case AFMOVFP:
		case AFMOVLP:
		case AFMOVVP:
		case AFMOVWP:
		case ACALL:
			for(z=0; z<BITS; z++)
				addrs.b[z] |= bit.b[z];
			break;
		}

		switch(p->as) {
		case AIMULL:
		case AIMULW:
			if(p->to.type != D_NONE)
				break;

		case AIDIVB:
		case AIDIVL:
		case AIDIVW:
		case AIMULB:
		case ADIVB:
		case ADIVL:
		case ADIVW:
		case AMULB:
		case AMULL:
		case AMULW:

		case ACWD:
		case ACDQ:
			r->regu |= RtoB(D_AX) | RtoB(D_DX);
			break;

		case AREP:
		case AREPN:
		case ALOOP:
		case ALOOPEQ:
		case ALOOPNE:
			r->regu |= RtoB(D_CX);
			break;

		case AMOVSB:
		case AMOVSL:
		case AMOVSW:
		case ACMPSB:
		case ACMPSL:
		case ACMPSW:
			r->regu |= RtoB(D_SI) | RtoB(D_DI);
			break;

		case ASTOSB:
		case ASTOSL:
		case ASTOSW:
		case ASCASB:
		case ASCASL:
		case ASCASW:
			r->regu |= RtoB(D_AX) | RtoB(D_DI);
			break;

		case AINSB:
		case AINSL:
		case AINSW:
		case AOUTSB:
		case AOUTSL:
		case AOUTSW:
			r->regu |= RtoB(D_DI) | RtoB(D_DX);
			break;

		case AFSTSW:
		case ASAHF:
			r->regu |= RtoB(D_AX);
			break;
		}
	}
	if(firstr == R)
		return;
	initpc = pc - val;
	npc = val;

	/*
	 * pass 2
	 * turn branch references to pointers
	 * build back pointers
	 */
	for(r = firstr; r != R; r = r->link) {
		p = r->prog;
		if(p->to.type == D_BRANCH) {
			val = p->to.offset - initpc;
			r1 = firstr;
			while(r1 != R) {
				r2 = r1->log5;
				if(r2 != R && val >= r2->pc) {
					r1 = r2;
					continue;
				}
				if(r1->pc == val)
					break;
				r1 = r1->link;
			}
			if(r1 == R) {
				nearln = p->lineno;
				diag(Z, "ref not found\n%P", p);
				continue;
			}
			if(r1 == r) {
				nearln = p->lineno;
				diag(Z, "ref to self\n%P", p);
				continue;
			}
			r->s2 = r1;
			r->p2link = r1->p2;
			r1->p2 = r;
		}
	}
	if(debug['R']) {
		p = firstr->prog;
		print("\n%L %D\n", p->lineno, &p->from);
	}

	/*
	 * pass 2.5
	 * find looping structure
	 */
	for(r = firstr; r != R; r = r->link)
		r->active = 0;
	change = 0;
	loopit(firstr, npc);
	if(debug['R'] && debug['v']) {
		print("\nlooping structure:\n");
		for(r = firstr; r != R; r = r->link) {
			print("%ld:%P", r->loop, r->prog);
			for(z=0; z<BITS; z++)
				bit.b[z] = r->use1.b[z] |
					   r->use2.b[z] |
					   r->set.b[z];
			if(bany(&bit)) {
				print("\t");
				if(bany(&r->use1))
					print(" u1=%B", r->use1);
				if(bany(&r->use2))
					print(" u2=%B", r->use2);
				if(bany(&r->set))
					print(" st=%B", r->set);
			}
			print("\n");
		}
	}

	/*
	 * pass 3
	 * iterate propagating usage
	 * 	back until flow graph is complete
	 */
loop1:
	change = 0;
	for(r = firstr; r != R; r = r->link)
		r->active = 0;
	for(r = firstr; r != R; r = r->link)
		if(r->prog->as == ARET)
			prop(r, zbits, zbits);
loop11:
	/* pick up unreachable code */
	i = 0;
	for(r = firstr; r != R; r = r1) {
		r1 = r->link;
		if(r1 && r1->active && !r->active) {
			prop(r, zbits, zbits);
			i = 1;
		}
	}
	if(i)
		goto loop11;
	if(change)
		goto loop1;


	/*
	 * pass 4
	 * iterate propagating register/variable synchrony
	 * 	forward until graph is complete
	 */
loop2:
	change = 0;
	for(r = firstr; r != R; r = r->link)
		r->active = 0;
	synch(firstr, zbits);
	if(change)
		goto loop2;


	/*
	 * pass 5
	 * isolate regions
	 * calculate costs (paint1)
	 */
	r = firstr;
	if(r) {
		for(z=0; z<BITS; z++)
			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
		if(bany(&bit)) {
			nearln = r->prog->lineno;
			warn(Z, "used and not set: %B", bit);
			if(debug['R'] && !debug['w'])
				print("used and not set: %B\n", bit);
		}
	}
	if(debug['R'] && debug['v'])
		print("\nprop structure:\n");
	for(r = firstr; r != R; r = r->link)
		r->act = zbits;
	rgp = region;
	nregion = 0;
	for(r = firstr; r != R; r = r->link) {
		if(debug['R'] && debug['v']) {
			print("%P\t", r->prog);
			if(bany(&r->set))
				print("s:%B ", r->set);
			if(bany(&r->refahead))
				print("ra:%B ", r->refahead);
			if(bany(&r->calahead))
				print("ca:%B ", r->calahead);
			print("\n");
		}
		for(z=0; z<BITS; z++)
			bit.b[z] = r->set.b[z] &
			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
		if(bany(&bit)) {
			nearln = r->prog->lineno;
			warn(Z, "set and not used: %B", bit);
			if(debug['R'])
				print("set and not used: %B\n", bit);
			excise(r);
		}
		for(z=0; z<BITS; z++)
			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
		while(bany(&bit)) {
			i = bnum(bit);
			rgp->enter = r;
			rgp->varno = i;
			change = 0;
			if(debug['R'] && debug['v'])
				print("\n");
			paint1(r, i);
			bit.b[i/32] &= ~(1L<<(i%32));
			if(change <= 0) {
				if(debug['R'])
					print("%L$%d: %B\n",
						r->prog->lineno, change, blsh(i));
				continue;
			}
			rgp->cost = change;
			nregion++;
			if(nregion >= NRGN) {
				warn(Z, "too many regions");
				goto brk;
			}
			rgp++;
		}
	}
brk:
	qsort(region, nregion, sizeof(region[0]), rcmp);

	/*
	 * pass 6
	 * determine used registers (paint2)
	 * replace code (paint3)
	 */
	rgp = region;
	for(i=0; i<nregion; i++) {
		bit = blsh(rgp->varno);
		vreg = paint2(rgp->enter, rgp->varno);
		vreg = allreg(vreg, rgp);
		if(debug['R']) {
			print("%L$%d %R: %B\n",
				rgp->enter->prog->lineno,
				rgp->cost,
				rgp->regno,
				bit);
		}
		if(rgp->regno != 0)
			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
		rgp++;
	}
	/*
	 * pass 7
	 * peep-hole on basic block
	 */
	if(!debug['R'] || debug['P'])
		peep();

	/*
	 * pass 8
	 * recalculate pc
	 */
	val = initpc;
	for(r = firstr; r != R; r = r1) {
		r->pc = val;
		p = r->prog;
		p1 = P;
		r1 = r->link;
		if(r1 != R)
			p1 = r1->prog;
		for(; p != p1; p = p->link) {
			switch(p->as) {
			default:
				val++;
				break;

			case ANOP:
			case ADATA:
			case AGLOBL:
			case ANAME:
			case ASIGNAME:
				break;
			}
		}
	}
	pc = val;

	/*
	 * fix up branches
	 */
	if(debug['R'])
		if(bany(&addrs))
			print("addrs: %B\n", addrs);

	r1 = 0; /* set */
	for(r = firstr; r != R; r = r->link) {
		p = r->prog;
		if(p->to.type == D_BRANCH)
			p->to.offset = r->s2->pc;
		r1 = r;
	}

	/*
	 * last pass
	 * eliminate nops
	 * free aux structures
	 */
	for(p = firstr->prog; p != P; p = p->link){
		while(p->link && p->link->as == ANOP)
			p->link = p->link->link;
	}
	if(r1 != R) {
		r1->link = freer;
		freer = firstr;
	}
}
Exemplo n.º 24
0
	void WordcodeEmitter::peepFlush()
	{
		peep(0, NULL);		// commits, but may start another match
		state = 0;			// ignore any partial match
	}
Exemplo n.º 25
0
void
regopt(Prog *firstp)
{
	Reg *r, *r1;
	Prog *p;
	int i, z, nr;
	uint32 vreg;
	Bits bit;

	if(first) {
		fmtinstall('Q', Qconv);
		exregoffset = D_DI;	// no externals
		first = 0;
	}
	
	fixjmp(firstp);

	// count instructions
	nr = 0;
	for(p=firstp; p!=P; p=p->link)
		nr++;
	// if too big dont bother
	if(nr >= 10000) {
//		print("********** %S is too big (%d)\n", curfn->nname->sym, nr);
		return;
	}

	r1 = R;
	firstr = R;
	lastr = R;
	
	/*
	 * control flow is more complicated in generated go code
	 * than in generated c code.  define pseudo-variables for
	 * registers, so we have complete register usage information.
	 */
	nvar = NREGVAR;
	memset(var, 0, NREGVAR*sizeof var[0]);
	for(i=0; i<NREGVAR; i++)
		var[i].node = newname(lookup(regname[i]));

	regbits = RtoB(D_SP);
	for(z=0; z<BITS; z++) {
		externs.b[z] = 0;
		params.b[z] = 0;
		consts.b[z] = 0;
		addrs.b[z] = 0;
		ovar.b[z] = 0;
	}

	// build list of return variables
	setoutvar();

	/*
	 * pass 1
	 * build aux data structure
	 * allocate pcs
	 * find use and set of variables
	 */
	nr = 0;
	for(p=firstp; p!=P; p=p->link) {
		switch(p->as) {
		case ADATA:
		case AGLOBL:
		case ANAME:
		case ASIGNAME:
			continue;
		}
		r = rega();
		nr++;
		if(firstr == R) {
			firstr = r;
			lastr = r;
		} else {
			lastr->link = r;
			r->p1 = lastr;
			lastr->s1 = r;
			lastr = r;
		}
		r->prog = p;
		p->reg = r;

		r1 = r->p1;
		if(r1 != R) {
			switch(r1->prog->as) {
			case ARET:
			case AJMP:
			case AIRETL:
				r->p1 = R;
				r1->s1 = R;
			}
		}

		bit = mkvar(r, &p->from);
		if(bany(&bit))
		switch(p->as) {
		/*
		 * funny
		 */
		case ALEAL:
		case AFMOVL: 
		case AFMOVW:
		case AFMOVV:
			setaddrs(bit);
			break;

		/*
		 * left side read
		 */
		default:
			for(z=0; z<BITS; z++)
				r->use1.b[z] |= bit.b[z];
			break;

		/*
		 * left side read+write
		 */
		case AXCHGB:
		case AXCHGW:
		case AXCHGL:
			for(z=0; z<BITS; z++) {
				r->use1.b[z] |= bit.b[z];
				r->set.b[z] |= bit.b[z];
			}
			break;
		}

		bit = mkvar(r, &p->to);
		if(bany(&bit))
		switch(p->as) {
		default:
			yyerror("reg: unknown op: %A", p->as);
			break;

		/*
		 * right side read
		 */
		case ACMPB:
		case ACMPL:
		case ACMPW:
		case ATESTB:
		case ATESTL:
		case ATESTW:
			for(z=0; z<BITS; z++)
				r->use2.b[z] |= bit.b[z];
			break;

		/*
		 * right side write
		 */
		case AFSTSW:
		case ALEAL:
		case ANOP:
		case AMOVL:
		case AMOVB:
		case AMOVW:
		case AMOVBLSX:
		case AMOVBLZX:
		case AMOVBWSX:
		case AMOVBWZX:
		case AMOVWLSX:
		case AMOVWLZX:
		case APOPL:
			for(z=0; z<BITS; z++)
				r->set.b[z] |= bit.b[z];
			break;

		/*
		 * right side read+write
		 */
		case AINCB:
		case AINCL:
		case AINCW:
		case ADECB:
		case ADECL:
		case ADECW:

		case AADDB:
		case AADDL:
		case AADDW:
		case AANDB:
		case AANDL:
		case AANDW:
		case ASUBB:
		case ASUBL:
		case ASUBW:
		case AORB:
		case AORL:
		case AORW:
		case AXORB:
		case AXORL:
		case AXORW:
		case ASALB:
		case ASALL:
		case ASALW:
		case ASARB:
		case ASARL:
		case ASARW:
		case ARCLB:
		case ARCLL:
		case ARCLW:
		case ARCRB:
		case ARCRL:
		case ARCRW:
		case AROLB:
		case AROLL:
		case AROLW:
		case ARORB:
		case ARORL:
		case ARORW:
		case ASHLB:
		case ASHLL:
		case ASHLW:
		case ASHRB:
		case ASHRL:
		case ASHRW:
		case AIMULL:
		case AIMULW:
		case ANEGB:
		case ANEGL:
		case ANEGW:
		case ANOTB:
		case ANOTL:
		case ANOTW:
		case AADCL:
		case ASBBL:

		case ASETCC:
		case ASETCS:
		case ASETEQ:
		case ASETGE:
		case ASETGT:
		case ASETHI:
		case ASETLE:
		case ASETLS:
		case ASETLT:
		case ASETMI:
		case ASETNE:
		case ASETOC:
		case ASETOS:
		case ASETPC:
		case ASETPL:
		case ASETPS:

		case AXCHGB:
		case AXCHGW:
		case AXCHGL:
			for(z=0; z<BITS; z++) {
				r->set.b[z] |= bit.b[z];
				r->use2.b[z] |= bit.b[z];
			}
			break;

		/*
		 * funny
		 */
		case AFMOVDP:
		case AFMOVFP:
		case AFMOVLP:
		case AFMOVVP:
		case AFMOVWP:
		case ACALL:
			setaddrs(bit);
			break;
		}

		switch(p->as) {
		case AIMULL:
		case AIMULW:
			if(p->to.type != D_NONE)
				break;

		case AIDIVL:
		case AIDIVW:
		case ADIVL:
		case ADIVW:
		case AMULL:
		case AMULW:
			r->set.b[0] |= RtoB(D_AX) | RtoB(D_DX);
			r->use1.b[0] |= RtoB(D_AX) | RtoB(D_DX);
			break;

		case AIDIVB:
		case AIMULB:
		case ADIVB:
		case AMULB:
			r->set.b[0] |= RtoB(D_AX);
			r->use1.b[0] |= RtoB(D_AX);
			break;

		case ACWD:
			r->set.b[0] |= RtoB(D_AX) | RtoB(D_DX);
			r->use1.b[0] |= RtoB(D_AX);
			break;

		case ACDQ:
			r->set.b[0] |= RtoB(D_DX);
			r->use1.b[0] |= RtoB(D_AX);
			break;

		case AREP:
		case AREPN:
		case ALOOP:
		case ALOOPEQ:
		case ALOOPNE:
			r->set.b[0] |= RtoB(D_CX);
			r->use1.b[0] |= RtoB(D_CX);
			break;

		case AMOVSB:
		case AMOVSL:
		case AMOVSW:
		case ACMPSB:
		case ACMPSL:
		case ACMPSW:
			r->set.b[0] |= RtoB(D_SI) | RtoB(D_DI);
			r->use1.b[0] |= RtoB(D_SI) | RtoB(D_DI);
			break;

		case ASTOSB:
		case ASTOSL:
		case ASTOSW:
		case ASCASB:
		case ASCASL:
		case ASCASW:
			r->set.b[0] |= RtoB(D_DI);
			r->use1.b[0] |= RtoB(D_AX) | RtoB(D_DI);
			break;

		case AINSB:
		case AINSL:
		case AINSW:
			r->set.b[0] |= RtoB(D_DX) | RtoB(D_DI);
			r->use1.b[0] |= RtoB(D_DI);
			break;

		case AOUTSB:
		case AOUTSL:
		case AOUTSW:
			r->set.b[0] |= RtoB(D_DI);
			r->use1.b[0] |= RtoB(D_DX) | RtoB(D_DI);
			break;
		}
	}
	if(firstr == R)
		return;

	for(i=0; i<nvar; i++) {
		Var *v = var+i;
		if(v->addr) {
			bit = blsh(i);
			for(z=0; z<BITS; z++)
				addrs.b[z] |= bit.b[z];
		}

//		print("bit=%2d addr=%d et=%-6E w=%-2d s=%S + %lld\n",
//			i, v->addr, v->etype, v->width, v->sym, v->offset);
	}

	if(debug['R'] && debug['v'])
		dumpit("pass1", firstr);

	/*
	 * pass 2
	 * turn branch references to pointers
	 * build back pointers
	 */
	for(r=firstr; r!=R; r=r->link) {
		p = r->prog;
		if(p->to.type == D_BRANCH) {
			if(p->to.branch == P)
				fatal("pnil %P", p);
			r1 = p->to.branch->reg;
			if(r1 == R)
				fatal("rnil %P", p);
			if(r1 == r) {
				//fatal("ref to self %P", p);
				continue;
			}
			r->s2 = r1;
			r->p2link = r1->p2;
			r1->p2 = r;
		}
	}

	if(debug['R'] && debug['v'])
		dumpit("pass2", firstr);

	/*
	 * pass 2.5
	 * find looping structure
	 */
	for(r = firstr; r != R; r = r->link)
		r->active = 0;
	change = 0;
	loopit(firstr, nr);

	if(debug['R'] && debug['v'])
		dumpit("pass2.5", firstr);

	/*
	 * pass 3
	 * iterate propagating usage
	 * 	back until flow graph is complete
	 */
loop1:
	change = 0;
	for(r = firstr; r != R; r = r->link)
		r->active = 0;
	for(r = firstr; r != R; r = r->link)
		if(r->prog->as == ARET)
			prop(r, zbits, zbits);
loop11:
	/* pick up unreachable code */
	i = 0;
	for(r = firstr; r != R; r = r1) {
		r1 = r->link;
		if(r1 && r1->active && !r->active) {
			prop(r, zbits, zbits);
			i = 1;
		}
	}
	if(i)
		goto loop11;
	if(change)
		goto loop1;

	if(debug['R'] && debug['v'])
		dumpit("pass3", firstr);

	/*
	 * pass 4
	 * iterate propagating register/variable synchrony
	 * 	forward until graph is complete
	 */
loop2:
	change = 0;
	for(r = firstr; r != R; r = r->link)
		r->active = 0;
	synch(firstr, zbits);
	if(change)
		goto loop2;

	if(debug['R'] && debug['v'])
		dumpit("pass4", firstr);

	/*
	 * pass 4.5
	 * move register pseudo-variables into regu.
	 */
	for(r = firstr; r != R; r = r->link) {
		r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS;

		r->set.b[0] &= ~REGBITS;
		r->use1.b[0] &= ~REGBITS;
		r->use2.b[0] &= ~REGBITS;
		r->refbehind.b[0] &= ~REGBITS;
		r->refahead.b[0] &= ~REGBITS;
		r->calbehind.b[0] &= ~REGBITS;
		r->calahead.b[0] &= ~REGBITS;
		r->regdiff.b[0] &= ~REGBITS;
		r->act.b[0] &= ~REGBITS;
	}

	/*
	 * pass 5
	 * isolate regions
	 * calculate costs (paint1)
	 */
	r = firstr;
	if(r) {
		for(z=0; z<BITS; z++)
			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
		if(bany(&bit) && !r->refset) {
			// should never happen - all variables are preset
			if(debug['w'])
				print("%L: used and not set: %Q\n", r->prog->lineno, bit);
			r->refset = 1;
		}
	}
	for(r = firstr; r != R; r = r->link)
		r->act = zbits;
	rgp = region;
	nregion = 0;
	for(r = firstr; r != R; r = r->link) {
		for(z=0; z<BITS; z++)
			bit.b[z] = r->set.b[z] &
			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
		if(bany(&bit) && !r->refset) {
			if(debug['w'])
				print("%L: set and not used: %Q\n", r->prog->lineno, bit);
			r->refset = 1;
			excise(r);
		}
		for(z=0; z<BITS; z++)
			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
		while(bany(&bit)) {
			i = bnum(bit);
			rgp->enter = r;
			rgp->varno = i;
			change = 0;
			paint1(r, i);
			bit.b[i/32] &= ~(1L<<(i%32));
			if(change <= 0)
				continue;
			rgp->cost = change;
			nregion++;
			if(nregion >= NRGN) {
				if(debug['R'] && debug['v'])
					print("too many regions\n");
				goto brk;
			}
			rgp++;
		}
	}
brk:
	qsort(region, nregion, sizeof(region[0]), rcmp);

	/*
	 * pass 6
	 * determine used registers (paint2)
	 * replace code (paint3)
	 */
	rgp = region;
	for(i=0; i<nregion; i++) {
		bit = blsh(rgp->varno);
		vreg = paint2(rgp->enter, rgp->varno);
		vreg = allreg(vreg, rgp);
		if(rgp->regno != 0)
			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
		rgp++;
	}

	if(debug['R'] && debug['v'])
		dumpit("pass6", firstr);

	/*
	 * pass 7
	 * peep-hole on basic block
	 */
	if(!debug['R'] || debug['P']) {
		peep();
	}

	/*
	 * eliminate nops
	 * free aux structures
	 */
	for(p=firstp; p!=P; p=p->link) {
		while(p->link != P && p->link->as == ANOP)
			p->link = p->link->link;
		if(p->to.type == D_BRANCH)
			while(p->to.branch != P && p->to.branch->as == ANOP)
				p->to.branch = p->to.branch->link;
	}

	if(r1 != R) {
		r1->link = freer;
		freer = firstr;
	}

	if(debug['R']) {
		if(ostats.ncvtreg ||
		   ostats.nspill ||
		   ostats.nreload ||
		   ostats.ndelmov ||
		   ostats.nvar ||
		   ostats.naddr ||
		   0)
			print("\nstats\n");

		if(ostats.ncvtreg)
			print("	%4d cvtreg\n", ostats.ncvtreg);
		if(ostats.nspill)
			print("	%4d spill\n", ostats.nspill);
		if(ostats.nreload)
			print("	%4d reload\n", ostats.nreload);
		if(ostats.ndelmov)
			print("	%4d delmov\n", ostats.ndelmov);
		if(ostats.nvar)
			print("	%4d var\n", ostats.nvar);
		if(ostats.naddr)
			print("	%4d addr\n", ostats.naddr);

		memset(&ostats, 0, sizeof(ostats));
	}
}
Exemplo n.º 26
0
	bool WordcodeEmitter::replace(uint32_t old_instr, uint32_t new_words, bool jump_has_been_translated) 
	{
		// Undo any relative offsets in the last instruction, if that wasn't done by
		// the commit code.

		if (isJumpInstruction(O[nextI - 1]) && !jump_has_been_translated)
			undoRelativeOffsetInJump();
		
		// Catenate unconsumed instructions onto R (it's easier than struggling with
		// moving instructions across buffer boundaries)

		uint32_t k = new_words;
		for ( uint32_t n=old_instr ; n < nextI ; n++ ) {
			uint32_t len = calculateInstructionWidth(O[n]);
			S[k] = O[n];
			for ( uint32_t j=0 ; j < len ; j++ )
				R[k++] = I[n][j];
		}
		
		// Unlink the last buffer segment if we took everything from it, push it onto
		// a reserve (there can only ever be one free).  We know I[nextI-1] points into the
		// current buffer, so check if I[0] is between the start of the buffer and
		// the last instruction.
		
		if (!(buffers->data <= I[0] && I[0] <= I[nextI-1])) {
			spare_buffer = buffers;
			buffers = buffers->next;
			spare_buffer->next = NULL;
			dest_limit = buffers->data + sizeof(buffers->data)/sizeof(buffers->data[0]);
			buffer_offset -= buffers->entries_used;
		}
		dest = I[0];
		
		// Emit the various instructions from new_data, handling branches specially.
		//
		// At this point the instance variables state, I, O, nextI, backtrack_stack,
		// and backtrack_idx are dead, and all the data we need for emitting the
		// instructions are in S and R.  In addition, dest has been rolled back and
		// points to the address of the first instruction in the peephole window, and
		// nothing is live in the code buffer beyond that point.  It's as if we are
		// in a context where we're just emitting instructions.
		//
		// Consequently, we set state to 0 and start emitting instructions from S/R
		// normally, calling peep() after each instruction that was not replaced by
		// the current action.  This works without having local copies of S and R
		// because peephole optimization cannot insert a replacement sequence that is 
		// longer than the matched sequence; so the segments of S and R used by any
		// recursive match will not affect what we're doing here.  Furthermore, 'dest'
		// is shared between this match and recursive matches, so if a recursive match
		// shortens the instruction sequence the correct value of dest will be used
		// when we get back to the present invocation of replace().

		// Reset the machine.
		
		state = 0;
		
		uint32_t i=0;
		while (i < k) {
			uintptr_t op = S[i];
			uintptr_t width = calculateInstructionWidth(op);
			CHECK(width);
			if (isJumpInstruction(op)) {
				*dest++ = R[i++];
				int32_t offset = int32_t(R[i++]);
				if (offset >= 0) {
					// Forward jump
					// Install a new backpatch structure
					makeAndInsertBackpatch(code_start + offset, uint32_t(buffer_offset + (dest + (width - 1) - buffers->data)));
				}
				else {
					// Backward jump
					// Compute new jump offset
					*dest = -int32_t(buffer_offset + (dest + (width - 1) - buffers->data) + offset);
					dest++;
				}
				if (width >= 3)
					*dest++ = R[i++];
				if (width >= 4)
					*dest++ = R[i++];
				AvmAssert(width <= 4);
			}
			else {
				switch (width) {
					default:
						AvmAssert(!"Can't happen");
					case 1:
						*dest++ = R[i++];
						break;
					case 2:
						*dest++ = R[i++];
						*dest++ = R[i++];
						break;
					case 3:
						*dest++ = R[i++];
						*dest++ = R[i++];
						*dest++ = R[i++];
						break;
					case 5:  // OP_debug
						*dest++ = R[i++];
						*dest++ = R[i++];
						*dest++ = R[i++];
						*dest++ = R[i++];
						*dest++ = R[i++];
						break;
				}
			}
			if (i-width >= new_words)
				peep((uint32_t)op, dest-width);
		}
		
		return true;  // always
	}
Exemplo n.º 27
0
void
regopt(Prog *p)
{
	Reg *r, *r1, *r2;
	Prog *p1;
	int i, z;
	long initpc, val, npc;
	ulong vreg;
	Bits bit;
	struct
	{
		long	m;
		long	c;
		Reg*	p;
	} log5[6], *lp;

	firstr = R;
	lastr = R;
	nvar = 0;
	regbits = 0;
	for(z=0; z<BITS; z++) {
		externs.b[z] = 0;
		params.b[z] = 0;
		consts.b[z] = 0;
		addrs.b[z] = 0;
	}

	/*
	 * pass 1
	 * build aux data structure
	 * allocate pcs
	 * find use and set of variables
	 */
	val = 5L * 5L * 5L * 5L * 5L;
	lp = log5;
	for(i=0; i<5; i++) {
		lp->m = val;
		lp->c = 0;
		lp->p = R;
		val /= 5L;
		lp++;
	}
	val = 0;
	for(; p != P; p = p->link) {
		switch(p->as) {
		case ADATA:
		case AGLOBL:
		case ANAME:
		case ASIGNAME:
			continue;
		}
		r = rega();
		if(firstr == R) {
			firstr = r;
			lastr = r;
		} else {
			lastr->link = r;
			r->p1 = lastr;
			lastr->s1 = r;
			lastr = r;
		}
		r->prog = p;
		r->pc = val;
		val++;

		lp = log5;
		for(i=0; i<5; i++) {
			lp->c--;
			if(lp->c <= 0) {
				lp->c = lp->m;
				if(lp->p != R)
					lp->p->log5 = r;
				lp->p = r;
				(lp+1)->c = 0;
				break;
			}
			lp++;
		}

		r1 = r->p1;
		if(r1 != R)
		switch(r1->prog->as) {
		case ARETURN:
		case ABR:
		case ARFI:
		case ARFCI:
		case ARFID:
			r->p1 = R;
			r1->s1 = R;
		}

		/*
		 * left side always read
		 */
		bit = mkvar(&p->from, p->as==AMOVW || p->as == AMOVWZ || p->as == AMOVD);
		for(z=0; z<BITS; z++)
			r->use1.b[z] |= bit.b[z];

		/*
		 * right side depends on opcode
		 */
		bit = mkvar(&p->to, 0);
		if(bany(&bit))
		switch(p->as) {
		default:
			diag(Z, "reg: unknown asop: %A", p->as);
			break;

		/*
		 * right side write
		 */
		case ANOP:
		case AMOVB:
		case AMOVBU:
		case AMOVBZ:
		case AMOVBZU:
		case AMOVH:
		case AMOVHBR:
		case AMOVWBR:
		case AMOVHU:
		case AMOVHZ:
		case AMOVHZU:
		case AMOVW:
		case AMOVWU:
		case AMOVWZ:
		case AMOVWZU:
		case AMOVD:
		case AMOVDU:
		case AFMOVD:
		case AFMOVDCC:
		case AFMOVDU:
		case AFMOVS:
		case AFMOVSU:
		case AFRSP:
			for(z=0; z<BITS; z++)
				r->set.b[z] |= bit.b[z];
			break;

		/*
		 * funny
		 */
		case ABL:
			for(z=0; z<BITS; z++)
				addrs.b[z] |= bit.b[z];
			break;
		}
	}
	if(firstr == R)
		return;
	initpc = pc - val;
	npc = val;

	/*
	 * pass 2
	 * turn branch references to pointers
	 * build back pointers
	 */
	for(r = firstr; r != R; r = r->link) {
		p = r->prog;
		if(p->to.type == D_BRANCH) {
			val = p->to.offset - initpc;
			r1 = firstr;
			while(r1 != R) {
				r2 = r1->log5;
				if(r2 != R && val >= r2->pc) {
					r1 = r2;
					continue;
				}
				if(r1->pc == val)
					break;
				r1 = r1->link;
			}
			if(r1 == R) {
				nearln = p->lineno;
				diag(Z, "ref not found\n%P", p);
				continue;
			}
			if(r1 == r) {
				nearln = p->lineno;
				diag(Z, "ref to self\n%P", p);
				continue;
			}
			r->s2 = r1;
			r->p2link = r1->p2;
			r1->p2 = r;
		}
	}
	if(debug['R']) {
		p = firstr->prog;
		print("\n%L %D\n", p->lineno, &p->from);
	}

	/*
	 * pass 2.5
	 * find looping structure
	 */
	for(r = firstr; r != R; r = r->link)
		r->active = 0;
	change = 0;
	loopit(firstr, npc);
	if(debug['R'] && debug['v']) {
		print("\nlooping structure:\n");
		for(r = firstr; r != R; r = r->link) {
			print("%ld:%P", r->loop, r->prog);
			for(z=0; z<BITS; z++)
				bit.b[z] = r->use1.b[z] |
					r->use2.b[z] | r->set.b[z];
			if(bany(&bit)) {
				print("\t");
				if(bany(&r->use1))
					print(" u1=%B", r->use1);
				if(bany(&r->use2))
					print(" u2=%B", r->use2);
				if(bany(&r->set))
					print(" st=%B", r->set);
			}
			print("\n");
		}
	}

	/*
	 * pass 3
	 * iterate propagating usage
	 * 	back until flow graph is complete
	 */
loop1:
	change = 0;
	for(r = firstr; r != R; r = r->link)
		r->active = 0;
	for(r = firstr; r != R; r = r->link)
		if(r->prog->as == ARETURN)
			prop(r, zbits, zbits);
loop11:
	/* pick up unreachable code */
	i = 0;
	for(r = firstr; r != R; r = r1) {
		r1 = r->link;
		if(r1 && r1->active && !r->active) {
			prop(r, zbits, zbits);
			i = 1;
		}
	}
	if(i)
		goto loop11;
	if(change)
		goto loop1;


	/*
	 * pass 4
	 * iterate propagating register/variable synchrony
	 * 	forward until graph is complete
	 */
loop2:
	change = 0;
	for(r = firstr; r != R; r = r->link)
		r->active = 0;
	synch(firstr, zbits);
	if(change)
		goto loop2;


	/*
	 * pass 5
	 * isolate regions
	 * calculate costs (paint1)
	 */
	r = firstr;
	if(r) {
		for(z=0; z<BITS; z++)
			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
		if(bany(&bit)) {
			nearln = r->prog->lineno;
			warn(Z, "used and not set: %B", bit);
			if(debug['R'] && !debug['w'])
				print("used and not set: %B\n", bit);
		}
	}
	if(debug['R'] && debug['v'])
		print("\nprop structure:\n");
	for(r = firstr; r != R; r = r->link)
		r->act = zbits;
	rgp = region;
	nregion = 0;
	for(r = firstr; r != R; r = r->link) {
		if(debug['R'] && debug['v'])
			print("%P\n	set = %B; rah = %B; cal = %B\n",
				r->prog, r->set, r->refahead, r->calahead);
		for(z=0; z<BITS; z++)
			bit.b[z] = r->set.b[z] &
			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
		if(bany(&bit)) {
			nearln = r->prog->lineno;
			warn(Z, "set and not used: %B", bit);
			if(debug['R'])
				print("set an not used: %B\n", bit);
			excise(r);
		}
		for(z=0; z<BITS; z++)
			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
		while(bany(&bit)) {
			i = bnum(bit);
			rgp->enter = r;
			rgp->varno = i;
			change = 0;
			if(debug['R'] && debug['v'])
				print("\n");
			paint1(r, i);
			bit.b[i/32] &= ~(1L<<(i%32));
			if(change <= 0) {
				if(debug['R'])
					print("%L$%d: %B\n",
						r->prog->lineno, change, blsh(i));
				continue;
			}
			rgp->cost = change;
			nregion++;
			if(nregion >= NRGN) {
				warn(Z, "too many regions");
				goto brk;
			}
			rgp++;
		}
	}
brk:
	qsort(region, nregion, sizeof(region[0]), rcmp);

	/*
	 * pass 6
	 * determine used registers (paint2)
	 * replace code (paint3)
	 */
	rgp = region;
	for(i=0; i<nregion; i++) {
		bit = blsh(rgp->varno);
		vreg = paint2(rgp->enter, rgp->varno);
		vreg = allreg(vreg, rgp);
		if(debug['R']) {
			if(rgp->regno >= NREG)
				print("%L$%d F%d: %B\n",
					rgp->enter->prog->lineno,
					rgp->cost,
					rgp->regno-NREG,
					bit);
			else
				print("%L$%d R%d: %B\n",
					rgp->enter->prog->lineno,
					rgp->cost,
					rgp->regno,
					bit);
		}
		if(rgp->regno != 0)
			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
		rgp++;
	}
	/*
	 * pass 7
	 * peep-hole on basic block
	 */
	if(!debug['R'] || debug['P'])
		peep();

	/*
	 * pass 8
	 * recalculate pc
	 */
	val = initpc;
	for(r = firstr; r != R; r = r1) {
		r->pc = val;
		p = r->prog;
		p1 = P;
		r1 = r->link;
		if(r1 != R)
			p1 = r1->prog;
		for(; p != p1; p = p->link) {
			switch(p->as) {
			default:
				val++;
				break;

			case ANOP:
			case ADATA:
			case AGLOBL:
			case ANAME:
			case ASIGNAME:
				break;
			}
		}
	}
	pc = val;

	/*
	 * fix up branches
	 */
	if(debug['R'])
		if(bany(&addrs))
			print("addrs: %B\n", addrs);

	r1 = 0; /* set */
	for(r = firstr; r != R; r = r->link) {
		p = r->prog;
		if(p->to.type == D_BRANCH)
			p->to.offset = r->s2->pc;
		r1 = r;
	}

	/*
	 * last pass
	 * eliminate nops
	 * free aux structures
	 */
	for(p = firstr->prog; p != P; p = p->link){
		while(p->link && p->link->as == ANOP)
			p->link = p->link->link;
	}
	if(r1 != R) {
		r1->link = freer;
		freer = firstr;
	}
}
Exemplo n.º 28
0
void
regopt(Prog *firstp)
{
	Reg *r, *r1;
	Prog *p;
	Graph *g;
	ProgInfo info;
	int i, z;
	uint32 vreg;
	Bits bit;

	if(first) {
		fmtinstall('Q', Qconv);
		exregoffset = D_R15;
		first = 0;
	}

	mergetemp(firstp);

	/*
	 * control flow is more complicated in generated go code
	 * than in generated c code.  define pseudo-variables for
	 * registers, so we have complete register usage information.
	 */
	nvar = NREGVAR;
	memset(var, 0, NREGVAR*sizeof var[0]);
	for(i=0; i<NREGVAR; i++) {
		if(regnodes[i] == N)
			regnodes[i] = newname(lookup(regname[i]));
		var[i].node = regnodes[i];
	}

	regbits = RtoB(D_SP);
	for(z=0; z<BITS; z++) {
		externs.b[z] = 0;
		params.b[z] = 0;
		consts.b[z] = 0;
		addrs.b[z] = 0;
		ovar.b[z] = 0;
	}

	// build list of return variables
	setoutvar();

	/*
	 * pass 1
	 * build aux data structure
	 * allocate pcs
	 * find use and set of variables
	 */
	g = flowstart(firstp, sizeof(Reg));
	if(g == nil)
		return;
	firstr = (Reg*)g->start;

	for(r = firstr; r != R; r = (Reg*)r->f.link) {
		p = r->f.prog;
		if(p->as == AVARDEF)
			continue;
		proginfo(&info, p);

		// Avoid making variables for direct-called functions.
		if(p->as == ACALL && p->to.type == D_EXTERN)
			continue;

		r->use1.b[0] |= info.reguse | info.regindex;
		r->set.b[0] |= info.regset;

		bit = mkvar(r, &p->from);
		if(bany(&bit)) {
			if(info.flags & LeftAddr)
				setaddrs(bit);
			if(info.flags & LeftRead)
				for(z=0; z<BITS; z++)
					r->use1.b[z] |= bit.b[z];
			if(info.flags & LeftWrite)
				for(z=0; z<BITS; z++)
					r->set.b[z] |= bit.b[z];
		}

		bit = mkvar(r, &p->to);
		if(bany(&bit)) {	
			if(info.flags & RightAddr)
				setaddrs(bit);
			if(info.flags & RightRead)
				for(z=0; z<BITS; z++)
					r->use2.b[z] |= bit.b[z];
			if(info.flags & RightWrite)
				for(z=0; z<BITS; z++)
					r->set.b[z] |= bit.b[z];
		}
	}

	for(i=0; i<nvar; i++) {
		Var *v = var+i;
		if(v->addr) {
			bit = blsh(i);
			for(z=0; z<BITS; z++)
				addrs.b[z] |= bit.b[z];
		}

		if(debug['R'] && debug['v'])
			print("bit=%2d addr=%d et=%-6E w=%-2d s=%N + %lld\n",
				i, v->addr, v->etype, v->width, v->node, v->offset);
	}

	if(debug['R'] && debug['v'])
		dumpit("pass1", &firstr->f, 1);

	/*
	 * pass 2
	 * find looping structure
	 */
	flowrpo(g);

	if(debug['R'] && debug['v'])
		dumpit("pass2", &firstr->f, 1);

	/*
	 * pass 3
	 * iterate propagating usage
	 * 	back until flow graph is complete
	 */
loop1:
	change = 0;
	for(r = firstr; r != R; r = (Reg*)r->f.link)
		r->f.active = 0;
	for(r = firstr; r != R; r = (Reg*)r->f.link)
		if(r->f.prog->as == ARET)
			prop(r, zbits, zbits);
loop11:
	/* pick up unreachable code */
	i = 0;
	for(r = firstr; r != R; r = r1) {
		r1 = (Reg*)r->f.link;
		if(r1 && r1->f.active && !r->f.active) {
			prop(r, zbits, zbits);
			i = 1;
		}
	}
	if(i)
		goto loop11;
	if(change)
		goto loop1;

	if(debug['R'] && debug['v'])
		dumpit("pass3", &firstr->f, 1);

	/*
	 * pass 4
	 * iterate propagating register/variable synchrony
	 * 	forward until graph is complete
	 */
loop2:
	change = 0;
	for(r = firstr; r != R; r = (Reg*)r->f.link)
		r->f.active = 0;
	synch(firstr, zbits);
	if(change)
		goto loop2;

	if(debug['R'] && debug['v'])
		dumpit("pass4", &firstr->f, 1);

	/*
	 * pass 4.5
	 * move register pseudo-variables into regu.
	 */
	for(r = firstr; r != R; r = (Reg*)r->f.link) {
		r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS;

		r->set.b[0] &= ~REGBITS;
		r->use1.b[0] &= ~REGBITS;
		r->use2.b[0] &= ~REGBITS;
		r->refbehind.b[0] &= ~REGBITS;
		r->refahead.b[0] &= ~REGBITS;
		r->calbehind.b[0] &= ~REGBITS;
		r->calahead.b[0] &= ~REGBITS;
		r->regdiff.b[0] &= ~REGBITS;
		r->act.b[0] &= ~REGBITS;
	}

	/*
	 * pass 5
	 * isolate regions
	 * calculate costs (paint1)
	 */
	r = firstr;
	if(r) {
		for(z=0; z<BITS; z++)
			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
		if(bany(&bit) && !r->f.refset) {
			// should never happen - all variables are preset
			if(debug['w'])
				print("%L: used and not set: %Q\n", r->f.prog->lineno, bit);
			r->f.refset = 1;
		}
	}
	for(r = firstr; r != R; r = (Reg*)r->f.link)
		r->act = zbits;
	rgp = region;
	nregion = 0;
	for(r = firstr; r != R; r = (Reg*)r->f.link) {
		for(z=0; z<BITS; z++)
			bit.b[z] = r->set.b[z] &
			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
		if(bany(&bit) && !r->f.refset) {
			if(debug['w'])
				print("%L: set and not used: %Q\n", r->f.prog->lineno, bit);
			r->f.refset = 1;
			excise(&r->f);
		}
		for(z=0; z<BITS; z++)
			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
		while(bany(&bit)) {
			i = bnum(bit);
			rgp->enter = r;
			rgp->varno = i;
			change = 0;
			paint1(r, i);
			bit.b[i/32] &= ~(1L<<(i%32));
			if(change <= 0)
				continue;
			rgp->cost = change;
			nregion++;
			if(nregion >= NRGN) {
				if(debug['R'] && debug['v'])
					print("too many regions\n");
				goto brk;
			}
			rgp++;
		}
	}
brk:
	qsort(region, nregion, sizeof(region[0]), rcmp);

	if(debug['R'] && debug['v'])
		dumpit("pass5", &firstr->f, 1);

	/*
	 * pass 6
	 * determine used registers (paint2)
	 * replace code (paint3)
	 */
	rgp = region;
	for(i=0; i<nregion; i++) {
		bit = blsh(rgp->varno);
		vreg = paint2(rgp->enter, rgp->varno);
		vreg = allreg(vreg, rgp);
		if(rgp->regno != 0) {
			if(debug['R'] && debug['v']) {
				Var *v;

				v = var + rgp->varno;
				print("registerize %N+%lld (bit=%2d et=%2E) in %R\n",
						v->node, v->offset, rgp->varno, v->etype, rgp->regno);
			}
			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
		}
		rgp++;
	}

	if(debug['R'] && debug['v'])
		dumpit("pass6", &firstr->f, 1);
	
	/*
	 * free aux structures. peep allocates new ones.
	 */
	flowend(g);
	firstr = R;

	/*
	 * pass 7
	 * peep-hole on basic block
	 */
	if(!debug['R'] || debug['P'])
		peep(firstp);

	/*
	 * eliminate nops
	 */
	for(p=firstp; p!=P; p=p->link) {
		while(p->link != P && p->link->as == ANOP)
			p->link = p->link->link;
		if(p->to.type == D_BRANCH)
			while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
				p->to.u.branch = p->to.u.branch->link;
	}

	if(debug['R']) {
		if(ostats.ncvtreg ||
		   ostats.nspill ||
		   ostats.nreload ||
		   ostats.ndelmov ||
		   ostats.nvar ||
		   ostats.naddr ||
		   0)
			print("\nstats\n");

		if(ostats.ncvtreg)
			print("	%4d cvtreg\n", ostats.ncvtreg);
		if(ostats.nspill)
			print("	%4d spill\n", ostats.nspill);
		if(ostats.nreload)
			print("	%4d reload\n", ostats.nreload);
		if(ostats.ndelmov)
			print("	%4d delmov\n", ostats.ndelmov);
		if(ostats.nvar)
			print("	%4d var\n", ostats.nvar);
		if(ostats.naddr)
			print("	%4d addr\n", ostats.naddr);

		memset(&ostats, 0, sizeof(ostats));
	}
}
Exemplo n.º 29
0
void main()
{
    int s[SIZE]= {0};
    int top= -1;
    int ch, pos, item;
    clrscr();
    do
    {
        clrscr();
        printf("\n 1 for Push");
        printf("\n 2 for Pop");
        printf("\n 3 for Peep");
        printf("\n 4 for Change");
        printf("\n 5 for Display");
        printf("\n 6. for Exit");

        printf("\n\t Enter choice:");
        scanf("%d", &ch);

        switch(ch)
        {
        case 1 :
            printf("\n\t Enter item for push:");
            scanf("%d", &item);
            push(s,top,item);
            getch();
            break;

        case 2 :
            item = pop(s,top);
            if(item!=-1)
                printf("\n\t%d is popped",item);
            getch();
            break;

        case 3:
            printf("\n\tEnter pos for peep:");
            scanf("%d",&pos);

            item = peep(s,top,pos);

            if(item!=-1)
                printf("%d",item);

            getch();
            break;

        case 4:
            printf("\n\tEnter new item :");
            scanf("%d",&item);
            printf("\n\tEnter pos:");
            scanf("%d",&pos);
            change(s,top,pos,item);
            getch();
            break;

        case 5 :
            display(s,top);
            getch();
            break;

        case 6 :
            printf("\n\t Thanks...!");
            getch();
            exit(0);
            break;

        default :
            printf("\n\t Wrong choice...!");
            getch();
            break;
        }
    } while(ch!=6);
    getch();
}