Skip to content

Commit ba3c477

Browse files
committed
[SVE] Add codegen support for vscale_range() function attribute
This commit adds support for the `vscale_range()` LLVM function attribute to be generated for SVE and SME targets. Some LLVM optimisation passes make use of the `vscale_range()` function attribute when scalable vectors are present (e.g. BasicAA llvm/llvm-project/pull/80445), so we include it alongside the "target_cpu" and "target-features" attributes.
1 parent 20d7696 commit ba3c477

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

src/target/llvm/codegen_llvm.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
#include <vector>
105105

106106
#include "../../arith/pattern_match.h"
107+
#include "../../arith/scalable_expression.h"
107108
#include "../build_common.h"
108109
#include "../func_registry_generator.h"
109110
#include "codegen_params.h"
@@ -1127,6 +1128,13 @@ void CodeGenLLVM::SetTargetAttributes(llvm::Function* func) {
11271128
if (!features.empty()) {
11281129
func->addFnAttr("target-features", features);
11291130
}
1131+
#if TVM_LLVM_VERSION >= 130
1132+
// Add vscale_range() function attribute when appropriate.
1133+
if (llvm_target_->TargetHasCPUFeature("sve") || llvm_target_->TargetHasCPUFeature("sme")) {
1134+
func->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1135+
*llvm_target_->GetContext(), 1, tvm::arith::kAArch64VScaleValues.size()));
1136+
}
1137+
#endif
11301138
}
11311139

11321140
void CodeGenLLVM::EmitFloat16ConversionBuiltins(bool use_float16_abi) {

src/target/llvm/codegen_llvm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ class CodeGenLLVM : public ExprFunctor<llvm::Value*(const PrimExpr&)>,
427427
llvm::ArrayRef<llvm::Type*> arg_types);
428428
/*!
429429
* \brief Set target-related attributes on the LLVM function \p func. This
430-
* includes "target-cpu" and "target-features" if present.
430+
* includes "target-cpu", "target-features" and "vscale_range()" if present.
431431
*
432432
* \param func The function to set attributes on.
433433
*/

tests/python/codegen/test_target_codegen_aarch64.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,44 @@ def my_func(a: T.handle):
537537
assert re.findall(r" store <vscale x 4 x float>", llvm), "No scalable store in generated LLVM."
538538

539539

540+
@pytest.mark.skipif(
541+
llvm_version_major() < 13,
542+
reason="Function attribute vscale_range() is not supported in earlier versions of LLVM",
543+
)
544+
@pytest.mark.parametrize(
545+
"mattr,expect_attr",
546+
[
547+
("+neon", False),
548+
("+sve", True),
549+
("+v9a", True),
550+
("+sme", True),
551+
],
552+
)
553+
def test_vscale_range_function_attribute(mattr, expect_attr):
554+
target = f"llvm -mtriple=aarch64-linux-gnu -mattr={mattr}"
555+
556+
m = te.var("m")
557+
A = te.placeholder(m, dtype="float32", name="A")
558+
C = te.compute((m), lambda i: A[i] + 1, name="C")
559+
s = te.create_schedule([C.op])
560+
561+
with tvm.target.Target(target) as target:
562+
f = tvm.build(s, [A, C], target)
563+
564+
# Check if the vscale_range() attribute exists
565+
ll = f.get_source("ll")
566+
attr = re.findall(rf".*vscale_range\(\d+,\d+\)*.", ll)
567+
568+
if expect_attr:
569+
assert (
570+
len(attr) > 0
571+
), f"Function attribute vscale_range() was not found in generated LLVM IR"
572+
else:
573+
assert (
574+
len(attr) == 0
575+
), f"Unexpected function attribute vscale_range() was found in generated LLVM IR"
576+
577+
540578
@pytest.mark.skipif(
541579
llvm_version_major() < 16, reason="Test requires an LLVM version of at least 16 to target SME"
542580
)

0 commit comments

Comments
 (0)