[clang] 4bf846b - [RISCV] Split out part of riscv_vector.td to riscv_vector_common.td

via cfe-commits cfe-commits at lists.llvm.org
Tue May 2 05:46:02 PDT 2023


Author: 4vtomat
Date: 2023-05-02T05:40:13-07:00
New Revision: 4bf846ba40f1867889e13596cdcd06ed6f036c7f

URL: https://github.com/llvm/llvm-project/commit/4bf846ba40f1867889e13596cdcd06ed6f036c7f
DIFF: https://github.com/llvm/llvm-project/commit/4bf846ba40f1867889e13596cdcd06ed6f036c7f.diff

LOG: [RISCV] Split out part of riscv_vector.td to riscv_vector_common.td

This makes other new targets able to reuse predefined classes
in their own *.td files.

Differential Revision: https://reviews.llvm.org/D148680

Added: 
    clang/include/clang/Basic/riscv_vector_common.td

Modified: 
    clang/include/clang/Basic/riscv_vector.td

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td
index aec204afdccb..f9e9c7d80cca 100644
--- a/clang/include/clang/Basic/riscv_vector.td
+++ b/clang/include/clang/Basic/riscv_vector.td
@@ -12,233 +12,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-//===----------------------------------------------------------------------===//
-// Instruction definitions
-//===----------------------------------------------------------------------===//
-// Each record of the class RVVBuiltin defines a collection of builtins (i.e.
-// "def vadd : RVVBuiltin" will be used to define things like "vadd_vv_i32m1",
-// "vadd_vv_i32m2", etc).
-//
-// The elements of this collection are defined by an instantiation process the
-// range of which is specified by the cross product of the LMUL attribute and
-// every element in the attribute TypeRange. By default builtins have LMUL = [1,
-// 2, 4, 8, 1/2, 1/4, 1/8] so the process is repeated 7 times. In tablegen we
-// use the Log2LMUL [0, 1, 2, 3, -1, -2, -3] to represent the LMUL.
-//
-// LMUL represents the fact that the types of values used by that builtin are
-// values generated by instructions that are executed under that LMUL. However,
-// this does not mean the builtin is necessarily lowered into an instruction
-// that executes under the specified LMUL. An example where this happens are
-// loads and stores of masks. A mask like `vbool8_t` can be generated, for
-// instance, by comparing two `__rvv_int8m1_t` (this is LMUL=1) or comparing two
-// `__rvv_int16m2_t` (this is LMUL=2). The actual load or store, however, will
-// be performed under LMUL=1 because mask registers are not grouped.
-//
-// TypeRange is a non-empty sequence of basic types:
-//
-//   c: int8_t (i8)
-//   s: int16_t (i16)
-//   i: int32_t (i32)
-//   l: int64_t (i64)
-//   x: float16_t (half)
-//   f: float32_t (float)
-//   d: float64_t (double)
-//
-// This way, given an LMUL, a record with a TypeRange "sil" will cause the
-// definition of 3 builtins. Each type "t" in the TypeRange (in this example
-// they are int16_t, int32_t, int64_t) is used as a parameter that drives the
-// definition of that particular builtin (for the given LMUL).
-//
-// During the instantiation, types can be transformed or modified using type
-// transformers. Given a type "t" the following primitive type transformers can
-// be applied to it to yield another type.
-//
-//   e: type of "t" as is (identity)
-//   v: computes a vector type whose element type is "t" for the current LMUL
-//   w: computes a vector type identical to what 'v' computes except for the
-//      element type which is twice as wide as the element type of 'v'
-//   q: computes a vector type identical to what 'v' computes except for the
-//      element type which is four times as wide as the element type of 'v'
-//   o: computes a vector type identical to what 'v' computes except for the
-//      element type which is eight times as wide as the element type of 'v'
-//   m: computes a vector type identical to what 'v' computes except for the
-//      element type which is bool
-//   0: void type, ignores "t"
-//   z: size_t, ignores "t"
-//   t: ptr
diff _t, ignores "t"
-//   u: unsigned long, ignores "t"
-//   l: long, ignores "t"
-//
-// So for instance if t is "i", i.e. int, then "e" will yield int again. "v"
-// will yield an RVV vector type (assume LMUL=1), so __rvv_int32m1_t.
-// Accordingly "w" would yield __rvv_int64m2_t.
-//
-// A type transformer can be prefixed by other non-primitive type transformers.
-//
-//   P: constructs a pointer to the current type
-//   C: adds const to the type
-//   K: requires the integer type to be a constant expression
-//   U: given an integer type or vector type, computes its unsigned variant
-//   I: given a vector type, compute the vector type with integer type
-//      elements of the same width
-//   F: given a vector type, compute the vector type with floating-point type
-//      elements of the same width
-//   S: given a vector type, computes its equivalent one for LMUL=1. This is a
-//      no-op if the vector was already LMUL=1
-//   (Log2EEW:Value): Log2EEW value could be 3/4/5/6 (8/16/32/64), given a
-//      vector type (SEW and LMUL) and EEW (8/16/32/64), computes its
-//      equivalent integer vector type with EEW and corresponding ELMUL (elmul =
-//      (eew/sew) * lmul). For example, vector type is __rvv_float16m4
-//      (SEW=16, LMUL=4) and Log2EEW is 3 (EEW=8), and then equivalent vector
-//      type is __rvv_uint8m2_t (elmul=(8/16)*4 = 2). Ignore to define a new
-//      builtins if its equivalent type has illegal lmul.
-//   (FixedSEW:Value): Given a vector type (SEW and LMUL), and computes another
-//      vector type which only changed SEW as given value. Ignore to define a new
-//      builtin if its equivalent type has illegal lmul or the SEW does not changed.
-//   (SFixedLog2LMUL:Value): Smaller Fixed Log2LMUL. Given a vector type (SEW
-//      and LMUL), and computes another vector type which only changed LMUL as
-//      given value. The new LMUL should be smaller than the old one. Ignore to
-//      define a new builtin if its equivalent type has illegal lmul.
-//   (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW
-//      and LMUL), and computes another vector type which only changed LMUL as
-//      given value. The new LMUL should be larger than the old one. Ignore to
-//      define a new builtin if its equivalent type has illegal lmul.
-//
-// Following with the example above, if t is "i", then "Ue" will yield unsigned
-// int and "Fv" will yield __rvv_float32m1_t (again assuming LMUL=1), Fw would
-// yield __rvv_float64m2_t, etc.
-//
-// Each builtin is then defined by applying each type in TypeRange against the
-// sequence of type transformers described in Suffix and Prototype.
-//
-// The name of the builtin is defined by the Name attribute (which defaults to
-// the name of the class) appended (separated with an underscore) the Suffix
-// attribute. For instance with Name="foo", Suffix = "v" and TypeRange = "il",
-// the builtin generated will be __builtin_rvv_foo_i32m1 and
-// __builtin_rvv_foo_i64m1 (under LMUL=1). If Suffix contains more than one
-// type transformer (say "vv") each of the types is separated with an
-// underscore as in "__builtin_rvv_foo_i32m1_i32m1".
-//
-// The C/C++ prototype of the builtin is defined by the Prototype attribute.
-// Prototype is a non-empty sequence of type transformers, the first of which
-// is the return type of the builtin and the rest are the parameters of the
-// builtin, in order. For instance if Prototype is "wvv" and TypeRange is "si"
-// a first builtin will have type
-// __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t) and the second builtin
-// will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t) (again
-// under LMUL=1).
-//
-// There are a number of attributes that are used to constraint the number and
-// shape of the builtins generated. Refer to the comments below for them.
-
-class PolicyScheme<int val>{
-  int Value = val;
-}
-def NonePolicy : PolicyScheme<0>;
-def HasPassthruOperand : PolicyScheme<1>;
-def HasPolicyOperand : PolicyScheme<2>;
-
-class RVVBuiltin<string suffix, string prototype, string type_range,
-                 string overloaded_suffix = ""> {
-  // Base name that will be prepended in __builtin_rvv_ and appended the
-  // computed Suffix.
-  string Name = NAME;
-
-  // If not empty, each instantiated builtin will have this appended after an
-  // underscore (_). It is instantiated like Prototype.
-  string Suffix = suffix;
-
-  // If empty, default OverloadedName is sub string of `Name` which end of first
-  // '_'. For example, the default overloaded name  is `vadd` for Name `vadd_vv`.
-  // It's used for describe some special naming cases.
-  string OverloadedName = "";
-
-  // If not empty, each OverloadedName will have this appended after an
-  // underscore (_). It is instantiated like Prototype.
-  string OverloadedSuffix = overloaded_suffix;
-
-  // The 
diff erent variants of the builtin, parameterised with a type.
-  string TypeRange = type_range;
-
-  // We use each type described in TypeRange and LMUL with prototype to
-  // instantiate a specific element of the set of builtins being defined.
-  // Prototype attribute defines the C/C++ prototype of the builtin. It is a
-  // non-empty sequence of type transformers, the first of which is the return
-  // type of the builtin and the rest are the parameters of the builtin, in
-  // order. For instance if Prototype is "wvv", TypeRange is "si" and LMUL=1, a
-  // first builtin will have type
-  // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t), and the second builtin
-  // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t).
-  string Prototype = prototype;
-
-  // This builtin has a masked form.
-  bit HasMasked = true;
-
-  // If HasMasked, this flag states that this builtin has a maskedoff operand. It
-  // is always the first operand in builtin and IR intrinsic.
-  bit HasMaskedOffOperand = true;
-
-  // This builtin has a granted vector length parameter.
-  bit HasVL = true;
-
-  // The policy scheme for masked intrinsic IR.
-  // It could be NonePolicy or HasPolicyOperand.
-  // HasPolicyOperand: Has a policy operand. 0 is tail and mask undisturbed, 1 is
-  // tail agnostic, 2 is mask undisturbed, and 3 is tail and mask agnostic. The
-  // policy operand is located at the last position.
-  PolicyScheme MaskedPolicyScheme = HasPolicyOperand;
-
-  // The policy scheme for unmasked intrinsic IR.
-  // It could be NonePolicy, HasPassthruOperand or HasPolicyOperand.
-  // HasPassthruOperand: Has a passthru operand to decide tail policy. If it is
-  // poison, tail policy is tail agnostic, otherwise policy is tail undisturbed.
-  // HasPolicyOperand: Has a policy operand. 1 is tail agnostic and 0 is tail
-  // undisturbed.
-  PolicyScheme UnMaskedPolicyScheme = NonePolicy;
-
-  // This builtin support tail agnostic and undisturbed policy.
-  bit HasTailPolicy = true;
-  // This builtin support mask agnostic and undisturbed policy.
-  bit HasMaskPolicy = true;
-
-  // This builtin prototype with TA or TAMA policy could not support overloading
-  // API. Other policy intrinsic functions would support overloading API with
-  // suffix `_tu`, `tumu`, `tuma`, `tamu` and `tama`.
-  bit SupportOverloading = true;
-
-  // This builtin is valid for the given Log2LMULs.
-  list<int> Log2LMUL = [0, 1, 2, 3, -1, -2, -3];
-
-  // Manual code in clang codegen riscv_vector_builtin_cg.inc
-  code ManualCodegen = [{}];
-
-  // When emit the automatic clang codegen, it describes what types we have to use
-  // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise,
-  // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd
-  // parameter of the unmasked version. k can't be the mask operand's position.
-  list<int> IntrinsicTypes = [];
-
-  // If these names are not empty, this is the ID of the LLVM intrinsic
-  // we want to lower to.
-  string IRName = NAME;
-
-  // If HasMasked, this is the ID of the LLVM intrinsic we want to lower to.
-  string MaskedIRName = NAME #"_mask";
-
-  // Use clang_builtin_alias to save the number of builtins.
-  bit HasBuiltinAlias = true;
-
-  // Features required to enable for this builtin.
-  list<string> RequiredFeatures = [];
-
-  // Number of fields for Load/Store Segment instructions.
-  int NF = 1;
-}
-
-// This is the code emitted in the header.
-class RVVHeader {
-  code HeaderCode;
-}
+include "riscv_vector_common.td"
 
 //===----------------------------------------------------------------------===//
 // Basic classes with automatic codegen.

