Add folding for complex mul and fix some major bugs in complex float
evaluation (alternate part of real/imag init was being set to 3 not 0
because the wrong APFloat constructor was being called).
- Test cases coming once some more support is in.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63264 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index af50de6..c444a19 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1257,7 +1257,7 @@
if (!EvaluateFloat(SubExpr, Result, Info))
return APValue();
- return APValue(APFloat(Result.getSemantics(), APFloat::fcZero),
+ return APValue(APFloat(Result.getSemantics(), APFloat::fcZero, false),
Result);
} else {
assert(SubExpr->getType()->isIntegerType() &&
@@ -1283,7 +1283,7 @@
return APValue();
return APValue(Result,
- APFloat(Result.getSemantics(), APFloat::fcZero));
+ APFloat(Result.getSemantics(), APFloat::fcZero, false));
} else if (SubExpr->getType()->isIntegerType()) {
APSInt Result;
@@ -1324,6 +1324,8 @@
if (!EvaluateComplex(E->getRHS(), RHS, Info))
return APValue();
+ assert(Result.isComplexFloat() == RHS.isComplexFloat() &&
+ "Invalid operands to binary operator.");
switch (E->getOpcode()) {
default: return APValue();
case BinaryOperator::Add:
@@ -1336,6 +1338,7 @@
Result.getComplexIntReal() += RHS.getComplexIntReal();
Result.getComplexIntImag() += RHS.getComplexIntImag();
}
+ break;
case BinaryOperator::Sub:
if (Result.isComplexFloat()) {
Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(),
@@ -1346,6 +1349,38 @@
Result.getComplexIntReal() -= RHS.getComplexIntReal();
Result.getComplexIntImag() -= RHS.getComplexIntImag();
}
+ break;
+ case BinaryOperator::Mul:
+ if (Result.isComplexFloat()) {
+ APValue LHS = Result;
+ APFloat &LHS_r = LHS.getComplexFloatReal();
+ APFloat &LHS_i = LHS.getComplexFloatImag();
+ APFloat &RHS_r = RHS.getComplexFloatReal();
+ APFloat &RHS_i = RHS.getComplexFloatImag();
+
+ APFloat Tmp = LHS_r;
+ Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatReal() = Tmp;
+ Tmp = LHS_i;
+ Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatReal().subtract(Tmp, APFloat::rmNearestTiesToEven);
+
+ Tmp = LHS_r;
+ Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatImag() = Tmp;
+ Tmp = LHS_i;
+ Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatImag().add(Tmp, APFloat::rmNearestTiesToEven);
+ } else {
+ APValue LHS = Result;
+ Result.getComplexIntReal() =
+ (LHS.getComplexIntReal() * RHS.getComplexIntReal() -
+ LHS.getComplexIntImag() * RHS.getComplexIntImag());
+ Result.getComplexIntImag() =
+ (LHS.getComplexIntReal() * RHS.getComplexIntImag() +
+ LHS.getComplexIntImag() * RHS.getComplexIntReal());
+ }
+ break;
}
return Result;