From 787313e887e0d621c7080aa2552991388a892a31 Mon Sep 17 00:00:00 2001 From: Layton Kifer Date: Fri, 18 Dec 2020 02:21:42 +0000 Subject: [PATCH] [DAGCombiner] Improve shift by select of constant Clean up a TODO, to support folding a shift of a constant by a select of constants, on targets with different shift operand sizes. Reviewed By: RKSimon, lebedev.ri Differential Revision: https://reviews.llvm.org/D90349 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 11 +--- test/CodeGen/AArch64/select_const.ll | 21 +++---- test/CodeGen/PowerPC/select_const.ll | 75 +++++++++++++++++------- test/CodeGen/X86/dagcombine-select.ll | 29 ++++----- 4 files changed, 75 insertions(+), 61 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 212e0a2ea98..74d3e1adcd6 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2150,16 +2150,7 @@ SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) { !isConstantFPBuildVectorOrConstantFP(CBO)) return SDValue(); - EVT VT = Sel.getValueType(); - - // In case of shift value and shift amount may have different VT. For instance - // on x86 shift amount is i8 regardles of LHS type. Bail out if we have - // swapped operands and value types do not match. NB: x86 is fine if operands - // are not swapped with shift amount VT being not bigger than shifted value. - // TODO: that is possible to check for a shift operation, correct VTs and - // still perform optimization on x86 if needed. - if (SelOpNo && VT != CBO.getValueType()) - return SDValue(); + EVT VT = BO->getValueType(0); // We have a select-of-constants followed by a binary operator with a // constant. Eliminate the binop by pulling the constant math into the select. diff --git a/test/CodeGen/AArch64/select_const.ll b/test/CodeGen/AArch64/select_const.ll index 945e7cdc35a..f58232e2ee8 100644 --- a/test/CodeGen/AArch64/select_const.ll +++ b/test/CodeGen/AArch64/select_const.ll @@ -437,10 +437,9 @@ define i8 @shl_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: shl_constant_sel_constants: ; CHECK: // %bb.0: ; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #2 -; CHECK-NEXT: cinc x8, x8, eq -; CHECK-NEXT: mov w9, #1 -; CHECK-NEXT: lsl w0, w9, w8 +; CHECK-NEXT: mov w8, #8 +; CHECK-NEXT: mov w9, #4 +; CHECK-NEXT: csel w0, w9, w8, ne ; CHECK-NEXT: ret %sel = select i1 %cond, i8 2, i8 3 %bo = shl i8 1, %sel @@ -463,10 +462,9 @@ define i8 @lshr_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: lshr_constant_sel_constants: ; CHECK: // %bb.0: ; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #2 -; CHECK-NEXT: cinc x8, x8, eq -; CHECK-NEXT: mov w9, #64 -; CHECK-NEXT: lsr w0, w9, w8 +; CHECK-NEXT: mov w8, #8 +; CHECK-NEXT: mov w9, #16 +; CHECK-NEXT: csel w0, w9, w8, ne ; CHECK-NEXT: ret %sel = select i1 %cond, i8 2, i8 3 %bo = lshr i8 64, %sel @@ -488,10 +486,9 @@ define i8 @ashr_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: ashr_constant_sel_constants: ; CHECK: // %bb.0: ; CHECK-NEXT: tst w0, #0x1 -; CHECK-NEXT: mov w8, #2 -; CHECK-NEXT: cinc x8, x8, eq -; CHECK-NEXT: mov w9, #-128 -; CHECK-NEXT: asr w0, w9, w8 +; CHECK-NEXT: mov w8, #-16 +; CHECK-NEXT: mov w9, #-32 +; CHECK-NEXT: csel w0, w9, w8, ne ; CHECK-NEXT: ret %sel = select i1 %cond, i8 2, i8 3 %bo = ashr i8 128, %sel diff --git a/test/CodeGen/PowerPC/select_const.ll b/test/CodeGen/PowerPC/select_const.ll index 7e8b6297ed3..804cc7736bf 100644 --- a/test/CodeGen/PowerPC/select_const.ll +++ b/test/CodeGen/PowerPC/select_const.ll @@ -610,13 +610,24 @@ define i8 @sel_constants_shl_constant(i1 %cond) { } define i8 @shl_constant_sel_constants(i1 %cond) { -; ALL-LABEL: shl_constant_sel_constants: -; ALL: # %bb.0: -; ALL-NEXT: clrlwi 3, 3, 31 -; ALL-NEXT: li 4, 1 -; ALL-NEXT: subfic 3, 3, 3 -; ALL-NEXT: slw 3, 4, 3 -; ALL-NEXT: blr +; ISEL-LABEL: shl_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: li 4, 4 +; ISEL-NEXT: li 3, 8 +; ISEL-NEXT: iselgt 3, 4, 3 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: shl_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: li 4, 4 +; NO_ISEL-NEXT: li 3, 8 +; NO_ISEL-NEXT: bc 12, 1, .LBB37_1 +; NO_ISEL-NEXT: blr +; NO_ISEL-NEXT: .LBB37_1: +; NO_ISEL-NEXT: addi 3, 4, 0 +; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 2, i8 3 %bo = shl i8 1, %sel ret i8 %bo @@ -647,13 +658,24 @@ define i8 @sel_constants_lshr_constant(i1 %cond) { } define i8 @lshr_constant_sel_constants(i1 %cond) { -; ALL-LABEL: lshr_constant_sel_constants: -; ALL: # %bb.0: -; ALL-NEXT: clrlwi 3, 3, 31 -; ALL-NEXT: li 4, 64 -; ALL-NEXT: subfic 3, 3, 3 -; ALL-NEXT: srw 3, 4, 3 -; ALL-NEXT: blr +; ISEL-LABEL: lshr_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: li 4, 16 +; ISEL-NEXT: li 3, 8 +; ISEL-NEXT: iselgt 3, 4, 3 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: lshr_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: li 4, 16 +; NO_ISEL-NEXT: li 3, 8 +; NO_ISEL-NEXT: bc 12, 1, .LBB39_1 +; NO_ISEL-NEXT: blr +; NO_ISEL-NEXT: .LBB39_1: +; NO_ISEL-NEXT: addi 3, 4, 0 +; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 2, i8 3 %bo = lshr i8 64, %sel ret i8 %bo @@ -672,13 +694,24 @@ define i8 @sel_constants_ashr_constant(i1 %cond) { } define i8 @ashr_constant_sel_constants(i1 %cond) { -; ALL-LABEL: ashr_constant_sel_constants: -; ALL: # %bb.0: -; ALL-NEXT: clrlwi 3, 3, 31 -; ALL-NEXT: li 4, -128 -; ALL-NEXT: subfic 3, 3, 3 -; ALL-NEXT: sraw 3, 4, 3 -; ALL-NEXT: blr +; ISEL-LABEL: ashr_constant_sel_constants: +; ISEL: # %bb.0: +; ISEL-NEXT: andi. 3, 3, 1 +; ISEL-NEXT: li 4, -32 +; ISEL-NEXT: li 3, -16 +; ISEL-NEXT: iselgt 3, 4, 3 +; ISEL-NEXT: blr +; +; NO_ISEL-LABEL: ashr_constant_sel_constants: +; NO_ISEL: # %bb.0: +; NO_ISEL-NEXT: andi. 3, 3, 1 +; NO_ISEL-NEXT: li 4, -32 +; NO_ISEL-NEXT: li 3, -16 +; NO_ISEL-NEXT: bc 12, 1, .LBB41_1 +; NO_ISEL-NEXT: blr +; NO_ISEL-NEXT: .LBB41_1: +; NO_ISEL-NEXT: addi 3, 4, 0 +; NO_ISEL-NEXT: blr %sel = select i1 %cond, i8 2, i8 3 %bo = ashr i8 128, %sel ret i8 %bo diff --git a/test/CodeGen/X86/dagcombine-select.ll b/test/CodeGen/X86/dagcombine-select.ll index ff022c3bf0f..9bebec6f5ec 100644 --- a/test/CodeGen/X86/dagcombine-select.ll +++ b/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,9 @@ define i32 @shl_constant_sel_constants(i1 %cond) { 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 @@ -224,12 +219,10 @@ define i32 @lshr_constant_sel_constants(i1 %cond) { 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