# HG changeset patch # User Christian Kamm # Date 1222108158 -7200 # Node ID 634fbbdec390628b132c852035d09aea5e2e28f2 # Parent 5ced42a55aa907f1944fcf24b0f2cc3b328e7909 Simplify complex number handling. Fixes bug with complex substraction. diff -r 5ced42a55aa9 -r 634fbbdec390 gen/complex.cpp --- a/gen/complex.cpp Sun Sep 21 19:28:57 2008 +0200 +++ b/gen/complex.cpp Mon Sep 22 20:29:18 2008 +0200 @@ -88,12 +88,50 @@ DValue* DtoComplex(Loc& loc, Type* to, DValue* val) { - Type* t = val->getType()->toBasetype(); + const LLType* complexTy = DtoType(to); - if (t->iscomplex()) { - return DtoCastComplex(loc, val, to); + Type* baserety; + Type* baseimty; + TY ty = to->ty; + if (ty == Tcomplex32) { + baserety = Type::tfloat32; + baseimty = Type::timaginary32; + } else if (ty == Tcomplex64) { + baserety = Type::tfloat64; + baseimty = Type::timaginary64; + } else if (ty == Tcomplex80) { + baserety = Type::tfloat80; + baseimty = Type::timaginary80; + } + else { + assert(0); } + LLValue *re, *im; + DtoGetComplexParts(loc, to, val, re, im); + + if(!re) + re = LLConstant::getNullValue(DtoType(baserety)); + if(!im) + im = LLConstant::getNullValue(DtoType(baseimty)); + + LLValue* res = DtoAggrPair(complexTy, re, im); + + return new DImValue(to, res); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im) +{ + DtoStore(re, DtoGEPi(c,0,0,"tmp")); + DtoStore(im, DtoGEPi(c,0,1,"tmp")); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoGetComplexParts(Loc& loc, Type* to, DValue* val, LLValue*& re, LLValue*& im) +{ const LLType* base = DtoComplexBaseType(to); Type* baserety; @@ -113,103 +151,57 @@ assert(0); } - const LLType* complexTy = DtoType(to); - LLValue* res; + Type* t = val->getType()->toBasetype(); - if (t->isimaginary()) { - res = DtoAggrPair(complexTy, LLConstant::getNullValue(DtoType(baserety)), DtoCastFloat(loc, val, baseimty)->getRVal()); + if (t->iscomplex()) { + DValue* v = DtoCastComplex(loc, val, to); + if (to->iscomplex()) { + re = gIR->ir->CreateExtractValue(v->getRVal(), 0, ".re_part"); + im = gIR->ir->CreateExtractValue(v->getRVal(), 1, ".im_part"); + } else + DtoGetComplexParts(loc, to, v, re, im); + } + else if (t->isimaginary()) { + re = NULL; + im = DtoCastFloat(loc, val, baseimty)->getRVal(); } else if (t->isfloating()) { - res = DtoAggrPair(complexTy, DtoCastFloat(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty))); + re = DtoCastFloat(loc, val, baserety)->getRVal(); + im = NULL; } else if (t->isintegral()) { - res = DtoAggrPair(complexTy, DtoCastInt(loc, val, baserety)->getRVal(), LLConstant::getNullValue(DtoType(baseimty))); + re = DtoCastInt(loc, val, baserety)->getRVal(); + im = NULL; } else { assert(0); } - return new DImValue(to, res); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im) -{ - DtoStore(re, DtoGEPi(c,0,0,"tmp")); - DtoStore(im, DtoGEPi(c,0,1,"tmp")); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im) -{ - LLValue* v = c->getRVal(); - Logger::cout() << "extracting real and imaginary parts from: " << *v << '\n'; - re = gIR->ir->CreateExtractValue(v, 0, ".re_part"); - im = gIR->ir->CreateExtractValue(v, 1, ".im_part"); -} - -DValue* resolveLR(DValue* val, bool getlval) -{ - if (DLRValue* lr = val->isLRValue()) { - if (getlval) - return lr->lvalue; - else - return lr->rvalue; - } - return val; -} - -////////////////////////////////////////////////////////////////////////////////////////// - -bool hasRe(Type* t) -{ - return - (t->ty != Timaginary32 && - t->ty != Timaginary64 && - t->ty != Timaginary80); -} - -bool hasIm(Type* t) -{ - return - (t->ty == Timaginary32 || - t->ty == Timaginary64 || - t->ty == Timaginary80 || - t->ty == Tcomplex32 || - t->ty == Tcomplex64 || - t->ty == Tcomplex80); } ////////////////////////////////////////////////////////////////////////////////////////// DValue* DtoComplexAdd(Loc& loc, Type* type, DValue* lhs, DValue* rhs) { - DValue* clhs = DtoComplex(loc, type, resolveLR(lhs, true)); - DValue* crhs = DtoComplex(loc, type, resolveLR(rhs, false)); - llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im; // lhs values - DtoGetComplexParts(clhs, lhs_re, lhs_im); + DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im); // rhs values - DtoGetComplexParts(crhs, rhs_re, rhs_im); + DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im); // add up - Type* lhstype = lhs->getType(); - Type* rhstype = rhs->getType(); - if(hasRe(lhstype) && hasRe(rhstype)) + if(lhs_re && rhs_re) res_re = gIR->ir->CreateAdd(lhs_re, rhs_re, "tmp"); - else if(hasRe(lhstype)) + else if(lhs_re) res_re = lhs_re; - else // either hasRe(rhstype) or no re at all (then use any) + else // either rhs_re or no re at all (then use any) res_re = rhs_re; - if(hasIm(lhstype) && hasIm(rhstype)) + if(lhs_im && rhs_im) res_im = gIR->ir->CreateAdd(lhs_im, rhs_im, "tmp"); - else if(hasIm(lhstype)) + else if(lhs_im) res_im = lhs_im; - else // either hasIm(rhstype) or no im at all (then use any) + else // either rhs_im or no im at all (then use any) res_im = rhs_im; LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im); @@ -220,28 +212,27 @@ DValue* DtoComplexSub(Loc& loc, Type* type, DValue* lhs, DValue* rhs) { - DValue* clhs = DtoComplex(loc, type, resolveLR(lhs, true)); - DValue* crhs = DtoComplex(loc, type, resolveLR(rhs, false)); - llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im; // lhs values - DtoGetComplexParts(clhs, lhs_re, lhs_im); + DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im); // rhs values - DtoGetComplexParts(crhs, rhs_re, rhs_im); + DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im); - // sub up - Type* lhstype = lhs->getType(); - Type* rhstype = rhs->getType(); - if(hasRe(rhstype)) + // add up + if(lhs_re && rhs_re) res_re = gIR->ir->CreateSub(lhs_re, rhs_re, "tmp"); - else + else if(lhs_re) res_re = lhs_re; + else // either rhs_re or no re at all (then use any) + res_re = gIR->ir->CreateNeg(rhs_re, "neg"); - if(hasIm(rhstype)) + if(lhs_im && rhs_im) res_im = gIR->ir->CreateSub(lhs_im, rhs_im, "tmp"); - else + else if(lhs_im) res_im = lhs_im; + else // either rhs_im or no im at all (then use any) + res_im = gIR->ir->CreateNeg(rhs_im, "neg"); LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im); return new DImValue(type, res); @@ -251,31 +242,26 @@ DValue* DtoComplexMul(Loc& loc, Type* type, DValue* lhs, DValue* rhs) { - DValue* clhs = DtoComplex(loc, type, resolveLR(lhs, true)); - DValue* crhs = DtoComplex(loc, type, resolveLR(rhs, false)); - llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im; // lhs values - DtoGetComplexParts(clhs, lhs_re, lhs_im); + DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im); // rhs values - DtoGetComplexParts(crhs, rhs_re, rhs_im); + DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im); // mul up llvm::Value *rere = NULL; llvm::Value *reim = NULL; llvm::Value *imre = NULL; llvm::Value *imim = NULL; - Type* lhstype = lhs->getType(); - Type* rhstype = rhs->getType(); - if(hasRe(lhstype) && hasRe(rhstype)) + if(lhs_re && rhs_re) rere = gIR->ir->CreateMul(lhs_re, rhs_re, "rere_mul"); - if(hasRe(lhstype) && hasIm(rhstype)) + if(lhs_re && rhs_im) reim = gIR->ir->CreateMul(lhs_re, rhs_im, "reim_mul"); - if(hasIm(lhstype) && hasRe(rhstype)) + if(lhs_im && rhs_re) imre = gIR->ir->CreateMul(lhs_im, rhs_re, "imre_mul"); - if(hasIm(lhstype) && hasIm(rhstype)) + if(lhs_im && rhs_im) imim = gIR->ir->CreateMul(lhs_im, rhs_im, "imim_mul"); if(rere && imim) @@ -285,7 +271,7 @@ else if(imim) res_re = gIR->ir->CreateNeg(imim, "imim_neg"); else - res_re = hasRe(lhstype) ? rhs_re : lhs_re; // null! + res_re = lhs_re ? rhs_re : lhs_re; // null! if(reim && imre) res_im = gIR->ir->CreateAdd(reim, imre, "reim_imre_add"); @@ -294,7 +280,7 @@ else if(imre) res_im = imre; else - res_im = hasRe(lhstype) ? rhs_im : lhs_re; // null! + res_im = lhs_re ? rhs_im : lhs_re; // null! LLValue* res = DtoAggrPair(DtoType(type), res_re, res_im); return new DImValue(type, res); @@ -304,37 +290,31 @@ DValue* DtoComplexDiv(Loc& loc, Type* type, DValue* lhs, DValue* rhs) { - DValue* clhs = DtoComplex(loc, type, resolveLR(lhs, true)); - DValue* crhs = DtoComplex(loc, type, resolveLR(rhs, false)); - llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im; // lhs values - DtoGetComplexParts(clhs, lhs_re, lhs_im); + DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im); // rhs values - DtoGetComplexParts(crhs, rhs_re, rhs_im); - - Type* lhstype = lhs->getType(); - Type* rhstype = rhs->getType(); + DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im); // if divisor is only real, division is simple - if(hasRe(rhstype) && !hasIm(rhstype)) { - if(hasRe(lhstype)) + if(rhs_re && !rhs_im) { + if(lhs_re) res_re = gIR->ir->CreateFDiv(lhs_re, rhs_re, "re_divby_re"); else res_re = lhs_re; - if(hasIm(lhstype)) + if(lhs_im) res_im = gIR->ir->CreateFDiv(lhs_im, rhs_re, "im_divby_re"); else res_im = lhs_im; } // if divisor is only imaginary, division is simple too - else if(!hasRe(rhstype) && hasIm(rhstype)) { - if(hasRe(lhstype)) + else if(!rhs_re && rhs_im) { + if(lhs_re) res_im = gIR->ir->CreateNeg(gIR->ir->CreateFDiv(lhs_re, rhs_im, "re_divby_im"), "neg"); else res_im = lhs_re; - if(hasIm(lhstype)) + if(lhs_im) res_re = gIR->ir->CreateFDiv(lhs_im, rhs_im, "im_divby_im"); else res_re = lhs_im; @@ -343,7 +323,7 @@ else { llvm::Value *tmp1, *tmp2, *denom; - if(hasRe(lhstype) && hasIm(lhstype)) { + if(lhs_re && lhs_im) { tmp1 = gIR->ir->CreateMul(lhs_re, rhs_re, "rere"); tmp2 = gIR->ir->CreateMul(lhs_im, rhs_im, "imim"); res_re = gIR->ir->CreateAdd(tmp1, tmp2, "rere_plus_imim"); @@ -352,13 +332,13 @@ tmp2 = gIR->ir->CreateMul(lhs_im, rhs_re, "imre"); res_im = gIR->ir->CreateSub(tmp2, tmp1, "imre_sub_reim"); } - else if(hasRe(lhstype)) { + else if(lhs_re) { res_re = gIR->ir->CreateMul(lhs_re, rhs_re, "rere"); res_im = gIR->ir->CreateMul(lhs_re, rhs_im, "reim"); res_im = gIR->ir->CreateNeg(res_im); } - else if(hasIm(lhstype)) { + else if(lhs_im) { res_re = gIR->ir->CreateMul(lhs_im, rhs_im, "imim"); res_im = gIR->ir->CreateMul(lhs_im, rhs_re, "imre"); } @@ -381,14 +361,13 @@ DValue* DtoComplexNeg(Loc& loc, Type* type, DValue* val) { - val = DtoComplex(loc, type, resolveLR(val, false)); - llvm::Value *a, *b, *re, *im; // values - DtoGetComplexParts(val, a, b); + DtoGetComplexParts(loc, type, val, a, b); - // sub up + // neg up + assert(a && b); re = gIR->ir->CreateNeg(a, "tmp"); im = gIR->ir->CreateNeg(b, "tmp"); @@ -402,15 +381,12 @@ { Type* type = lhs->getType(); - lhs = DtoComplex(loc, type, resolveLR(lhs, false)); - rhs = DtoComplex(loc, type, resolveLR(rhs, false)); - - llvm::Value *a, *b, *c, *d; + llvm::Value *lhs_re, *lhs_im, *rhs_re, *rhs_im, *res_re, *res_im; // lhs values - DtoGetComplexParts(lhs, a, b); + DtoGetComplexParts(loc, type, lhs, lhs_re, lhs_im); // rhs values - DtoGetComplexParts(rhs, c, d); + DtoGetComplexParts(loc, type, rhs, rhs_re, rhs_im); // select predicate llvm::FCmpInst::Predicate cmpop; @@ -420,8 +396,8 @@ cmpop = llvm::FCmpInst::FCMP_UNE; // (l.re==r.re && l.im==r.im) or (l.re!=r.re || l.im!=r.im) - LLValue* b1 = new llvm::FCmpInst(cmpop, a, c, "tmp", gIR->scopebb()); - LLValue* b2 = new llvm::FCmpInst(cmpop, b, d, "tmp", gIR->scopebb()); + LLValue* b1 = new llvm::FCmpInst(cmpop, lhs_re, rhs_re, "tmp", gIR->scopebb()); + LLValue* b2 = new llvm::FCmpInst(cmpop, lhs_im, rhs_im, "tmp", gIR->scopebb()); if (op == TOKequal) return gIR->ir->CreateAnd(b1,b2,"tmp"); @@ -440,7 +416,7 @@ return val; llvm::Value *re, *im; - DtoGetComplexParts(val, re, im); + DtoGetComplexParts(loc, val->getType(), val, re, im); const LLType* toty = DtoComplexBaseType(to); if (to->size() < vty->size()) { diff -r 5ced42a55aa9 -r 634fbbdec390 gen/complex.h --- a/gen/complex.h Sun Sep 21 19:28:57 2008 +0200 +++ b/gen/complex.h Mon Sep 22 20:29:18 2008 +0200 @@ -14,7 +14,7 @@ void DtoComplexSet(LLValue* c, LLValue* re, LLValue* im); -void DtoGetComplexParts(DValue* c, LLValue*& re, LLValue*& im); +void DtoGetComplexParts(Loc& loc, Type* to, DValue* c, LLValue*& re, LLValue*& im); DValue* DtoComplexAdd(Loc& loc, Type* type, DValue* lhs, DValue* rhs); DValue* DtoComplexSub(Loc& loc, Type* type, DValue* lhs, DValue* rhs);