[PATCH] [complex] Teach Clang to preserve different-type operands to arithmeticoperators where one type is a C complex type, and to emit both the efficientand correct implementation for complex arithmetic according to C11 AnnexG using this extra...

Richard Smith richard at metafoo.co.uk
Thu Oct 9 15:56:38 PDT 2014


I'd like to see some added tests for constant folding here.

================
Comment at: lib/AST/ExprConstant.cpp:7694-7697
@@ -7694,1 +7693,6 @@
+  assert(E->isRValue() && "Can only evaluate R-values!");
+  assert((E->getType()->isAnyComplexType() ||
+          E->getType()->isRealFloatingType()) &&
+         "Complex expressions can only be composed of complex and real "
+         "floating point types.");
   return ComplexExprEvaluator(Info, Result).Visit(E);
----------------
How do we reach this case? The below handling for real operands calls `EvaluateFloat` rather than `EvaluateComplex`.

================
Comment at: lib/AST/ExprConstant.cpp:7883
@@ +7882,3 @@
+  // the case we can simplify our evaluation strategy.
+  bool LHSReal = false, RHSReal = false;
+
----------------
You should assign `true` to these somewhere =)

================
Comment at: lib/AST/ExprConstant.cpp:7909
@@ -7884,3 +7908,3 @@
 
   assert(Result.isComplexFloat() == RHS.isComplexFloat() &&
          "Invalid operands to binary operator.");
----------------
Maybe `assert(!(LHSReal && RHSReal));` here?

================
Comment at: lib/AST/ExprConstant.cpp:7933
@@ +7932,3 @@
+        Result.getComplexFloatImag() = RHS.getComplexFloatImag();
+        Result.getComplexFloatImag().changeSign();
+      } else if (!RHSReal) {
----------------
Is `changeSign` right here? Should `0 - (0+0i)` be `0+0i` or `0-0i`?

================
Comment at: lib/AST/ExprConstant.cpp:8013-8014
@@ -7967,2 +8012,4 @@
+      if (!RHSReal) {
       Tmp = LHS_r;
       Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
+      }
----------------
Indentation looks off here. Maybe it's just Phab?

================
Comment at: lib/AST/ExprConstant.cpp:8023
@@ +8022,3 @@
+        assert(!RHSReal && "Cannot have both operands be real!");
+        Tmp.changeSign();
+        Res_i = Tmp;
----------------
Does this do the right thing with negative zeros? Eg, `1 / (1 + 0i)` will give `1-0i` but should presumably be `1+0i`.

================
Comment at: lib/CodeGen/CGExprComplex.cpp:556-557
@@ +555,4 @@
+    else
+      ResI = Op.LHS.second ? Op.LHS.second
+                           : Builder.CreateFNeg(Op.RHS.second, "sub.i");
+    assert(ResI && "Only one operand may be real!");
----------------
Same question as before regarding negative zeros.

================
Comment at: lib/CodeGen/CGExprComplex.cpp:593
@@ +592,3 @@
+  } else {
+    assert(Result->getType()->isAggregateType() && "Only vector and aggregate libcall returns are supported!");
+    unsigned ResRIndices[] = {0};
----------------
My 80-col sense is tingling.

================
Comment at: lib/CodeGen/CGExprComplex.cpp:618-619
@@ +617,4 @@
+    if (Op.LHS.second && Op.RHS.second) {
+      // If both operands are complex, delegate to a libcall which works to
+      // prevent underflow and overflow.
+      StringRef LibCallName;
----------------
Do we need to do anything about underflow/overflow in the constant evaluator?

http://reviews.llvm.org/D5698






More information about the cfe-commits mailing list