[llvm] [X86][CostModel] Estimate the codesize cost of switch (PR #163569)
Hongyu Chen via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 15 12:17:01 PDT 2025
https://github.com/XChy updated https://github.com/llvm/llvm-project/pull/163569
>From ffc4e6ddc6418962c3e45e6d9c13430136794368 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Wed, 15 Oct 2025 22:30:35 +0800
Subject: [PATCH 1/2] [X86] Estimate the codesize cost of switch
---
.../lib/Target/X86/X86TargetTransformInfo.cpp | 17 +
llvm/test/Analysis/CostModel/X86/switch.ll | 411 ++++++++++++++++++
2 files changed, 428 insertions(+)
create mode 100644 llvm/test/Analysis/CostModel/X86/switch.ll
diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
index 3d8d0a236a3c1..22a646f10507d 100644
--- a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
+++ b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
@@ -6155,6 +6155,23 @@ X86TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
InstructionCost X86TTIImpl::getCFInstrCost(unsigned Opcode,
TTI::TargetCostKind CostKind,
const Instruction *I) const {
+ if (Opcode == Instruction::Switch && CostKind == TTI::TCK_CodeSize) {
+ unsigned JumpTableSize, NumSuccs = I->getNumSuccessors();
+ getEstimatedNumberOfCaseClusters(*cast<SwitchInst>(I), JumpTableSize,
+ nullptr, nullptr);
+ // A trivial unconditional branch.
+ if (NumSuccs == 1)
+ return TTI::TCC_Basic;
+
+ // Assume that lowering the switch block is implemented by binary search if
+ // no jump table is generated.
+ if (JumpTableSize == 0)
+ return llvm::Log2_32_Ceil(NumSuccs) * 2 * TTI::TCC_Basic;
+
+ // Indirect branch + default compare + default jump
+ return 3 * TTI::TCC_Basic;
+ }
+
if (CostKind != TTI::TCK_RecipThroughput)
return Opcode == Instruction::PHI ? TTI::TCC_Free : TTI::TCC_Basic;
// Branches are assumed to be predicted.
diff --git a/llvm/test/Analysis/CostModel/X86/switch.ll b/llvm/test/Analysis/CostModel/X86/switch.ll
new file mode 100644
index 0000000000000..e668e365e899d
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/X86/switch.ll
@@ -0,0 +1,411 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes="print<cost-model>" -cost-kind=throughput 2>&1 -disable-output -mtriple=x86_64-unknown-linux-gnu | FileCheck %s -check-prefixes=CHECK,THROUGHPUT
+; RUN: opt < %s -passes="print<cost-model>" -cost-kind=latency 2>&1 -disable-output -mtriple=x86_64-unknown-linux-gnu | FileCheck %s -check-prefixes=CHECK,LATENCY
+; RUN: opt < %s -passes="print<cost-model>" -cost-kind=code-size 2>&1 -disable-output -mtriple=x86_64-unknown-linux-gnu | FileCheck %s -check-prefixes=CHECK,CODESIZE
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+define i32 @single_succ_switch(i32 %x) {
+; THROUGHPUT-LABEL: 'single_succ_switch'
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: ]
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 1
+;
+; LATENCY-LABEL: 'single_succ_switch'
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; LATENCY-NEXT: ]
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+;
+; CODESIZE-LABEL: 'single_succ_switch'
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; CODESIZE-NEXT: ]
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+;
+entry:
+ switch i32 %x, label %default [
+ ]
+default:
+ ret i32 1
+}
+
+define i32 @dense_switch(i32 %x) {
+; THROUGHPUT-LABEL: 'dense_switch'
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: i32 0, label %bb0
+; THROUGHPUT-NEXT: i32 1, label %bb1
+; THROUGHPUT-NEXT: i32 2, label %bb2
+; THROUGHPUT-NEXT: i32 3, label %bb3
+; THROUGHPUT-NEXT: i32 4, label %bb4
+; THROUGHPUT-NEXT: ]
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 0
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 1
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 2
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 3
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 4
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+; LATENCY-LABEL: 'dense_switch'
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; LATENCY-NEXT: i32 0, label %bb0
+; LATENCY-NEXT: i32 1, label %bb1
+; LATENCY-NEXT: i32 2, label %bb2
+; LATENCY-NEXT: i32 3, label %bb3
+; LATENCY-NEXT: i32 4, label %bb4
+; LATENCY-NEXT: ]
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+; CODESIZE-LABEL: 'dense_switch'
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: switch i32 %x, label %default [
+; CODESIZE-NEXT: i32 0, label %bb0
+; CODESIZE-NEXT: i32 1, label %bb1
+; CODESIZE-NEXT: i32 2, label %bb2
+; CODESIZE-NEXT: i32 3, label %bb3
+; CODESIZE-NEXT: i32 4, label %bb4
+; CODESIZE-NEXT: ]
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+entry:
+ switch i32 %x, label %default [
+ i32 0, label %bb0
+ i32 1, label %bb1
+ i32 2, label %bb2
+ i32 3, label %bb3
+ i32 4, label %bb4
+ ]
+bb0:
+ ret i32 0
+bb1:
+ ret i32 1
+bb2:
+ ret i32 2
+bb3:
+ ret i32 3
+bb4:
+ ret i32 4
+default:
+ unreachable
+}
+
+define i32 @sparse_switch(i32 %x) {
+; THROUGHPUT-LABEL: 'sparse_switch'
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: i32 0, label %bb0
+; THROUGHPUT-NEXT: i32 100, label %bb1
+; THROUGHPUT-NEXT: i32 200, label %bb2
+; THROUGHPUT-NEXT: i32 300, label %bb3
+; THROUGHPUT-NEXT: i32 400, label %bb4
+; THROUGHPUT-NEXT: ]
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 0
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 1
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 2
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 3
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 4
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+; LATENCY-LABEL: 'sparse_switch'
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; LATENCY-NEXT: i32 0, label %bb0
+; LATENCY-NEXT: i32 100, label %bb1
+; LATENCY-NEXT: i32 200, label %bb2
+; LATENCY-NEXT: i32 300, label %bb3
+; LATENCY-NEXT: i32 400, label %bb4
+; LATENCY-NEXT: ]
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+; CODESIZE-LABEL: 'sparse_switch'
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: switch i32 %x, label %default [
+; CODESIZE-NEXT: i32 0, label %bb0
+; CODESIZE-NEXT: i32 100, label %bb1
+; CODESIZE-NEXT: i32 200, label %bb2
+; CODESIZE-NEXT: i32 300, label %bb3
+; CODESIZE-NEXT: i32 400, label %bb4
+; CODESIZE-NEXT: ]
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+entry:
+ switch i32 %x, label %default [
+ i32 0, label %bb0
+ i32 100, label %bb1
+ i32 200, label %bb2
+ i32 300, label %bb3
+ i32 400, label %bb4
+ ]
+bb0:
+ ret i32 0
+bb1:
+ ret i32 1
+bb2:
+ ret i32 2
+bb3:
+ ret i32 3
+bb4:
+ ret i32 4
+default:
+ unreachable
+}
+
+define i32 @dense_big_switch(i32 %x) {
+; THROUGHPUT-LABEL: 'dense_big_switch'
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: i32 0, label %bb0
+; THROUGHPUT-NEXT: i32 1, label %bb1
+; THROUGHPUT-NEXT: i32 2, label %bb2
+; THROUGHPUT-NEXT: i32 3, label %bb3
+; THROUGHPUT-NEXT: i32 4, label %bb4
+; THROUGHPUT-NEXT: i32 5, label %bb5
+; THROUGHPUT-NEXT: i32 6, label %bb6
+; THROUGHPUT-NEXT: i32 7, label %bb7
+; THROUGHPUT-NEXT: i32 8, label %bb8
+; THROUGHPUT-NEXT: i32 9, label %bb9
+; THROUGHPUT-NEXT: i32 10, label %bb10
+; THROUGHPUT-NEXT: ]
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 0
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 1
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 2
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 3
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 4
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 5
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 6
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 7
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 8
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 9
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 10
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+; LATENCY-LABEL: 'dense_big_switch'
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; LATENCY-NEXT: i32 0, label %bb0
+; LATENCY-NEXT: i32 1, label %bb1
+; LATENCY-NEXT: i32 2, label %bb2
+; LATENCY-NEXT: i32 3, label %bb3
+; LATENCY-NEXT: i32 4, label %bb4
+; LATENCY-NEXT: i32 5, label %bb5
+; LATENCY-NEXT: i32 6, label %bb6
+; LATENCY-NEXT: i32 7, label %bb7
+; LATENCY-NEXT: i32 8, label %bb8
+; LATENCY-NEXT: i32 9, label %bb9
+; LATENCY-NEXT: i32 10, label %bb10
+; LATENCY-NEXT: ]
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 5
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 6
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 7
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 8
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 9
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 10
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+; CODESIZE-LABEL: 'dense_big_switch'
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: switch i32 %x, label %default [
+; CODESIZE-NEXT: i32 0, label %bb0
+; CODESIZE-NEXT: i32 1, label %bb1
+; CODESIZE-NEXT: i32 2, label %bb2
+; CODESIZE-NEXT: i32 3, label %bb3
+; CODESIZE-NEXT: i32 4, label %bb4
+; CODESIZE-NEXT: i32 5, label %bb5
+; CODESIZE-NEXT: i32 6, label %bb6
+; CODESIZE-NEXT: i32 7, label %bb7
+; CODESIZE-NEXT: i32 8, label %bb8
+; CODESIZE-NEXT: i32 9, label %bb9
+; CODESIZE-NEXT: i32 10, label %bb10
+; CODESIZE-NEXT: ]
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 5
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 6
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 7
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 8
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 9
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 10
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+entry:
+ switch i32 %x, label %default [
+ i32 0, label %bb0
+ i32 1, label %bb1
+ i32 2, label %bb2
+ i32 3, label %bb3
+ i32 4, label %bb4
+ i32 5, label %bb5
+ i32 6, label %bb6
+ i32 7, label %bb7
+ i32 8, label %bb8
+ i32 9, label %bb9
+ i32 10, label %bb10
+ ]
+bb0:
+ ret i32 0
+bb1:
+ ret i32 1
+bb2:
+ ret i32 2
+bb3:
+ ret i32 3
+bb4:
+ ret i32 4
+bb5:
+ ret i32 5
+bb6:
+ ret i32 6
+bb7:
+ ret i32 7
+bb8:
+ ret i32 8
+bb9:
+ ret i32 9
+bb10:
+ ret i32 10
+default:
+ unreachable
+}
+
+define i32 @sparse_big_switch(i32 %x) {
+; THROUGHPUT-LABEL: 'sparse_big_switch'
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: i32 0, label %bb0
+; THROUGHPUT-NEXT: i32 100, label %bb1
+; THROUGHPUT-NEXT: i32 200, label %bb2
+; THROUGHPUT-NEXT: i32 300, label %bb3
+; THROUGHPUT-NEXT: i32 400, label %bb4
+; THROUGHPUT-NEXT: i32 500, label %bb5
+; THROUGHPUT-NEXT: i32 600, label %bb6
+; THROUGHPUT-NEXT: i32 700, label %bb7
+; THROUGHPUT-NEXT: i32 800, label %bb8
+; THROUGHPUT-NEXT: i32 900, label %bb9
+; THROUGHPUT-NEXT: i32 1000, label %bb10
+; THROUGHPUT-NEXT: ]
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 0
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 1
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 2
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 3
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 4
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 5
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 6
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 7
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 8
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 9
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 10
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+; LATENCY-LABEL: 'sparse_big_switch'
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; LATENCY-NEXT: i32 0, label %bb0
+; LATENCY-NEXT: i32 100, label %bb1
+; LATENCY-NEXT: i32 200, label %bb2
+; LATENCY-NEXT: i32 300, label %bb3
+; LATENCY-NEXT: i32 400, label %bb4
+; LATENCY-NEXT: i32 500, label %bb5
+; LATENCY-NEXT: i32 600, label %bb6
+; LATENCY-NEXT: i32 700, label %bb7
+; LATENCY-NEXT: i32 800, label %bb8
+; LATENCY-NEXT: i32 900, label %bb9
+; LATENCY-NEXT: i32 1000, label %bb10
+; LATENCY-NEXT: ]
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 5
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 6
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 7
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 8
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 9
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 10
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+; CODESIZE-LABEL: 'sparse_big_switch'
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: switch i32 %x, label %default [
+; CODESIZE-NEXT: i32 0, label %bb0
+; CODESIZE-NEXT: i32 100, label %bb1
+; CODESIZE-NEXT: i32 200, label %bb2
+; CODESIZE-NEXT: i32 300, label %bb3
+; CODESIZE-NEXT: i32 400, label %bb4
+; CODESIZE-NEXT: i32 500, label %bb5
+; CODESIZE-NEXT: i32 600, label %bb6
+; CODESIZE-NEXT: i32 700, label %bb7
+; CODESIZE-NEXT: i32 800, label %bb8
+; CODESIZE-NEXT: i32 900, label %bb9
+; CODESIZE-NEXT: i32 1000, label %bb10
+; CODESIZE-NEXT: ]
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 5
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 6
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 7
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 8
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 9
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 10
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
+;
+entry:
+ switch i32 %x, label %default [
+ i32 0, label %bb0
+ i32 100, label %bb1
+ i32 200, label %bb2
+ i32 300, label %bb3
+ i32 400, label %bb4
+ i32 500, label %bb5
+ i32 600, label %bb6
+ i32 700, label %bb7
+ i32 800, label %bb8
+ i32 900, label %bb9
+ i32 1000, label %bb10
+ ]
+bb0:
+ ret i32 0
+bb1:
+ ret i32 1
+bb2:
+ ret i32 2
+bb3:
+ ret i32 3
+bb4:
+ ret i32 4
+bb5:
+ ret i32 5
+bb6:
+ ret i32 6
+bb7:
+ ret i32 7
+bb8:
+ ret i32 8
+bb9:
+ ret i32 9
+bb10:
+ ret i32 10
+default:
+ unreachable
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
>From 90ce69869072c78acc4c3214b3ebe2dbec3223ce Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Thu, 16 Oct 2025 03:16:42 +0800
Subject: [PATCH 2/2] resolve comments
---
llvm/include/llvm/CodeGen/BasicTTIImpl.h | 37 +++++
.../lib/Target/X86/X86TargetTransformInfo.cpp | 18 +--
llvm/test/Analysis/CostModel/X86/switch.ll | 150 +++++++++++++++++-
3 files changed, 182 insertions(+), 23 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 42ddb32d24093..ed7658ad62f8d 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -1365,6 +1365,43 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
InstructionCost
getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind,
const Instruction *I = nullptr) const override {
+ if (Opcode == Instruction::Switch && CostKind == TTI::TCK_CodeSize && I) {
+ const SwitchInst *SI = cast<SwitchInst>(I);
+ unsigned JumpTableSize, NumSuccs = I->getNumSuccessors();
+ auto BrCost = thisT()->getCFInstrCost(Instruction::Br, CostKind);
+ if (SI->defaultDestUnreachable())
+ NumSuccs--;
+
+ // An unreachable switch
+ if (NumSuccs == 0)
+ return TTI::TCC_Free;
+
+ // A trivial unconditional branch.
+ if (NumSuccs == 1)
+ return BrCost;
+
+ thisT()->getEstimatedNumberOfCaseClusters(*SI, JumpTableSize, nullptr,
+ nullptr);
+ Type *BoolTy = IntegerType::get(SI->getContext(), 1);
+ Type *CondTy = SI->getCondition()->getType();
+ auto CmpCost = thisT()->getCmpSelInstrCost(
+ BinaryOperator::ICmp, BoolTy, CondTy, CmpInst::ICMP_UGT, CostKind);
+
+ // Assume that lowering the switch block is implemented by binary search
+ // if no jump table is generated.
+ if (JumpTableSize == 0)
+ return llvm::Log2_32_Ceil(NumSuccs) * (CmpCost + BrCost);
+
+ // Cost for jump table: load + jump + default compare + default jump
+ Type *EntryTy = PointerType::get(SI->getContext(), 0);
+ Align Alignment = thisT()->DL.getABITypeAlign(EntryTy);
+ auto LoadCost = thisT()->getMemoryOpCost(Instruction::Load, EntryTy,
+ Alignment, 0, CostKind);
+
+ return LoadCost + BrCost +
+ (SI->defaultDestUnreachable() ? 0 : (CmpCost + BrCost));
+ }
+
return BaseT::getCFInstrCost(Opcode, CostKind, I);
}
diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
index 22a646f10507d..1cdb4397a4683 100644
--- a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
+++ b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
@@ -6155,22 +6155,8 @@ X86TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
InstructionCost X86TTIImpl::getCFInstrCost(unsigned Opcode,
TTI::TargetCostKind CostKind,
const Instruction *I) const {
- if (Opcode == Instruction::Switch && CostKind == TTI::TCK_CodeSize) {
- unsigned JumpTableSize, NumSuccs = I->getNumSuccessors();
- getEstimatedNumberOfCaseClusters(*cast<SwitchInst>(I), JumpTableSize,
- nullptr, nullptr);
- // A trivial unconditional branch.
- if (NumSuccs == 1)
- return TTI::TCC_Basic;
-
- // Assume that lowering the switch block is implemented by binary search if
- // no jump table is generated.
- if (JumpTableSize == 0)
- return llvm::Log2_32_Ceil(NumSuccs) * 2 * TTI::TCC_Basic;
-
- // Indirect branch + default compare + default jump
- return 3 * TTI::TCC_Basic;
- }
+ if (Opcode == Instruction::Switch)
+ return BaseT::getCFInstrCost(Opcode, CostKind, I);
if (CostKind != TTI::TCK_RecipThroughput)
return Opcode == Instruction::PHI ? TTI::TCC_Free : TTI::TCC_Basic;
diff --git a/llvm/test/Analysis/CostModel/X86/switch.ll b/llvm/test/Analysis/CostModel/X86/switch.ll
index e668e365e899d..ae0f6fe78d8d0 100644
--- a/llvm/test/Analysis/CostModel/X86/switch.ll
+++ b/llvm/test/Analysis/CostModel/X86/switch.ll
@@ -7,7 +7,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
define i32 @single_succ_switch(i32 %x) {
; THROUGHPUT-LABEL: 'single_succ_switch'
-; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
; THROUGHPUT-NEXT: ]
; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 1
;
@@ -30,7 +30,7 @@ default:
define i32 @dense_switch(i32 %x) {
; THROUGHPUT-LABEL: 'dense_switch'
-; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
; THROUGHPUT-NEXT: i32 0, label %bb0
; THROUGHPUT-NEXT: i32 1, label %bb1
; THROUGHPUT-NEXT: i32 2, label %bb2
@@ -60,7 +60,7 @@ define i32 @dense_switch(i32 %x) {
; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
;
; CODESIZE-LABEL: 'dense_switch'
-; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: switch i32 %x, label %default [
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: switch i32 %x, label %default [
; CODESIZE-NEXT: i32 0, label %bb0
; CODESIZE-NEXT: i32 1, label %bb1
; CODESIZE-NEXT: i32 2, label %bb2
@@ -96,9 +96,77 @@ default:
unreachable
}
+define i32 @dense_switch_reachable_default(i32 %x) {
+; THROUGHPUT-LABEL: 'dense_switch_reachable_default'
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: i32 0, label %bb0
+; THROUGHPUT-NEXT: i32 1, label %bb1
+; THROUGHPUT-NEXT: i32 2, label %bb2
+; THROUGHPUT-NEXT: i32 3, label %bb3
+; THROUGHPUT-NEXT: i32 4, label %bb4
+; THROUGHPUT-NEXT: ]
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 0
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 1
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 2
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 3
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 4
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 5
+;
+; LATENCY-LABEL: 'dense_switch_reachable_default'
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; LATENCY-NEXT: i32 0, label %bb0
+; LATENCY-NEXT: i32 1, label %bb1
+; LATENCY-NEXT: i32 2, label %bb2
+; LATENCY-NEXT: i32 3, label %bb3
+; LATENCY-NEXT: i32 4, label %bb4
+; LATENCY-NEXT: ]
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 5
+;
+; CODESIZE-LABEL: 'dense_switch_reachable_default'
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: switch i32 %x, label %default [
+; CODESIZE-NEXT: i32 0, label %bb0
+; CODESIZE-NEXT: i32 1, label %bb1
+; CODESIZE-NEXT: i32 2, label %bb2
+; CODESIZE-NEXT: i32 3, label %bb3
+; CODESIZE-NEXT: i32 4, label %bb4
+; CODESIZE-NEXT: ]
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 5
+;
+entry:
+ switch i32 %x, label %default [
+ i32 0, label %bb0
+ i32 1, label %bb1
+ i32 2, label %bb2
+ i32 3, label %bb3
+ i32 4, label %bb4
+ ]
+bb0:
+ ret i32 0
+bb1:
+ ret i32 1
+bb2:
+ ret i32 2
+bb3:
+ ret i32 3
+bb4:
+ ret i32 4
+default:
+ ret i32 5
+}
+
define i32 @sparse_switch(i32 %x) {
; THROUGHPUT-LABEL: 'sparse_switch'
-; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
; THROUGHPUT-NEXT: i32 0, label %bb0
; THROUGHPUT-NEXT: i32 100, label %bb1
; THROUGHPUT-NEXT: i32 200, label %bb2
@@ -164,9 +232,77 @@ default:
unreachable
}
+define i32 @sparse_switch_reachable_default(i32 %x) {
+; THROUGHPUT-LABEL: 'sparse_switch_reachable_default'
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: i32 0, label %bb0
+; THROUGHPUT-NEXT: i32 100, label %bb1
+; THROUGHPUT-NEXT: i32 200, label %bb2
+; THROUGHPUT-NEXT: i32 300, label %bb3
+; THROUGHPUT-NEXT: i32 400, label %bb4
+; THROUGHPUT-NEXT: ]
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 0
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 1
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 2
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 3
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 4
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 5
+;
+; LATENCY-LABEL: 'sparse_switch_reachable_default'
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
+; LATENCY-NEXT: i32 0, label %bb0
+; LATENCY-NEXT: i32 100, label %bb1
+; LATENCY-NEXT: i32 200, label %bb2
+; LATENCY-NEXT: i32 300, label %bb3
+; LATENCY-NEXT: i32 400, label %bb4
+; LATENCY-NEXT: ]
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 5
+;
+; CODESIZE-LABEL: 'sparse_switch_reachable_default'
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: switch i32 %x, label %default [
+; CODESIZE-NEXT: i32 0, label %bb0
+; CODESIZE-NEXT: i32 100, label %bb1
+; CODESIZE-NEXT: i32 200, label %bb2
+; CODESIZE-NEXT: i32 300, label %bb3
+; CODESIZE-NEXT: i32 400, label %bb4
+; CODESIZE-NEXT: ]
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 0
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 1
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 2
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 3
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 4
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 5
+;
+entry:
+ switch i32 %x, label %default [
+ i32 0, label %bb0
+ i32 100, label %bb1
+ i32 200, label %bb2
+ i32 300, label %bb3
+ i32 400, label %bb4
+ ]
+bb0:
+ ret i32 0
+bb1:
+ ret i32 1
+bb2:
+ ret i32 2
+bb3:
+ ret i32 3
+bb4:
+ ret i32 4
+default:
+ ret i32 5
+}
+
define i32 @dense_big_switch(i32 %x) {
; THROUGHPUT-LABEL: 'dense_big_switch'
-; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
; THROUGHPUT-NEXT: i32 0, label %bb0
; THROUGHPUT-NEXT: i32 1, label %bb1
; THROUGHPUT-NEXT: i32 2, label %bb2
@@ -220,7 +356,7 @@ define i32 @dense_big_switch(i32 %x) {
; LATENCY-NEXT: Cost Model: Found an estimated cost of 1 for instruction: unreachable
;
; CODESIZE-LABEL: 'dense_big_switch'
-; CODESIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: switch i32 %x, label %default [
+; CODESIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: switch i32 %x, label %default [
; CODESIZE-NEXT: i32 0, label %bb0
; CODESIZE-NEXT: i32 1, label %bb1
; CODESIZE-NEXT: i32 2, label %bb2
@@ -288,7 +424,7 @@ default:
define i32 @sparse_big_switch(i32 %x) {
; THROUGHPUT-LABEL: 'sparse_big_switch'
-; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: switch i32 %x, label %default [
+; THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: switch i32 %x, label %default [
; THROUGHPUT-NEXT: i32 0, label %bb0
; THROUGHPUT-NEXT: i32 100, label %bb1
; THROUGHPUT-NEXT: i32 200, label %bb2
More information about the llvm-commits
mailing list