Skip to content

Commit eb000ef

Browse files
committed
[CIR] Upstream splat op for VectorType
1 parent 459de73 commit eb000ef

File tree

7 files changed

+267
-1
lines changed

7 files changed

+267
-1
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,4 +2190,36 @@ def VecShuffleDynamicOp : CIR_Op<"vec.shuffle.dynamic",
21902190
let hasVerifier = 1;
21912191
}
21922192

2193+
//===----------------------------------------------------------------------===//
2194+
// VecSplatOp
2195+
//===----------------------------------------------------------------------===//
2196+
2197+
def VecSplatOp : CIR_Op<"vec.splat", [Pure,
2198+
TypesMatchWith<"type of 'value' matches element type of 'result'", "result",
2199+
"value", "cast<VectorType>($_self).getElementType()">]> {
2200+
2201+
let summary = "Convert a scalar into a vector";
2202+
let description = [{
2203+
The `cir.vec.splat` operation creates a vector value from a scalar value.
2204+
All elements of the vector have the same value, that of the given scalar.
2205+
2206+
It's a separate operation from `cir.vec.create` because more
2207+
efficient LLVM IR can be generated for it, and because some optimization and
2208+
analysis passes can benefit from knowing that all elements of the vector
2209+
have the same value.
2210+
2211+
```mlir
2212+
%value = cir.const #cir.int<3> : !s32i
2213+
%value_vec = cir.vec.splat %value : !s32i, !cir.vector<4 x !s32i>
2214+
```
2215+
}];
2216+
2217+
let arguments = (ins CIR_AnyType:$value);
2218+
let results = (outs CIR_VectorType:$result);
2219+
2220+
let assemblyFormat = [{
2221+
$value `:` type($value) `,` qualified(type($result)) attr-dict
2222+
}];
2223+
}
2224+
21932225
#endif // CLANG_CIR_DIALECT_IR_CIROPS_TD

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,14 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
16851685
cgf.convertType(destTy));
16861686
}
16871687

1688+
case CK_VectorSplat: {
1689+
// Create a vector object and fill all elements with the same scalar value.
1690+
assert(destTy->isVectorType() && "CK_VectorSplat to non-vector type");
1691+
return builder.create<cir::VecSplatOp>(
1692+
cgf.getLoc(subExpr->getSourceRange()), cgf.convertType(destTy),
1693+
Visit(subExpr));
1694+
}
1695+
16881696
default:
16891697
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
16901698
"CastExpr: ", ce->getCastKindName());

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
17081708
CIRToLLVMVecExtractOpLowering,
17091709
CIRToLLVMVecInsertOpLowering,
17101710
CIRToLLVMVecCmpOpLowering,
1711+
CIRToLLVMVecSplatOpLowering,
17111712
CIRToLLVMVecShuffleDynamicOpLowering
17121713
// clang-format on
17131714
>(converter, patterns.getContext());
@@ -1862,6 +1863,61 @@ mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
18621863
return mlir::success();
18631864
}
18641865

1866+
mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
1867+
cir::VecSplatOp op, OpAdaptor adaptor,
1868+
mlir::ConversionPatternRewriter &rewriter) const {
1869+
// Vector splat can be implemented with an `insertelement` and a
1870+
// `shufflevector`, which is better than an `insertelement` for each
1871+
// element in the vector. Start with an undef vector. Insert the value into
1872+
// the first element. Then use a `shufflevector` with a mask of all 0 to
1873+
// fill out the entire vector with that value.
1874+
const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
1875+
const mlir::Type llvmTy = typeConverter->convertType(vecTy);
1876+
const mlir::Location loc = op.getLoc();
1877+
const mlir::Value poison = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy);
1878+
1879+
const mlir::Value elementValue = adaptor.getValue();
1880+
if (mlir::isa<mlir::LLVM::PoisonOp>(elementValue.getDefiningOp())) {
1881+
// If the splat value is poison, then we can just use poison value
1882+
// for the entire vector.
1883+
rewriter.replaceOp(op, poison);
1884+
return mlir::success();
1885+
}
1886+
1887+
if (auto constValue =
1888+
dyn_cast<mlir::LLVM::ConstantOp>(elementValue.getDefiningOp())) {
1889+
if (auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
1890+
mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
1891+
mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
1892+
1893+
const mlir::Value indexValue = rewriter.create<mlir::LLVM::ConstantOp>(
1894+
loc, denseVec.getType(), denseVec);
1895+
rewriter.replaceOp(op, indexValue);
1896+
return mlir::success();
1897+
}
1898+
1899+
if (auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
1900+
mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
1901+
mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
1902+
1903+
const mlir::Value indexValue = rewriter.create<mlir::LLVM::ConstantOp>(
1904+
loc, denseVec.getType(), denseVec);
1905+
rewriter.replaceOp(op, indexValue);
1906+
return mlir::success();
1907+
}
1908+
}
1909+
1910+
const mlir::Value indexValue =
1911+
rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), 0);
1912+
const mlir::Value oneElement = rewriter.create<mlir::LLVM::InsertElementOp>(
1913+
loc, poison, elementValue, indexValue);
1914+
const SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
1915+
const mlir::Value shuffled = rewriter.create<mlir::LLVM::ShuffleVectorOp>(
1916+
loc, oneElement, poison, zeroValues);
1917+
rewriter.replaceOp(op, shuffled);
1918+
return mlir::success();
1919+
}
1920+
18651921
mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
18661922
cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
18671923
mlir::ConversionPatternRewriter &rewriter) const {

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,16 @@ class CIRToLLVMVecCmpOpLowering
352352
mlir::ConversionPatternRewriter &) const override;
353353
};
354354

