This patch to the Go frontend and libgo defers to the middle-end for
complex division.  Go used to use slightly different semantics than
C99 for complex division, so we used runtime routines to handle the
difference.  The gc compiler has changed its behavior to match C99, so
change ours as well.  This is for https://golang.org/issue/14644.
This requires updating a test as well; the patch attached here does
not include the changes to the generated file
gcc/testsuite/go.test/test/cmplxdivide1.go, as they are large.
Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
e9a4798d3c615d1aa576ff76af429a188c6cd90f
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 183e5cae9c9..f55daf7562c 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-6b01f8cdc11d86bd98165c91d6ae101bcf6b9e1a
+5364d15082de77d2759a01f254208d4cb4f579e3
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 23caf61db93..50574c2bc58 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -6979,27 +6979,6 @@ Binary_expression::do_get_backend(Translate_context* 
context)
   // been converted to a String_concat_expression in do_lower.
   go_assert(!left_type->is_string_type());
 
-  // For complex division Go might want slightly different results than the
-  // backend implementation provides, so we have our own runtime routine.
-  if (this->op_ == OPERATOR_DIV && this->left_->type()->complex_type() != NULL)
-    {
-      Runtime::Function complex_code;
-      switch (this->left_->type()->complex_type()->bits())
-       {
-       case 64:
-          complex_code = Runtime::COMPLEX64_DIV;
-         break;
-       case 128:
-          complex_code = Runtime::COMPLEX128_DIV;
-         break;
-       default:
-         go_unreachable();
-       }
-      Expression* complex_div =
-          Runtime::make_call(complex_code, loc, 2, this->left_, this->right_);
-      return complex_div->get_backend(context);
-    }
-
   Bexpression* left = this->left_->get_backend(context);
   Bexpression* right = this->right_->get_backend(context);
 
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 9a3c6809130..4b606a6c00c 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -62,12 +62,6 @@ DEF_GO_RUNTIME(STRINGTOSLICERUNE, 
"runtime.stringtoslicerune",
               P2(POINTER, STRING), R1(SLICE))
 
 
-// Complex division.
-DEF_GO_RUNTIME(COMPLEX64_DIV, "__go_complex64_div",
-              P2(COMPLEX64, COMPLEX64), R1(COMPLEX64))
-DEF_GO_RUNTIME(COMPLEX128_DIV, "__go_complex128_div",
-              P2(COMPLEX128, COMPLEX128), R1(COMPLEX128))
-
 // Make a slice.
 DEF_GO_RUNTIME(MAKESLICE, "runtime.makeslice", P3(TYPE, INT, INT),
               R1(POINTER))
diff --git a/gcc/testsuite/go.test/test/cmplxdivide.c 
b/gcc/testsuite/go.test/test/cmplxdivide.c
index 12dc4f1c0c9..89a2868b75b 100644
--- a/gcc/testsuite/go.test/test/cmplxdivide.c
+++ b/gcc/testsuite/go.test/test/cmplxdivide.c
@@ -1,8 +1,19 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// gcc '-std=c99' cmplxdivide.c && a.out >cmplxdivide1.go
+// This C program generates the file cmplxdivide1.go. It uses the
+// output of the operations by C99 as the reference to check
+// the implementation of complex numbers in Go.
+// The generated file, cmplxdivide1.go, is compiled along
+// with the driver cmplxdivide.go (the names are confusing
+// and unimaginative) to run the actual test. This is done by
+// the usual test runner.
+//
+// The file cmplxdivide1.go is checked in to the repository, but
+// if it needs to be regenerated, compile and run this C program
+// like this:
+//     gcc '-std=c99' cmplxdivide.c && a.out >cmplxdivide1.go
 
 #include <complex.h>
 #include <math.h>
@@ -12,50 +23,63 @@
 #define nelem(x) (sizeof(x)/sizeof((x)[0]))
 
 double f[] = {
-       0,
-       1,
-       -1,
-       2,
+       0.0,
+       -0.0,
+       1.0,
+       -1.0,
+       2.0,
        NAN,
        INFINITY,
        -INFINITY,
 };
 
-char*
-fmt(double g)
-{
+char* fmt(double g) {
        static char buf[10][30];
        static int n;
        char *p;
-       
+
        p = buf[n++];
-       if(n == 10)
+       if(n == 10) {
                n = 0;
+       }
+
        sprintf(p, "%g", g);
-       if(strcmp(p, "-0") == 0)
-               strcpy(p, "negzero");
-       return p;
-}
 
-int
-iscnan(double complex d)
-{
-       return !isinf(creal(d)) && !isinf(cimag(d)) && (isnan(creal(d)) || 
isnan(cimag(d)));
-}
+       if(strcmp(p, "0") == 0) {
+               strcpy(p, "zero");
+               return p;
+       }
+
+       if(strcmp(p, "-0") == 0) {
+               strcpy(p, "-zero");
+               return p;
+       }
 
-double complex zero;   // attempt to hide zero division from gcc
+       return p;
+}
 
