llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) <details> <summary>Changes</summary> Split the Complex binary operations into float and int versions and remove the unnecessary range kind from div and mul int ops --- Patch is 51.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/226725.diff 10 Files Affected: - (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+34) - (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+87-19) - (modified) clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td (+13) - (modified) clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp (+5-7) - (modified) clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp (+127-85) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+127-47) - (modified) clang/test/CIR/CodeGen/complex-compound-assignment.cpp (+3-3) - (modified) clang/test/CIR/CodeGen/complex-mul-div.cpp (+24-24) - (modified) clang/test/CIR/CodeGen/complex-plus-minus.cpp (+6-6) - (modified) clang/test/CIR/CodeGen/complex.cpp (+2-2) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 36d583cfe9fbe..820e504a9c636 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -328,6 +328,40 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return cir::ComplexImagOp::create(*this, loc, resultType, operand); } + mlir::Value createComplexAdd(mlir::Location loc, mlir::Value lhs, + mlir::Value rhs) { + auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType()); + if (cir::isAnyFloatingPointType(complexTy.getElementType())) + return cir::ComplexFAddOp::create(*this, loc, lhs, rhs); + return cir::ComplexAddOp::create(*this, loc, lhs, rhs); + } + + mlir::Value createComplexSub(mlir::Location loc, mlir::Value lhs, + mlir::Value rhs) { + auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType()); + if (cir::isAnyFloatingPointType(complexTy.getElementType())) + return cir::ComplexFSubOp::create(*this, loc, lhs, rhs); + return cir::ComplexSubOp::create(*this, loc, lhs, rhs); + } + + mlir::Value createComplexMul(mlir::Location loc, mlir::Value lhs, + mlir::Value rhs, + cir::ComplexRangeKind rangeKind) { + auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType()); + if (cir::isAnyFloatingPointType(complexTy.getElementType())) + return cir::ComplexFMulOp::create(*this, loc, lhs, rhs, rangeKind); + return cir::ComplexMulOp::create(*this, loc, lhs, rhs); + } + + mlir::Value createComplexDiv(mlir::Location loc, mlir::Value lhs, + mlir::Value rhs, + cir::ComplexRangeKind rangeKind) { + auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType()); + if (cir::isAnyFloatingPointType(complexTy.getElementType())) + return cir::ComplexFDivOp::create(*this, loc, lhs, rhs, rangeKind); + return cir::ComplexDivOp::create(*this, loc, lhs, rhs); + } + mlir::Value createComplexConj(mlir::Location loc, mlir::Value operand) { return cir::ComplexConjOp::create(*this, loc, operand.getType(), operand); } diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 4996037ea5f56..6ad827cd66e89 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -6623,13 +6623,13 @@ def CIR_ComplexImagPtrOp : CIR_ComplexPartPtrOp<"complex.imag_ptr"> { } //===----------------------------------------------------------------------===// -// ComplexAddOp and ComplexSubOp +// Complex binary operations //===----------------------------------------------------------------------===// class CIR_ComplexBinOp<string mnemonic> : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> { - let arguments = (ins CIR_ComplexType:$lhs, CIR_ComplexType:$rhs); - let results = (outs CIR_ComplexType:$result); + let arguments = (ins CIR_ComplexOfIntType:$lhs, CIR_ComplexOfIntType:$rhs); + let results = (outs CIR_ComplexOfIntType:$result); let assemblyFormat = [{ $lhs `,` $rhs `:` qualified(type($result)) attr-dict @@ -6645,7 +6645,7 @@ def CIR_ComplexAddOp : CIR_ComplexBinOp<"complex.add"> { Example: ``` - %2 = cir.complex.add %0, %1 : !cir.complex<!cir.float> + %2 = cir.complex.add %0, %1 : !cir.complex<s32i> ``` }]; } @@ -6659,13 +6659,83 @@ def CIR_ComplexSubOp : CIR_ComplexBinOp<"complex.sub"> { Example: ``` - %2 = cir.complex.sub %0, %1 : !cir.complex<!cir.float> + %2 = cir.complex.sub %0, %1 : !cir.complex<s32i> + ``` + }]; +} + +def CIR_ComplexMulOp : CIR_ComplexBinOp<"complex.mul"> { + let summary = "Complex subtraction"; + let description = [{ + The `cir.complex.mul` operation takes two complex numbers and returns + their product. + + Example: + + ``` + %2 = cir.complex.mul %0, %1 : !cir.complex<s32i> + ``` + }]; + + let hasLLVMLowering = false; +} + +def CIR_ComplexDivOp : CIR_ComplexBinOp<"complex.div"> { + let summary = "Complex subtraction"; + let description = [{ + The `cir.complex.div` operation takes two complex numbers and returns + their quotient. + + Example: + + ``` + %2 = cir.complex.div %0, %1 : !cir.complex<s32i> + ``` + }]; + + let hasLLVMLowering = false; +} + +class CIR_ComplexFPBinOp<string mnemonic> + : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> { + let arguments = (ins CIR_ComplexOfFloatType:$lhs, CIR_ComplexOfFloatType:$rhs); + let results = (outs CIR_ComplexOfFloatType:$result); + + let assemblyFormat = [{ + $lhs `,` $rhs `:` qualified(type($result)) attr-dict + }]; +} + +def CIR_ComplexFAddOp : CIR_ComplexFPBinOp<"complex.fadd"> { + let summary = "Complex addition"; + let description = [{ + The `cir.complex.fadd` operation takes two complex numbers and returns + their sum. + + Example: + + ``` + %2 = cir.complex.fadd %0, %1 : !cir.complex<!cir.float> + ``` + }]; +} + +def CIR_ComplexFSubOp : CIR_ComplexFPBinOp<"complex.fsub"> { + let summary = "Complex subtraction"; + let description = [{ + The `cir.complex.fsub` operation takes two complex numbers and returns + their difference. + + Example: + + ``` + %2 = cir.complex.fsub %0, %1 : !cir.complex<!cir.float> ``` }]; } //===----------------------------------------------------------------------===// -// ComplexMulOp and ComplexDivOp +// Complex binary operations with range //===----------------------------------------------------------------------===// def CIR_ComplexRangeKind : CIR_I32Enum< @@ -6682,12 +6752,12 @@ def CIR_ComplexRangeKindAttr class CIR_ComplexRangeBinOp<string mnemonic> : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> { let arguments = (ins - CIR_ComplexType:$lhs, - CIR_ComplexType:$rhs, + CIR_ComplexOfFloatType:$lhs, + CIR_ComplexOfFloatType:$rhs, CIR_ComplexRangeKindAttr:$range ); - let results = (outs CIR_ComplexType:$result); + let results = (outs CIR_ComplexOfFloatType:$result); let assemblyFormat = [{ $lhs `,` $rhs `range` `(` enum($range) `)` `:` qualified(type($result)) @@ -6697,16 +6767,15 @@ class CIR_ComplexRangeBinOp<string mnemonic> let hasLLVMLowering = false; } -def CIR_ComplexMulOp : CIR_ComplexRangeBinOp<"complex.mul"> { +def CIR_ComplexFMulOp : CIR_ComplexRangeBinOp<"complex.fmul"> { let summary = "Complex multiplication"; let description = [{ The `cir.complex.mul` operation takes two complex numbers and returns their product. - For complex types with floating-point components, the `range` attribute - specifies the algorithm to be used when the operation is lowered to - the LLVM dialect. For multiplication, 'improved', 'promoted', and 'basic' - are all handled equivalently, producing the algebraic formula with no + The `range` attribute specifies the algorithm to be used when the operation + is lowered to the LLVM dialect. For multiplication, 'improved', 'promoted', + and 'basic' are all handled equivalently, producing the algebraic formula with no special handling for NaN value. If 'full' is used, a runtime-library function is called if one of the intermediate calculations produced a NaN value. @@ -6720,16 +6789,15 @@ def CIR_ComplexMulOp : CIR_ComplexRangeBinOp<"complex.mul"> { }]; } -def CIR_ComplexDivOp : CIR_ComplexRangeBinOp<"complex.div"> { +def CIR_ComplexFDivOp : CIR_ComplexRangeBinOp<"complex.fdiv"> { let summary = "Complex division"; let description = [{ The `cir.complex.div` operation takes two complex numbers and returns their quotient. - For complex types with floating-point components, the `range` attribute - specifies the algorithm to be used when the operation is lowered to - the LLVM dialect. For division, 'improved' produces Smith's algorithms for - Complex division with no additional handling for NaN values. If 'promoted' + The `range` attribute specifies the algorithm to be used when the operation + is lowered to the LLVM dialect. For division, 'improved' produces Smith's algorithms + for Complex division with no additional handling for NaN values. If 'promoted' is used, the values are promoted to a higher precision type, if possible, and the calculation is performed using the algebraic formula, with no additional handling for NaN values. We fall back on Smith's algorithm diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td index c6afa74ba051f..a3de83f6cab63 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td @@ -202,6 +202,19 @@ def CIR_AnyIntOrBoolOrFloatType def CIR_AnyComplexType : CIR_TypeBase<"::cir::ComplexType", "complex type">; +class CIR_ComplexElementTypePred<Pred pred> : SubstLeaves<"$_self", + "::mlir::cast<::cir::ComplexType>($_self).getElementType()", pred>; + +class CIR_ComplexTypeOf<list<Type> types, string summary = ""> + : CIR_ConfinedType<CIR_AnyComplexType, + [Or<!foreach(type, types, CIR_ComplexElementTypePred<type.predicate>)>], + !if(!empty(summary), + "complex of " # CIR_TypeSummaries<types>.value, + summary)>; + +def CIR_ComplexOfIntType : CIR_ComplexTypeOf<[CIR_AnyIntType]>; +def CIR_ComplexOfFloatType : CIR_ComplexTypeOf<[CIR_AnyFloatType]>; + def CIR_AnyComplexOrIntOrBoolOrFloatType : AnyTypeOf<[CIR_AnyComplexType, CIR_AnyIntOrBoolOrFloatType], "complex, integer, boolean or floating point type"> { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index 91535c57132bd..7dd24a6d076e8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -623,7 +623,7 @@ mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) { if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && mlir::isa<cir::ComplexType>(op.rhs.getType())) - return cir::ComplexAddOp::create(builder, op.loc, op.lhs, op.rhs); + return builder.createComplexAdd(op.loc, op.lhs, op.rhs); auto createAdd = [&](mlir::Location loc, mlir::Value a, mlir::Value b) { return cir::isFPOrVectorOfFPType(a.getType()) @@ -651,7 +651,7 @@ mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) { if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && mlir::isa<cir::ComplexType>(op.rhs.getType())) - return cir::ComplexSubOp::create(builder, op.loc, op.lhs, op.rhs); + return builder.createComplexSub(op.loc, op.lhs, op.rhs); auto createSub = [&](mlir::Location loc, mlir::Value a, mlir::Value b) { return cir::isFPOrVectorOfFPType(a.getType()) @@ -704,8 +704,7 @@ mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) { mlir::isa<cir::ComplexType>(op.rhs.getType())) { cir::ComplexRangeKind rangeKind = getComplexRangeAttr(op.fpFeatures.getComplexRange()); - return cir::ComplexMulOp::create(builder, op.loc, op.lhs, op.rhs, - rangeKind); + return builder.createComplexMul(op.loc, op.lhs, op.rhs, rangeKind); } auto createMul = [&](mlir::Location loc, mlir::Value a, mlir::Value b) { @@ -742,8 +741,7 @@ mlir::Value ComplexExprEmitter::emitBinDiv(const BinOpInfo &op) { mlir::isa<cir::ComplexType>(op.rhs.getType())) { cir::ComplexRangeKind rangeKind = getComplexRangeAttr(op.fpFeatures.getComplexRange()); - return cir::ComplexDivOp::create(builder, op.loc, op.lhs, op.rhs, - rangeKind); + return builder.createComplexDiv(op.loc, op.lhs, op.rhs, rangeKind); } // The C99 standard (G.5.1) defines division of a complex value by a real @@ -763,7 +761,7 @@ mlir::Value ComplexExprEmitter::emitBinDiv(const BinOpInfo &op) { mlir::Value lhs = builder.createComplexCreate(op.loc, op.lhs, nullValue); cir::ComplexRangeKind rangeKind = getComplexRangeAttr(op.fpFeatures.getComplexRange()); - return cir::ComplexDivOp::create(builder, op.loc, lhs, op.rhs, rangeKind); + return builder.createComplexDiv(op.loc, lhs, op.rhs, rangeKind); } mlir::Value CIRGenFunction::emitUnPromotedValue(mlir::Value result, diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 9a3c9c9745eaa..7d30c71bb10ac 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -89,6 +89,8 @@ struct LoweringPreparePass void lowerComplexConjOp(cir::ComplexConjOp op); void lowerComplexDivOp(cir::ComplexDivOp op); void lowerComplexMulOp(cir::ComplexMulOp op); + void lowerComplexFDivOp(cir::ComplexFDivOp op); + void lowerComplexFMulOp(cir::ComplexFMulOp op); void lowerGetGlobalOp(cir::GetGlobalOp op); void lowerGlobalOp(cir::GlobalOp op); void lowerThreeWayCmpOp(cir::CmpThreeWayOp op); @@ -941,61 +943,81 @@ static mlir::Type higherPrecisionElementTypeForComplexArithmetic( return {}; } -static mlir::Value -lowerComplexDiv(LoweringPreparePass &pass, CIRBaseBuilderTy &builder, - mlir::Location loc, cir::ComplexDivOp op, mlir::Value lhsReal, - mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag, - mlir::MLIRContext &mlirCx, - const clang::TargetInfo &targetInfo) { +static mlir::Value lowerComplexFDiv(LoweringPreparePass &pass, + CIRBaseBuilderTy &builder, + mlir::Location loc, cir::ComplexFDivOp op, + mlir::Value lhsReal, mlir::Value lhsImag, + mlir::Value rhsReal, mlir::Value rhsImag, + mlir::MLIRContext &mlirCx, + const clang::TargetInfo &targetInfo) { cir::ComplexType complexTy = op.getType(); - if (mlir::isa<cir::FPTypeInterface>(complexTy.getElementType())) { - cir::ComplexRangeKind range = op.getRange(); - if (range == cir::ComplexRangeKind::Improved) + cir::ComplexRangeKind range = op.getRange(); + switch (range) { + case ComplexRangeKind::Full: { + return buildComplexBinOpLibCall(pass, builder, &getComplexDivLibCallName, + loc, complexTy, lhsReal, lhsImag, rhsReal, + rhsImag); + } + case ComplexRangeKind::Improved: { + return buildRangeReductionComplexDiv(builder, loc, lhsReal, lhsImag, + rhsReal, rhsImag); + } + case ComplexRangeKind::Promoted: { + mlir::Type originalElementType = complexTy.getElementType(); + mlir::Type higherPrecisionElementType = + higherPrecisionElementTypeForComplexArithmetic( + mlirCx, targetInfo, pass.getLangOpts(), builder, + originalElementType); + + if (!higherPrecisionElementType) return buildRangeReductionComplexDiv(builder, loc, lhsReal, lhsImag, rhsReal, rhsImag); - if (range == cir::ComplexRangeKind::Full) - return buildComplexBinOpLibCall(pass, builder, &getComplexDivLibCallName, - loc, complexTy, lhsReal, lhsImag, rhsReal, - rhsImag); - - if (range == cir::ComplexRangeKind::Promoted) { - mlir::Type originalElementType = complexTy.getElementType(); - mlir::Type higherPrecisionElementType = - higherPrecisionElementTypeForComplexArithmetic( - mlirCx, targetInfo, pass.getLangOpts(), builder, - originalElementType); - - if (!higherPrecisionElementType) - return buildRangeReductionComplexDiv(builder, loc, lhsReal, lhsImag, - rhsReal, rhsImag); - - cir::CastKind floatingCastKind = cir::CastKind::floating; - lhsReal = builder.createCast(floatingCastKind, lhsReal, - higherPrecisionElementType); - lhsImag = builder.createCast(floatingCastKind, lhsImag, - higherPrecisionElementType); - rhsReal = builder.createCast(floatingCastKind, rhsReal, - higherPrecisionElementType); - rhsImag = builder.createCast(floatingCastKind, rhsImag, - higherPrecisionElementType); - - mlir::Value algebraicResult = buildAlgebraicComplexDiv( - builder, loc, lhsReal, lhsImag, rhsReal, rhsImag); - - mlir::Value resultReal = builder.createComplexReal(loc, algebraicResult); - mlir::Value resultImag = builder.createComplexImag(loc, algebraicResult); - - mlir::Value finalReal = - builder.createCast(floatingCastKind, resultReal, originalElementType); - mlir::Value finalImag = - builder.createCast(floatingCastKind, resultImag, originalElementType); - return builder.createComplexCreate(loc, finalReal, finalImag); - } + cir::CastKind floatingCastKind = cir::CastKind::floating; + lhsReal = builder.createCast(floatingCastKind, lhsReal, + higherPrecisionElementType); + lhsImag = builder.createCast(floatingCastKind, lhsImag, + higherPrecisionElementType); + rhsReal = builder.createCast(floatingCastKind, rhsReal, + higherPrecisionElementType); + rhsImag = builder.createCast(floatingCastKind, rhsImag, + higherPrecisionElementType); + + mlir::Value algebraicResult = buildAlgebraicComplexDiv( + builder, loc, lhsReal, lhsImag, rhsReal, rhsImag); + + mlir::Value resultReal = builder.createComplexReal(loc, algebraicResult); + mlir::Value resultImag = builder.createComplexImag(loc, algebraicResult); + + mlir::Value finalReal = + builder.createCast(floatingCastKind, resultReal, originalElementType); + mlir::Value finalImag = + builder.createCast(floatingCastKind, resultImag, originalElementType); + return builder.createComplexCreate(loc, finalReal, finalImag); } + case ComplexRangeKind::Basic: { + return buildAlgebraicComplexDiv(builder, loc, lhsReal, lhsImag, rhsReal, + rhsImag); + } + } +} + +void LoweringPreparePass::lowerComplexFDivOp(cir::ComplexFDivOp op) { + cir::CIRBaseBuilderTy builder(getContext()); + builder.setInsertionPointAfter(op); + mlir::Location loc = op.getLoc(); + mlir::TypedValue<cir::ComplexType> lhs = op.getLhs(); + mlir::TypedValue<cir::ComplexType> rhs = op.getRhs(); + mlir::Value lhsReal = builder.createComplexReal(loc, lhs); + mlir::Value lhsImag = builder.createComplexImag(loc, lhs); + mlir::Value rhsReal = builder.createComplexReal(loc, rhs); + mlir::Value rhsImag = builder.createComplexImag(loc, rhs); - return buildAlgebraicComplexDiv(builder, loc, lhsReal, lhsImag, rhsReal, - rhsImag); + mlir::Value loweredResult = + lowerComplexFDiv(*this, builder, loc, op, lhsReal, lhsImag, rhsReal, + rhsImag, getContext(), getTargetInfo()); + op.replaceAllUsesWith(loweredResult); + op.erase(); } void LoweringPreparePass::lowerComplexDivOp(cir::ComplexDivOp op) { @@ -1009,9 +1031,8 @@ void LoweringPreparePass::lowerComplexDivOp(cir::ComplexDivOp op) { mlir::Value rhsReal = builder.createComplexReal(loc, rhs); mlir::Value rhsImag = builder.createComplexImag(loc, rhs); - mlir::Value loweredResult = - lowerComplexDiv(*this, builder, loc, op, lhsReal, lhsImag, rhsReal, - rhsImag, getContext(), getTargetInfo()); + mlir::Value loweredResult = buildAlgebraicComplexDiv( + builder, loc, lhsReal, lhsImag, rhsReal, rhsImag); op.replaceAllUsesWith(loweredResult); op.erase(); } @@ -1036,36 +1057,26 @@ getComplexMulLibCallName(llvm::APFloat::Semantics semantics) { } } -static mlir::Value lowerComplexMul(LoweringPreparePass &pass, - CIRBaseBuilderTy &builder, - mlir::Locati... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/226725 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
