Skip to content

Commit 83a5e37

Browse files
committed
[FastISel] Don't trivially kill extractvalues (PR49467)
All extractvalues of the same value at the same index will map to the same register, so even if one specific extractvalue only has one use, we should not mark it as a trivial kill, as there may be more extractvalues later. Fixes https://bugs.llvm.org/show_bug.cgi?id=49467. Differential Revision: https://reviews.llvm.org/D98145
1 parent 5f958e1 commit 83a5e37

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

llvm/include/llvm/CodeGen/FastISel.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,10 @@ class FastISel {
490490
/// - \c Add has a constant operand.
491491
bool canFoldAddIntoGEP(const User *GEP, const Value *Add);
492492

493-
/// Test whether the given value has exactly one use.
493+
/// Test whether the register associated with this value has exactly one use,
494+
/// in which case that single use is killing. Note that multiple IR values
495+
/// may map onto the same register, in which case this is not the same as
496+
/// checking that an IR value has one use.
494497
bool hasTrivialKill(const Value *V);
495498

496499
/// Create a machine mem operand from the given instruction.

llvm/lib/CodeGen/SelectionDAG/FastISel.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,16 @@ bool FastISel::hasTrivialKill(const Value *V) {
261261
if (GEP->hasAllZeroIndices() && !hasTrivialKill(GEP->getOperand(0)))
262262
return false;
263263

264+
// Casts and extractvalues may be trivially coalesced by fast-isel.
265+
if (I->getOpcode() == Instruction::BitCast ||
266+
I->getOpcode() == Instruction::PtrToInt ||
267+
I->getOpcode() == Instruction::IntToPtr ||
268+
I->getOpcode() == Instruction::ExtractValue)
269+
return false;
270+
264271
// Only instructions with a single use in the same basic block are considered
265272
// to have trivial kills.
266273
return I->hasOneUse() &&
267-
!(I->getOpcode() == Instruction::BitCast ||
268-
I->getOpcode() == Instruction::PtrToInt ||
269-
I->getOpcode() == Instruction::IntToPtr) &&
270274
cast<Instruction>(*I->user_begin())->getParent() == I->getParent();
271275
}
272276

llvm/test/CodeGen/X86/pr49467.ll

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -O0 -fast-isel -verify-machineinstrs -mtriple=x86_64 < %s | FileCheck %s
3+
4+
declare { i8*, i64 } @get()
5+
6+
declare void @use(i8*, i64)
7+
8+
define void @test(i64* %p) nounwind {
9+
; CHECK-LABEL: test:
10+
; CHECK: # %bb.0:
11+
; CHECK-NEXT: pushq %rax
12+
; CHECK-NEXT: movq %rdi, (%rsp) # 8-byte Spill
13+
; CHECK-NEXT: callq get@PLT
14+
; CHECK-NEXT: movq (%rsp), %rdi # 8-byte Reload
15+
; CHECK-NEXT: movq %rdx, %rsi
16+
; CHECK-NEXT: movq %rsi, (%rdi)
17+
; CHECK-NEXT: # implicit-def: $rdi
18+
; CHECK-NEXT: callq use@PLT
19+
; CHECK-NEXT: popq %rax
20+
; CHECK-NEXT: retq
21+
%struct = call { i8*, i64 } @get()
22+
%struct.1 = extractvalue { i8*, i64 } %struct, 1
23+
store i64 %struct.1, i64* %p, align 8
24+
%struct.2 = extractvalue { i8*, i64 } %struct, 1
25+
call void @use(i8* undef, i64 %struct.2)
26+
ret void
27+
}

0 commit comments

Comments
 (0)