-int
-main(void)
-{
+int main(void) {
        int i, j, k, l;
        double complex n, d, q;
-       
+
        printf("// skip\n");
        printf("// # generated by cmplxdivide.c\n");
        printf("\n");
        printf("package main\n");
-       printf("var tests = []Test{\n");
+       printf("\n");
+       printf("import \"math\"\n");
+       printf("\n");
+       printf("var (\n");
+       printf("\tnan     = math.NaN()\n");
+       printf("\tinf     = math.Inf(1)\n");
+       printf("\tzero    = 0.0\n");
+       printf(")\n");
+       printf("\n");
+       printf("var tests = []struct {\n");
+       printf("\tf, g complex128\n");
+       printf("\tout  complex128\n");
+       printf("}{\n");
+
        for(i=0; i<nelem(f); i++)
        for(j=0; j<nelem(f); j++)
        for(k=0; k<nelem(f); k++)
@@ -63,17 +87,8 @@ main(void)
                n = f[i] + f[j]*I;
                d = f[k] + f[l]*I;
                q = n/d;
-               
-               // BUG FIX.
-               // Gcc gets the wrong answer for NaN/0 unless both sides are 
NaN.
-               // That is, it treats (NaN+NaN*I)/0 = NaN+NaN*I (a complex NaN)
-               // but it then computes (1+NaN*I)/0 = Inf+NaN*I (a complex 
infinity).
-               // Since both numerators are complex NaNs, it seems that the
-               // results should agree in kind.  Override the gcc computation 
in this case.
-               if(iscnan(n) && d == 0)
-                       q = (NAN+NAN*I) / zero;
 
-               printf("\tTest{complex(%s, %s), complex(%s, %s), complex(%s, 
%s)},\n",
+               printf("\t{complex(%s, %s), complex(%s, %s), complex(%s, 
%s)},\n",
                        fmt(creal(n)), fmt(cimag(n)),
                        fmt(creal(d)), fmt(cimag(d)),
                        fmt(creal(q)), fmt(cimag(q)));
diff --git a/gcc/testsuite/go.test/test/cmplxdivide.go 
b/gcc/testsuite/go.test/test/cmplxdivide.go
index 40c84486da0..49cd5bf5824 100644
--- a/gcc/testsuite/go.test/test/cmplxdivide.go
+++ b/gcc/testsuite/go.test/test/cmplxdivide.go
@@ -1,36 +1,29 @@
 // run cmplxdivide1.go
 
-// Copyright 2010 The Go Authors.  All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 // Driver for complex division table defined in cmplxdivide1.go
+// For details, see the comment at the top of cmplxdivide.c.
 
 package main
 
 import (
        "fmt"
        "math"
-       "math/cmplx"
 )
 
-type Test struct {
-       f, g complex128
-       out  complex128
-}
-
-var nan = math.NaN()
-var inf = math.Inf(1)
-var negzero = math.Copysign(0, -1)
-
 func calike(a, b complex128) bool {
-       switch {
-       case cmplx.IsInf(a) && cmplx.IsInf(b):
-               return true
-       case cmplx.IsNaN(a) && cmplx.IsNaN(b):
-               return true
+       if imag(a) != imag(b) && !(math.IsNaN(imag(a)) && math.IsNaN(imag(b))) {
+               return false
        }
-       return a == b
+
+       if real(a) != real(b) && !(math.IsNaN(real(a)) && math.IsNaN(real(b))) {
+               return false
+       }
+
+       return true
 }
 
 func main() {
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index f7a163e4a84..4d3e54e9225 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -439,7 +439,6 @@ runtime_files = \
        runtime/go-assert.c \
        runtime/go-caller.c \
        runtime/go-callers.c \
-       runtime/go-cdiv.c \
        runtime/go-cgo.c \
        runtime/go-construct-map.c \
        runtime/go-ffi.c \
diff --git a/libgo/runtime/go-cdiv.c b/libgo/runtime/go-cdiv.c
deleted file mode 100644
index 0355e26fc8e..00000000000
--- a/libgo/runtime/go-cdiv.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* go-cdiv.c -- complex division routines
-
-   Copyright 2013 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.  */
-
-#include <complex.h>
-#include <math.h>
-
-/* Calls to these functions are generated by the Go frontend for
-   division of complex64 or complex128.  We use these because Go's
-   complex division expects slightly different results from the GCC
-   default.  When dividing NaN+1.0i / 0+0i, Go expects NaN+NaNi but
-   GCC generates NaN+Infi.  NaN+Infi seems wrong seems the rules of
-   C99 Annex G specify that if either side of a complex number is Inf,
-   the the whole number is Inf, but an operation involving NaN ought
-   to result in NaN, not Inf.  */
-
-complex float
-__go_complex64_div (complex float a, complex float b)
-{
-  if (__builtin_expect (b == 0, 0))
-    {
-      if (!isinf (crealf (a))
-         && !isinf (cimagf (a))
-         && (isnan (crealf (a)) || isnan (cimagf (a))))
-       {
-         /* Pass "1" to nanf to match math/bits.go.  */
-         return nanf("1") + nanf("1")*I;
-       }
-    }
-  return a / b;
-}
-
-complex double
-__go_complex128_div (complex double a, complex double b)
-{
-  if (__builtin_expect (b == 0, 0))
-    {
-      if (!isinf (creal (a))
-         && !isinf (cimag (a))
-         && (isnan (creal (a)) || isnan (cimag (a))))
-       {
-         /* Pass "1" to nan to match math/bits.go.  */
-         return nan("1") + nan("1")*I;
-       }
-    }
-  return a / b;
-}

Reply via email to