1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[DAGCombiner] fold assertzexts separated by trunc

If we have an AssertZext of a truncated value that has already been AssertZext'ed, 
we can assert on the wider source op to improve the zext-y knowledge:
 assert (trunc (assert X, i8) to iN), i1 --> trunc (assert X, i1) to iN

This moves a fold from being Mips-specific to general combining, and x86 shows
improvements.

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

llvm-svn: 313577
This commit is contained in:
Sanjay Patel 2017-09-18 22:05:35 +00:00
parent fb7cedf534
commit 458e63ca85
10 changed files with 57 additions and 71 deletions

View File

@ -7970,16 +7970,39 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) {
return SDValue();
}
// TODO: These transforms should work with AssertSext too.
// Change the function name, comments, opcode references, and caller.
SDValue DAGCombiner::visitAssertZext(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
EVT EVT = cast<VTSDNode>(N1)->getVT();
EVT AssertVT = cast<VTSDNode>(N1)->getVT();
// fold (assertzext (assertzext x, vt), vt) -> (assertzext x, vt)
if (N0.getOpcode() == ISD::AssertZext &&
EVT == cast<VTSDNode>(N0.getOperand(1))->getVT())
AssertVT == cast<VTSDNode>(N0.getOperand(1))->getVT())
return N0;
if (N0.getOpcode() == ISD::TRUNCATE && N0.hasOneUse() &&
N0.getOperand(0).getOpcode() == ISD::AssertZext) {
// We have an assert, truncate, assert sandwich. Make one stronger assert
// by asserting on the smallest asserted type to the larger source type.
// This eliminates the later assert:
// assert (trunc (assert X, i8) to iN), i1 --> trunc (assert X, i1) to iN
// assert (trunc (assert X, i1) to iN), i8 --> trunc (assert X, i1) to iN
SDValue BigA = N0.getOperand(0);
EVT BigA_AssertVT = cast<VTSDNode>(BigA.getOperand(1))->getVT();
assert(BigA_AssertVT.bitsLE(N0.getValueType()) &&
"Asserting zero/sign-extended bits from a type larger than the "
"truncated destination does not provide information");
SDLoc DL(N);
EVT MinAssertVT = AssertVT.bitsLT(BigA_AssertVT) ? AssertVT : BigA_AssertVT;
SDValue MinAssertVTVal = DAG.getValueType(MinAssertVT);
SDValue NewAssert = DAG.getNode(ISD::AssertZext, DL, BigA.getValueType(),
BigA.getOperand(0), MinAssertVTVal);
return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewAssert);
}
return SDValue();
}

View File

