r183821 - Add support for complex compound assignments where the LHS is a scalar.
Eli Friedman
eli.friedman at gmail.com
Tue Jun 11 18:40:06 PDT 2013
Author: efriedma
Date: Tue Jun 11 20:40:06 2013
New Revision: 183821
URL: http://llvm.org/viewvc/llvm-project?rev=183821&view=rev
Log:
Add support for complex compound assignments where the LHS is a scalar.
Fixes <rdar://problem/11224126> and PR12790.
Modified:
cfe/trunk/lib/CodeGen/CGExprComplex.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/test/CodeGen/complex.c
cfe/trunk/test/CodeGen/volatile-1.c
Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=183821&r1=183820&r2=183821&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Tue Jun 11 20:40:06 2013
@@ -81,6 +81,9 @@ public:
/// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
QualType DestType);
+ /// EmitComplexToComplexCast - Emit a cast from scalar value Val to DestType.
+ ComplexPairTy EmitScalarToComplexCast(llvm::Value *Val, QualType SrcType,
+ QualType DestType);
//===--------------------------------------------------------------------===//
// Visitor Methods
@@ -215,7 +218,7 @@ public:
LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)
(const BinOpInfo &),
- ComplexPairTy &Val);
+ RValue &Val);
ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)
(const BinOpInfo &));
@@ -379,6 +382,17 @@ ComplexPairTy ComplexExprEmitter::EmitCo
return Val;
}
+ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val,
+ QualType SrcType,
+ QualType DestType) {
+ // Convert the input element to the element type of the complex.
+ DestType = DestType->castAs<ComplexType>()->getElementType();
+ Val = CGF.EmitScalarConversion(Val, SrcType, DestType);
+
+ // Return (realval, 0).
+ return ComplexPairTy(Val, llvm::Constant::getNullValue(Val->getType()));
+}
+
ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op,
QualType DestTy) {
switch (CK) {
@@ -446,16 +460,9 @@ ComplexPairTy ComplexExprEmitter::EmitCa
llvm_unreachable("invalid cast kind for complex value");
case CK_FloatingRealToComplex:
- case CK_IntegralRealToComplex: {
- llvm::Value *Elt = CGF.EmitScalarExpr(Op);
-
- // Convert the input element to the element type of the complex.
- DestTy = DestTy->castAs<ComplexType>()->getElementType();
- Elt = CGF.EmitScalarConversion(Elt, Op->getType(), DestTy);
-
- // Return (realval, 0).
- return ComplexPairTy(Elt, llvm::Constant::getNullValue(Elt->getType()));
- }
+ case CK_IntegralRealToComplex:
+ return EmitScalarToComplexCast(CGF.EmitScalarExpr(Op),
+ Op->getType(), DestTy);
case CK_FloatingComplexCast:
case CK_FloatingComplexToIntegralComplex:
@@ -610,7 +617,7 @@ ComplexExprEmitter::EmitBinOps(const Bin
LValue ComplexExprEmitter::
EmitCompoundAssignLValue(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
- ComplexPairTy &Val) {
+ RValue &Val) {
TestAndClearIgnoreReal();
TestAndClearIgnoreImag();
QualType LHSTy = E->getLHS()->getType();
@@ -630,20 +637,29 @@ EmitCompoundAssignLValue(const CompoundA
LValue LHS = CGF.EmitLValue(E->getLHS());
- // Load from the l-value.
- ComplexPairTy LHSComplexPair = EmitLoadOfLValue(LHS);
-
- OpInfo.LHS = EmitComplexToComplexCast(LHSComplexPair, LHSTy, OpInfo.Ty);
+ // Load from the l-value and convert it.
+ if (LHSTy->isAnyComplexType()) {
+ ComplexPairTy LHSVal = EmitLoadOfLValue(LHS);
+ OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty);
+ } else {
+ llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS);
+ OpInfo.LHS = EmitScalarToComplexCast(LHSVal, LHSTy, OpInfo.Ty);
+ }
// Expand the binary operator.
ComplexPairTy Result = (this->*Func)(OpInfo);
- // Truncate the result back to the LHS type.
- Result = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
- Val = Result;
-
- // Store the result value into the LHS lvalue.
- EmitStoreOfComplex(Result, LHS, /*isInit*/ false);
+ // Truncate the result and store it into the LHS lvalue.
+ if (LHSTy->isAnyComplexType()) {
+ ComplexPairTy ResVal = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
+ EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false);
+ Val = RValue::getComplex(ResVal);
+ } else {
+ llvm::Value *ResVal =
+ CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy);
+ CGF.EmitStoreOfScalar(ResVal, LHS, /*isInit*/ false);
+ Val = RValue::get(ResVal);
+ }
return LHS;
}
@@ -652,16 +668,16 @@ EmitCompoundAssignLValue(const CompoundA
ComplexPairTy ComplexExprEmitter::
EmitCompoundAssign(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
- ComplexPairTy Val;
+ RValue Val;
LValue LV = EmitCompoundAssignLValue(E, Func, Val);
// The result of an assignment in C is the assigned r-value.
if (!CGF.getLangOpts().CPlusPlus)
- return Val;
+ return Val.getComplexVal();
// If the lvalue is non-volatile, return the computed value of the assignment.
if (!LV.isVolatileQualified())
- return Val;
+ return Val.getComplexVal();
return EmitLoadOfLValue(LV);
}
@@ -832,19 +848,33 @@ LValue CodeGenFunction::EmitComplexAssig
return ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val);
}
-LValue CodeGenFunction::
-EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
- ComplexPairTy(ComplexExprEmitter::*Op)(const ComplexExprEmitter::BinOpInfo &);
- switch (E->getOpcode()) {
- case BO_MulAssign: Op = &ComplexExprEmitter::EmitBinMul; break;
- case BO_DivAssign: Op = &ComplexExprEmitter::EmitBinDiv; break;
- case BO_SubAssign: Op = &ComplexExprEmitter::EmitBinSub; break;
- case BO_AddAssign: Op = &ComplexExprEmitter::EmitBinAdd; break;
+typedef ComplexPairTy (ComplexExprEmitter::*CompoundFunc)(
+ const ComplexExprEmitter::BinOpInfo &);
+static CompoundFunc getComplexOp(BinaryOperatorKind Op) {
+ switch (Op) {
+ case BO_MulAssign: return &ComplexExprEmitter::EmitBinMul;
+ case BO_DivAssign: return &ComplexExprEmitter::EmitBinDiv;
+ case BO_SubAssign: return &ComplexExprEmitter::EmitBinSub;
+ case BO_AddAssign: return &ComplexExprEmitter::EmitBinAdd;
default:
llvm_unreachable("unexpected complex compound assignment");
}
+}
- ComplexPairTy Val; // ignored
+LValue CodeGenFunction::
+EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
+ CompoundFunc Op = getComplexOp(E->getOpcode());
+ RValue Val;
return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
}
+
+LValue CodeGenFunction::
+EmitScalarCompooundAssignWithComplex(const CompoundAssignOperator *E,
+ llvm::Value *&Result) {
+ CompoundFunc Op = getComplexOp(E->getOpcode());
+ RValue Val;
+ LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
+ Result = Val.getScalarVal();
+ return Ret;
+}
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=183821&r1=183820&r2=183821&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Jun 11 20:40:06 2013
@@ -1931,15 +1931,8 @@ LValue ScalarExprEmitter::EmitCompoundAs
QualType LHSTy = E->getLHS()->getType();
BinOpInfo OpInfo;
- if (E->getComputationResultType()->isAnyComplexType()) {
- // This needs to go through the complex expression emitter, but it's a tad
- // complicated to do that... I'm leaving it out for now. (Note that we do
- // actually need the imaginary part of the RHS for multiplication and
- // division.)
- CGF.ErrorUnsupported(E, "complex compound assignment");
- Result = llvm::UndefValue::get(CGF.ConvertType(E->getType()));
- return LValue();
- }
+ if (E->getComputationResultType()->isAnyComplexType())
+ return CGF.EmitScalarCompooundAssignWithComplex(E, Result);
// Emit the RHS first. __block variables need to have the rhs evaluated
// first, plus this should improve codegen a little.
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=183821&r1=183820&r2=183821&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Jun 11 20:40:06 2013
@@ -1928,6 +1928,8 @@ public:
/// Emit an l-value for an assignment (simple or compound) of complex type.
LValue EmitComplexAssignmentLValue(const BinaryOperator *E);
LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E);
+ LValue EmitScalarCompooundAssignWithComplex(const CompoundAssignOperator *E,
+ llvm::Value *&Result);
// Note: only available for agg return types
LValue EmitBinaryOperatorLValue(const BinaryOperator *E);
Modified: cfe/trunk/test/CodeGen/complex.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/complex.c?rev=183821&r1=183820&r2=183821&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/complex.c (original)
+++ cfe/trunk/test/CodeGen/complex.c Tue Jun 11 20:40:06 2013
@@ -32,8 +32,7 @@ void test3() {
double Gr = __real g1;
cf += D;
- // FIXME: Currently unsupported!
- //D += cf;
+ D += cf;
cf /= g1;
g1 = g1 + D;
g1 = D + g1;
@@ -51,8 +50,7 @@ void test3int() {
i = __real ci1;
cs += i;
- // FIXME: Currently unsupported!
- //D += cf;
+ D += cf;
cs /= ci1;
ci1 = ci1 + i;
ci1 = i + ci1;
Modified: cfe/trunk/test/CodeGen/volatile-1.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/volatile-1.c?rev=183821&r1=183820&r2=183821&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/volatile-1.c (original)
+++ cfe/trunk/test/CodeGen/volatile-1.c Tue Jun 11 20:40:06 2013
@@ -313,3 +313,15 @@ void test1() {
(void) x;
return x;
}
+
+// CHECK: define i32 @test2()
+int test2() {
+ // CHECK: load volatile i32*
+ // CHECK-NEXT: load volatile i32*
+ // CHECK-NEXT: load volatile i32*
+ // CHECK-NEXT: add i32
+ // CHECK-NEXT: add i32
+ // CHECK-NEXT: store volatile i32
+ // CHECK-NEXT: ret i32
+ return i += ci;
+}
More information about the cfe-commits
mailing list