Skip to content

Commit d140109

Browse files
Lancernlanza
authored andcommitted
[CIR][CIRGen] Complex unary increment and decrement operator (#790)
This PR adds CIRGen and LLVMIR lowering for unary increment and decrement expressions of complex types. Currently blocked by #789 .
1 parent a1b7883 commit d140109

File tree

5 files changed

+183
-8
lines changed

5 files changed

+183
-8
lines changed

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1321,7 +1321,7 @@ LValue CIRGenFunction::buildUnaryOpLValue(const UnaryOperator *E) {
13211321
LValue LV = buildLValue(E->getSubExpr());
13221322

13231323
if (E->getType()->isAnyComplexType()) {
1324-
assert(0 && "not implemented");
1324+
buildComplexPrePostIncDec(E, LV, isInc, true /*isPre*/);
13251325
} else {
13261326
buildScalarPrePostIncDec(E, LV, isInc, isPre);
13271327
}

clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,7 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
134134

135135
// Operators.
136136
mlir::Value VisitPrePostIncDec(const UnaryOperator *E, bool isInc,
137-
bool isPre) {
138-
llvm_unreachable("NYI");
139-
}
137+
bool isPre);
140138
mlir::Value VisitUnaryPostDec(const UnaryOperator *E) {
141139
return VisitPrePostIncDec(E, false, false);
142140
}
@@ -524,6 +522,12 @@ mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
524522
return CGF.buildCallExpr(E).getComplexVal();
525523
}
526524

525+
mlir::Value ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
526+
bool isInc, bool isPre) {
527+
LValue LV = CGF.buildLValue(E->getSubExpr());
528+
return CGF.buildComplexPrePostIncDec(E, LV, isInc, isPre);
529+
}
530+
527531
mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *E,
528532
QualType PromotionType) {
529533
QualType promotionTy = PromotionType.isNull()
@@ -956,3 +960,27 @@ LValue CIRGenFunction::buildComplexCompoundAssignmentLValue(
956960
RValue Val;
957961
return ComplexExprEmitter(*this).buildCompoundAssignLValue(E, Op, Val);
958962
}
963+
964+
mlir::Value CIRGenFunction::buildComplexPrePostIncDec(const UnaryOperator *E,
965+
LValue LV, bool isInc,
966+
bool isPre) {
967+
mlir::Value InVal = buildLoadOfComplex(LV, E->getExprLoc());
968+
969+
auto Loc = getLoc(E->getExprLoc());
970+
auto OpKind =
971+
isInc ? mlir::cir::UnaryOpKind::Inc : mlir::cir::UnaryOpKind::Dec;
972+
mlir::Value IncVal = builder.createUnaryOp(Loc, OpKind, InVal);
973+
974+
// Store the updated result through the lvalue.
975+
buildStoreOfComplex(Loc, IncVal, LV, /*init*/ false);
976+
if (getLangOpts().OpenMP)
977+
llvm_unreachable("NYI");
978+
979+
// If this is a postinc, return the value read from memory, otherwise use the
980+
// updated value.
981+
return isPre ? IncVal : InVal;
982+
}
983+
984+
mlir::Value CIRGenFunction::buildLoadOfComplex(LValue src, SourceLocation loc) {
985+
return ComplexExprEmitter(*this).buildLoadOfLValue(src, loc);
986+
}

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,8 @@ class CIRGenFunction : public CIRGenTypeCache {
666666

667667
mlir::Value buildScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
668668
bool isInc, bool isPre);
669+
mlir::Value buildComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
670+
bool isInc, bool isPre);
669671

