// Checks if the group is abelian // Maybe incorrect? bool CayleyGraph::is_abelian (void) { int gen[MAX_GENERATORS]; for (int i = 0; i < MAX_GENERATORS; i++) gen[i] = out_edges[0][i]; for (int i = 0; i < MAX_GENERATORS; i++) { if (gen[i] != order) { for (int j = i; j < MAX_GENERATORS; j++) { if (gen[j] != order && !commutes(gen[i],gen[j])) return false; } } } return true; }
void cgen(Node *n, Node *nn) { Node *l, *r; Prog *p1; Node nod, nod1, nod2, nod3, nod4; int o, t; long v, curs; if(debug['g'] && nn == Z) { // prtree(nn, "cgen lhs"); prtree(n, "cgen"); } if(n == Z || n->type == T) return; if(typesuv[n->type->etype]) { sugen(n, nn, n->type->width); return; } l = n->left; r = n->right; o = n->op; if(n->addable >= INDEXED) { if(nn == Z) { switch(o) { default: nullwarn(Z, Z); break; case OINDEX: nullwarn(l, r); break; } return; } gmove(n, nn); return; } curs = cursafe; if(n->complex >= FNX) if(l->complex >= FNX) if(r != Z && r->complex >= FNX) switch(o) { default: regret(&nod, r); cgen(r, &nod); regsalloc(&nod1, r); gopcode(OAS, &nod, Z, &nod1); regfree(&nod); nod = *n; nod.right = &nod1; cgen(&nod, nn); return; case OFUNC: case OCOMMA: case OANDAND: case OOROR: case OCOND: case ODOT: break; } switch(o) { default: diag(n, "unknown op in cgen: %O", o); break; case OAS: if(l->op == OBIT) goto bitas; if(l->addable >= INDEXED && l->complex < FNX) { if(nn != Z || r->addable < INDEXED) { if(r->complex >= FNX && nn == Z) regret(&nod, r); else regalloc(&nod, r, nn); cgen(r, &nod); gmove(&nod, l); if(nn != Z) gmove(&nod, nn); regfree(&nod); } else gmove(r, l); break; } if(l->complex >= r->complex) { reglcgen(&nod1, l, Z); if(r->addable >= INDEXED) { gmove(r, &nod1); if(nn != Z) gmove(r, nn); regfree(&nod1); break; } regalloc(&nod, r, nn); cgen(r, &nod); } else { regalloc(&nod, r, nn); cgen(r, &nod); reglcgen(&nod1, l, Z); } gmove(&nod, &nod1); regfree(&nod); regfree(&nod1); break; bitas: n = l->left; regalloc(&nod, r, nn); if(l->complex >= r->complex) { reglcgen(&nod1, n, Z); cgen(r, &nod); } else { cgen(r, &nod); reglcgen(&nod1, n, Z); } regalloc(&nod2, n, Z); gopcode(OAS, &nod1, Z, &nod2); bitstore(l, &nod, &nod1, &nod2, nn); break; case OBIT: if(nn == Z) { nullwarn(l, Z); break; } bitload(n, &nod, Z, Z, nn); gopcode(OAS, &nod, Z, nn); regfree(&nod); break; case ODIV: case OMOD: if(nn != Z) if((t = vlog(r)) >= 0 && t <= 8) { /* signed div/mod by constant power of 2 */ cgen(l, nn); gopcode(OGE, nodconst(0), nn, Z); p1 = p; if(o == ODIV) { gopcode(OADD, nodconst((1<<t)-1), Z, nn); patch(p1, pc); gopcode(OASHR, nodconst(t), Z, nn); } else { gopcode(OSUB, nn, nodconst(0), nn); regalloc(&nod, l, Z); gopcode(OAS, nodconst((1<<t)-1), Z, &nod); gopcode(OAND, &nod, Z, nn); regfree(&nod); // gopcode(OAND, nodconst((1<<t)-1), Z, nn); gopcode(OSUB, nn, nodconst(0), nn); gbranch(OGOTO); patch(p1, pc); p1 = p; regalloc(&nod, l, Z); gopcode(OAS, nodconst((1<<t)-1), Z, &nod); gopcode(OAND, &nod, Z, nn); regfree(&nod); // gopcode(OAND, nodconst((1<<t)-1), Z, nn); patch(p1, pc); } break; } goto muldiv; case OADD: case OSUB: case OLSHR: case OASHL: case OASHR: /* * immediate operands */ if(nn != Z) if(sconst(r)) if(o == OADD || o == OSUB || r->vconst < (vlong)32) { // if(r->op == OCONST) // if(!typefd[n->type->etype]) { cgen(l, nn); if(r->vconst == 0) break; gopcode(o, r, Z, nn); break; } case OAND: case OOR: case OXOR: case OLMUL: case OLDIV: case OLMOD: case OMUL: muldiv: if(nn == Z) { nullwarn(l, r); break; } if(o == OMUL || o == OLMUL) { if(mulcon(n, nn)) break; } if(l->complex >= r->complex) { regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, r, Z); cgen(r, &nod1); gopcode(o, &nod1, Z, &nod); } else { if(o == OADD || o == OSUB) { regalloc(&nod, r, nn); cgen(r, &nod); regalloc(&nod1, l, Z); cgen(l, &nod1); gopcode(o, &nod, &nod1, &nod); } else { if(commutes(o)){ regalloc(&nod, r, nn); cgen(r, &nod); regalloc(&nod1, l, Z); cgen(l, &nod1); gopcode(o, &nod1, Z, &nod); } else{ regalloc(&nod1, r, Z); cgen(r, &nod1); regalloc(&nod, l, nn); cgen(l, &nod); gopcode(o, &nod1, Z, &nod); } } } gopcode(OAS, &nod, Z, nn); regfree(&nod); regfree(&nod1); break; /* case ONEG: if(nn == Z) { nullwarn(l, Z); break; } regalloc(&nod, l, nn); cgen(l, &nod); gopcode(o, &nod, Z, &nod); gopcode(OAS, &nod, Z, nn); regfree(&nod); break; */ case OASLSHR: case OASASHL: case OASASHR: case OASADD: case OASSUB: if(l->op == OBIT) goto asbitop; if(sconst(r)) if(o == OASADD || o == OASSUB || r->vconst < (vlong)32) { // if(r->op == OCONST) // if(!typefd[n->type->etype]) { if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, r, nn); gopcode(OAS, &nod2, Z, &nod); gopcode(o, r, Z, &nod); gopcode(OAS, &nod, Z, &nod2); regfree(&nod); if(l->addable < INDEXED) regfree(&nod2); break; } case OASAND: case OASXOR: case OASOR: case OASLMUL: case OASLDIV: case OASLMOD: case OASMUL: case OASDIV: case OASMOD: if(l->op == OBIT) goto asbitop; if(l->complex >= r->complex) { if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod1, r, Z); cgen(r, &nod1); } else { regalloc(&nod1, r, Z); cgen(r, &nod1); if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; } regalloc(&nod, n, nn); gmove(&nod2, &nod); gopcode(o, &nod1, Z, &nod); gmove(&nod, &nod2); if(nn != Z) gopcode(OAS, &nod, Z, nn); regfree(&nod); regfree(&nod1); if(l->addable < INDEXED) regfree(&nod2); break; asbitop: regalloc(&nod4, n, nn); if(l->complex >= r->complex) { bitload(l, &nod, &nod1, &nod2, &nod4); regalloc(&nod3, r, Z); cgen(r, &nod3); } else { regalloc(&nod3, r, Z); cgen(r, &nod3); bitload(l, &nod, &nod1, &nod2, &nod4); } gmove(&nod, &nod4); gopcode(o, &nod3, Z, &nod4); regfree(&nod3); gmove(&nod4, &nod); regfree(&nod4); bitstore(l, &nod, &nod1, &nod2, nn); break; case OADDR: if(nn == Z) { nullwarn(l, Z); break; } lcgen(l, nn); break; case OFUNC: if(l->complex >= FNX) { if(l->op != OIND) diag(n, "bad function call"); regret(&nod, l->left); cgen(l->left, &nod); regsalloc(&nod1, l->left); gopcode(OAS, &nod, Z, &nod1); regfree(&nod); nod = *n; nod.left = &nod2; nod2 = *l; nod2.left = &nod1; nod2.complex = 1; cgen(&nod, nn); return; } if(REGARG >= 0) o = reg[REGARG]; gargs(r, &nod, &nod1); if(l->addable < INDEXED) { reglcgen(&nod, l, Z); gopcode(OFUNC, Z, Z, &nod); regfree(&nod); } else gopcode(OFUNC, Z, Z, l); if(REGARG >= 0) if(o != reg[REGARG]) reg[REGARG]--; if(nn != Z) { regret(&nod, n); gopcode(OAS, &nod, Z, nn); regfree(&nod); } break; case OIND: if(nn == Z) { nullwarn(l, Z); break; } regialloc(&nod, n, nn); r = l; while(r->op == OADD) r = r->right; if(sconst(r) && (v = r->vconst+nod.xoffset) >= 0 && v < 32*r->type->width/SZ_LONG) { v = r->vconst; r->vconst = 0; cgen(l, &nod); nod.xoffset += v; r->vconst = v; } else cgen(l, &nod); regind(&nod, n); gopcode(OAS, &nod, Z, nn); regfree(&nod); break; case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: case OLO: case OLS: case OHI: case OHS: if(nn == Z) { nullwarn(l, r); break; } boolgen(n, 1, nn); break; case OANDAND: case OOROR: boolgen(n, 1, nn); if(nn == Z) patch(p, pc); break; case ONOT: if(nn == Z) { nullwarn(l, Z); break; } boolgen(n, 1, nn); break; case OCOMMA: cgen(l, Z); cgen(r, nn); break; case OCAST: if(nn == Z) { nullwarn(l, Z); break; } /* * convert from types l->n->nn */ if(nocast(l->type, n->type)) { if(nocast(n->type, nn->type)) { cgen(l, nn); break; } } regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, n, &nod); gopcode(OAS, &nod, Z, &nod1); gopcode(OAS, &nod1, Z, nn); regfree(&nod1); regfree(&nod); break; case ODOT: sugen(l, nodrat, l->type->width); if(nn != Z) { warn(n, "non-interruptable temporary"); nod = *nodrat; if(!r || r->op != OCONST) { diag(n, "DOT and no offset"); break; } nod.xoffset += (long)r->vconst; nod.type = n->type; cgen(&nod, nn); } break; case OCOND: bcgen(l, 1); p1 = p; cgen(r->left, nn); gbranch(OGOTO); patch(p1, pc); p1 = p; cgen(r->right, nn); patch(p1, pc); break; case OPOSTINC: case OPOSTDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPOSTDEC) v = -v; if(l->op == OBIT) goto bitinc; if(nn == Z) goto pre; if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, l, nn); gopcode(OAS, &nod2, Z, &nod); regalloc(&nod1, l, Z); if(typefd[l->type->etype]) { regalloc(&nod3, l, Z); if(v < 0) { gopcode(OAS, nodfconst(-v), Z, &nod3); gopcode(OSUB, &nod3, &nod, &nod1); } else { gopcode(OAS, nodfconst(v), Z, &nod3); gopcode(OADD, &nod3, &nod, &nod1); } regfree(&nod3); } else { if (v > 0 && v < 8) gopcode(OADD, nodconst(v), &nod, &nod1); else if (v < 0 && v > -8) gopcode(OSUB, nodconst(-v), &nod, &nod1); else { regalloc(&nod3, l, Z); gopcode(OAS, nodconst(v), Z, &nod3); gopcode(OADD, &nod3, &nod, &nod1); regfree(&nod3); } } gopcode(OAS, &nod1, Z, &nod2); regfree(&nod); regfree(&nod1); if(l->addable < INDEXED) regfree(&nod2); break; case OPREINC: case OPREDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPREDEC) v = -v; if(l->op == OBIT) goto bitinc; pre: if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, l, nn); gopcode(OAS, &nod2, Z, &nod); if(typefd[l->type->etype]) { regalloc(&nod3, l, Z); if(v < 0) { gopcode(OAS, nodfconst(-v), Z, &nod3); gopcode(OSUB, &nod3, Z, &nod); } else { gopcode(OAS, nodfconst(v), Z, &nod3); gopcode(OADD, &nod3, Z, &nod); } regfree(&nod3); } else { if (v > 0 && v < 256) gopcode(OADD, nodconst(v), Z, &nod); else if (v < 0 && v > -256) gopcode(OSUB, nodconst(-v), Z, &nod); else { regalloc(&nod3, l, Z); gopcode(OAS, nodconst(v), Z, &nod3); gopcode(OADD, &nod3, &nod, &nod); regfree(&nod3); } } gopcode(OAS, &nod, Z, &nod2); regfree(&nod); if(l->addable < INDEXED) regfree(&nod2); break; bitinc: if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { bitload(l, &nod, &nod1, &nod2, Z); gopcode(OAS, &nod, Z, nn); if (v > 0 && v < 256) gopcode(OADD, nodconst(v), Z, &nod); else if (v < 0 && v > -256) gopcode(OSUB, nodconst(-v), Z, &nod); else { regalloc(&nod3, l, Z); gopcode(OAS, nodconst(v), Z, &nod3); gopcode(OADD, &nod3, &nod, &nod); regfree(&nod3); } bitstore(l, &nod, &nod1, &nod2, Z); break; } bitload(l, &nod, &nod1, &nod2, nn); if (v > 0 && v < 256) gopcode(OADD, nodconst(v), Z, &nod); else if (v < 0 && v > -256) gopcode(OSUB, nodconst(-v), Z, &nod); else { regalloc(&nod3, l, Z); gopcode(OAS, nodconst(v), Z, &nod3); gopcode(OADD, &nod3, &nod, &nod); regfree(&nod3); } bitstore(l, &nod, &nod1, &nod2, nn); break; } cursafe = curs; return; }
bool CayleyGraph::is_central (int a) { for (int i = 0; i < order; i++) if (!commutes(a,i)) return false; return true; }