mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-04 01:26:41 +00: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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313577 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
83af88427f
commit
a3209ae52e
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user