llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: Henrich Lauko (xlauko) <details> <summary>Changes</summary> Traditional codegen never emits any operation for unary plus, it just visits the subexpression as a pure identity at the codegen level. Align CIRGen with this behavior by removing Plus from UnaryOpKind entirely and having VisitUnaryPlus directly visit the subexpression with the appropriate promotion/demotion handling. --- Patch is 52.15 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/185199.diff 16 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+3-4) - (modified) clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp (+18-16) - (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+14-12) - (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+2-9) - (modified) clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp (-1) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+2-22) - (modified) clang/lib/CodeGen/CGExprComplex.cpp (+68-67) - (modified) clang/test/CIR/CodeGen/complex-unary.cpp (+10-26) - (modified) clang/test/CIR/CodeGen/complex.cpp (+2-18) - (modified) clang/test/CIR/CodeGen/coro-task.cpp (+1-2) - (modified) clang/test/CIR/CodeGen/lambda-static-invoker.cpp (+1-2) - (modified) clang/test/CIR/CodeGen/unary.cpp (+7-8) - (modified) clang/test/CIR/CodeGen/vector-ext.cpp (+1-2) - (modified) clang/test/CIR/CodeGen/vector.cpp (+1-2) - (modified) clang/test/CIR/IR/unary.cir (+16-20) - (modified) clang/test/CIR/Transforms/canonicalize.cir (-72) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 9e0d4e6732021..871b45ef9d543 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1709,16 +1709,15 @@ def CIR_LabelOp : CIR_Op<"label", [AlwaysSpeculatable]> { def CIR_UnaryOpKind : CIR_I32EnumAttr<"UnaryOpKind", "unary operation kind", [ I32EnumAttrCase<"Inc", 0, "inc">, I32EnumAttrCase<"Dec", 1, "dec">, - I32EnumAttrCase<"Plus", 2, "plus">, - I32EnumAttrCase<"Minus", 3, "minus">, - I32EnumAttrCase<"Not", 4, "not"> + I32EnumAttrCase<"Minus", 2, "minus">, + I32EnumAttrCase<"Not", 3, "not"> ]>; def CIR_UnaryOp : CIR_Op<"unary", [Pure, SameOperandsAndResultType]> { let summary = "Unary operations"; let description = [{ `cir.unary` performs the unary operation according to - the specified opcode kind: [inc, dec, plus, minus, not]. + the specified opcode kind: [inc, dec, minus, not]. It requires one input operand and has one result, both types should be the same. diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index c57f9a3b2ce9d..95e50627c74aa 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -193,9 +193,9 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { mlir::Value VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); } mlir::Value VisitUnaryPlus(const UnaryOperator *e); + mlir::Value VisitUnaryPlus(const UnaryOperator *e, QualType promotionType); mlir::Value VisitUnaryMinus(const UnaryOperator *e); - mlir::Value VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind, - QualType promotionType); + mlir::Value VisitUnaryMinus(const UnaryOperator *e, QualType promotionType); mlir::Value VisitUnaryNot(const UnaryOperator *e); // LNot,Real,Imag never return complex. mlir::Value VisitUnaryExtension(const UnaryOperator *e) { @@ -574,32 +574,36 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op, mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) { QualType promotionTy = getPromotionType(e->getSubExpr()->getType()); - mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Plus, promotionTy); + mlir::Value result = VisitUnaryPlus(e, promotionTy); if (!promotionTy.isNull()) return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType()); return result; } +mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e, + QualType promotionType) { + if (!promotionType.isNull()) + return cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType); + return Visit(e->getSubExpr()); +} + mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) { QualType promotionTy = getPromotionType(e->getSubExpr()->getType()); - mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy); + mlir::Value result = VisitUnaryMinus(e, promotionTy); if (!promotionTy.isNull()) return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType()); return result; } -mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e, - cir::UnaryOpKind kind, - QualType promotionType) { - assert((kind == cir::UnaryOpKind::Plus || kind == cir::UnaryOpKind::Minus) && - "Invalid UnaryOp kind for ComplexType Plus or Minus"); - +mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e, + QualType promotionType) { mlir::Value op; if (!promotionType.isNull()) op = cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType); else op = Visit(e->getSubExpr()); - return builder.createUnaryOp(cgf.getLoc(e->getExprLoc()), kind, op); + return builder.createUnaryOp(cgf.getLoc(e->getExprLoc()), + cir::UnaryOpKind::Minus, op); } mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) { @@ -766,12 +770,10 @@ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e, } } else if (const auto *unaryOp = dyn_cast<UnaryOperator>(e)) { switch (unaryOp->getOpcode()) { + case UO_Plus: + return VisitUnaryPlus(unaryOp, promotionTy); case UO_Minus: - case UO_Plus: { - auto kind = unaryOp->getOpcode() == UO_Plus ? cir::UnaryOpKind::Plus - : cir::UnaryOpKind::Minus; - return VisitPlusMinus(unaryOp, kind, promotionTy); - } + return VisitUnaryMinus(unaryOp, promotionTy); default: break; } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 1b5ba5ee6783f..29aa35e762f45 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -766,25 +766,28 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { mlir::Value VisitUnaryPlus(const UnaryOperator *e) { QualType promotionType = getPromotionType(e->getSubExpr()->getType()); - mlir::Value result = - emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus, promotionType); + mlir::Value result = VisitUnaryPlus(e, promotionType); if (result && !promotionType.isNull()) return emitUnPromotedValue(result, e->getType()); return result; } + mlir::Value VisitUnaryPlus(const UnaryOperator *e, QualType promotionType) { + ignoreResultAssign = false; + if (!promotionType.isNull()) + return cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType); + return Visit(e->getSubExpr()); + } + mlir::Value VisitUnaryMinus(const UnaryOperator *e) { QualType promotionType = getPromotionType(e->getSubExpr()->getType()); - mlir::Value result = - emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus, promotionType); + mlir::Value result = VisitUnaryMinus(e, promotionType); if (result && !promotionType.isNull()) return emitUnPromotedValue(result, e->getType()); return result; } - mlir::Value emitUnaryPlusOrMinus(const UnaryOperator *e, - cir::UnaryOpKind kind, - QualType promotionType) { + mlir::Value VisitUnaryMinus(const UnaryOperator *e, QualType promotionType) { ignoreResultAssign = false; mlir::Value operand; if (!promotionType.isNull()) @@ -795,14 +798,13 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { // TODO(cir): We might have to change this to support overflow trapping. // Classic codegen routes unary minus through emitSub to ensure // that the overflow behavior is handled correctly. - bool nsw = kind == cir::UnaryOpKind::Minus && - e->getType()->isSignedIntegerType() && + bool nsw = e->getType()->isSignedIntegerType() && cgf.getLangOpts().getSignedOverflowBehavior() != LangOptions::SOB_Defined; // NOTE: LLVM codegen will lower this directly to either a FNeg // or a Sub instruction. In CIR this will be handled later in LowerToLLVM. - return emitUnaryOp(e, kind, operand, nsw); + return emitUnaryOp(e, cir::UnaryOpKind::Minus, operand, nsw); } mlir::Value emitUnaryOp(const UnaryOperator *e, cir::UnaryOpKind kind, @@ -1560,9 +1562,9 @@ mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e, case UO_Real: return VisitRealImag(uo, promotionType); case UO_Minus: - return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Minus, promotionType); + return VisitUnaryMinus(uo, promotionType); case UO_Plus: - return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Plus, promotionType); + return VisitUnaryPlus(uo, promotionType); default: break; } diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 8d2990af5de8c..87cf3950b04d6 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2671,7 +2671,6 @@ LogicalResult cir::UnaryOp::verify() { switch (getKind()) { case cir::UnaryOpKind::Inc: case cir::UnaryOpKind::Dec: - case cir::UnaryOpKind::Plus: case cir::UnaryOpKind::Minus: case cir::UnaryOpKind::Not: // Nothing to verify. @@ -2712,9 +2711,8 @@ OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) { // input attribute from the adapter, a new constant is materialized, but // if we return the input value directly, it avoids that. if (auto srcConst = getInput().getDefiningOp<cir::ConstantOp>()) { - if (getKind() == cir::UnaryOpKind::Plus || - (mlir::isa<cir::BoolType>(srcConst.getType()) && - getKind() == cir::UnaryOpKind::Minus)) + if (mlir::isa<cir::BoolType>(srcConst.getType()) && + getKind() == cir::UnaryOpKind::Minus) return srcConst.getResult(); } @@ -2733,8 +2731,6 @@ OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) { val.flipAllBits(); return cir::IntAttr::get(getType(), val); } - case cir::UnaryOpKind::Plus: - return attrT; case cir::UnaryOpKind::Minus: { APInt val = attrT.getValue(); val.negate(); @@ -2746,8 +2742,6 @@ OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) { }) .Case<cir::FPAttr>([&](cir::FPAttr attrT) { switch (getKind()) { - case cir::UnaryOpKind::Plus: - return attrT; case cir::UnaryOpKind::Minus: { APFloat val = attrT.getValue(); val.changeSign(); @@ -2761,7 +2755,6 @@ OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) { switch (getKind()) { case cir::UnaryOpKind::Not: return cir::BoolAttr::get(getContext(), !attrT.getValue()); - case cir::UnaryOpKind::Plus: case cir::UnaryOpKind::Minus: return attrT; default: diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 232d320d71f37..ad6c49ca87183 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -822,7 +822,6 @@ void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) { resultImag = operandImag; break; - case cir::UnaryOpKind::Plus: case cir::UnaryOpKind::Minus: resultReal = builder.createUnaryOp(loc, opKind, operandReal); resultImag = builder.createUnaryOp(loc, opKind, operandImag); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 8bcd040382ab3..58e7c8a65a1cd 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2726,7 +2726,7 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( mlir::Type llvmType = getTypeConverter()->convertType(type); mlir::Location loc = op.getLoc(); - // Integer unary operations: + - ~ ++ -- + // Integer unary operations: - ~ ++ -- if (mlir::isa<cir::IntType>(elementType)) { mlir::LLVM::IntegerOverflowFlags maybeNSW = op.getNoSignedWrap() ? mlir::LLVM::IntegerOverflowFlags::nsw @@ -2746,9 +2746,6 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( one, maybeNSW); return mlir::success(); } - case cir::UnaryOpKind::Plus: - rewriter.replaceOp(op, adaptor.getInput()); - return mlir::success(); case cir::UnaryOpKind::Minus: { mlir::Value zero; if (isVector) @@ -2780,7 +2777,7 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( llvm_unreachable("Unexpected unary op for int"); } - // Floating point unary operations: + - ++ -- + // Floating point unary operations: - ++ -- if (mlir::isa<cir::FPTypeInterface>(elementType)) { switch (op.getKind()) { case cir::UnaryOpKind::Inc: { @@ -2799,9 +2796,6 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( adaptor.getInput()); return mlir::success(); } - case cir::UnaryOpKind::Plus: - rewriter.replaceOp(op, adaptor.getInput()); - return mlir::success(); case cir::UnaryOpKind::Minus: rewriter.replaceOpWithNewOp<mlir::LLVM::FNegOp>(op, llvmType, adaptor.getInput()); @@ -2818,7 +2812,6 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( switch (op.getKind()) { case cir::UnaryOpKind::Inc: case cir::UnaryOpKind::Dec: - case cir::UnaryOpKind::Plus: case cir::UnaryOpKind::Minus: // Some of these are allowed in source code, but we shouldn't get here // with a boolean type. @@ -2834,19 +2827,6 @@ mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite( llvm_unreachable("Unexpected unary op for bool"); } - // Pointer unary operations: + only. (++ and -- of pointers are implemented - // with cir.ptr_stride, not cir.unary.) - if (mlir::isa<cir::PointerType>(elementType)) { - switch (op.getKind()) { - case cir::UnaryOpKind::Plus: - rewriter.replaceOp(op, adaptor.getInput()); - return mlir::success(); - default: - op.emitError() << "Unknown pointer unary operation during CIR lowering"; - return mlir::failure(); - } - } - return op.emitError() << "Unary operation has unsupported type: " << elementType; } diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 54f18064c8cbc..92129a041fd8e 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -39,9 +39,9 @@ static const ComplexType *getComplexType(QualType type) { } } -namespace { +namespace { class ComplexExprEmitter - : public StmtVisitor<ComplexExprEmitter, ComplexPairTy> { + : public StmtVisitor<ComplexExprEmitter, ComplexPairTy> { CodeGenFunction &CGF; CGBuilderTy &Builder; bool IgnoreReal; @@ -108,7 +108,9 @@ class ComplexExprEmitter Result->getAggregateElement(1U)); return Visit(E->getSubExpr()); } - ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());} + ComplexPairTy VisitParenExpr(ParenExpr *PE) { + return Visit(PE->getSubExpr()); + } ComplexPairTy VisitGenericSelectionExpr(GenericSelectionExpr *GE) { return Visit(GE->getResultExpr()); } @@ -185,15 +187,15 @@ class ComplexExprEmitter if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E)) CGF.CGM.EmitExplicitCastExprType(ECE, &CGF); if (E->changesVolatileQualification()) - return EmitLoadOfLValue(E); + return EmitLoadOfLValue(E); return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType()); } ComplexPairTy VisitCallExpr(const CallExpr *E); ComplexPairTy VisitStmtExpr(const StmtExpr *E); // Operators. - ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E, - bool isInc, bool isPre) { + ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E, bool isInc, + bool isPre) { LValue LV = CGF.EmitLValue(E->getSubExpr()); return CGF.EmitComplexPrePostIncDec(E, LV, isInc, isPre); } @@ -217,7 +219,7 @@ class ComplexExprEmitter ComplexPairTy VisitUnaryMinus(const UnaryOperator *E, QualType PromotionType = QualType()); ComplexPairTy VisitMinus(const UnaryOperator *E, QualType PromotionType); - ComplexPairTy VisitUnaryNot (const UnaryOperator *E); + ComplexPairTy VisitUnaryNot(const UnaryOperator *E); // LNot,Real,Imag never return complex. ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); @@ -247,15 +249,14 @@ class ComplexExprEmitter ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { assert(E->getType()->isAnyComplexType() && "Expected complex type!"); QualType Elem = E->getType()->castAs<ComplexType>()->getElementType(); - llvm::Constant *Null = - llvm::Constant::getNullValue(CGF.ConvertType(Elem)); + llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem)); return ComplexPairTy(Null, Null); } struct BinOpInfo { ComplexPairTy LHS; ComplexPairTy RHS; - QualType Ty; // Computation Type. + QualType Ty; // Computation Type. FPOptions FPFeatures; }; @@ -263,13 +264,13 @@ class ComplexExprEmitter QualType PromotionTy = QualType()); ComplexPairTy EmitPromoted(const Expr *E, QualType PromotionTy); ComplexPairTy EmitPromotedComplexOperand(const Expr *E, QualType PromotionTy); - LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func) - (const BinOpInfo &), - RValue &Val); - ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func) - (const BinOpInfo &)); + LValue EmitCompoundAssignLValue( + const CompoundAssignOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo &), + RValue &Val); + ComplexPairTy EmitCompoundAssign( + const CompoundAssignOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo &)); ComplexPairTy EmitBinAdd(const BinOpInfo &Op); ComplexPairTy EmitBinSub(const BinOpInfo &Op); @@ -381,11 +382,9 @@ class ComplexExprEmitter // No comparisons produce a complex result. - LValue EmitBinAssignLValue(const BinaryOperator *E, - ComplexPairTy &Val); - ComplexPairTy VisitBinAssign (const BinaryOperator *E); - ComplexPairTy VisitBinComma (const BinaryOperator *E); - + LValue EmitBinAssignLValue(const BinaryOperator *E, ComplexPairTy &Val); + ComplexPairTy VisitBinAssign(const BinaryOperator *E); + ComplexPairTy VisitBinComma(const BinaryOperator *E); ComplexPairTy VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO); @@ -407,7 +406,7 @@ class ComplexExprEmitter return Visit(E->getSelectedExpr()); } }; -} // end anonymous namespace. +} // end anonymous namespace. //===----------------------------------------------------------------------===// // Utilities @@ -469,8 +468,6 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue, CGF.addInstToCurrentSourceAtom(I, Val.second); } - - //===----------------------------------------------------------------------===// // Visitor Methods //===----------------------------------------------------------------------===// @@ -478,18 +475,17 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue, ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) { CGF.ErrorUnsupported(E, "complex expression"); llvm::Type *EltTy = - CGF.ConvertType(getComplexType(E->getType())->getElementType()); + CGF.ConvertType(getComplexType(E->getType())->getElementType()); llvm::Value *U = llvm::PoisonValue::get(EltTy); return ComplexPairTy(U, U); } -ComplexPairTy ComplexExprEmitter:: -VisitImaginaryLiteral(const ImaginaryLiteral *IL) { +ComplexPairTy +ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *IL) { llvm::Value *Imag = CGF.EmitScalarExpr(IL->getSubExpr()); return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag); } - ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) { if (E->getCallReturnType(CGF.getContext())->isReferenceType()) return EmitLoadOfLValue(E); @@ -539,7 +535,8 @@ ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val, ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/185199 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
