+ case ULE:
+ case ULT:
+ case UGE:
+ case UGT:
+ p->in.op -= (UGE-GE);
+ if( degenerate(p) )
+ break;
+ p->in.op += (UGE-GE);
+ break;
+
+ case EQ:
+ case NE:
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ (void) degenerate(p);
+ break;
+
+ case DIV:
+ if( p->in.right->in.op == ICON &&
+ p->in.right->tn.name[0] == '\0' &&
+ ISUNSIGNED(p->in.right->in.type) &&
+ (unsigned) p->in.right->tn.lval >= 0x80000000 ) {
+ /* easy to do here, harder to do in zzzcode() */
+ p->in.op = UGE;
+ break;
+ }
+ case MOD:
+ case ASG DIV:
+ case ASG MOD:
+ /*
+ * optimize DIV and MOD
+ *
+ * basically we spot UCHAR and USHORT and try to do them
+ * as signed ints... apparently div+mul+sub is always
+ * faster than ediv for finding MOD on the VAX, when
+ * full unsigned MOD isn't needed.
+ *
+ * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub
+ * are faster for unsigned dividend and a constant divisor
+ * in the right range (.5 to 1 of dividend's range for the
+ * first, .333+ to .5 for the second). full unsigned is
+ * already done cmp+sub in the appropriate case; the
+ * other cases are less common and require more ambition.
+ */
+ if( degenerate(p) )
+ break;
+ l = p->in.left;
+ r = p->in.right;
+ if( !ISUNSIGNED(r->in.type) ||
+ tlen(l) >= SZINT/SZCHAR ||
+ !(tlen(r) < SZINT/SZCHAR ||
+ (r->in.op == ICON && r->tn.name[0] == '\0')) )
+ break;
+ if( r->in.op == ICON )
+ r->tn.type = INT;
+ else {
+ NODE *t = talloc();
+ t->in.left = r;
+ r = t;
+ r->in.op = SCONV;
+ r->in.type = INT;
+ r->in.right = 0;
+ p->in.right = r;
+ }
+ if( o == DIV || o == MOD ) {
+ NODE *t = talloc();
+ t->in.left = l;
+ l = t;
+ l->in.op = SCONV;
+ l->in.type = INT;
+ l->in.right = 0;
+ p->in.left = l;
+ }
+ /* handle asgops in table */
+ break;
+
+ case RS:
+ case ASG RS:
+ case LS:
+ case ASG LS:
+ /* pick up degenerate shifts */
+ l = p->in.left;
+ r = p->in.right;
+ if( !(r->in.op == ICON && r->tn.name[0] == '\0') )
+ break;
+ i = r->tn.lval;
+ if( i < 0 )
+ /* front end 'fixes' this? */
+ if( o == LS || o == ASG LS )
+ o += (RS-LS);
+ else
+ o += (LS-RS);
+ if( (o == RS || o == ASG RS) &&
+ !ISUNSIGNED(l->in.type) )
+ /* can't optimize signed right shifts */
+ break;
+ if( i < tlen(l) * SZCHAR )
+ break;
+ zero:
+ if( !asgop( o ) )
+ if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
+ /* no side effects */
+ tfree(l);
+ ncopy(p, r);
+ r->in.op = FREE;
+ p->tn.lval = 0;
+ }
+ else {
+ p->in.op = COMOP;
+ r->tn.lval = 0;
+ }
+ else {
+ p->in.op = ASSIGN;
+ r->tn.lval = 0;
+ }
+ break;
+ }
+ }
+
+degenerate(p) register NODE *p; {
+ int o;
+ int result, i;
+ int lower, upper;
+ register NODE *l, *r;
+
+ /*
+ * try to keep degenerate comparisons with constants
+ * out of the table.
+ */
+ r = p->in.right;
+ l = p->in.left;
+ if( r->in.op != ICON ||
+ r->tn.name[0] != '\0' ||
+ tlen(l) >= tlen(r) )
+ return (0);
+ switch( l->in.type ) {
+ case CHAR:
+ lower = -(1 << SZCHAR - 1);
+ upper = (1 << SZCHAR - 1) - 1;
+ break;
+ case UCHAR:
+ lower = 0;
+ upper = (1 << SZCHAR) - 1;
+ break;
+ case SHORT:
+ lower = -(1 << SZSHORT - 1);
+ upper = (1 << SZSHORT - 1) - 1;
+ break;
+ case USHORT:
+ lower = 0;
+ upper = (1 << SZSHORT) - 1;
+ break;
+ default:
+ cerror("unsupported type in degenerate()");