diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 799d80d66a86..6975606c653a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -2050,9 +2050,11 @@ mlir::Value ScalarExprEmitter::VisitReal(const UnaryOperator *E) { // If it's an l-value, load through the appropriate subobject l-value. // Note that we have to ask E because Op might be an l-value that // this won't work for, e.g. an Obj-C property. - if (E->isGLValue()) - return CGF.emitLoadOfLValue(CGF.emitLValue(E), E->getExprLoc()) - .getScalarVal(); + if (E->isGLValue()) { + mlir::Location Loc = CGF.getLoc(E->getExprLoc()); + mlir::Value Complex = CGF.emitComplexExpr(Op); + return CGF.builder.createComplexReal(Loc, Complex); + } // Otherwise, calculate and project. llvm_unreachable("NYI"); } diff --git a/clang/test/CIR/CodeGen/complex.c b/clang/test/CIR/CodeGen/complex.c index 9b19b39c578f..22c495015fa5 100644 --- a/clang/test/CIR/CodeGen/complex.c +++ b/clang/test/CIR/CodeGen/complex.c @@ -261,25 +261,55 @@ void extract_real() { // CHECK-BEFORE: cir.func // CHECK-BEFORE: %[[#C_PTR:]] = cir.get_global @c : !cir.ptr> -// CHECK-BEFORE-NEXT: %[[#REAL_PTR:]] = cir.complex.real_ptr %[[#C_PTR]] : !cir.ptr> -> !cir.ptr -// CHECK-BEFORE-NEXT: %{{.+}} = cir.load{{.*}} %[[#REAL_PTR]] : !cir.ptr, !cir.double +// CHECK-BEFORE-NEXT: %[[COMPLEX:.*]] = cir.load{{.*}} %[[#C_PTR]] : !cir.ptr>, !cir.complex +// CHECK-BEFORE-NEXT: %[[#REAL:]] = cir.complex.real %[[COMPLEX]] : !cir.complex -> !cir.double // CHECK-BEFORE: %[[#CI_PTR:]] = cir.get_global @ci : !cir.ptr> -// CHECK-BEFORE-NEXT: %[[#REAL_PTR:]] = cir.complex.real_ptr %[[#CI_PTR]] : !cir.ptr> -> !cir.ptr -// CHECK-BEFORE-NEXT: %{{.+}} = cir.load{{.*}} %[[#REAL_PTR]] : !cir.ptr, !s32i +// CHECK-BEFORE-NEXT: %[[COMPLEX:.*]] = cir.load{{.*}} %[[#CI_PTR]] : !cir.ptr>, !cir.complex +// CHECK-BEFORE-NEXT: %[[#REAL:]] = cir.complex.real %[[COMPLEX]] : !cir.complex -> !s32i // CHECK-BEFORE: } // CHECK-AFTER: cir.func // CHECK-AFTER: %[[#C_PTR:]] = cir.get_global @c : !cir.ptr> -// CHECK-AFTER-NEXT: %[[#REAL_PTR:]] = cir.complex.real_ptr %[[#C_PTR]] : !cir.ptr> -> !cir.ptr -// CHECK-AFTER-NEXT: %{{.+}} = cir.load{{.*}} %[[#REAL_PTR]] : !cir.ptr, !cir.double +// CHECK-AFTER-NEXT: %[[COMPLEX:.*]] = cir.load{{.*}} %[[#C_PTR]] : !cir.ptr>, !cir.complex +// CHECK-AFTER-NEXT: %[[#REAL:]] = cir.complex.real %[[COMPLEX]] : !cir.complex -> !cir.double // CHECK-AFTER: %[[#CI_PTR:]] = cir.get_global @ci : !cir.ptr> -// CHECK-AFTER-NEXT: %[[#REAL_PTR:]] = cir.complex.real_ptr %[[#CI_PTR]] : !cir.ptr> -> !cir.ptr -// CHECK-AFTER-NEXT: %{{.+}} = cir.load{{.*}} %[[#REAL_PTR]] : !cir.ptr, !s32i +// CHECK-AFTER-NEXT: %[[COMPLEX:.*]] = cir.load{{.*}} %[[#CI_PTR]] : !cir.ptr>, !cir.complex +// CHECK-AFTER-NEXT: %[[#REAL:]] = cir.complex.real %[[COMPLEX]] : !cir.complex -> !s32i // CHECK-AFTER: } // LLVM: define dso_local void @extract_real() -// LLVM: %{{.+}} = load double, ptr @c, align 8 -// LLVM: %{{.+}} = load i32, ptr @ci, align 4 +// LLVM: %[[COMPLEX_D:.*]] = load { double, double }, ptr @c, align 8 +// LLVM: %[[R1:.*]] = extractvalue { double, double } %[[COMPLEX_D]], 0 +// LLVM: %[[COMPLEX_I:.*]] = load { i32, i32 }, ptr @ci, align 4 +// LLVM: %[[R2:.*]] = extractvalue { i32, i32 } %[[COMPLEX_I]], 0 +// LLVM: } + +int extract_real_and_add(int _Complex a, int _Complex b) { + return __real__ a + __real__ b; +} + +// CHECK-BEFORE: cir.func +// CHECK-BEFORE: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr>, !cir.complex +// CHECK-BEFORE-NEXT: %[[REAL_A:.*]] = cir.complex.real %[[COMPLEX_A]] : !cir.complex -> !s32i +// CHECK-BEFORE-NEXT: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr>, !cir.complex +// CHECK-BEFORE-NEXT: %[[REAL_B:.*]] = cir.complex.real %[[COMPLEX_B]] : !cir.complex -> !s32i +// CHECK-BEFORE-NEXT: %[[ADD:.*]] = cir.binop(add, %[[REAL_A]], %[[REAL_B]]) nsw : !s32i +// CHECK-BEFORE: } + +// CHECK-AFTER: cir.func +// CHECK-AFTER: %[[COMPLEX_A:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr>, !cir.complex +// CHECK-AFTER-NEXT: %[[REAL_A:.*]] = cir.complex.real %[[COMPLEX_A]] : !cir.complex -> !s32i +// CHECK-AFTER-NEXT: %[[COMPLEX_B:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr>, !cir.complex +// CHECK-AFTER-NEXT: %[[REAL_B:.*]] = cir.complex.real %[[COMPLEX_B]] : !cir.complex -> !s32i +// CHECK-AFTER-NEXT: %[[ADD:.*]] = cir.binop(add, %[[REAL_A]], %[[REAL_B]]) nsw : !s32i +// CHECK-AFTER: } + +// LLVM: define dso_local i32 @extract_real_and_add +// LLVM: %[[COMPLEX_A:.*]] = load { i32, i32 }, ptr {{.*}}, align 4 +// LLVM: %[[REAL_A:.*]] = extractvalue { i32, i32 } %[[COMPLEX_A]], 0 +// LLVM: %[[COMPLEX_B:.*]] = load { i32, i32 }, ptr {{.*}}, align 4 +// LLVM: %[[REAL_B:.*]] = extractvalue { i32, i32 } %[[COMPLEX_B]], 0 +// LLVM: %10 = add nsw i32 %[[REAL_A]], %[[REAL_B]] // LLVM: } void imag_ptr() {