From: Amaury Séchet Date: Sat, 30 Apr 2022 23:45:28 +0000 (+0000) Subject: [DAG] Peek through trunc when combining select into shifts. X-Git-Tag: upstream/17.0.6~4136 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=34d8c5b9ceae5002ae9cd1cbfcb1fd998018bebf;p=platform%2Fupstream%2Fllvm.git [DAG] Peek through trunc when combining select into shifts. This fixes a regression in D127115 Depends on D127115 Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D151916 --- diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 3d095b1..357b0c6 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2485,6 +2485,17 @@ SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) { if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse()) { SelOpNo = 1; Sel = BO->getOperand(1); + + // Peek through trunc to shift amount type. + if ((BinOpcode == ISD::SHL || BinOpcode == ISD::SRA || + BinOpcode == ISD::SRL) && Sel.hasOneUse()) { + // This is valid when the truncated bits of x are already zero. + SDValue Op; + KnownBits Known; + if (isTruncateOf(DAG, Sel, Op, Known) && + Known.countMaxActiveBits() < Sel.getScalarValueSizeInBits()) + Sel = Op; + } } if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse()) diff --git a/llvm/test/CodeGen/X86/dagcombine-select.ll b/llvm/test/CodeGen/X86/dagcombine-select.ll index be9c397..d29f161 100644 --- a/llvm/test/CodeGen/X86/dagcombine-select.ll +++ b/llvm/test/CodeGen/X86/dagcombine-select.ll @@ -194,12 +194,10 @@ define i32 @sel_constants_shl_constant(i1 %cond) { define i32 @shl_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: shl_constant_sel_constants: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: andb $1, %cl -; CHECK-NEXT: xorb $3, %cl -; CHECK-NEXT: movl $1, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: notb %dil +; CHECK-NEXT: movzbl %dil, %eax +; CHECK-NEXT: andl $1, %eax +; CHECK-NEXT: leal 4(,%rax,4), %eax ; CHECK-NEXT: retq %sel = select i1 %cond, i32 2, i32 3 %bo = shl i32 1, %sel @@ -209,12 +207,10 @@ define i32 @shl_constant_sel_constants(i1 %cond) { define i32 @shl_constant_sel_setcc(i32 %a) { ; CHECK-LABEL: shl_constant_sel_setcc: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: andb $1, %cl -; CHECK-NEXT: xorb $3, %cl -; CHECK-NEXT: movl $1, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: sete %al +; CHECK-NEXT: leal 4(,%rax,4), %eax ; CHECK-NEXT: retq %m = and i32 %a, 1 %cond = icmp ne i32 %m, 0 @@ -226,12 +222,9 @@ define i32 @shl_constant_sel_setcc(i32 %a) { define i32 @lshr_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: lshr_constant_sel_constants: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: andb $1, %cl -; CHECK-NEXT: xorb $3, %cl -; CHECK-NEXT: movl $64, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shrl %cl, %eax +; CHECK-NEXT: # kill: def $edi killed $edi def $rdi +; CHECK-NEXT: andl $1, %edi +; CHECK-NEXT: leal 8(,%rdi,8), %eax ; CHECK-NEXT: retq %sel = select i1 %cond, i32 2, i32 3 %bo = lshr i32 64, %sel @@ -241,12 +234,9 @@ define i32 @lshr_constant_sel_constants(i1 %cond) { define i32 @lshr_constant_sel_setcc(i32 %a) { ; CHECK-LABEL: lshr_constant_sel_setcc: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: andb $1, %cl -; CHECK-NEXT: xorb $3, %cl -; CHECK-NEXT: movl $64, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shrl %cl, %eax +; CHECK-NEXT: # kill: def $edi killed $edi def $rdi +; CHECK-NEXT: andl $1, %edi +; CHECK-NEXT: leal 8(,%rdi,8), %eax ; CHECK-NEXT: retq %m = and i32 %a, 1 %cond = icmp ne i32 %m, 0 @@ -258,12 +248,10 @@ define i32 @lshr_constant_sel_setcc(i32 %a) { define i32 @ashr_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: ashr_constant_sel_constants: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: andb $1, %cl -; CHECK-NEXT: xorb $3, %cl -; CHECK-NEXT: movl $128, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shrl %cl, %eax +; CHECK-NEXT: # kill: def $edi killed $edi def $rdi +; CHECK-NEXT: andl $1, %edi +; CHECK-NEXT: shll $4, %edi +; CHECK-NEXT: leal 16(%rdi), %eax ; CHECK-NEXT: retq %sel = select i1 %cond, i32 2, i32 3 %bo = ashr i32 128, %sel @@ -273,12 +261,10 @@ define i32 @ashr_constant_sel_constants(i1 %cond) { define i32 @ashr_constant_sel_setcc(i32 %a) { ; CHECK-LABEL: ashr_constant_sel_setcc: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: andb $1, %cl -; CHECK-NEXT: xorb $3, %cl -; CHECK-NEXT: movl $128, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shrl %cl, %eax +; CHECK-NEXT: # kill: def $edi killed $edi def $rdi +; CHECK-NEXT: andl $1, %edi +; CHECK-NEXT: shll $4, %edi +; CHECK-NEXT: leal 16(%rdi), %eax ; CHECK-NEXT: retq %m = and i32 %a, 1 %cond = icmp ne i32 %m, 0