Skip to content

Commit bd7175f

Browse files
committed
[CIR] Upstream splat op for VectorType
1 parent 9ec5afe commit bd7175f

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
@@ -2194,4 +2194,36 @@ def VecShuffleDynamicOp : CIR_Op<"vec.shuffle.dynamic",
21942194
let hasVerifier = 1;
21952195
}
21962196

2197+
//===----------------------------------------------------------------------===//
2198+
// VecSplatOp
2199+
//===----------------------------------------------------------------------===//
2200+
2201+
def VecSplatOp : CIR_Op<"vec.splat", [Pure,
2202+
TypesMatchWith<"type of 'value' matches element type of 'result'", "result",
2203+
"value", "cast<VectorType>($_self).getElementType()">]> {
2204+
2205+
let summary = "Convert a scalar into a vector";
2206+
let description = [{
2207+
The `cir.vec.splat` operation creates a vector value from a scalar value.
2208+
All elements of the vector have the same value, that of the given scalar.
2209+
2210+
It's a separate operation from `cir.vec.create` because more
2211+
efficient LLVM IR can be generated for it, and because some optimization and
2212+
analysis passes can benefit from knowing that all elements of the vector
2213+
have the same value.
2214+
2215+
```mlir
2216+
%value = cir.const #cir.int<3> : !s32i
2217+
%value_vec = cir.vec.splat %value : !s32i, !cir.vector<4 x !s32i>
2218+
```
2219+
}];
2220+
2221+
let arguments = (ins CIR_AnyType:$value);
2222+
let results = (outs CIR_VectorType:$result);
2223+
2224+
let assemblyFormat = [{
2225+
$value `:` type($value) `,` qualified(type($result)) attr-dict
2226+
}];
2227+
}
2228+
21972229
#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
@@ -1762,6 +1762,14 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
17621762
cgf.convertType(destTy));
17631763
}
17641764

1765+
case CK_VectorSplat: {
1766+
// Create a vector object and fill all elements with the same scalar value.
1767+
assert(destTy->isVectorType() && "CK_VectorSplat to non-vector type");
1768+
return builder.create<cir::VecSplatOp>(
1769+
cgf.getLoc(subExpr->getSourceRange()), cgf.convertType(destTy),
1770+
Visit(subExpr));
1771+
}
1772+
17651773
default:
17661774
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
17671775
"CastExpr: ", ce->getCastKindName());

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,6 +1730,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
17301730
CIRToLLVMVecExtractOpLowering,
17311731
CIRToLLVMVecInsertOpLowering,
17321732
CIRToLLVMVecCmpOpLowering,
1733+
CIRToLLVMVecSplatOpLowering,
17331734
CIRToLLVMVecShuffleDynamicOpLowering
17341735
// clang-format on
17351736
>(converter, patterns.getContext());
@@ -1880,6 +1881,61 @@ mlir::LogicalResult CIRToLLVMVecCmpOpLowering::matchAndRewrite(
18801881
return mlir::success();
18811882
}
18821883

1884+
mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
1885+
cir::VecSplatOp op, OpAdaptor adaptor,
1886+
mlir::ConversionPatternRewriter &rewriter) const {
1887+
// Vector splat can be implemented with an `insertelement` and a
1888+
// `shufflevector`, which is better than an `insertelement` for each
1889+
// element in the vector. Start with an undef vector. Insert the value into
1890+
// the first element. Then use a `shufflevector` with a mask of all 0 to
1891+
// fill out the entire vector with that value.
1892+
const auto vecTy = mlir::cast<cir::VectorType>(op.getType());
1893+
const mlir::Type llvmTy = typeConverter->convertType(vecTy);
1894+
const mlir::Location loc = op.getLoc();
1895+
const mlir::Value poison = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy);
1896+
1897+
const mlir::Value elementValue = adaptor.getValue();
1898+
if (mlir::isa<mlir::LLVM::PoisonOp>(elementValue.getDefiningOp())) {
1899+
// If the splat value is poison, then we can just use poison value
1900+
// for the entire vector.
1901+
rewriter.replaceOp(op, poison);
1902+
return mlir::success();
1903+
}
1904+
1905+
if (auto constValue =
1906+
dyn_cast<mlir::LLVM::ConstantOp>(elementValue.getDefiningOp())) {
1907+
if (auto intAttr = dyn_cast<mlir::IntegerAttr>(constValue.getValue())) {
1908+
mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
1909+
mlir::cast<mlir::ShapedType>(llvmTy), intAttr.getValue());
1910+
1911+
const mlir::Value indexValue = rewriter.create<mlir::LLVM::ConstantOp>(
1912+
loc, denseVec.getType(), denseVec);
1913+
rewriter.replaceOp(op, indexValue);
1914+
return mlir::success();
1915+
}
1916+
1917+
if (auto fpAttr = dyn_cast<mlir::FloatAttr>(constValue.getValue())) {
1918+
mlir::DenseFPElementsAttr denseVec = mlir::DenseFPElementsAttr::get(
1919+
mlir::cast<mlir::ShapedType>(llvmTy), fpAttr.getValue());
1920+
1921+
const mlir::Value indexValue = rewriter.create<mlir::LLVM::ConstantOp>(
1922+
loc, denseVec.getType(), denseVec);
1923+
rewriter.replaceOp(op, indexValue);
1924+
return mlir::success();
1925+
}
1926+
}
1927+
1928+
const mlir::Value indexValue =
1929+
rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), 0);
1930+
const mlir::Value oneElement = rewriter.create<mlir::LLVM::InsertElementOp>(
1931+
loc, poison, elementValue, indexValue);
1932+
const SmallVector<int32_t> zeroValues(vecTy.getSize(), 0);
1933+
const mlir::Value shuffled = rewriter.create<mlir::LLVM::ShuffleVectorOp>(
1934+
loc, oneElement, poison, zeroValues);
1935+
rewriter.replaceOp(op, shuffled);
1936+
return mlir::success();
1937+
}
1938+
18831939
mlir::LogicalResult CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
18841940
cir::VecShuffleDynamicOp op, OpAdaptor adaptor,
18851941
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
@@ -357,6 +357,16 @@ class CIRToLLVMVecCmpOpLowering
357357
mlir::ConversionPatternRewriter &) const override;
358358
};
359359

360+
class CIRToLLVMVecSplatOpLowering
361+
: public mlir::OpConversionPattern<cir::VecSplatOp> {
362+
public:
363+
using mlir::OpConversionPattern<cir::VecSplatOp>::OpConversionPattern;
364+
365+
mlir::LogicalResult
366+
matchAndRewrite(cir::VecSplatOp op, OpAdaptor,
367+
mlir::ConversionPatternRewriter &) const override;
368+
};
369+
360370
class CIRToLLVMVecShuffleDynamicOpLowering
361371
: public mlir::OpConversionPattern<cir::VecShuffleDynamicOp> {
362372
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)