r219570 - [complex] Teach the other two binary operators on complex numbers (==

Chandler Carruth chandlerc at gmail.com
Sat Oct 11 04:03:30 PDT 2014


Author: chandlerc
Date: Sat Oct 11 06:03:30 2014
New Revision: 219570

URL: http://llvm.org/viewvc/llvm-project?rev=219570&view=rev
Log:
[complex] Teach the other two binary operators on complex numbers (==
and !=) to support mixed complex and real operand types.

This requires removing an assert from SemaChecking, and adding support
both to the constant evaluator and the code generator to synthesize the
imaginary part when needed. This seemed somewhat cleaner than having
just the comparison operators force real-to-complex conversions.

I've added test cases for these operations. I'm really terrified that
there were *no* tests in-tree which exercised this.

This turned up when trying to build R after my change to the complex
type lowering.

Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/CodeGen/complex-math.c
    cfe/trunk/test/SemaCXX/complex-folding.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=219570&r1=219569&r2=219570&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sat Oct 11 06:03:30 2014
@@ -6780,15 +6780,27 @@ bool IntExprEvaluator::VisitBinaryOperat
   QualType LHSTy = E->getLHS()->getType();
   QualType RHSTy = E->getRHS()->getType();
 
-  if (LHSTy->isAnyComplexType()) {
-    assert(RHSTy->isAnyComplexType() && "Invalid comparison");
+  if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) {
     ComplexValue LHS, RHS;
-
-    bool LHSOK = EvaluateComplex(E->getLHS(), LHS, Info);
+    bool LHSOK;
+    if (E->getLHS()->getType()->isRealFloatingType()) {
+      LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info);
+      if (LHSOK) {
+        LHS.makeComplexFloat();
+        LHS.FloatImag = APFloat(LHS.FloatReal.getSemantics());
+      }
+    } else {
+      LHSOK = EvaluateComplex(E->getLHS(), LHS, Info);
+    }
     if (!LHSOK && !Info.keepEvaluatingAfterFailure())
       return false;
 
-    if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK)
+    if (E->getRHS()->getType()->isRealFloatingType()) {
+      if (!EvaluateFloat(E->getRHS(), RHS.FloatReal, Info) || !LHSOK)
+        return false;
+      RHS.makeComplexFloat();
+      RHS.FloatImag = APFloat(RHS.FloatReal.getSemantics());
+    } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK)
       return false;
 
     if (LHS.isComplexFloat()) {

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=219570&r1=219569&r2=219570&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sat Oct 11 06:03:30 2014
@@ -2754,6 +2754,7 @@ Value *ScalarExprEmitter::EmitCompare(co
   TestAndClearIgnoreResultAssign();
   Value *Result;
   QualType LHSTy = E->getLHS()->getType();
+  QualType RHSTy = E->getRHS()->getType();
   if (const MemberPointerType *MPT = LHSTy->getAs<MemberPointerType>()) {
     assert(E->getOpcode() == BO_EQ ||
            E->getOpcode() == BO_NE);
@@ -2761,7 +2762,7 @@ Value *ScalarExprEmitter::EmitCompare(co
     Value *RHS = CGF.EmitScalarExpr(E->getRHS());
     Result = CGF.CGM.getCXXABI().EmitMemberPointerComparison(
                    CGF, LHS, RHS, MPT, E->getOpcode() == BO_NE);
-  } else if (!LHSTy->isAnyComplexType()) {
+  } else if (!LHSTy->isAnyComplexType() && !RHSTy->isAnyComplexType()) {
     Value *LHS = Visit(E->getLHS());
     Value *RHS = Visit(E->getRHS());
 
@@ -2849,10 +2850,27 @@ Value *ScalarExprEmitter::EmitCompare(co
 
   } else {
     // Complex Comparison: can only be an equality comparison.
-    CodeGenFunction::ComplexPairTy LHS = CGF.EmitComplexExpr(E->getLHS());
-    CodeGenFunction::ComplexPairTy RHS = CGF.EmitComplexExpr(E->getRHS());
-
-    QualType CETy = LHSTy->getAs<ComplexType>()->getElementType();
+    CodeGenFunction::ComplexPairTy LHS, RHS;
+    QualType CETy;
+    if (auto *CTy = LHSTy->getAs<ComplexType>()) {
+      LHS = CGF.EmitComplexExpr(E->getLHS());
+      CETy = CTy->getElementType();
+    } else {
+      LHS.first = Visit(E->getLHS());
+      LHS.second = llvm::Constant::getNullValue(LHS.first->getType());
+      CETy = LHSTy;
+    }
+    if (auto *CTy = RHSTy->getAs<ComplexType>()) {
+      RHS = CGF.EmitComplexExpr(E->getRHS());
+      assert(CGF.getContext().hasSameUnqualifiedType(CETy,
+                                                     CTy->getElementType()) &&
+             "The element types must always match.");
+    } else {
+      RHS.first = Visit(E->getRHS());
+      RHS.second = llvm::Constant::getNullValue(RHS.first->getType());
+      assert(CGF.getContext().hasSameUnqualifiedType(CETy, RHSTy) &&
+             "The element types must always match.");
+    }
 
     Value *ResultR, *ResultI;
     if (CETy->isRealFloatingType()) {

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=219570&r1=219569&r2=219570&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Sat Oct 11 06:03:30 2014
@@ -5890,8 +5890,13 @@ static void AnalyzeImpConvsInComparison(
 static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
   // The type the comparison is being performed in.
   QualType T = E->getLHS()->getType();
-  assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType())
-         && "comparison with mismatched types");
+
+  // Only analyze comparison operators where both sides have been converted to
+  // the same type.
+  if (!S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType()))
+    return AnalyzeImpConvsInComparison(S, E);
+
+  // Don't analyze value-dependent comparisons directly.
   if (E->isValueDependent())
     return AnalyzeImpConvsInComparison(S, E);
 

Modified: cfe/trunk/test/CodeGen/complex-math.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/complex-math.c?rev=219570&r1=219569&r2=219570&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/complex-math.c (original)
+++ cfe/trunk/test/CodeGen/complex-math.c Sat Oct 11 06:03:30 2014
@@ -367,3 +367,54 @@ long double _Complex div_long_double_cc(
   // X86: ret
   return a / b;
 }
+
+// Comparison operators don't rely on library calls or have interseting math
+// properties, but test that mixed types work correctly here.
+_Bool eq_float_cr(float _Complex a, float b) {
+  // X86-LABEL: @eq_float_cr(
+  // X86: fcmp oeq
+  // X86: fcmp oeq
+  // X86: and i1
+  // X86: ret
+  return a == b;
+}
+_Bool eq_float_rc(float a, float _Complex b) {
+  // X86-LABEL: @eq_float_rc(
+  // X86: fcmp oeq
+  // X86: fcmp oeq
+  // X86: and i1
+  // X86: ret
+  return a == b;
+}
+_Bool eq_float_cc(float _Complex a, float _Complex b) {
+  // X86-LABEL: @eq_float_cc(
+  // X86: fcmp oeq
+  // X86: fcmp oeq
+  // X86: and i1
+  // X86: ret
+  return a == b;
+}
+_Bool ne_float_cr(float _Complex a, float b) {
+  // X86-LABEL: @ne_float_cr(
+  // X86: fcmp une
+  // X86: fcmp une
+  // X86: or i1
+  // X86: ret
+  return a != b;
+}
+_Bool ne_float_rc(float a, float _Complex b) {
+  // X86-LABEL: @ne_float_rc(
+  // X86: fcmp une
+  // X86: fcmp une
+  // X86: or i1
+  // X86: ret
+  return a != b;
+}
+_Bool ne_float_cc(float _Complex a, float _Complex b) {
+  // X86-LABEL: @ne_float_cc(
+  // X86: fcmp une
+  // X86: fcmp une
+  // X86: or i1
+  // X86: ret
+  return a != b;
+}

Modified: cfe/trunk/test/SemaCXX/complex-folding.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/complex-folding.cpp?rev=219570&r1=219569&r2=219570&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/complex-folding.cpp (original)
+++ cfe/trunk/test/SemaCXX/complex-folding.cpp Sat Oct 11 06:03:30 2014
@@ -3,6 +3,14 @@
 // Test the constant folding of builtin complex numbers.
 
 static_assert((0.0 + 0.0j) == (0.0 + 0.0j));
+static_assert((0.0 + 0.0j) != (0.0 + 0.0j)); // expected-error {{static_assert}}
+
+static_assert((0.0 + 0.0j) == 0.0);
+static_assert(0.0 == (0.0 + 0.0j));
+static_assert(0.0 == 0.0j);
+static_assert((0.0 + 1.0j) != 0.0);
+static_assert(1.0 != (0.0 + 0.0j));
+static_assert(0.0 != 1.0j);
 
 // Walk around the complex plane stepping between angular differences and
 // equality.





More information about the cfe-commits mailing list