Skip to content

[ARM] Update costs for ARM insts #142843

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

[ARM] Update costs for ARM insts #142843

wants to merge 1 commit into from

Conversation

AZero13
Copy link
Contributor

@AZero13 AZero13 commented Jun 4, 2025

Things that can be encoded in an immediate should not have a cost.

@llvmbot
Copy link
Member

llvmbot commented Jun 4, 2025

@llvm/pr-subscribers-backend-arm

Author: AZero13 (AZero13)

Changes

Things that can be encoded in an immediate should not have a cost.


Full diff: https://github.com/llvm/llvm-project/pull/142843.diff

2 Files Affected:

  • (modified) llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp (+35-9)
  • (modified) llvm/test/CodeGen/ARM/ssat.ll (+7-8)
diff --git a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
index 6c3a1ae7e1775..f61808d2a1cee 100644
--- a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
@@ -428,6 +428,13 @@ InstructionCost ARMTTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx,
   if (Opcode == Instruction::GetElementPtr && Idx != 0)
     return 0;
 
+  if ((Opcode == Instruction::Shl || Opcode == Instruction::LShr ||
+       Opcode == Instruction::AShr) &&
+      Idx == 1) {
+    // Shifts are free (are we really going to get a shift of more than 64)?
+    return 0;
+  }
+
   if (Opcode == Instruction::And) {
     // UXTB/UXTH
     if (Imm == 255 || Imm == 65535)
@@ -437,19 +444,38 @@ InstructionCost ARMTTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx,
                     getIntImmCost(~Imm, Ty, CostKind));
   }
 
-  if (Opcode == Instruction::Add)
+  if (Opcode == Instruction::Add || Opcode == Instruction::Sub) {
+    int64_t ImmVal = Imm.getSExtValue();
+    if (!ST->isThumb())
+      if (ARM_AM::getSOImmVal((uint32_t)ImmVal) != -1 ||
+          ARM_AM::getSOImmVal(-(uint32_t)ImmVal) != -1)
+        return 0;
+    if (ST->isThumb2())
+      if (ARM_AM::getT2SOImmVal((uint32_t)ImmVal) != -1 ||
+          ARM_AM::getT2SOImmVal(-(uint32_t)ImmVal) != -1)
+        return 0;
+    // Thumb1 doesn't have cmn, and only 8-bit immediates.
+    ImmVal = ImmVal < 0 ? -ImmVal : ImmVal;
+    if (ImmVal >= 0 && ImmVal <= 255)
+      return 0;
     // Conversion to SUB is free, and means we can use -Imm instead.
     return std::min(getIntImmCost(Imm, Ty, CostKind),
                     getIntImmCost(-Imm, Ty, CostKind));
+  }
 
-  if (Opcode == Instruction::ICmp && Imm.isNegative() &&
-      Ty->getIntegerBitWidth() == 32) {
-    int64_t NegImm = -Imm.getSExtValue();
-    if (ST->isThumb2() && NegImm < 1<<12)
-      // icmp X, #-C -> cmn X, #C
-      return 0;
-    if (ST->isThumb() && NegImm < 1<<8)
-      // icmp X, #-C -> adds X, #C
+  if (Opcode == Instruction::ICmp && Ty->getIntegerBitWidth() == 32) {
+    int64_t ImmVal = Imm.getSExtValue();
+    if (!ST->isThumb())
+      if (ARM_AM::getSOImmVal((uint32_t)ImmVal) != -1 ||
+          ARM_AM::getSOImmVal(-(uint32_t)ImmVal) != -1)
+        return 0;
+    if (ST->isThumb2())
+      if (ARM_AM::getT2SOImmVal((uint32_t)ImmVal) != -1 ||
+          ARM_AM::getT2SOImmVal(-(uint32_t)ImmVal) != -1)
+        return 0;
+    // Thumb1 doesn't have cmn, and only 8-bit immediates.
+    ImmVal = ImmVal < 0 ? -ImmVal : ImmVal;
+    if (ImmVal >= 0 && ImmVal <= 255)
       return 0;
   }
 
diff --git a/llvm/test/CodeGen/ARM/ssat.ll b/llvm/test/CodeGen/ARM/ssat.ll
index ed777f2b1882b..40058e0dcf635 100644
--- a/llvm/test/CodeGen/ARM/ssat.ll
+++ b/llvm/test/CodeGen/ARM/ssat.ll
@@ -390,12 +390,10 @@ entry:
 define i32 @no_sat_incorrect_constant(i32 %x) #0 {
 ; V4T-LABEL: no_sat_incorrect_constant:
 ; V4T:       @ %bb.0: @ %entry
-; V4T-NEXT:    mov r1, #1065353216
+; V4T-NEXT:    ldr r2, .LCPI11_0
 ; V4T-NEXT:    cmn r0, #8388608
-; V4T-NEXT:    orr r1, r1, #-1073741824
-; V4T-NEXT:    mov r2, r0
-; V4T-NEXT:    orrlt r2, r1, #1
-; V4T-NEXT:    ldr r1, .LCPI11_0
+; V4T-NEXT:    movge r2, r0
+; V4T-NEXT:    ldr r1, .LCPI11_1
 ; V4T-NEXT:    cmp r0, #8388608
 ; V4T-NEXT:    movlt r1, r2
 ; V4T-NEXT:    mov r0, r1
@@ -403,15 +401,16 @@ define i32 @no_sat_incorrect_constant(i32 %x) #0 {
 ; V4T-NEXT:    .p2align 2
 ; V4T-NEXT:  @ %bb.1:
 ; V4T-NEXT:  .LCPI11_0:
+; V4T-NEXT:    .long 4286578689 @ 0xff800001
+; V4T-NEXT:  .LCPI11_1:
 ; V4T-NEXT:    .long 8388607 @ 0x7fffff
 ;
 ; V6T2-LABEL: no_sat_incorrect_constant:
 ; V6T2:       @ %bb.0: @ %entry
-; V6T2-NEXT:    movw r2, #0
 ; V6T2-NEXT:    cmn r0, #8388608
 ; V6T2-NEXT:    mov r1, r0
-; V6T2-NEXT:    movt r2, #65408
-; V6T2-NEXT:    orrlt r1, r2, #1
+; V6T2-NEXT:    movwlt r1, #1
+; V6T2-NEXT:    movtlt r1, #65408
 ; V6T2-NEXT:    cmp r0, #8388608
 ; V6T2-NEXT:    movwge r1, #65535
 ; V6T2-NEXT:    movtge r1, #127

@AZero13 AZero13 force-pushed the costing branch 3 times, most recently from ae7ee74 to b10ff0e Compare June 5, 2025 14:48
Copy link

github-actions bot commented Jun 5, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Things that can be encoded in an immediate should not have a cost.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants