[clang] [CIR] Add cir.fshl and cir.fshr for elementwise funnel shifts (PR #222396)
Letu Ren via cfe-commits
cfe-commits at lists.llvm.org
Sat Sep 12 10:38:58 PDT 2026
https://github.com/FantasqueX updated https://github.com/llvm/llvm-project/pull/222396
>From 36cd407ce87d271d3636c3dc9f10371b18ba9356 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Thu, 10 Sep 2026 01:22:42 +0800
Subject: [PATCH] [CIR] Add cir.fshl and cir.fshr for elementwise funnel shifts
Emit dedicated CIR ops from __builtin_elementwise_fshl/fshr instead of
cir.call_llvm_intrinsic.
Assisted-by: grok-4.6
Assisted-by: gpt-5.6-sol
Signed-off-by: Letu Ren <fantasquex at gmail.com>
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 62 +++++++++++++++++++
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 34 +++++-----
.../X86/avx512vbmi2-builtins.c | 6 +-
.../CodeGenBuiltins/builtins-elementwise.c | 24 +++----
clang/test/CIR/IR/funnel-shift.cir | 34 ++++++++++
clang/test/CIR/IR/invalid-funnel-shift.cir | 32 ++++++++++
clang/test/CIR/Lowering/funnel-shift.cir | 26 ++++++++
7 files changed, 187 insertions(+), 31 deletions(-)
create mode 100644 clang/test/CIR/IR/funnel-shift.cir
create mode 100644 clang/test/CIR/IR/invalid-funnel-shift.cir
create mode 100644 clang/test/CIR/Lowering/funnel-shift.cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index f03c591fe9597..a4336ac20a6ac 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -6956,6 +6956,68 @@ def CIR_RotateOp : CIR_Op<"rotate", [Pure, SameOperandsAndResultType]> {
let hasFolder = 1;
}
+//===----------------------------------------------------------------------===//
+// Funnel Shift Operations
+//===----------------------------------------------------------------------===//
+
+// Concatenate `a` and `b`, shift by `c`, and return one half of the doubled
+// width. All operands and the result share an integer or vector-of-integer
+// type.
+class CIR_FunnelShiftOp<string mnemonic, string llvmOpName>
+ : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> {
+ let arguments = (ins
+ CIR_AnyIntOrVecOfIntType:$a,
+ CIR_AnyIntOrVecOfIntType:$b,
+ CIR_AnyIntOrVecOfIntType:$c
+ );
+
+ let results = (outs CIR_AnyIntOrVecOfIntType:$result);
+
+ let assemblyFormat = "$a `,` $b `,` $c `:` type($a) attr-dict";
+
+ let llvmOp = llvmOpName;
+}
+
+def CIR_FshlOp : CIR_FunnelShiftOp<"fshl", "FshlOp"> {
+ let summary = "Funnel shift left";
+ let description = [{
+ The `cir.fshl` operation concatenates `a` and `b` (with `a` in the high
+ half), shifts the concatenation left by `c` bit positions, and returns the
+ high half of the result. The shift amount is treated modulo the bitwidth
+ of the operands.
+
+ All operands and the result must have the same integer type or
+ vector-of-integer type.
+
+ Example:
+
+ ```
+ %r = cir.fshl %a, %b, %c : !u32i
+ %v = cir.fshl %va, %vb, %vc : !cir.vector<4 x !s32i>
+ ```
+ }];
+}
+
+def CIR_FshrOp : CIR_FunnelShiftOp<"fshr", "FshrOp"> {
+ let summary = "Funnel shift right";
+ let description = [{
+ The `cir.fshr` operation concatenates `a` and `b` (with `a` in the high
+ half), shifts the concatenation right by `c` bit positions, and returns
+ the low half of the result. The shift amount is treated modulo the bitwidth
+ of the operands.
+
+ All operands and the result must have the same integer type or
+ vector-of-integer type.
+
+ Example:
+
+ ```
+ %r = cir.fshr %a, %b, %c : !u32i
+ %v = cir.fshr %va, %vb, %vc : !cir.vector<4 x !s32i>
+ ```
+ }];
+}
+
//===----------------------------------------------------------------------===//
// FPClass Test Flags
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index c7ce147b68d61..cdaf6c0daeded 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -595,6 +595,20 @@ static RValue emitBinaryFPBuiltin(CIRGenFunction &cgf, const CallExpr &e) {
return RValue::get(call->getResult(0));
}
+template <typename Op>
+static RValue emitTernarySameTypeBuiltin(CIRGenFunction &cgf,
+ const CallExpr &e) {
+ mlir::Value arg0 = cgf.emitScalarExpr(e.getArg(0));
+ mlir::Value arg1 = cgf.emitScalarExpr(e.getArg(1));
+ mlir::Value arg2 = cgf.emitScalarExpr(e.getArg(2));
+
+ mlir::Location loc = cgf.getLoc(e.getExprLoc());
+ mlir::Type ty = cgf.convertType(e.getType());
+ auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1, arg2);
+
+ return RValue::get(call->getResult(0));
+}
+
template <typename Op>
static RValue emitTernaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
const CallExpr &e) {
@@ -2044,22 +2058,10 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
case Builtin::BI__builtin_elementwise_canonicalize:
case Builtin::BI__builtin_elementwise_copysign:
return errorBuiltinNYI(*this, e, builtinID);
- case Builtin::BI__builtin_elementwise_fshl: {
- mlir::Location loc = getLoc(e->getExprLoc());
- mlir::Value a = emitScalarExpr(e->getArg(0));
- mlir::Value b = emitScalarExpr(e->getArg(1));
- mlir::Value c = emitScalarExpr(e->getArg(2));
- return RValue::get(builder.emitIntrinsicCallOp(loc, "fshl", a.getType(),
- mlir::ValueRange{a, b, c}));
- }
- case Builtin::BI__builtin_elementwise_fshr: {
- mlir::Location loc = getLoc(e->getExprLoc());
- mlir::Value a = emitScalarExpr(e->getArg(0));
- mlir::Value b = emitScalarExpr(e->getArg(1));
- mlir::Value c = emitScalarExpr(e->getArg(2));
- return RValue::get(builder.emitIntrinsicCallOp(loc, "fshr", a.getType(),
- mlir::ValueRange{a, b, c}));
- }
+ case Builtin::BI__builtin_elementwise_fshl:
+ return emitTernarySameTypeBuiltin<cir::FshlOp>(*this, *e);
+ case Builtin::BI__builtin_elementwise_fshr:
+ return emitTernarySameTypeBuiltin<cir::FshrOp>(*this, *e);
case Builtin::BI__builtin_elementwise_clmul:
case Builtin::BI__builtin_elementwise_pext:
case Builtin::BI__builtin_elementwise_pdep:
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx512vbmi2-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx512vbmi2-builtins.c
index d8cd6a2c089b1..c56a1b5ab06b6 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx512vbmi2-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx512vbmi2-builtins.c
@@ -13,7 +13,7 @@ __m512i test_mm512_shldv_epi64(__m512i s, __m512i a, __m512i b) {
// CIR: %{{.*}} = cir.call @_mm512_shldv_epi64
// CIR-LABEL: cir.func{{.*}} @_mm512_shldv_epi64(
// CIR: %{{.*}} = cir.cast bitcast %{{.*}} : !cir.vector<8 x !s64i> -> !cir.vector<8 x !u64i>
- // CIR: %{{.*}} = cir.call_llvm_intrinsic "fshl" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<8 x !u64i>{{.*}}, !cir.vector<8 x !u64i>{{.*}}, !cir.vector<8 x !u64i>{{.*}}) -> !cir.vector<8 x !u64i>
+ // CIR: %{{.*}} = cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<8 x !u64i>
// CIR: %{{.*}} = cir.cast bitcast %{{.*}} : !cir.vector<8 x !u64i> -> !cir.vector<8 x !s64i>
// LLVM-LABEL: @test_mm512_shldv_epi64
// LLVM: call <8 x i64> @llvm.fshl.v8i64(<8 x i64> {{.*}}, <8 x i64> {{.*}}, <8 x i64>
@@ -151,7 +151,7 @@ __m512i test_mm512_shldv_epi32(__m512i s, __m512i a, __m512i b) {
// CIR-LABEL: test_mm512_shldv_epi32
// CIR: cir.call @_mm512_shldv_epi32
// CIR-LABEL: cir.func{{.*}} @_mm512_shldv_epi32(
- // CIR: cir.call_llvm_intrinsic "fshl" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<16 x !u32i>, !cir.vector<16 x !u32i>, !cir.vector<16 x !u32i>) -> !cir.vector<16 x !u32i>
+ // CIR: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<16 x !u32i>
// CIR: cir.cast bitcast %{{.*}} : !cir.vector<16 x !u32i> -> !cir.vector<8 x !s64i>
// LLVM-LABEL: @test_mm512_shldv_epi32
// LLVM: call <16 x i32> @llvm.fshl.v16i32(<16 x i32> {{.*}}, <16 x i32> {{.*}}, <16 x i32>
@@ -194,7 +194,7 @@ __m512i test_mm512_shldv_epi16(__m512i s, __m512i a, __m512i b) {
// CIR-LABEL: @test_mm512_shldv_epi16
// CIR: cir.call @_mm512_shldv_epi16
// CIR-LABEL: cir.func{{.*}} @_mm512_shldv_epi16(
- // CIR: cir.call_llvm_intrinsic "fshl" %{{.*}}, %{{.*}}, %{{.*}}{{.*}} : (!cir.vector<32 x !u16i>, !cir.vector<32 x !u16i>, !cir.vector<32 x !u16i>) -> !cir.vector<32 x !u16i>
+ // CIR: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<32 x !u16i>
// CIR: cir.cast bitcast %{{.*}} : !cir.vector<32 x !u16i> -> !cir.vector<8 x !s64i>
// LLVM-LABEL: @test_mm512_shldv_epi16
// LLVM: call <32 x i16> @llvm.fshl.v32i16(<32 x i16> {{.*}}, <32 x i16> {{.*}}, <32 x i16>
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
index f89c9278c082d..2825c7df1684c 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
@@ -604,27 +604,27 @@ void test_builtin_elementwise_fshl(long long int i1, long long int i2,
// CIR-LABEL: test_builtin_elementwise_fshl
// LLVM-LABEL: test_builtin_elementwise_fshl
- // CIR: cir.call_llvm_intrinsic "fshl" %{{.*}}, %{{.*}}, %{{.*}} : (!s64i, !s64i, !s64i) -> !s64i
+ // CIR: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !s64i
// LLVM: call i64 @llvm.fshl.i64(i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}})
i1 = __builtin_elementwise_fshl(i1, i2, i3);
- // CIR: cir.call_llvm_intrinsic "fshl" %{{.*}}, %{{.*}}, %{{.*}} : (!u16i, !u16i, !u16i) -> !u16i
+ // CIR: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !u16i
// LLVM: call i16 @llvm.fshl.i16(i16 %{{.*}}, i16 %{{.*}}, i16 %{{.*}})
us1 = __builtin_elementwise_fshl(us1, us2, us3);
- // CIR: cir.call_llvm_intrinsic "fshl" %{{.*}}, %{{.*}}, %{{.*}} : (!s8i, !s8i, !s8i) -> !s8i
+ // CIR: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !s8i
// LLVM: call i8 @llvm.fshl.i8(i8 %{{.*}}, i8 %{{.*}}, i8 %{{.*}})
c1 = __builtin_elementwise_fshl(c1, c2, c3);
- // CIR: cir.call_llvm_intrinsic "fshl" %{{.*}}, %{{.*}}, %{{.*}} : (!u8i, !u8i, !u8i) -> !u8i
+ // CIR: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !u8i
// LLVM: call i8 @llvm.fshl.i8(i8 %{{.*}}, i8 %{{.*}}, i8 %{{.*}})
uc1 = __builtin_elementwise_fshl(uc1, uc2, uc3);
- // CIR: cir.call_llvm_intrinsic "fshl" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i>
+ // CIR: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<8 x !s16i>
// LLVM: call <8 x i16> @llvm.fshl.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
vi1 = __builtin_elementwise_fshl(vi1, vi2, vi3);
- // CIR: cir.call_llvm_intrinsic "fshl" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
+ // CIR: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !s32i>
// LLVM: call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
vu1 = __builtin_elementwise_fshl(vu1, vu2, vu3);
}
@@ -640,27 +640,27 @@ void test_builtin_elementwise_fshr(long long int i1, long long int i2,
// CIR-LABEL: test_builtin_elementwise_fshr
// LLVM-LABEL: test_builtin_elementwise_fshr
- // CIR: cir.call_llvm_intrinsic "fshr" %{{.*}}, %{{.*}}, %{{.*}} : (!s64i, !s64i, !s64i) -> !s64i
+ // CIR: cir.fshr %{{.*}}, %{{.*}}, %{{.*}} : !s64i
// LLVM: call i64 @llvm.fshr.i64(i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}})
i1 = __builtin_elementwise_fshr(i1, i2, i3);
- // CIR: cir.call_llvm_intrinsic "fshr" %{{.*}}, %{{.*}}, %{{.*}} : (!u16i, !u16i, !u16i) -> !u16i
+ // CIR: cir.fshr %{{.*}}, %{{.*}}, %{{.*}} : !u16i
// LLVM: call i16 @llvm.fshr.i16(i16 %{{.*}}, i16 %{{.*}}, i16 %{{.*}})
us1 = __builtin_elementwise_fshr(us1, us2, us3);
- // CIR: cir.call_llvm_intrinsic "fshr" %{{.*}}, %{{.*}}, %{{.*}} : (!s8i, !s8i, !s8i) -> !s8i
+ // CIR: cir.fshr %{{.*}}, %{{.*}}, %{{.*}} : !s8i
// LLVM: call i8 @llvm.fshr.i8(i8 %{{.*}}, i8 %{{.*}}, i8 %{{.*}})
c1 = __builtin_elementwise_fshr(c1, c2, c3);
- // CIR: cir.call_llvm_intrinsic "fshr" %{{.*}}, %{{.*}}, %{{.*}} : (!u8i, !u8i, !u8i) -> !u8i
+ // CIR: cir.fshr %{{.*}}, %{{.*}}, %{{.*}} : !u8i
// LLVM: call i8 @llvm.fshr.i8(i8 %{{.*}}, i8 %{{.*}}, i8 %{{.*}})
uc1 = __builtin_elementwise_fshr(uc1, uc2, uc3);
- // CIR: cir.call_llvm_intrinsic "fshr" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i>
+ // CIR: cir.fshr %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<8 x !s16i>
// LLVM: call <8 x i16> @llvm.fshr.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}})
vi1 = __builtin_elementwise_fshr(vi1, vi2, vi3);
- // CIR: cir.call_llvm_intrinsic "fshr" %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
+ // CIR: cir.fshr %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !s32i>
// LLVM: call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}})
vu1 = __builtin_elementwise_fshr(vu1, vu2, vu3);
}
diff --git a/clang/test/CIR/IR/funnel-shift.cir b/clang/test/CIR/IR/funnel-shift.cir
new file mode 100644
index 0000000000000..1bf1f04738db3
--- /dev/null
+++ b/clang/test/CIR/IR/funnel-shift.cir
@@ -0,0 +1,34 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+!u16i = !cir.int<u, 16>
+
+module {
+ cir.func @fshl_scalar(%a : !s32i, %b : !s32i, %c : !s32i) -> !s32i {
+ // CHECK: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !s32i
+ %0 = cir.fshl %a, %b, %c : !s32i
+ cir.return %0 : !s32i
+ }
+
+ cir.func @fshr_scalar(%a : !u16i, %b : !u16i, %c : !u16i) -> !u16i {
+ // CHECK: cir.fshr %{{.*}}, %{{.*}}, %{{.*}} : !u16i
+ %0 = cir.fshr %a, %b, %c : !u16i
+ cir.return %0 : !u16i
+ }
+
+ cir.func @fshl_vector(%a : !cir.vector<4 x !s32i>,
+ %b : !cir.vector<4 x !s32i>,
+ %c : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i> {
+ // CHECK: cir.fshl %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !s32i>
+ %0 = cir.fshl %a, %b, %c : !cir.vector<4 x !s32i>
+ cir.return %0 : !cir.vector<4 x !s32i>
+ }
+
+ cir.func @fshr_vector(%a : !cir.vector<4 x !s32i>,
+ %b : !cir.vector<4 x !s32i>,
+ %c : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i> {
+ // CHECK: cir.fshr %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !s32i>
+ %0 = cir.fshr %a, %b, %c : !cir.vector<4 x !s32i>
+ cir.return %0 : !cir.vector<4 x !s32i>
+ }
+}
diff --git a/clang/test/CIR/IR/invalid-funnel-shift.cir b/clang/test/CIR/IR/invalid-funnel-shift.cir
new file mode 100644
index 0000000000000..e0f7631c349cb
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-funnel-shift.cir
@@ -0,0 +1,32 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+module {
+ cir.func @fshl_float(%a : !cir.float, %b : !cir.float, %c : !cir.float) {
+ // expected-error at +1 {{'cir.fshl' op operand #0 must be integer or vector of integer type, but got '!cir.float'}}
+ %0 = cir.fshl %a, %b, %c : !cir.float
+ cir.return
+ }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!u32i = !cir.int<u, 32>
+
+module {
+ cir.func @fshl_mixed_signedness(%a : !s32i, %b : !s32i, %c : !u32i) {
+ // expected-error at +1 {{'cir.fshl' op requires the same type for all operands and results}}
+ %0 = "cir.fshl"(%a, %b, %c) : (!s32i, !s32i, !u32i) -> !s32i
+ cir.return
+ }
+}
+
+// -----
+
+module {
+ cir.func @fshr_float(%a : !cir.float, %b : !cir.float, %c : !cir.float) {
+ // expected-error at +1 {{'cir.fshr' op operand #0 must be integer or vector of integer type, but got '!cir.float'}}
+ %0 = cir.fshr %a, %b, %c : !cir.float
+ cir.return
+ }
+}
diff --git a/clang/test/CIR/Lowering/funnel-shift.cir b/clang/test/CIR/Lowering/funnel-shift.cir
new file mode 100644
index 0000000000000..a59f6ae6843a7
--- /dev/null
+++ b/clang/test/CIR/Lowering/funnel-shift.cir
@@ -0,0 +1,26 @@
+// RUN: cir-opt %s -cir-to-llvm -o - | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+!u16i = !cir.int<u, 16>
+
+module {
+ cir.func @fshl_scalar(%a : !s32i, %b : !s32i, %c : !s32i) -> !s32i {
+ %0 = cir.fshl %a, %b, %c : !s32i
+ // CHECK: llvm.intr.fshl(%{{.*}}, %{{.*}}, %{{.*}}) : (i32, i32, i32) -> i32
+ cir.return %0 : !s32i
+ }
+
+ cir.func @fshr_scalar(%a : !u16i, %b : !u16i, %c : !u16i) -> !u16i {
+ %0 = cir.fshr %a, %b, %c : !u16i
+ // CHECK: llvm.intr.fshr(%{{.*}}, %{{.*}}, %{{.*}}) : (i16, i16, i16) -> i16
+ cir.return %0 : !u16i
+ }
+
+ cir.func @fshl_vector(%a : !cir.vector<4 x !s32i>,
+ %b : !cir.vector<4 x !s32i>,
+ %c : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i> {
+ %0 = cir.fshl %a, %b, %c : !cir.vector<4 x !s32i>
+ // CHECK: llvm.intr.fshl(%{{.*}}, %{{.*}}, %{{.*}}) : (vector<4xi32>, vector<4xi32>, vector<4xi32>) -> vector<4xi32>
+ cir.return %0 : !cir.vector<4 x !s32i>
+ }
+}
More information about the cfe-commits
mailing list