Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2663,6 +2663,16 @@ } } + // sub C, X -> xor X, C if there's no chance any bit will need to borrow + // from an adjacent bit. + if (ConstantSDNode *N0C = getAsNonOpaqueConstant(N0)) { + KnownBits Known; + DAG.computeKnownBits(N1, Known); + // Ensure all possible ones have a corresponding one in the constant. + if ((~Known.Zero).isSubsetOf(N0C->getAPIntValue())) + return DAG.getNode(ISD::XOR, DL, VT, N1, N0); + } + return SDValue(); } Index: test/CodeGen/AMDGPU/ds-sub-offset.ll =================================================================== --- test/CodeGen/AMDGPU/ds-sub-offset.ll +++ test/CodeGen/AMDGPU/ds-sub-offset.ll @@ -23,10 +23,9 @@ ; GCN-LABEL: {{^}}add_x_shl_neg_to_sub_max_offset: ; GCN-DAG: v_lshlrev_b32_e32 [[SCALED:v[0-9]+]], 2, v0 -; CI-DAG: v_sub_i32_e32 [[NEG:v[0-9]+]], vcc, 0, [[SCALED]] -; GFX9-DAG: v_sub_u32_e32 [[NEG:v[0-9]+]], 0, [[SCALED]] +; GCN-DAG: v_xor_b32_e32 [[NEG:v[0-9]+]], 0xffff, [[SCALED]] ; GCN-DAG: v_mov_b32_e32 [[K:v[0-9]+]], 13 -; GCN: ds_write_b8 [[NEG]], [[K]] offset:65535 +; GCN: ds_write_b8 [[NEG]], [[K]] define amdgpu_kernel void @add_x_shl_neg_to_sub_max_offset() #1 { %x.i = call i32 @llvm.amdgcn.workitem.id.x() #0 %neg = sub i32 0, %x.i @@ -114,8 +113,7 @@ ; GCN-LABEL: {{^}}add_x_shl_neg_to_sub_misaligned_i64_max_offset_p1: ; GCN-DAG: v_lshlrev_b32_e32 [[SCALED:v[0-9]+]], 2, v0 -; CI-DAG: v_sub_i32_e32 [[NEG:v[0-9]+]], vcc, 0x3fc, [[SCALED]] -; GFX9-DAG: v_sub_u32_e32 [[NEG:v[0-9]+]], 0x3fc, [[SCALED]] +; GCN-DAG: v_xor_b32_e32 [[NEG:v[0-9]+]], 0x3fc, [[SCALED]] ; GCN: ds_write2_b32 [[NEG]], {{v[0-9]+}}, {{v[0-9]+}} offset1:1{{$}} define amdgpu_kernel void @add_x_shl_neg_to_sub_misaligned_i64_max_offset_p1() #1 { %x.i = call i32 @llvm.amdgcn.workitem.id.x() #0 Index: test/CodeGen/ARM/intrinsics-overflow.ll =================================================================== --- test/CodeGen/ARM/intrinsics-overflow.ll +++ test/CodeGen/ARM/intrinsics-overflow.ll @@ -64,18 +64,18 @@ ; ARM: subs r[[R0:[0-9]+]], r[[R0]], r[[R1:[0-9]+]] ; ARM: mov r[[R2:[0-9]+]], #0 ; ARM: adc r[[R0]], r[[R2]], #0 - ; ARM: rsb r[[R0]], r[[R0]], #1 + ; ARM: eor r[[R0]], r[[R0]], #1 ; THUMBV6: movs r[[R2:[0-9]+]], #0 ; THUMBV6: subs r[[R0:[0-9]+]], r[[R0]], r[[R1:[0-9]+]] ; THUMBV6: adcs r[[R2]], r[[R2]] ; THUMBV6: movs r[[R0]], #1 - ; THUMBV6: subs r[[R0]], r[[R0]], r[[R2]] + ; THUMBV6: eors r[[R0]], r[[R2]] ; THUMBV7: subs r[[R0:[0-9]+]], r[[R0]], r[[R1:[0-9]+]] ; THUMBV7: mov.w r[[R2:[0-9]+]], #0 ; THUMBV7: adc r[[R0]], r[[R2]], #0 - ; THUMBV7: rsb.w r[[R0]], r[[R0]], #1 + ; THUMBV7: eor r[[R0]], r[[R0]], #1 ; We should know that the overflow is just 1 bit, ; no need to clear any other bit Index: test/CodeGen/PowerPC/bool-math.ll =================================================================== --- test/CodeGen/PowerPC/bool-math.ll +++ test/CodeGen/PowerPC/bool-math.ll @@ -44,8 +44,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: rlwinm 3, 3, 0, 31, 31 -; CHECK-NEXT: subfic 3, 3, 27 +; CHECK-NEXT: clrldi 3, 3, 63 +; CHECK-NEXT: xori 3, 3, 27 ; CHECK-NEXT: blr %a = and i8 %x, 1 %c = icmp eq i8 %a, 0 @@ -57,8 +57,8 @@ define i32 @add_zext_cmp_mask_wider_result(i8 %x) { ; CHECK-LABEL: add_zext_cmp_mask_wider_result: ; CHECK: # %bb.0: -; CHECK-NEXT: rlwinm 3, 3, 0, 31, 31 -; CHECK-NEXT: subfic 3, 3, 27 +; CHECK-NEXT: clrldi 3, 3, 63 +; CHECK-NEXT: xori 3, 3, 27 ; CHECK-NEXT: blr %a = and i8 %x, 1 %c = icmp eq i8 %a, 0 @@ -70,8 +70,8 @@ define i8 @add_zext_cmp_mask_narrower_result(i32 %x) { ; CHECK-LABEL: add_zext_cmp_mask_narrower_result: ; CHECK: # %bb.0: -; CHECK-NEXT: rlwinm 3, 3, 0, 31, 31 -; CHECK-NEXT: subfic 3, 3, 43 +; CHECK-NEXT: clrldi 3, 3, 63 +; CHECK-NEXT: xori 3, 3, 43 ; CHECK-NEXT: blr %a = and i32 %x, 1 %c = icmp eq i32 %a, 0 @@ -85,7 +85,7 @@ ; CHECK: # %bb.0: ; CHECK-NEXT: not 3, 3 ; CHECK-NEXT: clrldi 3, 3, 63 -; CHECK-NEXT: subfic 3, 3, 43 +; CHECK-NEXT: xori 3, 3, 43 ; CHECK-NEXT: blr %a = and i32 %x, 1 %c = icmp eq i32 %a, 0 @@ -98,7 +98,7 @@ ; CHECK: # %bb.0: ; CHECK-NEXT: not 3, 3 ; CHECK-NEXT: clrldi 3, 3, 63 -; CHECK-NEXT: subfic 3, 3, 27 +; CHECK-NEXT: xori 3, 3, 27 ; CHECK-NEXT: blr %a = and i32 %x, 1 %c = icmp eq i32 %a, 0 @@ -109,9 +109,10 @@ define i16 @low_bit_select_constants_bigger_false_narrower_result(i32 %x) { ; CHECK-LABEL: low_bit_select_constants_bigger_false_narrower_result: ; CHECK: # %bb.0: -; CHECK-NEXT: nor 3, 3, 3 -; CHECK-NEXT: clrlwi 3, 3, 31 -; CHECK-NEXT: subfic 3, 3, 37 +; CHECK-NEXT: xori 3, 3, 65535 +; CHECK-NEXT: xoris 3, 3, 65535 +; CHECK-NEXT: clrldi 3, 3, 63 +; CHECK-NEXT: xori 3, 3, 37 ; CHECK-NEXT: blr %a = and i32 %x, 1 %c = icmp eq i32 %a, 0 @@ -122,8 +123,9 @@ 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: rlwinm 3, 3, 0, 31, 31 -; CHECK-NEXT: subfic 3, 3, -29 +; CHECK-NEXT: clrldi 3, 3, 63 +; CHECK-NEXT: xori 3, 3, 65507 +; CHECK-NEXT: xoris 3, 3, 65535 ; CHECK-NEXT: blr %a = and i8 %x, 1 %c = icmp eq i8 %a, 0 @@ -135,7 +137,7 @@ ; CHECK-LABEL: low_bit_select_constants_bigger_true_wider_result: ; CHECK: # %bb.0: ; CHECK-NEXT: clrldi 3, 3, 63 -; CHECK-NEXT: subfic 3, 3, 227 +; CHECK-NEXT: xori 3, 3, 227 ; CHECK-NEXT: blr %a = and i8 %x, 1 %c = icmp eq i8 %a, 0 @@ -146,8 +148,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: rlwinm 3, 3, 0, 31, 31 -; CHECK-NEXT: subfic 3, 3, 41 +; CHECK-NEXT: clrldi 3, 3, 63 +; CHECK-NEXT: xori 3, 3, 41 ; CHECK-NEXT: blr %a = and i16 %x, 1 %c = icmp eq i16 %a, 0 Index: test/CodeGen/PowerPC/select_const.ll =================================================================== --- test/CodeGen/PowerPC/select_const.ll +++ test/CodeGen/PowerPC/select_const.ll @@ -595,8 +595,8 @@ define i8 @sel_constants_urem_constant(i1 %cond) { ; ALL-LABEL: sel_constants_urem_constant: ; ALL: # %bb.0: -; ALL-NEXT: rlwinm 3, 3, 0, 31, 31 -; ALL-NEXT: subfic 3, 3, 3 +; ALL-NEXT: clrldi 3, 3, 63 +; ALL-NEXT: xori 3, 3, 3 ; ALL-NEXT: blr %sel = select i1 %cond, i8 -4, i8 23 %bo = urem i8 %sel, 5 @@ -630,8 +630,8 @@ define i8 @sel_constants_and_constant(i1 %cond) { ; ALL-LABEL: sel_constants_and_constant: ; ALL: # %bb.0: -; ALL-NEXT: rlwinm 3, 3, 0, 31, 31 -; ALL-NEXT: subfic 3, 3, 5 +; ALL-NEXT: clrldi 3, 3, 63 +; ALL-NEXT: xori 3, 3, 5 ; ALL-NEXT: blr %sel = select i1 %cond, i8 -4, i8 23 %bo = and i8 %sel, 5 @@ -729,7 +729,7 @@ ; ALL: # %bb.0: ; ALL-NEXT: rlwinm 3, 3, 0, 31, 31 ; ALL-NEXT: li 4, 1 -; ALL-NEXT: subfic 3, 3, 3 +; ALL-NEXT: xori 3, 3, 3 ; ALL-NEXT: slw 3, 4, 3 ; ALL-NEXT: blr %sel = select i1 %cond, i8 2, i8 3 @@ -766,7 +766,7 @@ ; ALL: # %bb.0: ; ALL-NEXT: rlwinm 3, 3, 0, 31, 31 ; ALL-NEXT: li 4, 64 -; ALL-NEXT: subfic 3, 3, 3 +; ALL-NEXT: xori 3, 3, 3 ; ALL-NEXT: srw 3, 4, 3 ; ALL-NEXT: blr %sel = select i1 %cond, i8 2, i8 3 @@ -791,7 +791,7 @@ ; ALL: # %bb.0: ; ALL-NEXT: rlwinm 3, 3, 0, 31, 31 ; ALL-NEXT: li 4, -128 -; ALL-NEXT: subfic 3, 3, 3 +; ALL-NEXT: xori 3, 3, 3 ; ALL-NEXT: sraw 3, 4, 3 ; ALL-NEXT: blr %sel = select i1 %cond, i8 2, i8 3 Index: test/CodeGen/SPARC/64bit.ll =================================================================== --- test/CodeGen/SPARC/64bit.ll +++ test/CodeGen/SPARC/64bit.ll @@ -238,8 +238,8 @@ declare void @g(i8*) ; CHECK: expand_setcc -; CHECK: cmp %i0, 1 -; CHECK: movl %xcc, 1, +; CHECK: cmp %i0, 0 +; CHECK: movg %xcc, 1, define i32 @expand_setcc(i64 %a) { %cond = icmp sle i64 %a, 0 %cast2 = zext i1 %cond to i32 Index: test/CodeGen/X86/bool-math.ll =================================================================== --- test/CodeGen/X86/bool-math.ll +++ test/CodeGen/X86/bool-math.ll @@ -47,8 +47,8 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 Index: test/CodeGen/X86/dagcombine-select.ll =================================================================== --- test/CodeGen/X86/dagcombine-select.ll +++ test/CodeGen/X86/dagcombine-select.ll @@ -194,9 +194,9 @@ ; 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 @@ ; 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 @@ ; 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