[llvm] [AArch64] Add costs for ROTR and ROTL. (PR #169335)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 24 06:57:26 PST 2025
https://github.com/davemgreen created https://github.com/llvm/llvm-project/pull/169335
A funnel shift with the first two operands is a rotate. AArch64 has scalar instructions for ror so can handle a ROTR by a constant or variant amount cheaply. A ROTL is a ROTR by the opposite amount, which for constants is cheap and for variable shifts requires an extra neg.
>From af72dfe39ab43f1a107bf3ee0ac3920776e59bf3 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Mon, 24 Nov 2025 14:43:13 +0000
Subject: [PATCH] [AArch64] Add costs for ROTR and ROTL.
A funnel shift with the first two operands is a rotate. AArch64 has scalar
instructions for ror so can handle a ROTR but a constant or variant amount
cheaply. A ROTL is a ROTR by the opposite amount, which for constants is cheap
and for variable shifts requires a neg.
---
.../Target/AArch64/AArch64TargetTransformInfo.cpp | 13 ++++++++++++-
llvm/test/Analysis/CostModel/AArch64/fshl.ll | 4 ++--
llvm/test/Analysis/CostModel/AArch64/fshr.ll | 4 ++--
3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 0bae00bafee3c..7572aec43e919 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -921,8 +921,19 @@ AArch64TTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
if (ICA.getArgs().empty())
break;
- // TODO: Add handling for fshl where third argument is not a constant.
const TTI::OperandValueInfo OpInfoZ = TTI::getOperandInfo(ICA.getArgs()[2]);
+
+ // ROTR / ROTL on integer registers can be done in a single instruction. A
+ // fshl with a non-constant shift uses a neg + ror.
+ if (RetTy->isIntegerTy() && ICA.getArgs()[0] == ICA.getArgs()[1] &&
+ (RetTy->getPrimitiveSizeInBits() == 32 ||
+ RetTy->getPrimitiveSizeInBits() == 64)) {
+ InstructionCost NegCost =
+ (ICA.getID() == Intrinsic::fshl && !OpInfoZ.isConstant()) ? 1 : 0;
+ return 1 + NegCost;
+ }
+
+ // TODO: Add handling for fshl where third argument is not a constant.
if (!OpInfoZ.isConstant())
break;
diff --git a/llvm/test/Analysis/CostModel/AArch64/fshl.ll b/llvm/test/Analysis/CostModel/AArch64/fshl.ll
index cd6068d382169..61296a8e3c5d3 100644
--- a/llvm/test/Analysis/CostModel/AArch64/fshl.ll
+++ b/llvm/test/Analysis/CostModel/AArch64/fshl.ll
@@ -349,7 +349,7 @@ entry:
define i32 @rotl_i32_3rd_arg_var(i32 %a, i32 %c) {
; CHECK-LABEL: 'rotl_i32_3rd_arg_var'
-; CHECK-NEXT: Cost Model: Found costs of 5 for: %r = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %c)
+; CHECK-NEXT: Cost Model: Found costs of 2 for: %r = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %c)
; CHECK-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret i32 %r
;
entry:
@@ -369,7 +369,7 @@ entry:
define i64 @rotl_i64_3rd_arg_var(i64 %a, i64 %c) {
; CHECK-LABEL: 'rotl_i64_3rd_arg_var'
-; CHECK-NEXT: Cost Model: Found costs of 5 for: %r = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %c)
+; CHECK-NEXT: Cost Model: Found costs of 2 for: %r = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %c)
; CHECK-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret i64 %r
;
entry:
diff --git a/llvm/test/Analysis/CostModel/AArch64/fshr.ll b/llvm/test/Analysis/CostModel/AArch64/fshr.ll
index 795371e9f3f68..213013092e827 100644
--- a/llvm/test/Analysis/CostModel/AArch64/fshr.ll
+++ b/llvm/test/Analysis/CostModel/AArch64/fshr.ll
@@ -349,7 +349,7 @@ entry:
define i32 @rotl_i32_3rd_arg_var(i32 %a, i32 %c) {
; CHECK-LABEL: 'rotl_i32_3rd_arg_var'
-; CHECK-NEXT: Cost Model: Found costs of 5 for: %r = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %c)
+; CHECK-NEXT: Cost Model: Found costs of 1 for: %r = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %c)
; CHECK-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret i32 %r
;
entry:
@@ -369,7 +369,7 @@ entry:
define i64 @rotl_i64_3rd_arg_var(i64 %a, i64 %c) {
; CHECK-LABEL: 'rotl_i64_3rd_arg_var'
-; CHECK-NEXT: Cost Model: Found costs of 5 for: %r = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %c)
+; CHECK-NEXT: Cost Model: Found costs of 1 for: %r = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %c)
; CHECK-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret i64 %r
;
entry:
More information about the llvm-commits
mailing list