diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 7ffc3d54df2b..2fac443af834 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1514,18 +1514,20 @@ def CIR_ComplexCreateOp : CIR_Op<"complex.create", [Pure, SameTypeOperands]> { def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> { let summary = "Extract the real part of a complex value"; let description = [{ - `cir.complex.real` operation takes an operand of `!cir.complex` type and - yields the real part of it. + `cir.complex.real` operation takes an operand of `!cir.complex`, `cir.int`, + `!cir.bool` or `!cir.float`. If the operand is `!cir.complex`, the real + part of it will be returned, otherwise the value returned unmodified. Example: ```mlir - %1 = cir.complex.real %0 : !cir.complex -> !cir.float + %real = cir.complex.real %complex : !cir.complex -> !cir.float + %real = cir.complex.real %scalar : !cir.float -> !cir.float ``` }]; - let results = (outs CIR_AnyIntOrFloatType:$result); - let arguments = (ins CIR_AnyComplexOrIntOrFloatType:$operand); + let results = (outs CIR_AnyIntOrBoolOrFloatType:$result); + let arguments = (ins CIR_AnyComplexOrIntOrBoolOrFloatType:$operand); let assemblyFormat = [{ $operand `:` qualified(type($operand)) `->` qualified(type($result)) @@ -1540,8 +1542,8 @@ def CIR_ComplexImagOp : CIR_Op<"complex.imag", [Pure]> { let summary = "Extract the imaginary part of a complex value"; let description = [{ `cir.complex.imag` operation takes an operand of `!cir.complex`, `!cir.int` - or `!cir.float`. If the operand is `!cir.complex`, the imag part of it will - be returned, otherwise a zero value will be returned. + `!cir.bool` or `!cir.float`. If the operand is `!cir.complex`, the imag + part of it will be returned, otherwise a zero value will be returned. Example: @@ -1551,8 +1553,8 @@ def CIR_ComplexImagOp : CIR_Op<"complex.imag", [Pure]> { ``` }]; - let results = (outs CIR_AnyIntOrFloatType:$result); - let arguments = (ins CIR_AnyComplexOrIntOrFloatType:$operand); + let results = (outs CIR_AnyIntOrBoolOrFloatType:$result); + let arguments = (ins CIR_AnyComplexOrIntOrBoolOrFloatType:$operand); let assemblyFormat = [{ $operand `:` qualified(type($operand)) `->` qualified(type($result)) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td index b8e3b4f3e2da..7feb96eedd2e 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td @@ -163,16 +163,22 @@ def CIR_AnyIntOrFloatType : AnyTypeOf<[CIR_AnyFloatType, CIR_AnyIntType], let cppFunctionName = "isAnyIntegerOrFloatingPointType"; } +def CIR_AnyIntOrBoolOrFloatType + : AnyTypeOf<[CIR_AnyBoolType, CIR_AnyFloatType, CIR_AnyIntType], + "integer, boolean or floating point type"> { + let cppFunctionName = "isAnyIntegerOrBooleanOrFloatingPointType"; +} + //===----------------------------------------------------------------------===// // Complex Type predicates //===----------------------------------------------------------------------===// def CIR_AnyComplexType : CIR_TypeBase<"::cir::ComplexType", "complex type">; -def CIR_AnyComplexOrIntOrFloatType : AnyTypeOf<[ - CIR_AnyComplexType, CIR_AnyFloatType, CIR_AnyIntType -], "complex, integer or floating point type"> { - let cppFunctionName = "isComplexOrIntegerOrFloatingPointType"; +def CIR_AnyComplexOrIntOrBoolOrFloatType + : AnyTypeOf<[CIR_AnyComplexType, CIR_AnyIntOrBoolOrFloatType], + "complex, integer, bool or floating point type"> { + let cppFunctionName = "isComplexOrIntegerOrBoolOrFloatingPointType"; } //===----------------------------------------------------------------------===// diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index 948f9013387d..1429d26570d2 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -410,3 +410,49 @@ void imag_on_scalar_glvalue() { // OGCG: %[[A_ADDR:.*]] = alloca float, align 4 // OGCG: %[[B_ADDR:.*]] = alloca float, align 4 // OGCG: store float 0.000000e+00, ptr %[[B_ADDR]], align 4 + +void real_on_scalar_bool() { + bool a; + bool b = __real__ a; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr, ["a"] +// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr, ["b", init] +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr, !cir.bool +// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.bool -> !cir.bool +// CIR: cir.store{{.*}} %[[A_REAL]], %[[B_ADDR]] : !cir.bool, !cir.ptr + +// LLVM: %[[A_ADDR:.*]] = alloca i8, i64 1, align 1 +// LLVM: %[[B_ADDR:.*]] = alloca i8, i64 1, align 1 +// LLVM: %[[TMP_A:.*]] = load i8, ptr %[[A_ADDR]], align 1 +// LLVM: %[[TMP_A_I1:.*]] = trunc i8 %[[TMP_A]] to i1 +// LLVM: %[[TMP_A_I8:.*]] = zext i1 %[[TMP_A_I1]] to i8 +// LLVM: store i8 %[[TMP_A_I8]], ptr %[[B_ADDR]], align 1 + +// OGCG: %[[A_ADDR:.*]] = alloca i8, align 1 +// OGCG: %[[B_ADDR:.*]] = alloca i8, align 1 +// OGCG: %[[TMP_A:.*]] = load i8, ptr %[[A_ADDR]], align 1 +// OGCG: %[[TMP_A_I1:.*]] = trunc i8 %[[TMP_A]] to i1 +// OGCG: %[[TMP_A_I8:.*]] = zext i1 %[[TMP_A_I1]] to i8 +// OGCG: store i8 %[[TMP_A_I8]], ptr %[[B_ADDR]], align 1 + +void imag_on_scalar_bool() { + bool a; + bool b = __imag__ a; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr, ["a"] +// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr, ["b", init] +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr, !cir.bool +// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.bool -> !cir.bool +// CIR: cir.store{{.*}} %[[A_IMAG]], %[[B_ADDR]] : !cir.bool, !cir.ptr + +// LLVM: %[[A_ADDR:.*]] = alloca i8, i64 1, align 1 +// LLVM: %[[B_ADDR:.*]] = alloca i8, i64 1, align 1 +// LLVM: %[[TMP_A:.*]] = load i8, ptr %[[A_ADDR]], align 1 +// LLVM: %[[TMP_A_I1:.*]] = trunc i8 %[[TMP_A]] to i1 +// LLVM: store i8 0, ptr %[[B_ADDR]], align 1 + +// OGCG: %[[A_ADDR:.*]] = alloca i8, align 1 +// OGCG: %[[B_ADDR:.*]] = alloca i8, align 1 +// OGCG: store i8 0, ptr %[[B_ADDR]], align 1