From 702b88ddc28d01a0c173db877b15ea43721a4059 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 26 Jun 2018 03:11:15 +0000 Subject: [PATCH] [X86] Use XOR for SUB (C, X) during isel if will help fold an immediate Summary: Same idea as D48529, but restricted to X86 and done very late to avoid any surprises where subtract might be better for DAG combining. This seems like the safest way to do this trick. And we consider doing it as a DAG combine later. Reviewers: spatel, RKSimon Reviewed By: spatel Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D48557 llvm-svn: 335575 --- lib/Target/X86/X86InstrCompiler.td | 38 +++++++++++++++++++++++++++ test/CodeGen/X86/bool-math.ll | 24 ++++++++--------- test/CodeGen/X86/dagcombine-select.ll | 12 ++++----- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/lib/Target/X86/X86InstrCompiler.td b/lib/Target/X86/X86InstrCompiler.td index b5d7ea69df8..44fb44d55c1 100644 --- a/lib/Target/X86/X86InstrCompiler.td +++ b/lib/Target/X86/X86InstrCompiler.td @@ -1364,6 +1364,44 @@ def ADD64ri32_DB : I<0, Pseudo, } } // AddedComplexity, SchedRW +//===----------------------------------------------------------------------===// +// Pattern match SUB as XOR +//===----------------------------------------------------------------------===// + +// An immediate in the LHS of a subtract can't be encoded in the instruction. +// If there is no possibility of a borrow we can use an XOR instead of a SUB +// to enable the immediate to be folded. +// TODO: Move this to a DAG combine? + +def sub_is_xor : PatFrag<(ops node:$lhs, node:$rhs), (sub node:$lhs, node:$rhs),[{ + if (ConstantSDNode *CN = dyn_cast(N->getOperand(0))) { + KnownBits Known; + CurDAG->computeKnownBits(N->getOperand(1), Known); + + // If all possible ones in the RHS are set in the LHS then there can't be + // a borrow and we can use xor. + return (~Known.Zero).isSubsetOf(CN->getAPIntValue()); + } + + return false; +}]>; + +let AddedComplexity = 5 in { +def : Pat<(sub_is_xor imm:$src2, GR8:$src1), + (XOR8ri GR8:$src1, imm:$src2)>; +def : Pat<(sub_is_xor i16immSExt8:$src2, GR16:$src1), + (XOR16ri8 GR16:$src1, i16immSExt8:$src2)>; +def : Pat<(sub_is_xor imm:$src2, GR16:$src1), + (XOR16ri GR16:$src1, imm:$src2)>; +def : Pat<(sub_is_xor i32immSExt8:$src2, GR32:$src1), + (XOR32ri8 GR32:$src1, i32immSExt8:$src2)>; +def : Pat<(sub_is_xor imm:$src2, GR32:$src1), + (XOR32ri GR32:$src1, imm:$src2)>; +def : Pat<(sub_is_xor i64immSExt8:$src2, GR64:$src1), + (XOR64ri8 GR64:$src1, i64immSExt8:$src2)>; +def : Pat<(sub_is_xor i64immSExt32:$src2, GR64:$src1), + (XOR64ri32 GR64:$src1, i64immSExt32:$src2)>; +} //===----------------------------------------------------------------------===// // Some peepholes diff --git a/test/CodeGen/X86/bool-math.ll b/test/CodeGen/X86/bool-math.ll index fb1dce1839f..8a63d52a694 100644 --- a/test/CodeGen/X86/bool-math.ll +++ b/test/CodeGen/X86/bool-math.ll @@ -47,8 +47,8 @@ define i8 @add_zext_cmp_mask_same_size_result(i8 %x) { ; CHECK-LABEL: add_zext_cmp_mask_same_size_result: ; CHECK: # %bb.0: ; CHECK-NEXT: andb $1, %dil -; CHECK-NEXT: movb $27, %al -; CHECK-NEXT: subb %dil, %al +; CHECK-NEXT: xorb $27, %dil +; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq %a = and i8 %x, 1 %c = icmp eq i8 %a, 0 @@ -61,8 +61,8 @@ define i32 @add_zext_cmp_mask_wider_result(i8 %x) { ; CHECK-LABEL: add_zext_cmp_mask_wider_result: ; CHECK: # %bb.0: ; CHECK-NEXT: andl $1, %edi -; CHECK-NEXT: movl $27, %eax -; CHECK-NEXT: subl %edi, %eax +; CHECK-NEXT: xorl $27, %edi +; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq %a = and i8 %x, 1 %c = icmp eq i8 %a, 0 @@ -75,8 +75,8 @@ define i8 @add_zext_cmp_mask_narrower_result(i32 %x) { ; CHECK-LABEL: add_zext_cmp_mask_narrower_result: ; CHECK: # %bb.0: ; CHECK-NEXT: andl $1, %edi -; CHECK-NEXT: movb $43, %al -; CHECK-NEXT: subb %dil, %al +; CHECK-NEXT: xorb $43, %dil +; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq %a = and i32 %x, 1 %c = icmp eq i32 %a, 0 @@ -129,8 +129,8 @@ define i8 @low_bit_select_constants_bigger_true_same_size_result(i8 %x) { ; CHECK-LABEL: low_bit_select_constants_bigger_true_same_size_result: ; CHECK: # %bb.0: ; CHECK-NEXT: andb $1, %dil -; CHECK-NEXT: movb $-29, %al -; CHECK-NEXT: subb %dil, %al +; CHECK-NEXT: xorb $-29, %dil +; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq %a = and i8 %x, 1 %c = icmp eq i8 %a, 0 @@ -142,8 +142,8 @@ define i32 @low_bit_select_constants_bigger_true_wider_result(i8 %x) { ; CHECK-LABEL: low_bit_select_constants_bigger_true_wider_result: ; CHECK: # %bb.0: ; CHECK-NEXT: andl $1, %edi -; CHECK-NEXT: movl $227, %eax -; CHECK-NEXT: subl %edi, %eax +; CHECK-NEXT: xorl $227, %edi +; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq %a = and i8 %x, 1 %c = icmp eq i8 %a, 0 @@ -155,8 +155,8 @@ define i8 @low_bit_select_constants_bigger_true_narrower_result(i16 %x) { ; CHECK-LABEL: low_bit_select_constants_bigger_true_narrower_result: ; CHECK: # %bb.0: ; CHECK-NEXT: andl $1, %edi -; CHECK-NEXT: movb $41, %al -; CHECK-NEXT: subb %dil, %al +; CHECK-NEXT: xorb $41, %dil +; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq %a = and i16 %x, 1 %c = icmp eq i16 %a, 0 diff --git a/test/CodeGen/X86/dagcombine-select.ll b/test/CodeGen/X86/dagcombine-select.ll index 8be1333cec2..4c81ede4231 100644 --- a/test/CodeGen/X86/dagcombine-select.ll +++ b/test/CodeGen/X86/dagcombine-select.ll @@ -194,9 +194,9 @@ define i32 @shl_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: shl_constant_sel_constants: ; CHECK: # %bb.0: ; CHECK-NEXT: andb $1, %dil -; CHECK-NEXT: movb $3, %cl -; CHECK-NEXT: subb %dil, %cl +; CHECK-NEXT: xorb $3, %dil ; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: movl %edi, %ecx ; CHECK-NEXT: shll %cl, %eax ; CHECK-NEXT: retq %sel = select i1 %cond, i32 2, i32 3 @@ -208,9 +208,9 @@ define i32 @lshr_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: lshr_constant_sel_constants: ; CHECK: # %bb.0: ; CHECK-NEXT: andb $1, %dil -; CHECK-NEXT: movb $3, %cl -; CHECK-NEXT: subb %dil, %cl +; CHECK-NEXT: xorb $3, %dil ; CHECK-NEXT: movl $64, %eax +; CHECK-NEXT: movl %edi, %ecx ; CHECK-NEXT: shrl %cl, %eax ; CHECK-NEXT: retq %sel = select i1 %cond, i32 2, i32 3 @@ -222,9 +222,9 @@ define i32 @ashr_constant_sel_constants(i1 %cond) { ; CHECK-LABEL: ashr_constant_sel_constants: ; CHECK: # %bb.0: ; CHECK-NEXT: andb $1, %dil -; CHECK-NEXT: movb $3, %cl -; CHECK-NEXT: subb %dil, %cl +; CHECK-NEXT: xorb $3, %dil ; CHECK-NEXT: movl $128, %eax +; CHECK-NEXT: movl %edi, %ecx ; CHECK-NEXT: shrl %cl, %eax ; CHECK-NEXT: retq %sel = select i1 %cond, i32 2, i32 3