diff  --git a/clang/include/clang/Basic/riscv_vector_common.td b/clang/include/clang/Basic/riscv_vector_common.td
new file mode 100644
index 000000000000..6fd1dbde52be
--- /dev/null
+++ b/clang/include/clang/Basic/riscv_vector_common.td
@@ -0,0 +1,239 @@
+//==------ riscv_vector_common.td - RISC-V V-ext builtin class ------------===//
+//
+//  Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+//  See https://llvm.org/LICENSE.txt for license information.
+//  SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines RVV builtin base class for RISC-V V-extension.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction definitions
+//===----------------------------------------------------------------------===//
+// Each record of the class RVVBuiltin defines a collection of builtins (i.e.
+// "def vadd : RVVBuiltin" will be used to define things like "vadd_vv_i32m1",
+// "vadd_vv_i32m2", etc).
+//
+// The elements of this collection are defined by an instantiation process the
+// range of which is specified by the cross product of the LMUL attribute and
+// every element in the attribute TypeRange. By default builtins have LMUL = [1,
+// 2, 4, 8, 1/2, 1/4, 1/8] so the process is repeated 7 times. In tablegen we
+// use the Log2LMUL [0, 1, 2, 3, -1, -2, -3] to represent the LMUL.
+//
+// LMUL represents the fact that the types of values used by that builtin are
+// values generated by instructions that are executed under that LMUL. However,
+// this does not mean the builtin is necessarily lowered into an instruction
+// that executes under the specified LMUL. An example where this happens are
+// loads and stores of masks. A mask like `vbool8_t` can be generated, for
+// instance, by comparing two `__rvv_int8m1_t` (this is LMUL=1) or comparing two
+// `__rvv_int16m2_t` (this is LMUL=2). The actual load or store, however, will
+// be performed under LMUL=1 because mask registers are not grouped.
+//
+// TypeRange is a non-empty sequence of basic types:
+//
+//   c: int8_t (i8)
+//   s: int16_t (i16)
+//   i: int32_t (i32)
+//   l: int64_t (i64)
+//   x: float16_t (half)
+//   f: float32_t (float)
+//   d: float64_t (double)
+//
+// This way, given an LMUL, a record with a TypeRange "sil" will cause the
+// definition of 3 builtins. Each type "t" in the TypeRange (in this example
+// they are int16_t, int32_t, int64_t) is used as a parameter that drives the
+// definition of that particular builtin (for the given LMUL).
+//
+// During the instantiation, types can be transformed or modified using type
+// transformers. Given a type "t" the following primitive type transformers can
+// be applied to it to yield another type.
+//
+//   e: type of "t" as is (identity)
+//   v: computes a vector type whose element type is "t" for the current LMUL
+//   w: computes a vector type identical to what 'v' computes except for the
+//      element type which is twice as wide as the element type of 'v'
+//   q: computes a vector type identical to what 'v' computes except for the
+//      element type which is four times as wide as the element type of 'v'
+//   o: computes a vector type identical to what 'v' computes except for the
+//      element type which is eight times as wide as the element type of 'v'
+//   m: computes a vector type identical to what 'v' computes except for the
+//      element type which is bool
+//   0: void type, ignores "t"
+//   z: size_t, ignores "t"
+//   t: ptr
diff _t, ignores "t"
+//   u: unsigned long, ignores "t"
+//   l: long, ignores "t"
+//
+// So for instance if t is "i", i.e. int, then "e" will yield int again. "v"
+// will yield an RVV vector type (assume LMUL=1), so __rvv_int32m1_t.
+// Accordingly "w" would yield __rvv_int64m2_t.
+//
+// A type transformer can be prefixed by other non-primitive type transformers.
+//
+//   P: constructs a pointer to the current type
+//   C: adds const to the type
+//   K: requires the integer type to be a constant expression
+//   U: given an integer type or vector type, computes its unsigned variant
+//   I: given a vector type, compute the vector type with integer type
+//      elements of the same width
+//   F: given a vector type, compute the vector type with floating-point type
+//      elements of the same width
+//   S: given a vector type, computes its equivalent one for LMUL=1. This is a
+//      no-op if the vector was already LMUL=1
+//   (Log2EEW:Value): Log2EEW value could be 3/4/5/6 (8/16/32/64), given a
+//      vector type (SEW and LMUL) and EEW (8/16/32/64), computes its
+//      equivalent integer vector type with EEW and corresponding ELMUL (elmul =
+//      (eew/sew) * lmul). For example, vector type is __rvv_float16m4
+//      (SEW=16, LMUL=4) and Log2EEW is 3 (EEW=8), and then equivalent vector
+//      type is __rvv_uint8m2_t (elmul=(8/16)*4 = 2). Ignore to define a new
+//      builtins if its equivalent type has illegal lmul.
+//   (FixedSEW:Value): Given a vector type (SEW and LMUL), and computes another
+//      vector type which only changed SEW as given value. Ignore to define a new
+//      builtin if its equivalent type has illegal lmul or the SEW does not changed.
+//   (SFixedLog2LMUL:Value): Smaller Fixed Log2LMUL. Given a vector type (SEW
+//      and LMUL), and computes another vector type which only changed LMUL as
+//      given value. The new LMUL should be smaller than the old one. Ignore to
+//      define a new builtin if its equivalent type has illegal lmul.
+//   (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW
+//      and LMUL), and computes another vector type which only changed LMUL as
+//      given value. The new LMUL should be larger than the old one. Ignore to
+//      define a new builtin if its equivalent type has illegal lmul.
+//
+// Following with the example above, if t is "i", then "Ue" will yield unsigned
+// int and "Fv" will yield __rvv_float32m1_t (again assuming LMUL=1), Fw would
+// yield __rvv_float64m2_t, etc.
+//
+// Each builtin is then defined by applying each type in TypeRange against the
+// sequence of type transformers described in Suffix and Prototype.
+//
+// The name of the builtin is defined by the Name attribute (which defaults to
+// the name of the class) appended (separated with an underscore) the Suffix
+// attribute. For instance with Name="foo", Suffix = "v" and TypeRange = "il",
+// the builtin generated will be __builtin_rvv_foo_i32m1 and
+// __builtin_rvv_foo_i64m1 (under LMUL=1). If Suffix contains more than one
+// type transformer (say "vv") each of the types is separated with an
+// underscore as in "__builtin_rvv_foo_i32m1_i32m1".
+//
+// The C/C++ prototype of the builtin is defined by the Prototype attribute.
+// Prototype is a non-empty sequence of type transformers, the first of which
+// is the return type of the builtin and the rest are the parameters of the
+// builtin, in order. For instance if Prototype is "wvv" and TypeRange is "si"
+// a first builtin will have type
+// __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t) and the second builtin
+// will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t) (again
+// under LMUL=1).
+//
+// There are a number of attributes that are used to constraint the number and
+// shape of the builtins generated. Refer to the comments below for them.
+
+class PolicyScheme<int val>{
+  int Value = val;
+}
+def NonePolicy : PolicyScheme<0>;
+def HasPassthruOperand : PolicyScheme<1>;
+def HasPolicyOperand : PolicyScheme<2>;
+
+class RVVBuiltin<string suffix, string prototype, string type_range,
+                 string overloaded_suffix = ""> {
+  // Base name that will be prepended in __builtin_rvv_ and appended the
+  // computed Suffix.
+  string Name = NAME;
+
+  // If not empty, each instantiated builtin will have this appended after an
+  // underscore (_). It is instantiated like Prototype.
+  string Suffix = suffix;
+
+  // If empty, default OverloadedName is sub string of `Name` which end of first
+  // '_'. For example, the default overloaded name  is `vadd` for Name `vadd_vv`.
+  // It's used for describe some special naming cases.
+  string OverloadedName = "";
+
+  // If not empty, each OverloadedName will have this appended after an
+  // underscore (_). It is instantiated like Prototype.
+  string OverloadedSuffix = overloaded_suffix;
+
+  // The 
diff erent variants of the builtin, parameterised with a type.
+  string TypeRange = type_range;
+
+  // We use each type described in TypeRange and LMUL with prototype to
+  // instantiate a specific element of the set of builtins being defined.
+  // Prototype attribute defines the C/C++ prototype of the builtin. It is a
+  // non-empty sequence of type transformers, the first of which is the return
+  // type of the builtin and the rest are the parameters of the builtin, in
+  // order. For instance if Prototype is "wvv", TypeRange is "si" and LMUL=1, a
+  // first builtin will have type
+  // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t), and the second builtin
+  // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t).
+  string Prototype = prototype;
+
+  // This builtin has a masked form.
+  bit HasMasked = true;
+
+  // If HasMasked, this flag states that this builtin has a maskedoff operand. It
+  // is always the first operand in builtin and IR intrinsic.
+  bit HasMaskedOffOperand = true;
+
+  // This builtin has a granted vector length parameter.
+  bit HasVL = true;
+
+  // The policy scheme for masked intrinsic IR.
+  // It could be NonePolicy or HasPolicyOperand.
+  // HasPolicyOperand: Has a policy operand. 0 is tail and mask undisturbed, 1 is
+  // tail agnostic, 2 is mask undisturbed, and 3 is tail and mask agnostic. The
+  // policy operand is located at the last position.
+  PolicyScheme MaskedPolicyScheme = HasPolicyOperand;
+
+  // The policy scheme for unmasked intrinsic IR.
+  // It could be NonePolicy, HasPassthruOperand or HasPolicyOperand.
+  // HasPassthruOperand: Has a passthru operand to decide tail policy. If it is
+  // poison, tail policy is tail agnostic, otherwise policy is tail undisturbed.
+  // HasPolicyOperand: Has a policy operand. 1 is tail agnostic and 0 is tail
+  // undisturbed.
+  PolicyScheme UnMaskedPolicyScheme = NonePolicy;
+
+  // This builtin support tail agnostic and undisturbed policy.
+  bit HasTailPolicy = true;
+  // This builtin support mask agnostic and undisturbed policy.
+  bit HasMaskPolicy = true;
+
+  // This builtin prototype with TA or TAMA policy could not support overloading
+  // API. Other policy intrinsic functions would support overloading API with
+  // suffix `_tu`, `tumu`, `tuma`, `tamu` and `tama`.
+  bit SupportOverloading = true;
+
+  // This builtin is valid for the given Log2LMULs.
+  list<int> Log2LMUL = [0, 1, 2, 3, -1, -2, -3];
+
+  // Manual code in clang codegen riscv_vector_builtin_cg.inc
+  code ManualCodegen = [{}];
+
+  // When emit the automatic clang codegen, it describes what types we have to use
+  // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise,
+  // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd
+  // parameter of the unmasked version. k can't be the mask operand's position.
+  list<int> IntrinsicTypes = [];
+
+  // If these names are not empty, this is the ID of the LLVM intrinsic
+  // we want to lower to.
+  string IRName = NAME;
+
+  // If HasMasked, this is the ID of the LLVM intrinsic we want to lower to.
+  string MaskedIRName = NAME #"_mask";
+
+  // Use clang_builtin_alias to save the number of builtins.
+  bit HasBuiltinAlias = true;
+
+  // Features required to enable for this builtin.
+  list<string> RequiredFeatures = [];
+
+  // Number of fields for Load/Store Segment instructions.
+  int NF = 1;
+}
+
+// This is the code emitted in the header.
+class RVVHeader {
+  code HeaderCode;
+}


        


More information about the cfe-commits mailing list