summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/X86/X86InstrCompiler.td38
-rw-r--r--llvm/test/CodeGen/X86/bool-math.ll24
-rw-r--r--llvm/test/CodeGen/X86/dagcombine-select.ll12
3 files changed, 56 insertions, 18 deletions
diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td
index b5d7ea69df8..44fb44d55c1 100644
--- a/llvm/lib/Target/X86/X86InstrCompiler.td
+++ b/llvm/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<ConstantSDNode>(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/llvm/test/CodeGen/X86/bool-math.ll b/llvm/test/CodeGen/X86/bool-math.ll
index fb1dce1839f..8a63d52a694 100644
--- a/llvm/test/CodeGen/X86/bool-math.ll
+++ b/llvm/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/llvm/test/CodeGen/X86/dagcombine-select.ll b/llvm/test/CodeGen/X86/dagcombine-select.ll
index 8be1333cec2..4c81ede4231 100644
--- a/llvm/test/CodeGen/X86/dagcombine-select.ll
+++ b/llvm/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
OpenPOWER on IntegriCloud