; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=instcombine -S < %s | FileCheck %s ; Test folding of ~x | (x - 1) to ~(x & -x) define i64 @fold_or_not_dec(i64 %x) { ; CHECK-LABEL: define i64 @fold_or_not_dec( ; CHECK-SAME: i64 [[X:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[X]] ; CHECK-NEXT: [[AND:%.*]] = and i64 [[X]], [[TMP1]] ; CHECK-NEXT: [[NOT:%.*]] = xor i64 [[AND]], -1 ; CHECK-NEXT: ret i64 [[NOT]] ; %xor = xor i64 %x, -1 %add = add i64 %x, -1 %or = or i64 %xor, %add ret i64 %or } define i64 @fold_or_dec_not(i64 %x) { ; CHECK-LABEL: define i64 @fold_or_dec_not( ; CHECK-SAME: i64 [[X:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[X]] ; CHECK-NEXT: [[TMP2:%.*]] = and i64 [[X]], [[TMP1]] ; CHECK-NEXT: [[OR:%.*]] = xor i64 [[TMP2]], -1 ; CHECK-NEXT: ret i64 [[OR]] ; %xor = xor i64 %x, -1 %add = add i64 %x, -1 %or = or i64 %add, %xor ret i64 %or } ; NEGATIVE TEST: add has multiple uses define i64 @negative_multiuse_add(i64 %x, ptr %p) { ; CHECK-LABEL: define i64 @negative_multiuse_add( ; CHECK-SAME: i64 [[X:%.*]], ptr [[P:%.*]]) { ; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[X]], -1 ; CHECK-NEXT: [[ADD:%.*]] = add i64 [[X]], -1 ; CHECK-NEXT: store i64 [[ADD]], ptr [[P]], align 4 ; CHECK-NEXT: [[OR:%.*]] = or i64 [[ADD]], [[XOR]] ; CHECK-NEXT: ret i64 [[OR]] ; %xor = xor i64 %x, -1 %add = add i64 %x, -1 store i64 %add, ptr %p ; second use of %add %or = or i64 %add, %xor ret i64 %or } ; NEGATIVE TEST: xor has multiple uses define i64 @negative_multiuse_xor(i64 %x, ptr %p) { ; CHECK-LABEL: define i64 @negative_multiuse_xor( ; CHECK-SAME: i64 [[X:%.*]], ptr [[P:%.*]]) { ; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[X]], -1 ; CHECK-NEXT: [[ADD:%.*]] = add i64 [[X]], -1 ; CHECK-NEXT: store i64 [[XOR]], ptr [[P]], align 4 ; CHECK-NEXT: [[OR:%.*]] = or i64 [[ADD]], [[XOR]] ; CHECK-NEXT: ret i64 [[OR]] ; %xor = xor i64 %x, -1 %add = add i64 %x, -1 store i64 %xor, ptr %p ; second use of %xor %or = or i64 %add, %xor ret i64 %or }