[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