355+
class CIRToLLVMVecSplatOpLowering
356+
: public mlir::OpConversionPattern<cir::VecSplatOp> {
357+
public:
358+
using mlir::OpConversionPattern<cir::VecSplatOp>::OpConversionPattern;
359+
360+
mlir::LogicalResult
361+
matchAndRewrite(cir::VecSplatOp op, OpAdaptor,
362+
mlir::ConversionPatternRewriter &) const override;
363+
};
364+
355365
class CIRToLLVMVecShuffleDynamicOpLowering
356366
: public mlir::OpConversionPattern<cir::VecShuffleDynamicOp> {
357367
public:

clang/test/CIR/CodeGen/vector-ext.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,3 +1091,66 @@ void foo17() {
10911091
// OGCG: %[[VEC_A:.*]] = alloca <2 x double>, align 16
10921092
// OGCG: %[[TMP:.*]] = load <2 x double>, ptr %[[VEC_A]], align 16
10931093
// OGCG: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16>
1094+
1095+
void foo18() {
1096+
vi4 a = {1, 2, 3, 4};
1097+
vi4 shl = a << 3;
1098+
1099+
uvi4 b = {1u, 2u, 3u, 4u};
1100+
uvi4 shr = b >> 3u;
1101+
}
1102+
1103+
// CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init]
1104+
// CIR: %[[SHL_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["shl", init]
1105+
// CIR: %[[VEC_B:.*]] = cir.alloca !cir.vector<4 x !u32i>, !cir.ptr<!cir.vector<4 x !u32i>>, ["b", init]
1106+
// CIR: %[[SHR_RES:.*]] = cir.alloca !cir.vector<4 x !u32i>, !cir.ptr<!cir.vector<4 x !u32i>>, ["shr", init]
1107+
// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i
1108+
// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i
1109+
// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !s32i
1110+
// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !s32i
1111+
// CIR: %[[VEC_A_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], %[[CONST_3]], %[[CONST_4]] :
1112+
// CIR-SAME: !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i>
1113+
// CIR: cir.store{{.*}} %[[VEC_A_VAL]], %[[VEC_A]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
1114+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[VEC_A]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
1115+
// CIR: %[[SH_AMOUNT:.*]] = cir.const #cir.int<3> : !s32i
1116+
// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[SH_AMOUNT]] : !s32i, !cir.vector<4 x !s32i>
1117+
// CIR: %[[SHL:.*]] = cir.shift(left, %[[TMP_A]] : !cir.vector<4 x !s32i>, %[[SPLAT_VEC]] : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
1118+
// CIR: cir.store{{.*}} %[[SHL]], %[[SHL_RES]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
1119+
// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !u32i
1120+
// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !u32i
1121+
// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !u32i
1122+
// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !u32i
1123+
// CIR: %[[VEC_B_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], %[[CONST_3]], %[[CONST_4]] :
1124+
// CIR-SAME: !u32i, !u32i, !u32i, !u32i) : !cir.vector<4 x !u32i>
1125+
// CIR: cir.store{{.*}} %[[VEC_B_VAL]], %[[VEC_B]] : !cir.vector<4 x !u32i>, !cir.ptr<!cir.vector<4 x !u32i>>
1126+
// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[VEC_B]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
1127+
// CIR: %[[SH_AMOUNT:.*]] = cir.const #cir.int<3> : !u32i
1128+
// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[SH_AMOUNT]] : !u32i, !cir.vector<4 x !u32i>
1129+
// CIR: %[[SHR:.*]] = cir.shift(right, %[[TMP_B]] : !cir.vector<4 x !u32i>, %[[SPLAT_VEC]] : !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
1130+
// CIR: cir.store{{.*}} %[[SHR]], %[[SHR_RES]] : !cir.vector<4 x !u32i>, !cir.ptr<!cir.vector<4 x !u32i>>
1131+
1132+
// LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16
1133+
// LLVM: %[[SHL_RES:.*]] = alloca <4 x i32>, i64 1, align 16
1134+
// LLVM: %[[VEC_B:.*]] = alloca <4 x i32>, i64 1, align 16
1135+
// LLVM: %[[SHR_RES:.*]] = alloca <4 x i32>, i64 1, align 16
1136+
// LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_A]], align 16
1137+
// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[VEC_A]], align 16
1138+
// LLVM: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], splat (i32 3)
1139+
// LLVM: store <4 x i32> %[[SHL]], ptr %[[SHL_RES]], align 16
1140+
// LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_B]], align 16
1141+
// LLVM: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[VEC_B]], align 16
1142+
// LLVM: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], splat (i32 3)
1143+
// LLVM: store <4 x i32> %[[SHR]], ptr %[[SHR_RES]], align 16
1144+
1145+
// OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16
1146+
// OGCG: %[[SHL_RES:.*]] = alloca <4 x i32>, align 16
1147+
// OGCG: %[[VEC_B:.*]] = alloca <4 x i32>, align 16
1148+
// OGCG: %[[SHR_RES:.*]] = alloca <4 x i32>, align 16
1149+
// OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_A]], align 16
1150+
// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[VEC_A]], align 16
1151+
// OGCG: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], splat (i32 3)
1152+
// OGCG: store <4 x i32> %[[SHL]], ptr %[[SHL_RES]], align 16
1153+
// OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_B]], align 16
1154+
// OGCG: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[VEC_B]], align 16
1155+
// OGCG: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], splat (i32 3)
1156+
// OGCG: store <4 x i32> %[[SHR]], ptr %[[SHR_RES]], align 16

clang/test/CIR/CodeGen/vector.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1069,4 +1069,67 @@ void foo17() {
10691069

10701070
// OGCG: %[[VEC_A:.*]] = alloca <2 x double>, align 16
10711071
// OGCG: %[[TMP:.*]] = load <2 x double>, ptr %[[VEC_A]], align 16
1072-
// OGCG: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16>
1072+
// OGCG: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16>
1073+
1074+
void foo18() {
1075+
vi4 a = {1, 2, 3, 4};
1076+
vi4 shl = a << 3;
1077+
1078+
uvi4 b = {1u, 2u, 3u, 4u};
1079+
uvi4 shr = b >> 3u;
1080+
}
1081+
1082+
// CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init]
1083+
// CIR: %[[SHL_RES:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["shl", init]
1084+
// CIR: %[[VEC_B:.*]] = cir.alloca !cir.vector<4 x !u32i>, !cir.ptr<!cir.vector<4 x !u32i>>, ["b", init]
1085+
// CIR: %[[SHR_RES:.*]] = cir.alloca !cir.vector<4 x !u32i>, !cir.ptr<!cir.vector<4 x !u32i>>, ["shr", init]
1086+
// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i
1087+
// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i
1088+
// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !s32i
1089+
// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !s32i
1090+
// CIR: %[[VEC_A_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], %[[CONST_3]], %[[CONST_4]] :
1091+
// CIR-SAME: !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i>
1092+
// CIR: cir.store{{.*}} %[[VEC_A_VAL]], %[[VEC_A]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
1093+
// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[VEC_A]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
1094+
// CIR: %[[SH_AMOUNT:.*]] = cir.const #cir.int<3> : !s32i
1095+
// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[SH_AMOUNT]] : !s32i, !cir.vector<4 x !s32i>
1096+
// CIR: %[[SHL:.*]] = cir.shift(left, %[[TMP_A]] : !cir.vector<4 x !s32i>, %[[SPLAT_VEC]] : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
1097+
// CIR: cir.store{{.*}} %[[SHL]], %[[SHL_RES]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
1098+
// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !u32i
1099+
// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !u32i
1100+
// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !u32i
1101+
// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !u32i
1102+
// CIR: %[[VEC_B_VAL:.*]] = cir.vec.create(%[[CONST_1]], %[[CONST_2]], %[[CONST_3]], %[[CONST_4]] :
1103+
// CIR-SAME: !u32i, !u32i, !u32i, !u32i) : !cir.vector<4 x !u32i>
1104+
// CIR: cir.store{{.*}} %[[VEC_B_VAL]], %[[VEC_B]] : !cir.vector<4 x !u32i>, !cir.ptr<!cir.vector<4 x !u32i>>
1105+
// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[VEC_B]] : !cir.ptr<!cir.vector<4 x !u32i>>, !cir.vector<4 x !u32i>
1106+
// CIR: %[[SH_AMOUNT:.*]] = cir.const #cir.int<3> : !u32i
1107+
// CIR: %[[SPLAT_VEC:.*]] = cir.vec.splat %[[SH_AMOUNT]] : !u32i, !cir.vector<4 x !u32i>
1108+
// CIR: %[[SHR:.*]] = cir.shift(right, %[[TMP_B]] : !cir.vector<4 x !u32i>, %[[SPLAT_VEC]] : !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i>
1109+
// CIR: cir.store{{.*}} %[[SHR]], %[[SHR_RES]] : !cir.vector<4 x !u32i>, !cir.ptr<!cir.vector<4 x !u32i>>
1110+
1111+
// LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16
1112+
// LLVM: %[[SHL_RES:.*]] = alloca <4 x i32>, i64 1, align 16
1113+
// LLVM: %[[VEC_B:.*]] = alloca <4 x i32>, i64 1, align 16
1114+
// LLVM: %[[SHR_RES:.*]] = alloca <4 x i32>, i64 1, align 16
1115+
// LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_A]], align 16
1116+
// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[VEC_A]], align 16
1117+
// LLVM: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], splat (i32 3)
1118+
// LLVM: store <4 x i32> %[[SHL]], ptr %[[SHL_RES]], align 16
1119+
// LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_B]], align 16
1120+
// LLVM: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[VEC_B]], align 16
1121+
// LLVM: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], splat (i32 3)
1122+
// LLVM: store <4 x i32> %[[SHR]], ptr %[[SHR_RES]], align 16
1123+
1124+
// OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16
1125+
// OGCG: %[[SHL_RES:.*]] = alloca <4 x i32>, align 16
1126+
// OGCG: %[[VEC_B:.*]] = alloca <4 x i32>, align 16
1127+
// OGCG: %[[SHR_RES:.*]] = alloca <4 x i32>, align 16
1128+
// OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_A]], align 16
1129+
// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[VEC_A]], align 16
1130+
// OGCG: %[[SHL:.*]] = shl <4 x i32> %[[TMP_A]], splat (i32 3)
1131+
// OGCG: store <4 x i32> %[[SHL]], ptr %[[SHL_RES]], align 16
1132+
// OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_B]], align 16
1133+
// OGCG: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[VEC_B]], align 16
1134+
// OGCG: %[[SHR:.*]] = lshr <4 x i32> %[[TMP_B]], splat (i32 3)
1135+
// OGCG: store <4 x i32> %[[SHR]], ptr %[[SHR_RES]], align 16

clang/test/CIR/IR/vector.cir

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,38 @@ cir.func @vector_shuffle_dynamic_test() {
187187
// CHECK: cir.return
188188
// CHECK: }
189189

190+
cir.func @vector_splat_test() {
191+
%0 = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init]
192+
%1 = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["shl", init]
193+
%2 = cir.const #cir.int<1> : !s32i
194+
%3 = cir.const #cir.int<2> : !s32i
195+
%4 = cir.const #cir.int<3> : !s32i
196+
%5 = cir.const #cir.int<4> : !s32i
197+
%6 = cir.vec.create(%2, %3, %4, %5 : !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i>
198+
cir.store %6, %0 : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
199+
%7 = cir.load %0 : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
200+
%8 = cir.const #cir.int<3> : !s32i
201+
%9 = cir.vec.splat %8 : !s32i, !cir.vector<4 x !s32i>
202+
%10 = cir.shift(left, %7 : !cir.vector<4 x !s32i>, %9 : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
203+
cir.store %10, %1 : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
204+
cir.return
205+
}
206+
207+
// CHECK: cir.func @vector_splat_test() {
208+
// CHECK: %0 = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init]
209+
// CHECK: %1 = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["shl", init]
210+
// CHECK: %2 = cir.const #cir.int<1> : !s32i
211+
// CHECK: %3 = cir.const #cir.int<2> : !s32i
212+
// CHECK: %4 = cir.const #cir.int<3> : !s32i
213+
// CHECK: %5 = cir.const #cir.int<4> : !s32i
214+
// CHECK: %6 = cir.vec.create(%2, %3, %4, %5 : !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i>
215+
// CHECK: cir.store %6, %0 : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
216+
// CHECK: %7 = cir.load %0 : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
217+
// CHECK: %8 = cir.const #cir.int<3> : !s32i
218+
// CHECK: %9 = cir.vec.splat %8 : !s32i, !cir.vector<4 x !s32i>
219+
// CHECK: %10 = cir.shift(left, %7 : !cir.vector<4 x !s32i>, %9 : !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>
220+
// CHECK: cir.store %10, %1 : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
221+
// CHECK: cir.return
222+
// CHECK: }
223+
190224
}

0 commit comments

Comments
 (0)