@ -1112,37 +1112,6 @@ static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG,
return DAG.getNode(ISD::ADD, DL, ValTy, Add1, Lo);
}
static SDValue performAssertZextCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget &Subtarget) {
SDValue N0 = N->getOperand(0);
EVT NarrowerVT = cast<VTSDNode>(N->getOperand(1))->getVT();
if (N0.getOpcode() != ISD::TRUNCATE)
return SDValue();
if (N0.getOperand(0).getOpcode() != ISD::AssertZext)
return SDValue();
// fold (AssertZext (trunc (AssertZext x))) -> (trunc (AssertZext x))
// if the type of the extension of the innermost AssertZext node is
// smaller from that of the outermost node, eg:
// (AssertZext:i32 (trunc:i32 (AssertZext:i64 X, i32)), i8)
// -> (trunc:i32 (AssertZext X, i8))
SDValue WiderAssertZext = N0.getOperand(0);
EVT WiderVT = cast<VTSDNode>(WiderAssertZext->getOperand(1))->getVT();
if (NarrowerVT.bitsLT(WiderVT)) {
SDValue NewAssertZext = DAG.getNode(
ISD::AssertZext, SDLoc(N), WiderAssertZext.getValueType(),
WiderAssertZext.getOperand(0), DAG.getValueType(NarrowerVT));
return DAG.getNode(ISD::TRUNCATE, SDLoc(N), N->getValueType(0),
NewAssertZext);
}
return SDValue();
}
static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget &Subtarget) {
@ -1215,8 +1184,6 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
return performORCombine(N, DAG, DCI, Subtarget);
case ISD::ADD:
return performADDCombine(N, DAG, DCI, Subtarget);
case ISD::AssertZext:
return performAssertZextCombine(N, DAG, DCI, Subtarget);
case ISD::SHL:
return performSHLCombine(N, DAG, DCI, Subtarget);
case ISD::SUB:

View File

@ -2,7 +2,7 @@
; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s -check-prefix=X32
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s -check-prefix=X64
; Check that the argument gets zero-extended before calling.
; It's not necessary to zero-extend the arg because it is specified 'zeroext'.
define void @bar1(i1 zeroext %v1) nounwind ssp {
; X32-LABEL: bar1:
; X32: # BB#0:
@ -14,7 +14,6 @@ define void @bar1(i1 zeroext %v1) nounwind ssp {
;
; X64-LABEL: bar1:
; X64: # BB#0:
; X64-NEXT: movzbl %dil, %edi
; X64-NEXT: xorl %eax, %eax
; X64-NEXT: jmp foo1 # TAILCALL
%conv = zext i1 %v1 to i32

View File

@ -12,7 +12,7 @@ define i16 @test1(i1 zeroext %C, i8** nocapture %argv) nounwind ssp {
; CHECK-LABEL: test1:
; CHECK: # BB#0: # %entry
; CHECK-NEXT: movw $1, %ax
; CHECK-NEXT: testb %dil, %dil
; CHECK-NEXT: testl %edi, %edi
; CHECK-NEXT: jne .LBB0_2
; CHECK-NEXT: # BB#1: # %cond.false.i
; CHECK-NEXT: movl $g_4, %eax

View File

@ -11,7 +11,7 @@
define void @test_select(fp128* %p, fp128* %q, i1 zeroext %c) {
; MMX-LABEL: test_select:
; MMX: # BB#0:
; MMX-NEXT: testb %dl, %dl
; MMX-NEXT: testl %edx, %edx
; MMX-NEXT: jne .LBB0_1
; MMX-NEXT: # BB#2:
; MMX-NEXT: movaps {{.*}}(%rip), %xmm0
@ -25,7 +25,7 @@ define void @test_select(fp128* %p, fp128* %q, i1 zeroext %c) {
; CHECK-LABEL: test_select:
; CHECK: # BB#0:
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: testb %dl, %dl
; CHECK-NEXT: testl %edx, %edx
; CHECK-NEXT: cmovneq (%rdi), %rax
; CHECK-NEXT: movabsq $9223231299366420480, %rcx # imm = 0x7FFF800000000000
; CHECK-NEXT: cmovneq 8(%rdi), %rcx

View File

@ -87,16 +87,15 @@ define void @i24_insert_bit(i24* %a, i1 zeroext %bit) {
;
; X64-LABEL: i24_insert_bit:
; X64: # BB#0:
; X64-NEXT: movzbl %sil, %eax
; X64-NEXT: movzwl (%rdi), %ecx
; X64-NEXT: movzbl 2(%rdi), %edx
; X64-NEXT: movb %dl, 2(%rdi)
; X64-NEXT: shll $16, %edx
; X64-NEXT: orl %ecx, %edx
; X64-NEXT: shll $13, %eax
; X64-NEXT: andl $16769023, %edx # imm = 0xFFDFFF
; X64-NEXT: orl %eax, %edx
; X64-NEXT: movw %dx, (%rdi)
; X64-NEXT: movzwl (%rdi), %eax
; X64-NEXT: movzbl 2(%rdi), %ecx
; X64-NEXT: movb %cl, 2(%rdi)
; X64-NEXT: shll $16, %ecx
; X64-NEXT: orl %eax, %ecx
; X64-NEXT: shll $13, %esi
; X64-NEXT: andl $16769023, %ecx # imm = 0xFFDFFF
; X64-NEXT: orl %esi, %ecx
; X64-NEXT: movw %cx, (%rdi)
; X64-NEXT: retq
%extbit = zext i1 %bit to i24
%b = load i24, i24* %a, align 1
@ -185,7 +184,7 @@ define void @i56_insert_bit(i56* %a, i1 zeroext %bit) {
;
; X64-LABEL: i56_insert_bit:
; X64: # BB#0:
; X64-NEXT: movzbl %sil, %eax
; X64-NEXT: movl %esi, %eax
; X64-NEXT: movzwl 4(%rdi), %ecx
; X64-NEXT: movzbl 6(%rdi), %edx
; X64-NEXT: movb %dl, 6(%rdi)

View File

@ -16,7 +16,7 @@ define i32 @mask_negated_zext_bool1(i1 %x) {
define i32 @mask_negated_zext_bool2(i1 zeroext %x) {
; CHECK-LABEL: mask_negated_zext_bool2:
; CHECK: # BB#0:
; CHECK-NEXT: movzbl %dil, %eax
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
%ext = zext i1 %x to i32
%neg = sub i32 0, %ext
@ -50,7 +50,7 @@ define i32 @mask_negated_sext_bool1(i1 %x) {
define i32 @mask_negated_sext_bool2(i1 zeroext %x) {
; CHECK-LABEL: mask_negated_sext_bool2:
; CHECK: # BB#0:
; CHECK-NEXT: movzbl %dil, %eax
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
%ext = sext i1 %x to i32
%neg = sub i32 0, %ext

View File

@ -58,9 +58,8 @@ define i16 @select_i16_neg1_or_0(i1 %a) {
define i16 @select_i16_neg1_or_0_zeroext(i1 zeroext %a) {
; X64-LABEL: select_i16_neg1_or_0_zeroext:
; X64: # BB#0:
; X64-NEXT: movzbl %dil, %eax
; X64-NEXT: negl %eax
; X64-NEXT: # kill: %AX<def> %AX<kill> %EAX<kill>
; X64-NEXT: negl %edi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: retq
;
; X32-LABEL: select_i16_neg1_or_0_zeroext:
@ -94,8 +93,8 @@ define i32 @select_i32_neg1_or_0(i1 %a) {
define i32 @select_i32_neg1_or_0_zeroext(i1 zeroext %a) {
; X64-LABEL: select_i32_neg1_or_0_zeroext:
; X64: # BB#0:
; X64-NEXT: movzbl %dil, %eax
; X64-NEXT: negl %eax
; X64-NEXT: negl %edi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: retq
;
; X32-LABEL: select_i32_neg1_or_0_zeroext:
@ -130,7 +129,7 @@ define i64 @select_i64_neg1_or_0(i1 %a) {
define i64 @select_i64_neg1_or_0_zeroext(i1 zeroext %a) {
; X64-LABEL: select_i64_neg1_or_0_zeroext:
; X64: # BB#0:
; X64-NEXT: movzbl %dil, %eax
; X64-NEXT: movl %edi, %eax
; X64-NEXT: negq %rax
; X64-NEXT: retq
;

View File

@ -53,7 +53,7 @@ define i32 @select_1_or_0(i1 %cond) {
define i32 @select_1_or_0_zeroext(i1 zeroext %cond) {
; CHECK-LABEL: select_1_or_0_zeroext:
; CHECK: # BB#0:
; CHECK-NEXT: movzbl %dil, %eax
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
%sel = select i1 %cond, i32 1, i32 0
ret i32 %sel
@ -85,8 +85,8 @@ define i32 @select_0_or_neg1(i1 %cond) {
define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) {
; CHECK-LABEL: select_0_or_neg1_zeroext:
; CHECK: # BB#0:
; CHECK-NEXT: movzbl %dil, %eax
; CHECK-NEXT: decl %eax
; CHECK-NEXT: # kill: %EDI<def> %EDI<kill> %RDI<def>
; CHECK-NEXT: leal -1(%rdi), %eax
; CHECK-NEXT: retq
%sel = select i1 %cond, i32 0, i32 -1
ret i32 %sel
@ -119,8 +119,8 @@ define i32 @select_neg1_or_0(i1 %cond) {
define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) {
; CHECK-LABEL: select_neg1_or_0_zeroext:
; CHECK: # BB#0:
; CHECK-NEXT: movzbl %dil, %eax
; CHECK-NEXT: negl %eax
; CHECK-NEXT: negl %edi
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
%sel = select i1 %cond, i32 -1, i32 0
ret i32 %sel
@ -151,8 +151,8 @@ define i32 @select_Cplus1_C(i1 %cond) {
define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) {
; CHECK-LABEL: select_Cplus1_C_zeroext:
; CHECK: # BB#0:
; CHECK-NEXT: movzbl %dil, %eax
; CHECK-NEXT: addl $41, %eax
; CHECK-NEXT: # kill: %EDI<def> %EDI<kill> %RDI<def>
; CHECK-NEXT: leal 41(%rdi), %eax
; CHECK-NEXT: retq
%sel = select i1 %cond, i32 42, i32 41
ret i32 %sel
@ -185,9 +185,8 @@ define i32 @select_C_Cplus1(i1 %cond) {
define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) {
; CHECK-LABEL: select_C_Cplus1_zeroext:
; CHECK: # BB#0:
; CHECK-NEXT: movzbl %dil, %ecx
; CHECK-NEXT: movl $42, %eax
; CHECK-NEXT: subl %ecx, %eax
; CHECK-NEXT: subl %edi, %eax
; CHECK-NEXT: retq
%sel = select i1 %cond, i32 41, i32 42
ret i32 %sel
@ -413,7 +412,7 @@ define i32 @select_C1_C2(i1 %cond) {
define i32 @select_C1_C2_zeroext(i1 zeroext %cond) {
; CHECK-LABEL: select_C1_C2_zeroext:
; CHECK: # BB#0:
; CHECK-NEXT: testb %dil, %dil
; CHECK-NEXT: testl %edi, %edi
; CHECK-NEXT: movl $421, %ecx # imm = 0x1A5
; CHECK-NEXT: movl $42, %eax
; CHECK-NEXT: cmovnel %ecx, %eax

View File

@ -144,8 +144,8 @@ define i32 @select_0_or_1s_zeroext(i1 zeroext %cond) {
;
; X64-LABEL: select_0_or_1s_zeroext:
; X64: # BB#0:
; X64-NEXT: movzbl %dil, %eax
; X64-NEXT: decl %eax
; X64-NEXT: # kill: %EDI<def> %EDI<kill> %RDI<def>
; X64-NEXT: leal -1(%rdi), %eax
; X64-NEXT: retq
%not = xor i1 %cond, 1
%sext = sext i1 %not to i32