[llvm] [CodeGenPrepare] Reuse free wider zero extensions (PR #228750)
Dávid Bolvanský via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 3 10:54:23 PDT 2026
https://github.com/davidbolvansky updated https://github.com/llvm/llvm-project/pull/228750
>From 4911096fd3a1b3126fb0d1f59902552333c2bbaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A1vid=20Bolvansk=C3=BD?= <david.bolvansky at gmail.com>
Date: Sat, 3 Oct 2026 19:41:34 +0200
Subject: [PATCH 1/2] [CodeGenPrepare] Reuse free wider extensions without
truncating
Reuse an existing extension for a wider extension of the same kind when the target considers it free. Avoid hiding extending-load promotion behind a truncate/re-extend pair.
Assisted-by: OpenAI Codex
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 16 ++
.../CodeGenPrepare/reuse-extension.ll | 228 ++++++++++++++++++
2 files changed, 244 insertions(+)
create mode 100644 llvm/test/Transforms/CodeGenPrepare/reuse-extension.ll
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 0b96c77ff33ea..fbb4d3b4e0261 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -7391,6 +7391,22 @@ bool CodeGenPrepare::optimizeExtUses(Instruction *I) {
continue;
// Both src and def are live in this block. Rewrite the use.
+ // Reuse an extension directly when a wider extension of the same kind is
+ // free for its users.
+ // Going through a truncation instead can hide an extending-load
+ // opportunity.
+ if (I->getOpcode() == User->getOpcode() &&
+ User->getType()->getScalarSizeInBits() >
+ I->getType()->getScalarSizeInBits()) {
+ U = I;
+ if (TLI->isExtFree(User)) {
+ ++NumExtUses;
+ MadeChange = true;
+ continue;
+ }
+ U = Src;
+ }
+
Instruction *&InsertedTrunc = InsertedTruncs[UserBB];
if (!InsertedTrunc) {
diff --git a/llvm/test/Transforms/CodeGenPrepare/reuse-extension.ll b/llvm/test/Transforms/CodeGenPrepare/reuse-extension.ll
new file mode 100644
index 0000000000000..8484ea8b42f7a
--- /dev/null
+++ b/llvm/test/Transforms/CodeGenPrepare/reuse-extension.ll
@@ -0,0 +1,228 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' -mtriple=aarch64 < %s | FileCheck %s --check-prefixes=CHECK,AARCH64
+; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' -mtriple=x86_64 < %s | FileCheck %s --check-prefixes=CHECK,X86
+; REQUIRES: aarch64-registered-target, x86-registered-target
+
+; Reusing a free wider extension must not introduce a truncation that
+; prevents CodeGenPrepare from moving the extension to the original load.
+declare void @consume(i32)
+declare void @consume64(i64)
+
+define i64 @zext_i8(ptr %p, ptr %table, i1 %cold) {
+;
+; CHECK-LABEL: @zext_i8(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P:%.*]], align 1
+; CHECK-NEXT: [[PROMOTED:%.*]] = zext i8 [[V]] to i64
+; CHECK-NEXT: [[V32:%.*]] = zext i8 [[V]] to i32
+; CHECK-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
+; CHECK: call:
+; CHECK-NEXT: call void @consume(i32 [[V32]])
+; CHECK-NEXT: br label [[JOIN]]
+; CHECK: join:
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[TABLE:%.*]], i64 [[PROMOTED]]
+; CHECK-NEXT: [[MASK:%.*]] = load i32, ptr [[PTR]], align 4
+; CHECK-NEXT: [[SUM:%.*]] = add i32 [[MASK]], [[V32]]
+; CHECK-NEXT: [[RESULT:%.*]] = zext i32 [[SUM]] to i64
+; CHECK-NEXT: ret i64 [[RESULT]]
+;
+entry:
+ %v = load i8, ptr %p
+ %v32 = zext i8 %v to i32
+ br i1 %cold, label %call, label %join
+call:
+ call void @consume(i32 %v32)
+ br label %join
+join:
+ %v64 = zext i8 %v to i64
+ %ptr = getelementptr i32, ptr %table, i64 %v64
+ %mask = load i32, ptr %ptr
+ %sum = add i32 %mask, %v32
+ %result = zext i32 %sum to i64
+ ret i64 %result
+}
+
+define i64 @zext_i16(ptr %p, ptr %table, i1 %cold) {
+;
+; CHECK-LABEL: @zext_i16(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = load i16, ptr [[P:%.*]], align 2
+; CHECK-NEXT: [[PROMOTED:%.*]] = zext i16 [[V]] to i64
+; CHECK-NEXT: [[V32:%.*]] = zext i16 [[V]] to i32
+; CHECK-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
+; CHECK: call:
+; CHECK-NEXT: call void @consume(i32 [[V32]])
+; CHECK-NEXT: br label [[JOIN]]
+; CHECK: join:
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[TABLE:%.*]], i64 [[PROMOTED]]
+; CHECK-NEXT: [[MASK:%.*]] = load i32, ptr [[PTR]], align 4
+; CHECK-NEXT: [[SUM:%.*]] = add i32 [[MASK]], [[V32]]
+; CHECK-NEXT: [[RESULT:%.*]] = zext i32 [[SUM]] to i64
+; CHECK-NEXT: ret i64 [[RESULT]]
+;
+entry:
+ %v = load i16, ptr %p
+ %v32 = zext i16 %v to i32
+ br i1 %cold, label %call, label %join
+call:
+ call void @consume(i32 %v32)
+ br label %join
+join:
+ %v64 = zext i16 %v to i64
+ %ptr = getelementptr i32, ptr %table, i64 %v64
+ %mask = load i32, ptr %ptr
+ %sum = add i32 %mask, %v32
+ %result = zext i32 %sum to i64
+ ret i64 %result
+}
+
+define i64 @sext_then_zext(ptr %p, ptr %table, i1 %cold) {
+;
+; CHECK-LABEL: @sext_then_zext(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P:%.*]], align 1
+; CHECK-NEXT: [[V32:%.*]] = sext i8 [[V]] to i32
+; CHECK-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
+; CHECK: call:
+; CHECK-NEXT: call void @consume(i32 [[V32]])
+; CHECK-NEXT: br label [[JOIN]]
+; CHECK: join:
+; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[V32]] to i8
+; CHECK-NEXT: [[V64:%.*]] = zext i8 [[TMP0]] to i64
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[TABLE:%.*]], i64 [[V64]]
+; CHECK-NEXT: [[MASK:%.*]] = load i32, ptr [[PTR]], align 4
+; CHECK-NEXT: [[SUM:%.*]] = add i32 [[MASK]], [[V32]]
+; CHECK-NEXT: [[RESULT:%.*]] = zext i32 [[SUM]] to i64
+; CHECK-NEXT: ret i64 [[RESULT]]
+;
+entry:
+ %v = load i8, ptr %p
+ %v32 = sext i8 %v to i32
+ br i1 %cold, label %call, label %join
+call:
+ call void @consume(i32 %v32)
+ br label %join
+join:
+ %v64 = zext i8 %v to i64
+ %ptr = getelementptr i32, ptr %table, i64 %v64
+ %mask = load i32, ptr %ptr
+ %sum = add i32 %mask, %v32
+ %result = zext i32 %sum to i64
+ ret i64 %result
+}
+
+define i64 @zext_then_sext(ptr %p, ptr %table, i1 %cold) {
+;
+; CHECK-LABEL: @zext_then_sext(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P:%.*]], align 1
+; CHECK-NEXT: [[V32:%.*]] = zext i8 [[V]] to i32
+; CHECK-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
+; CHECK: call:
+; CHECK-NEXT: call void @consume(i32 [[V32]])
+; CHECK-NEXT: br label [[JOIN]]
+; CHECK: join:
+; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[V32]] to i8
+; CHECK-NEXT: [[V64:%.*]] = sext i8 [[TMP0]] to i64
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[TABLE:%.*]], i64 [[V64]]
+; CHECK-NEXT: [[MASK:%.*]] = load i32, ptr [[PTR]], align 4
+; CHECK-NEXT: [[SUM:%.*]] = add i32 [[MASK]], [[V32]]
+; CHECK-NEXT: [[RESULT:%.*]] = zext i32 [[SUM]] to i64
+; CHECK-NEXT: ret i64 [[RESULT]]
+;
+entry:
+ %v = load i8, ptr %p
+ %v32 = zext i8 %v to i32
+ br i1 %cold, label %call, label %join
+call:
+ call void @consume(i32 %v32)
+ br label %join
+join:
+ %v64 = sext i8 %v to i64
+ %ptr = getelementptr i32, ptr %table, i64 %v64
+ %mask = load i32, ptr %ptr
+ %sum = add i32 %mask, %v32
+ %result = zext i32 %sum to i64
+ ret i64 %result
+}
+
+
+define i64 @sext_address(ptr %p, ptr %table, i1 %cold) {
+; AARCH64-LABEL: @sext_address(
+; AARCH64-NEXT: entry:
+; AARCH64-NEXT: [[V:%.*]] = load i8, ptr [[P:%.*]], align 1
+; AARCH64-NEXT: [[V64:%.*]] = sext i8 [[V]] to i64
+; AARCH64-NEXT: [[V32:%.*]] = sext i8 [[V]] to i32
+; AARCH64-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
+; AARCH64: call:
+; AARCH64-NEXT: call void @consume(i32 [[V32]])
+; AARCH64-NEXT: br label [[JOIN]]
+; AARCH64: join:
+; AARCH64-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[TABLE:%.*]], i64 [[V64]]
+; AARCH64-NEXT: [[MASK:%.*]] = load i32, ptr [[PTR]], align 4
+; AARCH64-NEXT: [[SUM:%.*]] = add i32 [[MASK]], [[V32]]
+; AARCH64-NEXT: [[RESULT:%.*]] = zext i32 [[SUM]] to i64
+; AARCH64-NEXT: ret i64 [[RESULT]]
+;
+; X86-LABEL: @sext_address(
+; X86-NEXT: entry:
+; X86-NEXT: [[V:%.*]] = load i8, ptr [[P:%.*]], align 1
+; X86-NEXT: [[V32:%.*]] = sext i8 [[V]] to i32
+; X86-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
+; X86: call:
+; X86-NEXT: call void @consume(i32 [[V32]])
+; X86-NEXT: br label [[JOIN]]
+; X86: join:
+; X86-NEXT: [[TMP0:%.*]] = trunc i32 [[V32]] to i8
+; X86-NEXT: [[V64:%.*]] = sext i8 [[TMP0]] to i64
+; X86-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[TABLE:%.*]], i64 [[V64]]
+; X86-NEXT: [[MASK:%.*]] = load i32, ptr [[PTR]], align 4
+; X86-NEXT: [[SUM:%.*]] = add i32 [[MASK]], [[V32]]
+; X86-NEXT: [[RESULT:%.*]] = zext i32 [[SUM]] to i64
+; X86-NEXT: ret i64 [[RESULT]]
+;
+entry:
+ %v = load i8, ptr %p
+ %v32 = sext i8 %v to i32
+ br i1 %cold, label %call, label %join
+call:
+ call void @consume(i32 %v32)
+ br label %join
+join:
+ %v64 = sext i8 %v to i64
+ %ptr = getelementptr i32, ptr %table, i64 %v64
+ %mask = load i32, ptr %ptr
+ %sum = add i32 %mask, %v32
+ %result = zext i32 %sum to i64
+ ret i64 %result
+}
+
+define i64 @sext_standalone(ptr %p, ptr %table, i1 %cold) {
+; CHECK-LABEL: @sext_standalone(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P:%.*]], align 1
+; CHECK-NEXT: [[V32:%.*]] = sext i8 [[V]] to i32
+; CHECK-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
+; CHECK: call:
+; CHECK-NEXT: call void @consume(i32 [[V32]])
+; CHECK-NEXT: br label [[JOIN]]
+; CHECK: join:
+; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[V32]] to i8
+; CHECK-NEXT: [[V64:%.*]] = sext i8 [[TMP0]] to i64
+; CHECK-NEXT: call void @consume64(i64 [[V64]])
+; CHECK-NEXT: [[RESULT:%.*]] = zext i32 [[V32]] to i64
+; CHECK-NEXT: ret i64 [[RESULT]]
+;
+entry:
+ %v = load i8, ptr %p
+ %v32 = sext i8 %v to i32
+ br i1 %cold, label %call, label %join
+call:
+ call void @consume(i32 %v32)
+ br label %join
+join:
+ %v64 = sext i8 %v to i64
+ call void @consume64(i64 %v64)
+ %result = zext i32 %v32 to i64
+ ret i64 %result
+}
>From 2df6bdb373b2b96d304e055a0af3726f6259e993 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A1vid=20Bolvansk=C3=BD?= <david.bolvansky at gmail.com>
Date: Sat, 3 Oct 2026 19:54:07 +0200
Subject: [PATCH 2/2] Query zero-extension cost before changing operands and
check final x86 assembly
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 17 ++--
llvm/test/CodeGen/X86/reuse-extension.ll | 95 +++++++++++++++++++
.../CodeGenPrepare/reuse-extension.ll | 53 ++++-------
3 files changed, 122 insertions(+), 43 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/reuse-extension.ll
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index fbb4d3b4e0261..48a57f8017a5c 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -7391,20 +7391,17 @@ bool CodeGenPrepare::optimizeExtUses(Instruction *I) {
continue;
// Both src and def are live in this block. Rewrite the use.
- // Reuse an extension directly when a wider extension of the same kind is
- // free for its users.
+ // Reuse a zero extension directly when a wider zero extension is free.
// Going through a truncation instead can hide an extending-load
// opportunity.
- if (I->getOpcode() == User->getOpcode() &&
+ if (isa<ZExtInst>(I) && isa<ZExtInst>(User) &&
User->getType()->getScalarSizeInBits() >
- I->getType()->getScalarSizeInBits()) {
+ I->getType()->getScalarSizeInBits() &&
+ TLI->isZExtFree(I->getType(), User->getType())) {
U = I;
- if (TLI->isExtFree(User)) {
- ++NumExtUses;
- MadeChange = true;
- continue;
- }
- U = Src;
+ ++NumExtUses;
+ MadeChange = true;
+ continue;
}
Instruction *&InsertedTrunc = InsertedTruncs[UserBB];
diff --git a/llvm/test/CodeGen/X86/reuse-extension.ll b/llvm/test/CodeGen/X86/reuse-extension.ll
new file mode 100644
index 0000000000000..38fd66ef27f43
--- /dev/null
+++ b/llvm/test/CodeGen/X86/reuse-extension.ll
@@ -0,0 +1,95 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64 -verify-machineinstrs < %s | FileCheck %s
+
+; Reusing the extending load's register avoids a redundant 32-bit copy before
+; the indexed memory operand, even when the value survives a call.
+declare void @consume(i32)
+
+define i64 @zext_i8(ptr %p, ptr %table, i1 %cold) {
+; CHECK-LABEL: zext_i8:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: .cfi_offset %rbx, -24
+; CHECK-NEXT: .cfi_offset %r14, -16
+; CHECK-NEXT: movq %rsi, %rbx
+; CHECK-NEXT: movzbl (%rdi), %r14d
+; CHECK-NEXT: testb $1, %dl
+; CHECK-NEXT: je .LBB0_2
+; CHECK-NEXT: # %bb.1: # %call
+; CHECK-NEXT: movl %r14d, %edi
+; CHECK-NEXT: callq consume at PLT
+; CHECK-NEXT: .LBB0_2: # %join
+; CHECK-NEXT: addl (%rbx,%r14,4), %r14d
+; CHECK-NEXT: movq %r14, %rax
+; CHECK-NEXT: addq $8, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+entry:
+ %v = load i8, ptr %p
+ %v32 = zext i8 %v to i32
+ br i1 %cold, label %call, label %join
+call:
+ call void @consume(i32 %v32)
+ br label %join
+join:
+ %v64 = zext i8 %v to i64
+ %ptr = getelementptr i32, ptr %table, i64 %v64
+ %mask = load i32, ptr %ptr
+ %sum = add i32 %mask, %v32
+ %result = zext i32 %sum to i64
+ ret i64 %result
+}
+
+define i64 @zext_i16(ptr %p, ptr %table, i1 %cold) {
+; CHECK-LABEL: zext_i16:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: .cfi_offset %rbx, -24
+; CHECK-NEXT: .cfi_offset %r14, -16
+; CHECK-NEXT: movq %rsi, %rbx
+; CHECK-NEXT: movzwl (%rdi), %r14d
+; CHECK-NEXT: testb $1, %dl
+; CHECK-NEXT: je .LBB1_2
+; CHECK-NEXT: # %bb.1: # %call
+; CHECK-NEXT: movl %r14d, %edi
+; CHECK-NEXT: callq consume at PLT
+; CHECK-NEXT: .LBB1_2: # %join
+; CHECK-NEXT: addl (%rbx,%r14,4), %r14d
+; CHECK-NEXT: movq %r14, %rax
+; CHECK-NEXT: addq $8, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+entry:
+ %v = load i16, ptr %p
+ %v32 = zext i16 %v to i32
+ br i1 %cold, label %call, label %join
+call:
+ call void @consume(i32 %v32)
+ br label %join
+join:
+ %v64 = zext i16 %v to i64
+ %ptr = getelementptr i32, ptr %table, i64 %v64
+ %mask = load i32, ptr %ptr
+ %sum = add i32 %mask, %v32
+ %result = zext i32 %sum to i64
+ ret i64 %result
+}
+
diff --git a/llvm/test/Transforms/CodeGenPrepare/reuse-extension.ll b/llvm/test/Transforms/CodeGenPrepare/reuse-extension.ll
index 8484ea8b42f7a..6762cfb44641c 100644
--- a/llvm/test/Transforms/CodeGenPrepare/reuse-extension.ll
+++ b/llvm/test/Transforms/CodeGenPrepare/reuse-extension.ll
@@ -3,7 +3,7 @@
; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' -mtriple=x86_64 < %s | FileCheck %s --check-prefixes=CHECK,X86
; REQUIRES: aarch64-registered-target, x86-registered-target
-; Reusing a free wider extension must not introduce a truncation that
+; Reusing a free wider zero extension must not introduce a truncation that
; prevents CodeGenPrepare from moving the extension to the original load.
declare void @consume(i32)
declare void @consume64(i64)
@@ -148,38 +148,22 @@ join:
define i64 @sext_address(ptr %p, ptr %table, i1 %cold) {
-; AARCH64-LABEL: @sext_address(
-; AARCH64-NEXT: entry:
-; AARCH64-NEXT: [[V:%.*]] = load i8, ptr [[P:%.*]], align 1
-; AARCH64-NEXT: [[V64:%.*]] = sext i8 [[V]] to i64
-; AARCH64-NEXT: [[V32:%.*]] = sext i8 [[V]] to i32
-; AARCH64-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
-; AARCH64: call:
-; AARCH64-NEXT: call void @consume(i32 [[V32]])
-; AARCH64-NEXT: br label [[JOIN]]
-; AARCH64: join:
-; AARCH64-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[TABLE:%.*]], i64 [[V64]]
-; AARCH64-NEXT: [[MASK:%.*]] = load i32, ptr [[PTR]], align 4
-; AARCH64-NEXT: [[SUM:%.*]] = add i32 [[MASK]], [[V32]]
-; AARCH64-NEXT: [[RESULT:%.*]] = zext i32 [[SUM]] to i64
-; AARCH64-NEXT: ret i64 [[RESULT]]
-;
-; X86-LABEL: @sext_address(
-; X86-NEXT: entry:
-; X86-NEXT: [[V:%.*]] = load i8, ptr [[P:%.*]], align 1
-; X86-NEXT: [[V32:%.*]] = sext i8 [[V]] to i32
-; X86-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
-; X86: call:
-; X86-NEXT: call void @consume(i32 [[V32]])
-; X86-NEXT: br label [[JOIN]]
-; X86: join:
-; X86-NEXT: [[TMP0:%.*]] = trunc i32 [[V32]] to i8
-; X86-NEXT: [[V64:%.*]] = sext i8 [[TMP0]] to i64
-; X86-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[TABLE:%.*]], i64 [[V64]]
-; X86-NEXT: [[MASK:%.*]] = load i32, ptr [[PTR]], align 4
-; X86-NEXT: [[SUM:%.*]] = add i32 [[MASK]], [[V32]]
-; X86-NEXT: [[RESULT:%.*]] = zext i32 [[SUM]] to i64
-; X86-NEXT: ret i64 [[RESULT]]
+; CHECK-LABEL: @sext_address(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[P:%.*]], align 1
+; CHECK-NEXT: [[V32:%.*]] = sext i8 [[V]] to i32
+; CHECK-NEXT: br i1 [[COLD:%.*]], label [[CALL:%.*]], label [[JOIN:%.*]]
+; CHECK: call:
+; CHECK-NEXT: call void @consume(i32 [[V32]])
+; CHECK-NEXT: br label [[JOIN]]
+; CHECK: join:
+; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[V32]] to i8
+; CHECK-NEXT: [[V64:%.*]] = sext i8 [[TMP0]] to i64
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[TABLE:%.*]], i64 [[V64]]
+; CHECK-NEXT: [[MASK:%.*]] = load i32, ptr [[PTR]], align 4
+; CHECK-NEXT: [[SUM:%.*]] = add i32 [[MASK]], [[V32]]
+; CHECK-NEXT: [[RESULT:%.*]] = zext i32 [[SUM]] to i64
+; CHECK-NEXT: ret i64 [[RESULT]]
;
entry:
%v = load i8, ptr %p
@@ -226,3 +210,6 @@ join:
%result = zext i32 %v32 to i64
ret i64 %result
}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; AARCH64: {{.*}}
+; X86: {{.*}}
More information about the llvm-commits
mailing list