[X86] Make sure we still emit zext for GR32 to GR64 when the source of the zext is AssertZext

The AssertZext we might see in this case is only giving information about the lower 32 bits. It isn't providing information about the upper 32 bits. So we should emit a zext.

This fixes PR28540.

Differential Revision: https://reviews.llvm.org/D37729

llvm-svn: 313563
This commit is contained in:
Craig Topper 2017-09-18 20:49:13 +00:00
parent 194d0edf73
commit 39cdb84560
2 changed files with 46 additions and 2 deletions

View File

@ -1247,12 +1247,14 @@ def : Pat<(i64 (anyext GR32:$src)),
// Any instruction that defines a 32-bit result leaves the high half of the
// register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may
// be copying from a truncate. Any other 32-bit operation will zero-extend
// up to 64 bits.
// up to 64 bits. AssertSext/AssertZext aren't saying anything about the upper
// 32 bits, they're probably just qualifying a CopyFromReg.
def def32 : PatLeaf<(i32 GR32:$src), [{
return N->getOpcode() != ISD::TRUNCATE &&
N->getOpcode() != TargetOpcode::EXTRACT_SUBREG &&
N->getOpcode() != ISD::CopyFromReg &&
N->getOpcode() != ISD::AssertSext;
N->getOpcode() != ISD::AssertSext &&
N->getOpcode() != ISD::AssertZext;
}]>;
// In the case of a 32-bit def that is known to implicitly zero-extend,

View File

@ -0,0 +1,42 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -O2 -mtriple=x86_64-unknown-unknown | FileCheck %s
; Checks that a zeroing mov is inserted for the trunc/zext pair even when
; the source of the zext is an AssertZext node
; PR28540
define i64 @foo() {
; CHECK-LABEL: foo:
; CHECK: # BB#0:
; CHECK-NEXT: movq $-1, %rax
; CHECK-NEXT: retq
ret i64 -1
}
define i64 @main() {
; CHECK-LABEL: main:
; CHECK: # BB#0:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .Lcfi0:
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: callq foo
; CHECK-NEXT: movabsq $-4294967041, %rcx # imm = 0xFFFFFFFF000000FF
; CHECK-NEXT: andq %rax, %rcx
; CHECK-NEXT: movl %ecx, %ecx
; CHECK-NEXT: leaq (,%rcx,8), %rax
; CHECK-NEXT: subq %rcx, %rax
; CHECK-NEXT: shrq $32, %rax
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: retq
%b = call i64 @foo()
%or = and i64 %b, 18446744069414584575 ; this is 0xffffffff000000ff
%trunc = trunc i64 %or to i32
br label %l
l:
%ext = zext i32 %trunc to i64
%mul = mul i64 %ext, 7
br label %m
m: ; keeps dag combine from seeing the multiply and the shift together
%shr = lshr i64 %mul, 32
trunc i64 %or to i32 ; keeps the and alive so it doesn't simplify
ret i64 %shr
}