From 96e41820f6cf191ceae3aad7e2b28b53bf8b4ca9 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 14 Jan 2012 00:25:41 -0800 Subject: [PATCH 1/2] more vector ops --- src/backend/el.c | 58 ++++++++++++++++++++- src/backend/optabgen.c | 1 + src/backend/ty.h | 3 ++ src/cast.c | 12 +++++ src/e2ir.c | 61 ++++++++++++++++++++-- src/expression.c | 115 +++++++++++++++++++++++++++++++++-------- src/expression.h | 11 ++++ src/mtype.c | 14 +++-- src/optimize.c | 1 + src/parse.c | 1 + 10 files changed, 249 insertions(+), 28 deletions(-) diff --git a/src/backend/el.c b/src/backend/el.c index 61cd8b1dd772..4d2f76ad2aba 100644 --- a/src/backend/el.c +++ b/src/backend/el.c @@ -1869,6 +1869,7 @@ elem *el_convfloat(elem *e) default: assert(0); } + #if 0 printf("%gL+%gLi\n", (double)e->EV.Vcldouble.re, (double)e->EV.Vcldouble.im); printf("el_convfloat() %g %g sz=%d\n", e->EV.Vcdouble.re, e->EV.Vcdouble.im, sz); @@ -1877,6 +1878,46 @@ unsigned short *p = (unsigned short *)&e->EV.Vcldouble; for (int i = 0; i < sz/2; i++) printf("%04x ", p[i]); printf("\n"); #endif + + symbol *s = out_readonly_sym(ty, p, sz); + el_free(e); + e = el_var(s); + e->Ety = ty; + if (e->Eoper == OPvar) + e->Ety |= mTYconst; + //printf("s: %s %d:x%x\n", s->Sident, s->Sseg, s->Soffset); +#endif + return e; +} + +/************************************ + * Convert vector constant to a read-only symbol. + * Needed iff vector code can't load immediate constants. + */ + +elem *el_convxmm(elem *e) +{ + unsigned char buffer[16]; + +#if TX86 + // Do not convert if the constants can be loaded with the special XMM instructions +#if 0 + if (loadconst(e)) + return e; +#endif + + changes++; + tym_t ty = e->Ety; + int sz = tysize(ty); + assert(sz <= sizeof(buffer)); + void *p = &e->EV.Vcent; + +#if 0 +printf("el_convxmm(): sz = %d\n", sz); +for (size i = 0; i < sz; i++) printf("%02x ", ((unsigned char *)p)[i]); +printf("\n"); +#endif + symbol *s = out_readonly_sym(ty, p, sz); el_free(e); e = el_var(s); @@ -2027,7 +2068,9 @@ elem *el_convert(elem *e) case OPconst: #if TX86 - if (tyfloating(e->Ety) && config.inline8087) + if (tyvector(e->Ety)) + e = el_convxmm(e); + else if (tyfloating(e->Ety) && config.inline8087) e = el_convfloat(e); #endif break; @@ -3125,6 +3168,19 @@ void elem_print(elem *e) dbg_printf("%gL+%gLi ", (double)e->EV.Vcldouble.re, (double)e->EV.Vcldouble.im); break; + case TYfloat4: + case TYdouble2: + case TYschar16: + case TYuchar16: + case TYshort8: + case TYushort8: + case TYlong4: + case TYulong4: + case TYllong2: + case TYullong2: + dbg_printf("%llxLL+%llxLL ", e->EV.Vcent.msw, e->EV.Vcent.lsw); + break; + #if !MARS case TYident: dbg_printf("'%s' ", e->ET->Tident); diff --git a/src/backend/optabgen.c b/src/backend/optabgen.c index 9757adb752ee..69e2ac6dae10 100644 --- a/src/backend/optabgen.c +++ b/src/backend/optabgen.c @@ -837,6 +837,7 @@ void dotytab() #if TX86 static tym_t _xmmreg[] = { TYfloat,TYdouble,TYifloat,TYidouble, + TYfloat4,TYdouble2, TYschar16,TYuchar16,TYshort8,TYushort8, TYlong4,TYulong4,TYllong2,TYullong2, }; diff --git a/src/backend/ty.h b/src/backend/ty.h index 6a2efa9a1ad9..120c79339a95 100644 --- a/src/backend/ty.h +++ b/src/backend/ty.h @@ -246,6 +246,9 @@ extern unsigned tytab[]; // Can go in XMM floating point register #define tyxmmreg(ty) (tytab[(ty) & 0xFF] & TYFLxmmreg) +// Is a vector type +#define tyvector(ty) (tybasic(ty) >= TYfloat4 && tybasic(ty) <= TYullong2) + #ifndef tyshort /* Types that are chars or shorts */ #define tyshort(ty) (tytab[(ty) & 0xFF] & TYFLshort) diff --git a/src/cast.c b/src/cast.c index ca8dc3c33dde..c2a4eb1fa0b7 100644 --- a/src/cast.c +++ b/src/cast.c @@ -209,6 +209,12 @@ MATCH IntegerExp::implicitConvTo(Type *t) if (m == MATCHnomatch && t->ty == Tenum) goto Lno; + if (t->ty == Tvector) + { TypeVector *tv = (TypeVector *)t; + TypeBasic *tb = tv->elementType(); + toty = tb->ty; + } + switch (ty) { case Tbool: @@ -867,6 +873,12 @@ Expression *Expression::castTo(Scope *sc, Type *t) } L1: ; } + else if (tb->ty == Tvector && typeb->ty != Tvector) + { + e = new VectorExp(loc, e, tb); + e = e->semantic(sc); + return e; + } e = new CastExp(loc, e, tb); } } diff --git a/src/e2ir.c b/src/e2ir.c index 83f1ffa91678..338e58368611 100644 --- a/src/e2ir.c +++ b/src/e2ir.c @@ -1272,9 +1272,8 @@ elem *ThisExp::toElem(IRState *irs) */ elem *IntegerExp::toElem(IRState *irs) -{ elem *e; - - e = el_long(type->totym(), value); +{ + elem *e = el_long(type->totym(), value); el_setLoc(e,loc); return e; } @@ -3692,6 +3691,62 @@ elem *DeleteExp::toElem(IRState *irs) return e; } +elem *VectorExp::toElem(IRState *irs) +{ +#if 0 + printf("VectorExp::toElem()\n"); + print(); + printf("\tfrom: %s\n", e1->type->toChars()); + printf("\tto : %s\n", to->toChars()); +#endif + + dinteger_t d; + real_t r; + if (e1->type->isfloating()) + r = e1->toReal(); + else if (e1->type->isintegral()) + d = e1->toInteger(); + else + assert(0); + elem *e = el_calloc(); + e->Eoper = OPconst; + e->Ety = type->totym(); + switch (tybasic(e->Ety)) + { + case TYfloat4: + for (size_t i = 0; i < 4; i++) + ((targ_float *)&e->EV.Vcent)[i] = r; + break; + case TYdouble2: + ((targ_double *)&e->EV.Vcent.lsw)[0] = r; + ((targ_double *)&e->EV.Vcent.msw)[0] = r; + break; + case TYschar16: + case TYuchar16: + for (size_t i = 0; i < 16; i++) + ((targ_uchar *)&e->EV.Vcent)[i] = d; + break; + case TYshort8: + case TYushort8: + for (size_t i = 0; i < 8; i++) + ((targ_ushort *)&e->EV.Vcent)[i] = d; + break; + case TYlong4: + case TYulong4: + for (size_t i = 0; i < 4; i++) + ((targ_ulong *)&e->EV.Vcent)[i] = d; + break; + case TYllong2: + case TYullong2: e->EV.Vcent.lsw = d; + e->EV.Vcent.msw = d; + break; + default: + assert(0); + } + el_setLoc(e, loc); + return e; +} + elem *CastExp::toElem(IRState *irs) { TY fty; diff --git a/src/expression.c b/src/expression.c index 014ec30bc23d..21143ae33fbe 100644 --- a/src/expression.c +++ b/src/expression.c @@ -5881,9 +5881,14 @@ Expression *BinAssignExp::commonSemanticAssign(Scope *sc) e1->checkArithmetic(); e2->checkArithmetic(); - if (op == TOKmodass && e2->type->iscomplex()) - { error("cannot perform modulo complex arithmetic"); - return new ErrorExp(); + if (op == TOKmodass) + { + if (e2->type->iscomplex()) + { error("cannot perform modulo complex arithmetic"); + return new ErrorExp(); + } + else if (type->toBasetype()->ty == Tvector) + return incompatibleTypes(); } } return this; @@ -8463,6 +8468,12 @@ Expression *CastExp::semantic(Scope *sc) return new ErrorExp(); } } + + // Look for casting to a vector type + if (tob->ty == Tvector && t1b->ty != Tvector) + { + return new VectorExp(loc, e1, to); + } } else if (!to) { error("cannot cast tuple"); @@ -8573,6 +8584,49 @@ void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } +/************************************************************/ + +VectorExp::VectorExp(Loc loc, Expression *e, Type *t) + : UnaExp(loc, TOKvector, sizeof(VectorExp), e) +{ + assert(t->ty == Tvector); + to = t; + dim = ~0; +} + +Expression *VectorExp::syntaxCopy() +{ + return new VectorExp(loc, e1->syntaxCopy(), to->syntaxCopy()); +} + +Expression *VectorExp::semantic(Scope *sc) +{ +#if LOGSEMANTIC + printf("VectorExp::semantic('%s')\n", toChars()); +#endif + + if (type) + return this; + e1 = e1->semantic(sc); + type = to->semantic(loc, sc); + if (e1->op == TOKerror || type->ty == Terror) + return e1; + Type *tb = type->toBasetype(); + assert(tb->ty == Tvector); + TypeVector *tv = (TypeVector *)tb; + Type *te = tv->elementType(); + dim = tv->size(loc) / te->size(loc); + return this; +} + +void VectorExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("cast("); + to->toCBuffer(buf, NULL, hgs); + buf->writeByte(')'); + expToCBuffer(buf, hgs, e1, precedence[op]); +} + /************************************************************/ SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr) @@ -9884,7 +9938,17 @@ Expression *AssignExp::semantic(Scope *sc) e1 = e1->modifiableLvalue(sc, e1old); } - Type *t2 = e2->type; + Type *t2 = e2->type->toBasetype(); +#if 0 + if (t1->ty == Tvector && t2->ty != Tvector && + e2->implicitConvTo(((TypeVector *)t1)->basetype->nextOf()) + ) + { // memset + ismemset = 1; // make it easy for back end to tell what this is + e2 = e2->implicitCastTo(sc, ((TypeVector *)t1)->basetype->nextOf()); + } + else +#endif if (e1->op == TOKslice && t1->nextOf() && e2->implicitConvTo(t1->nextOf()) @@ -9905,8 +9969,8 @@ Expression *AssignExp::semantic(Scope *sc) } //error("cannot assign to static array %s", e1->toChars()); } - else if (e1->op == TOKslice && t2->toBasetype()->ty == Tarray && - t2->toBasetype()->nextOf()->implicitConvTo(t1->nextOf())) + else if (e1->op == TOKslice && t2->ty == Tarray && + t2->nextOf()->implicitConvTo(t1->nextOf())) { e2 = e2->implicitCastTo(sc, e1->type->constOf()); } @@ -10240,11 +10304,9 @@ Expression *MulAssignExp::semantic(Scope *sc) e2->checkArithmetic(); checkComplexMulAssign(); if (e2->type->isfloating()) - { Type *t1; - Type *t2; - - t1 = e1->type; - t2 = e2->type; + { + Type *t1 = e1->type; + Type *t2 = e2->type; if (t1->isreal()) { if (t2->isimaginary() || t2->iscomplex()) @@ -10268,6 +10330,11 @@ Expression *MulAssignExp::semantic(Scope *sc) } } } + else if (type->toBasetype()->ty == Tvector && + ((TypeVector *)type->toBasetype())->elementType()->size(loc) != 2) + { // Only short[8] and ushort[8] work with multiply + return incompatibleTypes(); + } return this; } @@ -10312,10 +10379,8 @@ Expression *DivAssignExp::semantic(Scope *sc) e2->checkArithmetic(); checkComplexMulAssign(); if (e2->type->isimaginary()) - { Type *t1; - Type *t2; - - t1 = e1->type; + { + Type *t1 = e1->type; if (t1->isreal()) { // x/iv = i(-x/v) // Therefore, the result is 0 @@ -10326,7 +10391,7 @@ Expression *DivAssignExp::semantic(Scope *sc) return e; } else if (t1->isimaginary()) - { Expression *e; + { Type *t2; switch (t1->ty) { @@ -10337,11 +10402,13 @@ Expression *DivAssignExp::semantic(Scope *sc) assert(0); } e2 = e2->castTo(sc, t2); - e = new AssignExp(loc, e1, e2); + Expression *e = new AssignExp(loc, e1, e2); e->type = t1; return e; } } + else if (type->toBasetype()->ty == Tvector) + return incompatibleTypes(); return this; } @@ -10393,6 +10460,8 @@ Expression *ShlAssignExp::semantic(Scope *sc) e1->checkScalar(); e1->checkNoBool(); type = e1->type; + if (e1->type->toBasetype()->ty == Tvector || e2->type->toBasetype()->ty == Tvector) + return incompatibleTypes(); typeCombine(sc); e1->checkIntegral(); e2 = e2->checkIntegral(); @@ -10425,6 +10494,8 @@ Expression *ShrAssignExp::semantic(Scope *sc) e1->checkScalar(); e1->checkNoBool(); type = e1->type; + if (e1->type->toBasetype()->ty == Tvector || e2->type->toBasetype()->ty == Tvector) + return incompatibleTypes(); typeCombine(sc); e1->checkIntegral(); e2 = e2->checkIntegral(); @@ -10457,6 +10528,8 @@ Expression *UshrAssignExp::semantic(Scope *sc) e1->checkScalar(); e1->checkNoBool(); type = e1->type; + if (e1->type->toBasetype()->ty == Tvector || e2->type->toBasetype()->ty == Tvector) + return incompatibleTypes(); typeCombine(sc); e1->checkIntegral(); e2 = e2->checkIntegral(); @@ -10563,10 +10636,11 @@ Expression *PowAssignExp::semantic(Scope *sc) e = new CommaExp(loc, de, e); } e = e->semantic(sc); + if (e->type->toBasetype()->ty == Tvector) + return incompatibleTypes(); return e; } - incompatibleTypes(); - return new ErrorExp(); + return incompatibleTypes(); } @@ -10932,8 +11006,7 @@ Expression *MulExp::semantic(Scope *sc) else if (type->toBasetype()->ty == Tvector && ((TypeVector *)type->toBasetype())->elementType()->size(loc) != 2) { // Only short[8] and ushort[8] work with multiply - incompatibleTypes(); - return new ErrorExp(); + return incompatibleTypes(); } return this; } diff --git a/src/expression.h b/src/expression.h index e395cf254713..2ea35120ff34 100644 --- a/src/expression.h +++ b/src/expression.h @@ -1080,6 +1080,17 @@ struct CastExp : UnaExp Expression *op_overload(Scope *sc); }; +struct VectorExp : UnaExp +{ + Type *to; + unsigned dim; // number of elements in the vector + + VectorExp(Loc loc, Expression *e, Type *t); + Expression *syntaxCopy(); + Expression *semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + elem *toElem(IRState *irs); +}; struct SliceExp : UnaExp { diff --git a/src/mtype.c b/src/mtype.c index 187251d75d91..850839906e2a 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -3184,10 +3184,18 @@ MATCH TypeBasic::implicitConvTo(Type *to) return MATCHnomatch; if (to->ty == Tbool) return MATCHnomatch; - if (!to->isTypeBasic()) + + TypeBasic *tob; + if (to->ty == Tvector) + { + TypeVector *tv = (TypeVector *)to; + tob = tv->elementType(); + } + else + tob = to->isTypeBasic(); + if (!tob) return MATCHnomatch; - TypeBasic *tob = (TypeBasic *)to; if (flags & TFLAGSintegral) { // Disallow implicit conversion of integers to imaginary or complex @@ -3196,7 +3204,7 @@ MATCH TypeBasic::implicitConvTo(Type *to) #if DMDV2 // If converting from integral to integral - if (1 && tob->flags & TFLAGSintegral) + if (tob->flags & TFLAGSintegral) { d_uns64 sz = size(0); d_uns64 tosz = tob->size(0); diff --git a/src/optimize.c b/src/optimize.c index 9ced0f0be05d..e69584039d2c 100644 --- a/src/optimize.c +++ b/src/optimize.c @@ -262,6 +262,7 @@ Expression *TypeExp::optimize(int result) Expression *UnaExp::optimize(int result) { + //printf("UnaExp::optimize() %s\n", toChars()); e1 = e1->optimize(result); return this; } diff --git a/src/parse.c b/src/parse.c index dd481dfe8852..860603bfdfd8 100644 --- a/src/parse.c +++ b/src/parse.c @@ -6604,6 +6604,7 @@ void initPrecedence() precedence[TOKcast] = PREC_unary; #if DMDV2 + precedence[TOKvector] = PREC_unary; precedence[TOKpow] = PREC_pow; #endif From ad2a2785550cf3e5ca558c2800763a7879d5b733 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 14 Jan 2012 10:04:41 -0800 Subject: [PATCH 2/2] forgot return value --- src/expression.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/expression.c b/src/expression.c index 21143ae33fbe..d55aed49f72c 100644 --- a/src/expression.c +++ b/src/expression.c @@ -5840,6 +5840,7 @@ Expression *BinExp::incompatibleTypes() e1->type->toChars(), e2->type->toChars()); return new ErrorExp(); } + return this; } /********************** BinAssignExp **************************************/