[rv32] Enable 32-bit mulsi_extended lowering for +zve32f (#12266)
Make sure that the 32-bit lowering is used when +zve32f is used.
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp b/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp
index b19f1ca..70715fe 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/ConvertToLLVM.cpp
@@ -503,11 +503,12 @@
bool use32BitImpl = false;
auto targetAttr = IREE::HAL::ExecutableTargetAttr::lookup(module);
if (isRISCV(targetAttr)) {
- // Use the 32-bit lowering for RISC-V if 'zve32x' is specified and there is
+ // Use the 32-bit lowering for RISC-V if 'zve32*' is specified and there is
// no 64-bit integer vector support.
// TODO(#9440) Simplify logic when 'cpu_features' is simplified.
- use32BitImpl = hasZve32xFeature(targetAttr) && !hasVFeature(targetAttr) &&
- !hasZve64xFeature(targetAttr);
+ use32BitImpl =
+ (hasZve32xFeature(targetAttr) || hasZve32fFeature(targetAttr)) &&
+ !hasVFeature(targetAttr) && !hasZve64xFeature(targetAttr);
}
tosa::populateTosaRescaleToArithConversionPatterns(&patterns, use32BitImpl);
diff --git a/compiler/src/iree/compiler/Codegen/LLVMCPU/test/apply_scale_lowering.mlir b/compiler/src/iree/compiler/Codegen/LLVMCPU/test/apply_scale_lowering.mlir
index a86a5af..627c6ed 100644
--- a/compiler/src/iree/compiler/Codegen/LLVMCPU/test/apply_scale_lowering.mlir
+++ b/compiler/src/iree/compiler/Codegen/LLVMCPU/test/apply_scale_lowering.mlir
@@ -9,7 +9,7 @@
#executable_target_embedded_elf_riscv_64_ = #hal.executable.target<"llvm-cpu", "embedded-elf-riscv_64", {
cpu_features = "+m,+a,+f,+d,+c",
data_layout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128",
- native_vector_size = 256 : index,
+ native_vector_size = 512 : index,
target_triple = "riscv64-unknown-unknown-eabi-elf"
}>
#map = affine_map<()[s0] -> (s0 ceildiv 2)>
@@ -55,9 +55,9 @@
]>
]>
#executable_target_embedded_elf_riscv_64_ = #hal.executable.target<"llvm-cpu", "embedded-elf-riscv_64", {
- cpu_features = "+m,+a,+f,+d,+c,+v",
+ cpu_features = "+m,+a,+f,+d,+c,+zvl512b,+v",
data_layout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128",
- native_vector_size = 256 : index,
+ native_vector_size = 512 : index,
target_triple = "riscv64-unknown-unknown-eabi-elf"
}>
#map = affine_map<()[s0] -> (s0 ceildiv 2)>
@@ -101,9 +101,9 @@
]>
]>
#executable_target_embedded_elf_riscv_64_ = #hal.executable.target<"llvm-cpu", "embedded-elf-riscv_64", {
- cpu_features = "+m,+a,+f,+d,+c,+zve64x",
+ cpu_features = "+m,+a,+f,+d,+c,+zvl512b,+zve64x",
data_layout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128",
- native_vector_size = 256 : index,
+ native_vector_size = 512 : index,
target_triple = "riscv64-unknown-unknown-eabi-elf"
}>
#map = affine_map<()[s0] -> (s0 ceildiv 2)>
@@ -147,9 +147,9 @@
]>
]>
#executable_target_embedded_elf_riscv_64_ = #hal.executable.target<"llvm-cpu", "embedded-elf-riscv_64", {
- cpu_features = "+m,+a,+f,+d,+c,+zve32x",
+ cpu_features = "+m,+a,+f,+d,+c,+zvl512b,+zve32x",
data_layout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128",
- native_vector_size = 256 : index,
+ native_vector_size = 512 : index,
target_triple = "riscv64-unknown-unknown-eabi-elf"
}>
#map = affine_map<()[s0] -> (s0 ceildiv 2)>
@@ -190,3 +190,56 @@
// CHECK: %[[MULLOW:.*]] = llvm.mul %[[LHS]], %[[RHS]] : vector<2xi32>
// CHECK: %[[SHR:.*]] = llvm.lshr %[[MULEXT]], %{{.*}} : vector<2xi64>
// CHECK-NEXT: llvm.trunc %[[SHR]] : vector<2xi64> to vector<2xi32>
+
+// -----
+
+#pipeline_layout = #hal.pipeline.layout<push_constants = 0, sets = [
+ #hal.descriptor_set.layout<0, bindings = [
+ #hal.descriptor_set.binding<0, storage_buffer>,
+ #hal.descriptor_set.binding<1, storage_buffer>
+ ]>
+]>
+#executable_target_embedded_elf_riscv_64_ = #hal.executable.target<"llvm-cpu", "embedded-elf-riscv_64", {
+ cpu_features = "+m,+a,+f,+d,+c,+zvl512b,+zve32f",
+ data_layout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128",
+ native_vector_size = 512 : index,
+ target_triple = "riscv64-unknown-unknown-eabi-elf"
+}>
+#map = affine_map<()[s0] -> (s0 ceildiv 2)>
+#translation = #iree_codegen.translation_info<CPUDoubleTilingExpert>
+hal.executable private @apply_scale_zve32f {
+ hal.executable.variant public @embedded_elf_riscv_64, target = #executable_target_embedded_elf_riscv_64_ {
+ hal.executable.export public @apply_scale_zve32f ordinal(0) layout(#pipeline_layout) attributes {translation_info = #translation} {
+ ^bb0(%arg0: !hal.device, %arg1: index, %arg2: index, %arg3: index):
+ %c1 = arith.constant 1 : index
+ %0 = affine.apply #map()[%arg1]
+ hal.return %0, %c1, %c1 : index, index, index
+ }
+ builtin.module {
+ func.func @apply_scale_zve32f() {
+ %cst = arith.constant dense<19689> : vector<2xi32>
+ %cst_0 = arith.constant dense<15> : vector<2xi8>
+ %c0 = arith.constant 0 : index
+ %0 = hal.interface.binding.subspan set(0) binding(0) type(storage_buffer) alignment(64) offset(%c0) : memref<2xi32>
+ %1 = hal.interface.binding.subspan set(0) binding(1) type(storage_buffer) alignment(64) offset(%c0) : memref<2xi32>
+ %2 = vector.load %0[%c0] : memref<2xi32>, vector<2xi32>
+ %3 = "tosa.apply_scale"(%2, %cst, %cst_0) {double_round = false} : (vector<2xi32>, vector<2xi32>, vector<2xi8>) -> vector<2xi32>
+ vector.store %3, %1[%c0] : memref<2xi32>, vector<2xi32>
+ return
+ }
+ }
+ }
+}
+
+// 32-bit lowering is used with '+zve32f'. Note that the 32-bit lowering
+// generates 64-bit mul operations that are decomposed into 32-bit operations by
+// the LLVM backend. The backend expects both the low half to be an `llvm.mul` op.
+// CHECK-LABEL: llvm.func @apply_scale_zve32f
+// CHECK-DAG: %[[RHS:.+]] = llvm.mlir.constant(dense<19689> : vector<2xi32>) : vector<2xi32>
+// CHECK-DAG: %[[RHSEXT:.+]] = llvm.mlir.constant(dense<19689> : vector<2xi64>) : vector<2xi64>
+// CHECK: %[[LHS:.+]] = llvm.load %{{.+}} {alignment = 4 : i64} : !llvm.ptr<vector<2xi32>>
+// CHECK: %[[LHSEXT:.+]] = llvm.sext %[[LHS]] : vector<2xi32> to vector<2xi64>
+// CHECK: %[[MULEXT:.*]] = llvm.mul %[[LHSEXT]], %[[RHSEXT]] : vector<2xi64>
+// CHECK: %[[MULLOW:.*]] = llvm.mul %[[LHS]], %[[RHS]] : vector<2xi32>
+// CHECK: %[[SHR:.*]] = llvm.lshr %[[MULEXT]], %{{.*}} : vector<2xi64>
+// CHECK-NEXT: llvm.trunc %[[SHR]] : vector<2xi64> to vector<2xi32>
diff --git a/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp b/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp
index 5192971..c07ce92 100644
--- a/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp
+++ b/compiler/src/iree/compiler/Codegen/Utils/Utils.cpp
@@ -187,6 +187,10 @@
return hasFeature(targetAttr, "+zve32x");
}
+bool hasZve32fFeature(IREE::HAL::ExecutableTargetAttr targetAttr) {
+ return hasFeature(targetAttr, "+zve32f");
+}
+
bool hasZve64xFeature(IREE::HAL::ExecutableTargetAttr targetAttr) {
return hasFeature(targetAttr, "+zve64x");
}
diff --git a/compiler/src/iree/compiler/Codegen/Utils/Utils.h b/compiler/src/iree/compiler/Codegen/Utils/Utils.h
index ca8f43f..3593354 100644
--- a/compiler/src/iree/compiler/Codegen/Utils/Utils.h
+++ b/compiler/src/iree/compiler/Codegen/Utils/Utils.h
@@ -86,6 +86,9 @@
/// Returns true if the 'targetAttr' contains '+zve32x' in its cpu features.
bool hasZve32xFeature(IREE::HAL::ExecutableTargetAttr targetAttr);
+/// Returns true if the 'targetAttr' contains '+zve32f' in its cpu features.
+bool hasZve32fFeature(IREE::HAL::ExecutableTargetAttr targetAttr);
+
/// Returns true if the 'targetAttr' contains '+zve64x' in its cpu features.
bool hasZve64xFeature(IREE::HAL::ExecutableTargetAttr targetAttr);