[clang] Upstream support for ATan2Op (FPToFPBuiltin) (PR #179078)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 31 16:39:49 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Ayokunle Amodu (ayokunle321)
<details>
<summary>Changes</summary>
This upstreams support for `builtin_elementwise_atan2`.
---
Patch is 121.10 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/179078.diff
4 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+766-979)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+11)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+9)
- (modified) clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c (+26)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index ee84df93b4933..0fa597a3dc5a8 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -73,16 +73,12 @@ include "mlir/Interfaces/SideEffectInterfaces.td"
//
// If you want fully customized LLVM IR lowering logic, simply exclude the
// `llvmOp` field from your CIR operation definition.
-class LLVMLoweringInfo {
- string llvmOp = "";
-}
+class LLVMLoweringInfo { string llvmOp = ""; }
-class LoweringBuilders<dag p> {
- dag dagParams = p;
-}
+class LoweringBuilders<dag p> { dag dagParams = p; }
-class CIR_Op<string mnemonic, list<Trait> traits = []> :
- Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo {
+class CIR_Op<string mnemonic, list<Trait> traits = []>
+ : Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo {
// Should we generate an ABI lowering pattern for this op?
bit hasCXXABILowering = false;
// Should we generate an LLVM lowering pattern for this op?
@@ -113,97 +109,94 @@ class CIR_Op<string mnemonic, list<Trait> traits = []> :
// CIR Operation Traits
//===----------------------------------------------------------------------===//
-class HasAtMostOneOfAttrsPred<list<string> names> :
- CPred<!foldl("0", names, acc, name, acc # " + (" # name # " ? 1 : 0)")
- # " <= 1">;
+class HasAtMostOneOfAttrsPred<list<string> names>
+ : CPred<!foldl("0", names, acc, name, acc#" + ("#name#" ? 1 : 0)")#" <= 1">;
-class HasAtMostOneOfAttrs<list<string> names> : PredOpTrait<
- "has only one of the optional attributes: " # !interleave(names, ", "),
- HasAtMostOneOfAttrsPred<!foreach(name, names, "$" # name)>
->;
+class HasAtMostOneOfAttrs<list<string> names>
+ : PredOpTrait<"has only one of the optional attributes: "#!interleave(names,
+ ", "),
+ HasAtMostOneOfAttrsPred<!foreach(name, names, "$"#name)>>;
//===----------------------------------------------------------------------===//
// CastOp
//===----------------------------------------------------------------------===//
-def CIR_CastKind : CIR_I32EnumAttr<"CastKind", "cast kind", [
- I32EnumAttrCase<"bitcast", 1>,
- // CK_LValueBitCast
- // CK_LValueToRValueBitCast
- // CK_LValueToRValue
- // CK_NoOp
- // CK_BaseToDerived
- // CK_DerivedToBase
- // CK_UncheckedDerivedToBase
- // CK_Dynamic
- // CK_ToUnion
- I32EnumAttrCase<"array_to_ptrdecay", 11>,
- // CK_FunctionToPointerDecay
- // CK_NullToPointer
- // CK_NullToMemberPointer
- // CK_BaseToDerivedMemberPointer
- // CK_DerivedToBaseMemberPointer
- I32EnumAttrCase<"member_ptr_to_bool", 17>,
- // CK_ReinterpretMemberPointer
- // CK_UserDefinedConversion
- // CK_ConstructorConversion
- I32EnumAttrCase<"int_to_ptr", 21>,
- I32EnumAttrCase<"ptr_to_int", 22>,
- I32EnumAttrCase<"ptr_to_bool", 23>,
- // CK_ToVoid
- // CK_MatrixCast
- // CK_VectorSplat
- I32EnumAttrCase<"integral", 27>,
- I32EnumAttrCase<"int_to_bool", 28>,
- I32EnumAttrCase<"int_to_float", 29>,
- // CK_FloatingToFixedPoint
- // CK_FixedPointToFloating
- // CK_FixedPointCast
- // CK_FixedPointToIntegral
- // CK_IntegralToFixedPoint
- // CK_FixedPointToBoolean
- I32EnumAttrCase<"float_to_int", 36>,
- I32EnumAttrCase<"float_to_bool", 37>,
- I32EnumAttrCase<"bool_to_int", 38>,
- I32EnumAttrCase<"floating", 39>,
- // CK_CPointerToObjCPointerCast
- // CK_BlockPointerToObjCPointerCast
- // CK_AnyPointerToBlockPointerCast
- // CK_ObjCObjectLValueCast
- I32EnumAttrCase<"float_to_complex", 44>,
- I32EnumAttrCase<"float_complex_to_real", 45>,
- I32EnumAttrCase<"float_complex_to_bool", 46>,
- I32EnumAttrCase<"float_complex", 47>,
- I32EnumAttrCase<"float_complex_to_int_complex", 48>,
- I32EnumAttrCase<"int_to_complex", 49>,
- I32EnumAttrCase<"int_complex_to_real", 50>,
- I32EnumAttrCase<"int_complex_to_bool", 51>,
- I32EnumAttrCase<"int_complex", 52>,
- I32EnumAttrCase<"int_complex_to_float_complex", 53>,
- // CK_ARCProduceObject
- // CK_ARCConsumeObject
- // CK_ARCReclaimReturnedObject
- // CK_ARCExtendBlockObject
- // CK_AtomicToNonAtomic
- // CK_NonAtomicToAtomic
- // CK_CopyAndAutoreleaseBlockObject
- // CK_BuiltinFnToFnPtr
- // CK_ZeroToOCLOpaqueType
- I32EnumAttrCase<"address_space", 63>,
- // CK_IntToOCLSampler
- // CK_HLSLVectorTruncation
- // CK_HLSLArrayRValue
- // CK_HLSLElementwiseCast
- // CK_HLSLAggregateSplatCast
-
- // Enums below are specific to CIR and don't have a correspondence to classic
- // codegen:
- I32EnumAttrCase<"bool_to_float", 1000>,
+def CIR_CastKind
+ : CIR_I32EnumAttr<
+ "CastKind", "cast kind",
+ [I32EnumAttrCase<"bitcast", 1>,
+ // CK_LValueBitCast
+ // CK_LValueToRValueBitCast
+ // CK_LValueToRValue
+ // CK_NoOp
+ // CK_BaseToDerived
+ // CK_DerivedToBase
+ // CK_UncheckedDerivedToBase
+ // CK_Dynamic
+ // CK_ToUnion
+ I32EnumAttrCase<"array_to_ptrdecay", 11>,
+ // CK_FunctionToPointerDecay
+ // CK_NullToPointer
+ // CK_NullToMemberPointer
+ // CK_BaseToDerivedMemberPointer
+ // CK_DerivedToBaseMemberPointer
+ I32EnumAttrCase<"member_ptr_to_bool", 17>,
+ // CK_ReinterpretMemberPointer
+ // CK_UserDefinedConversion
+ // CK_ConstructorConversion
+ I32EnumAttrCase<"int_to_ptr", 21>, I32EnumAttrCase<"ptr_to_int", 22>,
+ I32EnumAttrCase<"ptr_to_bool", 23>,
+ // CK_ToVoid
+ // CK_MatrixCast
+ // CK_VectorSplat
+ I32EnumAttrCase<"integral", 27>, I32EnumAttrCase<"int_to_bool", 28>,
+ I32EnumAttrCase<"int_to_float", 29>,
+ // CK_FloatingToFixedPoint
+ // CK_FixedPointToFloating
+ // CK_FixedPointCast
+ // CK_FixedPointToIntegral
+ // CK_IntegralToFixedPoint
+ // CK_FixedPointToBoolean
+ I32EnumAttrCase<"float_to_int", 36>,
+ I32EnumAttrCase<"float_to_bool", 37>,
+ I32EnumAttrCase<"bool_to_int", 38>, I32EnumAttrCase<"floating", 39>,
+ // CK_CPointerToObjCPointerCast
+ // CK_BlockPointerToObjCPointerCast
+ // CK_AnyPointerToBlockPointerCast
+ // CK_ObjCObjectLValueCast
+ I32EnumAttrCase<"float_to_complex", 44>,
+ I32EnumAttrCase<"float_complex_to_real", 45>,
+ I32EnumAttrCase<"float_complex_to_bool", 46>,
+ I32EnumAttrCase<"float_complex", 47>,
+ I32EnumAttrCase<"float_complex_to_int_complex", 48>,
+ I32EnumAttrCase<"int_to_complex", 49>,
+ I32EnumAttrCase<"int_complex_to_real", 50>,
+ I32EnumAttrCase<"int_complex_to_bool", 51>,
+ I32EnumAttrCase<"int_complex", 52>,
+ I32EnumAttrCase<"int_complex_to_float_complex", 53>,
+ // CK_ARCProduceObject
+ // CK_ARCConsumeObject
+ // CK_ARCReclaimReturnedObject
+ // CK_ARCExtendBlockObject
+ // CK_AtomicToNonAtomic
+ // CK_NonAtomicToAtomic
+ // CK_CopyAndAutoreleaseBlockObject
+ // CK_BuiltinFnToFnPtr
+ // CK_ZeroToOCLOpaqueType
+ I32EnumAttrCase<"address_space", 63>,
+ // CK_IntToOCLSampler
+ // CK_HLSLVectorTruncation
+ // CK_HLSLArrayRValue
+ // CK_HLSLElementwiseCast
+ // CK_HLSLAggregateSplatCast
+
+ // Enums below are specific to CIR and don't have a correspondence to
+ // classic codegen:
+ I32EnumAttrCase<"bool_to_float", 1000>,
]>;
-def CIR_CastOp : CIR_Op<"cast", [
- Pure, DeclareOpInterfaceMethods<PromotableOpInterface>
-]> {
+def CIR_CastOp
+ : CIR_Op<"cast", [Pure, DeclareOpInterfaceMethods<PromotableOpInterface>]> {
// FIXME: not all conversions are free of side effects.
let summary = "Conversion between values of different types";
let description = [{
@@ -271,11 +264,10 @@ def CIR_CastOp : CIR_Op<"cast", [
// DynamicCastOp
//===----------------------------------------------------------------------===//
-def CIR_DynamicCastKind : CIR_I32EnumAttr<
- "DynamicCastKind", "dynamic cast kind", [
- I32EnumAttrCase<"Ptr", 0, "ptr">,
- I32EnumAttrCase<"Ref", 1, "ref">
-]>;
+def CIR_DynamicCastKind
+ : CIR_I32EnumAttr<"DynamicCastKind", "dynamic cast kind",
+ [I32EnumAttrCase<"Ptr", 0, "ptr">,
+ I32EnumAttrCase<"Ref", 1, "ref">]>;
def CIR_DynamicCastOp : CIR_Op<"dyn_cast"> {
let summary = "Perform dynamic cast on record pointers";
@@ -329,16 +321,10 @@ def CIR_DynamicCastOp : CIR_Op<"dyn_cast"> {
```
}];
- let arguments = (ins
- CIR_DynamicCastKind:$kind,
- CIR_PtrToRecordType:$src,
- OptionalAttr<CIR_DynamicCastInfoAttr>:$info,
- UnitAttr:$relative_layout
- );
+ let arguments = (ins CIR_DynamicCastKind:$kind, CIR_PtrToRecordType:$src,
+ OptionalAttr<CIR_DynamicCastInfoAttr>:$info, UnitAttr:$relative_layout);
- let results = (outs
- CIR_PtrToAnyOf<[CIR_VoidType, CIR_RecordType]>:$result
- );
+ let results = (outs CIR_PtrToAnyOf<[CIR_VoidType, CIR_RecordType]>:$result);
let assemblyFormat = [{
$kind (`relative_layout` $relative_layout^)? $src
@@ -367,9 +353,8 @@ def CIR_DynamicCastOp : CIR_Op<"dyn_cast"> {
// PtrStrideOp
//===----------------------------------------------------------------------===//
-def CIR_PtrStrideOp : CIR_Op<"ptr_stride", [
- Pure, AllTypesMatch<["base", "result"]>
-]> {
+def CIR_PtrStrideOp
+ : CIR_Op<"ptr_stride", [Pure, AllTypesMatch<["base", "result"]>]> {
let summary = "Pointer access with stride";
let description = [{
The `cir.ptr_stride` operation computes a new pointer from a base pointer
@@ -382,10 +367,8 @@ def CIR_PtrStrideOp : CIR_Op<"ptr_stride", [
```
}];
- let arguments = (ins
- CIR_PointerType:$base,
- CIR_AnyFundamentalIntType:$stride
- );
+ let arguments = (ins CIR_PointerType:$base,
+ CIR_AnyFundamentalIntType:$stride);
let results = (outs CIR_PointerType:$result);
@@ -405,9 +388,8 @@ def CIR_PtrStrideOp : CIR_Op<"ptr_stride", [
// ConstantOp
//===----------------------------------------------------------------------===//
-def CIR_ConstantOp : CIR_Op<"const", [
- ConstantLike, Pure, AllTypesMatch<["value", "res"]>
-]> {
+def CIR_ConstantOp
+ : CIR_Op<"const", [ConstantLike, Pure, AllTypesMatch<["value", "res"]>]> {
let summary = "Create a CIR constant from a literal attribute";
let description = [{
The `cir.const` operation turns a literal into an SSA value. The data is
@@ -488,46 +470,47 @@ def CIR_ConstantOp : CIR_Op<"const", [
// C/C++ memory order definitions
//===----------------------------------------------------------------------===//
-def CIR_MemOrder : CIR_I32EnumAttr<
- "MemOrder", "Memory order according to C++11 memory model", [
- I32EnumAttrCase<"Relaxed", 0, "relaxed">,
- I32EnumAttrCase<"Consume", 1, "consume">,
- I32EnumAttrCase<"Acquire", 2, "acquire">,
- I32EnumAttrCase<"Release", 3, "release">,
- I32EnumAttrCase<"AcquireRelease", 4, "acq_rel">,
- I32EnumAttrCase<"SequentiallyConsistent", 5, "seq_cst">
-]>;
+def CIR_MemOrder
+ : CIR_I32EnumAttr<
+ "MemOrder", "Memory order according to C++11 memory model",
+ [I32EnumAttrCase<"Relaxed", 0, "relaxed">,
+ I32EnumAttrCase<"Consume", 1, "consume">,
+ I32EnumAttrCase<"Acquire", 2, "acquire">,
+ I32EnumAttrCase<"Release", 3, "release">,
+ I32EnumAttrCase<"AcquireRelease", 4, "acq_rel">,
+ I32EnumAttrCase<"SequentiallyConsistent", 5, "seq_cst">]>;
//===----------------------------------------------------------------------===//
// C/C++ sync scope definitions
//===----------------------------------------------------------------------===//
-def CIR_SyncScopeKind : CIR_I32EnumAttr<"SyncScopeKind", "sync scope kind", [
- I32EnumAttrCase<"SingleThread", 0, "single_thread">,
- I32EnumAttrCase<"System", 1, "system">
-]>;
+def CIR_SyncScopeKind
+ : CIR_I32EnumAttr<"SyncScopeKind", "sync scope kind",
+ [I32EnumAttrCase<"SingleThread", 0, "single_thread">,
+ I32EnumAttrCase<"System", 1, "system">]>;
//===----------------------------------------------------------------------===//
// AllocaOp
//===----------------------------------------------------------------------===//
-class CIR_AllocaTypesMatchWith<
- string summary, string lhsArg, string rhsArg, string transform,
- string comparator = "std::equal_to<>()"
-> : PredOpTrait<summary, CPred<comparator # "(" #
- !subst("$_self", "$" # lhsArg # ".getType()", transform) #
- ", $" # rhsArg # ")">
-> {
+class CIR_AllocaTypesMatchWith<string summary, string lhsArg, string rhsArg,
+ string transform,
+ string comparator = "std::equal_to<>()">
+ : PredOpTrait<summary,
+ CPred<comparator#"("#!subst("$_self", "$"#lhsArg#".getType()",
+ transform)#", $"#rhsArg#")">> {
string lhs = lhsArg;
string rhs = rhsArg;
string transformer = transform;
}
-def CIR_AllocaOp : CIR_Op<"alloca", [
- CIR_AllocaTypesMatchWith<"'allocaType' matches pointee type of 'addr'",
- "addr", "allocaType", "mlir::cast<cir::PointerType>($_self).getPointee()">,
- DeclareOpInterfaceMethods<PromotableAllocationOpInterface>
-]> {
+def CIR_AllocaOp
+ : CIR_Op<"alloca",
+ [CIR_AllocaTypesMatchWith<
+ "'allocaType' matches pointee type of 'addr'", "addr",
+ "allocaType",
+ "mlir::cast<cir::PointerType>($_self).getPointee()">,
+ DeclareOpInterfaceMethods<PromotableAllocationOpInterface>]> {
let summary = "Defines a scope-local variable";
let description = [{
The `cir.alloca` operation defines a scope-local variable.
@@ -554,37 +537,28 @@ def CIR_AllocaOp : CIR_Op<"alloca", [
```
}];
- let arguments = (ins
- Optional<CIR_AnyFundamentalIntType>:$dynAllocSize,
- TypeAttr:$allocaType,
- StrAttr:$name,
- UnitAttr:$init,
- UnitAttr:$constant,
- ConfinedAttr<I64Attr, [IntMinValue<1>]>:$alignment,
- OptionalAttr<ArrayAttr>:$annotations
- );
+ let arguments = (ins Optional<CIR_AnyFundamentalIntType>:$dynAllocSize,
+ TypeAttr:$allocaType, StrAttr:$name, UnitAttr:$init, UnitAttr:$constant,
+ ConfinedAttr<I64Attr, [IntMinValue<1>]>:$alignment,
+ OptionalAttr<ArrayAttr>:$annotations);
- let results = (outs Res<CIR_PointerType, "",
- [MemAlloc<AutomaticAllocationScopeResource>]>:$addr);
+ let results =
+ (outs Res<CIR_PointerType,
+ "", [MemAlloc<AutomaticAllocationScopeResource>]>:$addr);
let skipDefaultBuilders = 1;
- let builders = [
- OpBuilder<(ins "mlir::Type":$addr,
- "mlir::Type":$allocaType,
- "llvm::StringRef":$name,
- "mlir::IntegerAttr":$alignment)>,
-
- OpBuilder<(ins "mlir::Type":$addr,
- "mlir::Type":$allocaType,
- "llvm::StringRef":$name,
- "mlir::IntegerAttr":$alignment,
- "mlir::Value":$dynAllocSize),
- [{
+ let builders = [OpBuilder<(ins "mlir::Type":$addr, "mlir::Type":$allocaType,
+ "llvm::StringRef":$name, "mlir::IntegerAttr":$alignment)>,
+
+ OpBuilder<(ins "mlir::Type":$addr, "mlir::Type":$allocaType,
+ "llvm::StringRef":$name,
+ "mlir::IntegerAttr":$alignment,
+ "mlir::Value":$dynAllocSize),
+ [{
if (dynAllocSize)
$_state.addOperands(dynAllocSize);
build($_builder, $_state, addr, allocaType, name, alignment);
- }]>
- ];
+ }]>];
let extraClassDeclaration = [{
// Whether the alloca input type is a pointer.
@@ -609,11 +583,12 @@ def CIR_AllocaOp : CIR_Op<"alloca", [
// LoadOp
//===----------------------------------------------------------------------===//
-def CIR_LoadOp : CIR_Op<"load", [
- TypesMatchWith<"type of 'result' matches pointee type of 'addr'",
- "addr", "result", "mlir::cast<cir::PointerType>($_self).getPointee()">,
- DeclareOpInterfaceMethods<PromotableMemOpInterface>
-]> {
+def CIR_LoadOp
+ : CIR_Op<"load", [TypesMatchWith<
+ "type of 'result' matches pointee type of 'addr'",
+ "addr", "result",
+ "mlir::cast<cir::PointerType>($_self).getPointee()">,
+ DeclareOpInterfaceMethods<PromotableMemOpInterface>]> {
let summary = "Load value from memory adddress";
let description = [{
`cir.load` reads a value (lvalue to rvalue conversion) given an address
@@ -644,13 +619,12 @@ def CIR_LoadOp : CIR_Op<"load", [
```
}];
- let arguments = (ins Arg<CIR_PointerType, "the address to load from",
- [MemRead]>:$addr,
- UnitAttr:$isDeref,
- UnitAttr:$is_volatile,
- OptionalAttr<I64Attr>:$alignment,
- OptionalAttr<CIR_SyncScopeKind>:$sync_scope,
- OptionalAttr<CIR_MemOrder>:$mem_order);
+ let arguments =
+ (ins Arg<CIR_PointerType, "the address to load from", [MemRead]>:$addr,
+ UnitAttr:$isDeref, UnitAttr:$is_volatile,
+ OptionalAttr<I64Attr>:$alignment,
+ OptionalAttr<CIR_SyncScopeKind>:$sync_scope,
+ OptionalAttr<CIR_MemOrder>:$mem_order);
let results = (outs CIR_AnyType:$result);
let assemblyFormat = [{
@@ -669,11 +643,12 @@ def CIR_LoadOp : CIR_Op<"load", [
// StoreOp
//===----------------------------------------------------------------------===//
-def CIR_StoreOp : CIR_Op<"store", [
- TypesMatchWith<"type of 'value' matches pointee type of 'addr'",
- "addr", "value", "mlir::cast<cir::PointerType>($_self).getPointee()">,
- DeclareOpInterfaceMethods<PromotableMemOpInterface>
-]> {
+def CIR_StoreOp
+ : CIR_Op<"store", [TypesMatchWith<
+ "type of 'value' matches pointee type of 'addr'",
+ "addr", "value",
+ "mlir::cast<cir::PointerType>($_self).getPointee()">,
+ DeclareOpInterfaceMethods<PromotableMemOpInterface>]> {
let summary = "Store value to memory address";
let description = [{
`cir.store` stores a value (first operand) to the memory address specified
@@ -699,12 +674,10 @@ def CIR_StoreOp : CIR_Op<"store", [
}];
let arguments = (ins CIR_AnyType:$value,
- Arg<CIR_PointerType, "the address to store the value",
- [MemWrite]>:$addr,
- UnitAttr:$is_volatile,
- OptionalAttr<I64Attr>:$alignment,
- OptionalAttr<CIR_SyncScopeKind>:$sync_scope,
- OptionalAttr<CIR_MemOrder>:$mem_order);
+ Arg<CIR_PointerType, "the address to store the value", [MemWrite]>:$addr,
+ UnitAttr:$is_volatile, OptionalAttr<I64Attr>:$alignment,
+ OptionalAttr<CIR_SyncScopeKind>:$sync_scope,
+ OptionalAttr<CIR_MemOrder>:$mem_order);
let assemblyFormat = [{
(`volatile` $is_volatile^)?
@@ -721,14 +694,12 @@ def CIR_StoreOp : CIR_Op<"store", [
// ReturnOp
//===----------------------------------------------------------------------===//
-defvar CIR_ReturnableScopes = [
- "FuncOp", "ScopeOp", "IfOp", "SwitchOp", "CaseOp",
- "DoWhileOp", "WhileOp", "ForOp", "TryOp"
-];
+defvar CIR_ReturnableScopes = ["FuncOp", "ScopeOp", "IfOp", "SwitchOp",
+ "CaseOp", "DoWhileOp", "WhileOp", "ForOp",
+ "TryOp"];
-def CIR_ReturnOp : CIR_Op<"return", [
- ParentOneOf<CIR_ReturnableScopes>, Terminator
-]> {
+def CIR_ReturnOp
+ : CIR_Op<"return", [ParentOneOf<CIR_ReturnableScopes>, Terminator]> {
let summary = "Return from function";
let description = [{
The "return" operation represents a return operation within a function.
@@ -752,9 +723,7 @@ def CIR_ReturnOp : CIR_Op<"return", [
l...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/179078
More information about the cfe-commits
mailing list