forked from OSchip/llvm-project
Add support for complex compound assignments where the LHS is a scalar.
Fixes <rdar://problem/11224126> and PR12790. llvm-svn: 183821
This commit is contained in:
parent
d8cf1a119d
commit
f045007f11
|
@ -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::EmitComplexToComplexCast(ComplexPairTy Val,
|
|||
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::EmitCast(CastExpr::CastKind CK, Expr *Op,
|
|||
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 BinaryOperator *E) {
|
|||
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 CompoundAssignOperator *E,
|
|||
|
||||
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 CompoundAssignOperator *E,
|
|||
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::EmitComplexAssignmentLValue(const BinaryOperator *E) {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -1931,15 +1931,8 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
|
|||
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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue