changeset 617:634fbbdec390

Simplify complex number handling. Fixes bug with complex substraction.
author Christian Kamm <kamm incasoftware de>
date Mon, 22 Sep 2008 20:29:18 +0200
parents 5ced42a55aa9
children c9aa338280ed 718ddecc053c
files gen/complex.cpp gen/complex.h
diffstat 2 files changed, 105 insertions(+), 129 deletions(-) [+]
line wrap: on
line diff
--- 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()) {
--- 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);