670672
// Wrapper for function prototype sources. Wraps either a FunctionProtoType or
671673
// an ObjCMethodDecl.
@@ -799,6 +801,9 @@ class CIRGenFunction : public CIRGenTypeCache {
799801
mlir::Value buildLoadOfScalar(LValue lvalue, clang::SourceLocation Loc);
800802
mlir::Value buildLoadOfScalar(LValue lvalue, mlir::Location Loc);
801803

804+
/// Load a complex number from the specified l-value.
805+
mlir::Value buildLoadOfComplex(LValue src, SourceLocation loc);
806+
802807
Address buildLoadOfReference(LValue RefLVal, mlir::Location Loc,
803808
LValueBaseInfo *PointeeBaseInfo = nullptr);
804809
LValue buildLoadOfReferenceLValue(LValue RefLVal, mlir::Location Loc);

clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,6 @@ void LoweringPreparePass::lowerUnaryOp(UnaryOp op) {
356356

357357
auto loc = op.getLoc();
358358
auto opKind = op.getKind();
359-
assert((opKind == mlir::cir::UnaryOpKind::Plus ||
360-
opKind == mlir::cir::UnaryOpKind::Minus ||
361-
opKind == mlir::cir::UnaryOpKind::Not) &&
362-
"invalid unary op kind on complex numbers");
363359

364360
CIRBaseBuilderTy builder(getContext());
365361
builder.setInsertionPointAfter(op);
@@ -372,6 +368,12 @@ void LoweringPreparePass::lowerUnaryOp(UnaryOp op) {
372368
mlir::Value resultReal;
373369
mlir::Value resultImag;
374370
switch (opKind) {
371+
case mlir::cir::UnaryOpKind::Inc:
372+
case mlir::cir::UnaryOpKind::Dec:
373+
resultReal = builder.createUnaryOp(loc, opKind, operandReal);
374+
resultImag = operandImag;
375+
break;
376+
375377
case mlir::cir::UnaryOpKind::Plus:
376378
case mlir::cir::UnaryOpKind::Minus:
377379
resultReal = builder.createUnaryOp(loc, opKind, operandReal);

clang/test/CIR/CodeGen/complex-arithmetic.c

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,3 +776,143 @@ void builtin_conj() {
776776
// LLVM-NEXT: %{{.+}} = insertvalue { double, double } %[[#A]], double %[[#RESI]], 1
777777

778778
// CHECK: }
779+
780+
void pre_increment() {
781+
++cd1;
782+
++ci1;
783+
}
784+
785+
// CLANG: @pre_increment
786+
// CPPLANG: @_Z13pre_incrementv
787+
788+
// CIRGEN: %{{.+}} = cir.unary(inc, %{{.+}}) : !cir.complex<!cir.double>, !cir.complex<!cir.double>
789+
// CIRGEN: %{{.+}} = cir.unary(inc, %{{.+}}) : !cir.complex<!s32i>, !cir.complex<!s32i>
790+
791+
// CIR: %[[#R:]] = cir.complex.real %{{.+}} : !cir.complex<!cir.double> -> !cir.double
792+
// CIR-NEXT: %[[#I:]] = cir.complex.imag %{{.+}} : !cir.complex<!cir.double> -> !cir.double
793+
// CIR-NEXT: %[[#IR:]] = cir.unary(inc, %[[#R]]) : !cir.double, !cir.double
794+
// CIR-NEXT: %{{.+}} = cir.complex.create %[[#IR]], %[[#I]] : !cir.double -> !cir.complex<!cir.double>
795+
796+
// CIR: %[[#R:]] = cir.complex.real %{{.+}} : !cir.complex<!s32i> -> !s32i
797+
// CIR-NEXT: %[[#I:]] = cir.complex.imag %{{.+}} : !cir.complex<!s32i> -> !s32i
798+
// CIR-NEXT: %[[#IR:]] = cir.unary(inc, %[[#R]]) : !s32i, !s32i
799+
// CIR-NEXT: %{{.+}} = cir.complex.create %[[#IR]], %[[#I]] : !s32i -> !cir.complex<!s32i>
800+
801+
// LLVM: %[[#R:]] = extractvalue { double, double } %{{.+}}, 0
802+
// LLVM-NEXT: %[[#I:]] = extractvalue { double, double } %{{.+}}, 1
803+
// LLVM-NEXT: %[[#IR:]] = fadd double 1.000000e+00, %[[#R]]
804+
// LLVM-NEXT: %[[#A:]] = insertvalue { double, double } undef, double %[[#IR]], 0
805+
// LLVM-NEXT: %{{.+}} = insertvalue { double, double } %[[#A]], double %[[#I]], 1
806+
807+
// LLVM: %[[#R:]] = extractvalue { i32, i32 } %{{.+}}, 0
808+
// LLVM-NEXT: %[[#I:]] = extractvalue { i32, i32 } %{{.+}}, 1
809+
// LLVM-NEXT: %[[#IR:]] = add i32 %[[#R]], 1
810+
// LLVM-NEXT: %[[#A:]] = insertvalue { i32, i32 } undef, i32 %[[#IR]], 0
811+
// LLVM-NEXT: %{{.+}} = insertvalue { i32, i32 } %[[#A]], i32 %[[#I]], 1
812+
813+
// CHECK: }
814+
815+
void post_increment() {
816+
cd1++;
817+
ci1++;
818+
}
819+
820+
// CLANG: @post_increment
821+
// CPPLANG: @_Z14post_incrementv
822+
823+
// CIRGEN: %{{.+}} = cir.unary(inc, %{{.+}}) : !cir.complex<!cir.double>, !cir.complex<!cir.double>
824+
// CIRGEN: %{{.+}} = cir.unary(inc, %{{.+}}) : !cir.complex<!s32i>, !cir.complex<!s32i>
825+
826+
// CIR: %[[#R:]] = cir.complex.real %{{.+}} : !cir.complex<!cir.double> -> !cir.double
827+
// CIR-NEXT: %[[#I:]] = cir.complex.imag %{{.+}} : !cir.complex<!cir.double> -> !cir.double
828+
// CIR-NEXT: %[[#IR:]] = cir.unary(inc, %[[#R]]) : !cir.double, !cir.double
829+
// CIR-NEXT: %{{.+}} = cir.complex.create %[[#IR]], %[[#I]] : !cir.double -> !cir.complex<!cir.double>
830+
831+
// CIR: %[[#R:]] = cir.complex.real %{{.+}} : !cir.complex<!s32i> -> !s32i
832+
// CIR-NEXT: %[[#I:]] = cir.complex.imag %{{.+}} : !cir.complex<!s32i> -> !s32i
833+
// CIR-NEXT: %[[#IR:]] = cir.unary(inc, %[[#R]]) : !s32i, !s32i
834+
// CIR-NEXT: %{{.+}} = cir.complex.create %[[#IR]], %[[#I]] : !s32i -> !cir.complex<!s32i>
835+
836+
// LLVM: %[[#R:]] = extractvalue { double, double } %{{.+}}, 0
837+
// LLVM-NEXT: %[[#I:]] = extractvalue { double, double } %{{.+}}, 1
838+
// LLVM-NEXT: %[[#IR:]] = fadd double 1.000000e+00, %[[#R]]
839+
// LLVM-NEXT: %[[#A:]] = insertvalue { double, double } undef, double %[[#IR]], 0
840+
// LLVM-NEXT: %{{.+}} = insertvalue { double, double } %[[#A]], double %[[#I]], 1
841+
842+
// LLVM: %[[#R:]] = extractvalue { i32, i32 } %{{.+}}, 0
843+
// LLVM-NEXT: %[[#I:]] = extractvalue { i32, i32 } %{{.+}}, 1
844+
// LLVM-NEXT: %[[#IR:]] = add i32 %[[#R]], 1
845+
// LLVM-NEXT: %[[#A:]] = insertvalue { i32, i32 } undef, i32 %[[#IR]], 0
846+
// LLVM-NEXT: %{{.+}} = insertvalue { i32, i32 } %[[#A]], i32 %[[#I]], 1
847+
848+
// CHECK: }
849+
850+
void pre_decrement() {
851+
--cd1;
852+
--ci1;
853+
}
854+
855+
// CLANG: @pre_decrement
856+
// CPPLANG: @_Z13pre_decrementv
857+
858+
// CIRGEN: %{{.+}} = cir.unary(dec, %{{.+}}) : !cir.complex<!cir.double>, !cir.complex<!cir.double>
859+
// CIRGEN: %{{.+}} = cir.unary(dec, %{{.+}}) : !cir.complex<!s32i>, !cir.complex<!s32i>
860+
861+
// CIR: %[[#R:]] = cir.complex.real %{{.+}} : !cir.complex<!cir.double> -> !cir.double
862+
// CIR-NEXT: %[[#I:]] = cir.complex.imag %{{.+}} : !cir.complex<!cir.double> -> !cir.double
863+
// CIR-NEXT: %[[#IR:]] = cir.unary(dec, %[[#R]]) : !cir.double, !cir.double
864+
// CIR-NEXT: %{{.+}} = cir.complex.create %[[#IR]], %[[#I]] : !cir.double -> !cir.complex<!cir.double>
865+
866+
// CIR: %[[#R:]] = cir.complex.real %{{.+}} : !cir.complex<!s32i> -> !s32i
867+
// CIR-NEXT: %[[#I:]] = cir.complex.imag %{{.+}} : !cir.complex<!s32i> -> !s32i
868+
// CIR-NEXT: %[[#IR:]] = cir.unary(dec, %[[#R]]) : !s32i, !s32i
869+
// CIR-NEXT: %{{.+}} = cir.complex.create %[[#IR]], %[[#I]] : !s32i -> !cir.complex<!s32i>
870+
871+
// LLVM: %[[#R:]] = extractvalue { double, double } %{{.+}}, 0
872+
// LLVM-NEXT: %[[#I:]] = extractvalue { double, double } %{{.+}}, 1
873+
// LLVM-NEXT: %[[#IR:]] = fadd double -1.000000e+00, %[[#R]]
874+
// LLVM-NEXT: %[[#A:]] = insertvalue { double, double } undef, double %[[#IR]], 0
875+
// LLVM-NEXT: %{{.+}} = insertvalue { double, double } %[[#A]], double %[[#I]], 1
876+
877+
// LLVM: %[[#R:]] = extractvalue { i32, i32 } %{{.+}}, 0
878+
// LLVM-NEXT: %[[#I:]] = extractvalue { i32, i32 } %{{.+}}, 1
879+
// LLVM-NEXT: %[[#IR:]] = sub i32 %[[#R]], 1
880+
// LLVM-NEXT: %[[#A:]] = insertvalue { i32, i32 } undef, i32 %[[#IR]], 0
881+
// LLVM-NEXT: %{{.+}} = insertvalue { i32, i32 } %[[#A]], i32 %[[#I]], 1
882+
883+
// CHECK: }
884+
885+
void post_decrement() {
886+
cd1--;
887+
ci1--;
888+
}
889+
890+
// CLANG: @post_decrement
891+
// CPPLANG: @_Z14post_decrementv
892+
893+
// CIRGEN: %{{.+}} = cir.unary(dec, %{{.+}}) : !cir.complex<!cir.double>, !cir.complex<!cir.double>
894+
// CIRGEN: %{{.+}} = cir.unary(dec, %{{.+}}) : !cir.complex<!s32i>, !cir.complex<!s32i>
895+
896+
// CIR: %[[#R:]] = cir.complex.real %{{.+}} : !cir.complex<!cir.double> -> !cir.double
897+
// CIR-NEXT: %[[#I:]] = cir.complex.imag %{{.+}} : !cir.complex<!cir.double> -> !cir.double
898+
// CIR-NEXT: %[[#IR:]] = cir.unary(dec, %[[#R]]) : !cir.double, !cir.double
899+
// CIR-NEXT: %{{.+}} = cir.complex.create %[[#IR]], %[[#I]] : !cir.double -> !cir.complex<!cir.double>
900+
901+
// CIR: %[[#R:]] = cir.complex.real %{{.+}} : !cir.complex<!s32i> -> !s32i
902+
// CIR-NEXT: %[[#I:]] = cir.complex.imag %{{.+}} : !cir.complex<!s32i> -> !s32i
903+
// CIR-NEXT: %[[#IR:]] = cir.unary(dec, %[[#R]]) : !s32i, !s32i
904+
// CIR-NEXT: %{{.+}} = cir.complex.create %[[#IR]], %[[#I]] : !s32i -> !cir.complex<!s32i>
905+
906+
// LLVM: %[[#R:]] = extractvalue { double, double } %{{.+}}, 0
907+
// LLVM-NEXT: %[[#I:]] = extractvalue { double, double } %{{.+}}, 1
908+
// LLVM-NEXT: %[[#IR:]] = fadd double -1.000000e+00, %[[#R]]
909+
// LLVM-NEXT: %[[#A:]] = insertvalue { double, double } undef, double %[[#IR]], 0
910+
// LLVM-NEXT: %{{.+}} = insertvalue { double, double } %[[#A]], double %[[#I]], 1
911+
912+
// LLVM: %[[#R:]] = extractvalue { i32, i32 } %{{.+}}, 0
913+
// LLVM-NEXT: %[[#I:]] = extractvalue { i32, i32 } %{{.+}}, 1
914+
// LLVM-NEXT: %[[#IR:]] = sub i32 %[[#R]], 1
915+
// LLVM-NEXT: %[[#A:]] = insertvalue { i32, i32 } undef, i32 %[[#IR]], 0
916+
// LLVM-NEXT: %{{.+}} = insertvalue { i32, i32 } %[[#A]], i32 %[[#I]], 1
917+
918+
// CHECK: }

0 commit comments

Comments
 (0)