diff --git a/llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll b/llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll @@ -0,0 +1,414 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i32 @cmp_ne_0_sub_xor_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_ne_0_sub_xor_eval( +; CHECK-NEXT: [[Y:%.*]] = add i32 [[X:%.*]], 1 +; CHECK-NEXT: [[Z:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and i32 [[Z]], 1 +; CHECK-NEXT: ret i32 [[B]] +; + %C1 = or i32 %C, 13 + %y = sub i32 %x, %C1 + %z = xor i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + +define i32 @cmp_ne_0_sub_or_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_ne_0_sub_or_eval( +; CHECK-NEXT: [[Y:%.*]] = add i32 [[X:%.*]], 1 +; CHECK-NEXT: [[Z:%.*]] = or i32 [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and i32 [[Z]], 1 +; CHECK-NEXT: ret i32 [[B]] +; + %C1 = or i32 %C, 5 + %y = sub i32 %x, %C1 + %z = or i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + +define i32 @cmp_eq_0_sub2_or_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_eq_0_sub2_or_eval( +; CHECK-NEXT: ret i32 1 +; + %C1 = or i32 %C, 3 + %y = sub i32 %C1, %x + %z = or i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + +define i32 @cmp_ne_0_add_and_no_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_ne_0_add_and_no_eval( +; CHECK-NEXT: [[Y:%.*]] = add i32 [[C:%.*]], [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = and i32 [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and i32 [[Z]], 1 +; CHECK-NEXT: ret i32 [[B]] +; + %C1 = or i32 %C, 132 + %y = add i32 %C1, %x + %z = and i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + +define i32 @cmp_eq_0_sub2_and_no_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_eq_0_sub2_and_no_eval( +; CHECK-NEXT: [[Y:%.*]] = sub i32 [[C:%.*]], [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = and i32 [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and i32 [[Z]], 1 +; CHECK-NEXT: ret i32 [[B]] +; + %C1 = or i32 %C, 8 + %y = sub i32 %C1, %x + %z = and i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + +define i32 @cmp_eq_0_add_xor_no_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_eq_0_add_xor_no_eval( +; CHECK-NEXT: [[Y:%.*]] = add i32 [[C:%.*]], [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and i32 [[Z]], 1 +; CHECK-NEXT: ret i32 [[B]] +; + %C1 = or i32 %C, 4 + %y = add i32 %x, %C1 + %z = xor i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + +define i32 @cmp_ne_0_sub_xor_no_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_ne_0_sub_xor_no_eval( +; CHECK-NEXT: [[Y:%.*]] = sub i32 [[X:%.*]], [[C:%.*]] +; CHECK-NEXT: [[Z:%.*]] = xor i32 [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and i32 [[Z]], 1 +; CHECK-NEXT: ret i32 [[B]] +; + %C1 = or i32 %C, 2 + %y = sub i32 %x, %C1 + %z = xor i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + + +define i32 @cmp_sgt_0_add_or_no_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_sgt_0_add_or_no_eval( +; CHECK-NEXT: [[Y:%.*]] = add i32 [[C:%.*]], [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = or i32 [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and i32 [[Z]], 1 +; CHECK-NEXT: ret i32 [[B]] +; + %C1 = or i32 %C, 6 + %y = add i32 %x, %C1 + %z = or i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + +define i32 @cmp_ne_0_sub_or_no_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_ne_0_sub_or_no_eval( +; CHECK-NEXT: [[Y:%.*]] = sub i32 [[X:%.*]], [[C:%.*]] +; CHECK-NEXT: [[Z:%.*]] = or i32 [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and i32 [[Z]], 1 +; CHECK-NEXT: ret i32 [[B]] +; + %C1 = or i32 %C, 4 + %y = sub i32 %x, %C1 + %z = or i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + +define i32 @cmp_eq_0_sub2_or_no_eval(i32 %x, i32 %C) { +; CHECK-LABEL: @cmp_eq_0_sub2_or_no_eval( +; CHECK-NEXT: [[Y:%.*]] = sub i32 [[C:%.*]], [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = or i32 [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and i32 [[Z]], 1 +; CHECK-NEXT: ret i32 [[B]] +; + %C1 = or i32 %C, 128 + %y = sub i32 %C1, %x + %z = or i32 %x, %y + %b = and i32 %z, 1 + ret i32 %b +} + +define <2 x i32> @cmp_ne_0_add_and_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_ne_0_add_and_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = add <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[Z:%.*]] = and <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = add <2 x i32> %C1, %x + %z = and <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i32> @cmp_ugt_0_sub_and_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_ugt_0_sub_and_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = add <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[Z:%.*]] = and <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = sub <2 x i32> %x, %C1 + %z = and <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i32> @cmp_ne_0_sub_xor_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_ne_0_sub_xor_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = add <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[Z:%.*]] = xor <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = sub <2 x i32> %x, %C1 + %z = xor <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i32> @cmp_ne_0_sub_or_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_ne_0_sub_or_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = add <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[Z:%.*]] = or <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = sub <2 x i32> %x, %C1 + %z = or <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i32> @cmp_ne_0_add_and_no_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_ne_0_add_and_no_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = add <2 x i32> [[C:%.*]], [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = and <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = add <2 x i32> %C1, %x + %z = and <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i32> @cmp_ugt_0_sub_and_no_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_ugt_0_sub_and_no_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = sub <2 x i32> [[X:%.*]], [[C:%.*]] +; CHECK-NEXT: [[Z:%.*]] = and <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = sub <2 x i32> %x, %C1 + %z = and <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i32> @cmp_eq_0_add_xor_no_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_eq_0_add_xor_no_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = add <2 x i32> [[C:%.*]], [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = xor <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = add <2 x i32> %x, %C1 + %z = xor <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i32> @cmp_ne_0_sub_xor_no_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_ne_0_sub_xor_no_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = sub <2 x i32> [[X:%.*]], [[C:%.*]] +; CHECK-NEXT: [[Z:%.*]] = xor <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = sub <2 x i32> %x, %C1 + %z = xor <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i32> @cmp_sgt_0_add_or_no_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_sgt_0_add_or_no_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = add <2 x i32> [[C:%.*]], [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = or <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = add <2 x i32> %x, %C1 + %z = or <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i32> @cmp_ne_0_sub_or_no_eval_vec(<2 x i32> %x, <2 x i32> %C) { +; CHECK-LABEL: @cmp_ne_0_sub_or_no_eval_vec( +; CHECK-NEXT: [[Y:%.*]] = sub <2 x i32> [[X:%.*]], [[C:%.*]] +; CHECK-NEXT: [[Z:%.*]] = or <2 x i32> [[Y]], [[X]] +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[Z]], +; CHECK-NEXT: ret <2 x i32> [[B]] +; + %C1 = or <2 x i32> %C, + %y = sub <2 x i32> %x, %C1 + %z = or <2 x i32> %x, %y + %b = and <2 x i32> %z, + ret <2 x i32> %b +} + +define <2 x i1> @sub_XY_and_bit0_is_zero(<2 x i8> %x, <2 x i8> %C) nounwind { +; CHECK-LABEL: @sub_XY_and_bit0_is_zero( +; CHECK-NEXT: [[C1:%.*]] = or <2 x i8> [[C:%.*]], +; CHECK-NEXT: [[Y:%.*]] = sub <2 x i8> [[X:%.*]], [[C1]] +; CHECK-NEXT: [[W:%.*]] = and <2 x i8> [[Y]], [[X]] +; CHECK-NEXT: [[Z_MASK:%.*]] = and <2 x i8> [[W]], +; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[Z_MASK]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %C1 = or <2 x i8> %C, + %y = sub <2 x i8> %x, %C1 + %w = and <2 x i8> %x, %y + %z = add <2 x i8> %w, %w + %r = icmp slt <2 x i8> %z, + ret <2 x i1> %r +} + +define i1 @sub_XY_xor_bit0_is_one(i8 %x, i8 %C) nounwind { +; CHECK-LABEL: @sub_XY_xor_bit0_is_one( +; CHECK-NEXT: [[Y:%.*]] = add i8 [[X:%.*]], 1 +; CHECK-NEXT: [[W:%.*]] = xor i8 [[Y]], [[X]] +; CHECK-NEXT: [[Z_MASK:%.*]] = and i8 [[W]], 1 +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[Z_MASK]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %C1 = or i8 %C, 1 + %y = sub i8 %x, %C1 + %w = xor i8 %x, %y + %z = shl i8 %w, 7 + %r = icmp slt i8 %z, 0 + ret i1 %r +} + +define i1 @sub_XY_or_bit0_is_one(i8 %x, i8 %C) nounwind { +; CHECK-LABEL: @sub_XY_or_bit0_is_one( +; CHECK-NEXT: [[Y:%.*]] = add i8 [[X:%.*]], 1 +; CHECK-NEXT: [[W:%.*]] = or i8 [[Y]], [[X]] +; CHECK-NEXT: [[Z_MASK:%.*]] = and i8 [[W]], 1 +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[Z_MASK]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %C1 = or i8 %C, 1 + %y = sub i8 %x, %C1 + %w = or i8 %x, %y + %z = shl i8 %w, 7 + %r = icmp slt i8 %z, 0 + ret i1 %r +} + +define i1 @sub_YX_and_bit0_is_zero(i8 %x, i8 %C) nounwind { +; CHECK-LABEL: @sub_YX_and_bit0_is_zero( +; CHECK-NEXT: [[C1:%.*]] = or i8 [[C:%.*]], 1 +; CHECK-NEXT: [[Y:%.*]] = sub i8 [[C1]], [[X:%.*]] +; CHECK-NEXT: [[W:%.*]] = and i8 [[Y]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[W]], -1 +; CHECK-NEXT: ret i1 [[R]] +; + %C1 = or i8 %C, 1 + %y = sub i8 %C1, %x + %w = and i8 %x, %y + %z = add i8 %w, 1 + %r = icmp eq i8 %z, 0 + ret i1 %r +} + +define <2 x i1> @sub_YX_xor_bit0_is_one(<2 x i8> %x, <2 x i8> %C) nounwind { +; CHECK-LABEL: @sub_YX_xor_bit0_is_one( +; CHECK-NEXT: [[C1:%.*]] = or <2 x i8> [[C:%.*]], +; CHECK-NEXT: [[Y:%.*]] = sub <2 x i8> [[C1]], [[X:%.*]] +; CHECK-NEXT: [[W:%.*]] = xor <2 x i8> [[Y]], [[X]] +; CHECK-NEXT: [[Z_MASK:%.*]] = and <2 x i8> [[W]], +; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[Z_MASK]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %C1 = or <2 x i8> %C, + %y = sub <2 x i8> %C1, %x + %w = xor <2 x i8> %x, %y + %z = add <2 x i8> %w, %w + %r = icmp eq <2 x i8> %z, + ret <2 x i1> %r +} + +define i1 @sub_YX_or_bit0_is_one(i8 %x, i8 %C) nounwind { +; CHECK-LABEL: @sub_YX_or_bit0_is_one( +; CHECK-NEXT: [[C1:%.*]] = or i8 [[C:%.*]], 1 +; CHECK-NEXT: [[Y:%.*]] = sub i8 [[C1]], [[X:%.*]] +; CHECK-NEXT: [[W:%.*]] = or i8 [[Y]], [[X]] +; CHECK-NEXT: [[Z_MASK:%.*]] = and i8 [[W]], 127 +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[Z_MASK]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %C1 = or i8 %C, 1 + %y = sub i8 %C1, %x + %w = or i8 %x, %y + %z = add i8 %w, %w + %r = icmp eq i8 %z, 0 + ret i1 %r +} + + +define i1 @add_YX_xor_bit0_is_one(i8 %x, i8 %C) nounwind { +; CHECK-LABEL: @add_YX_xor_bit0_is_one( +; CHECK-NEXT: [[C1:%.*]] = or i8 [[C:%.*]], 1 +; CHECK-NEXT: [[Y:%.*]] = add i8 [[C1]], [[X:%.*]] +; CHECK-NEXT: [[W:%.*]] = xor i8 [[Y]], [[X]] +; CHECK-NEXT: [[Z_MASK:%.*]] = and i8 [[W]], 127 +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[Z_MASK]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %C1 = or i8 %C, 1 + %y = add i8 %C1, %x + %w = xor i8 %x, %y + %z = add i8 %w, %w + %r = icmp eq i8 %z, 0 + ret i1 %r +} + +define <2 x i1> @add_XY_or_bit0_is_one(<2 x i8> %x, <2 x i8> %C) nounwind { +; CHECK-LABEL: @add_XY_or_bit0_is_one( +; CHECK-NEXT: [[C1:%.*]] = or <2 x i8> [[C:%.*]], +; CHECK-NEXT: [[Y:%.*]] = add <2 x i8> [[C1]], [[X:%.*]] +; CHECK-NEXT: [[W:%.*]] = or <2 x i8> [[Y]], [[X]] +; CHECK-NEXT: [[Z_MASK:%.*]] = and <2 x i8> [[W]], +; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[Z_MASK]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %C1 = or <2 x i8> %C, + %y = add <2 x i8> %C1, %x + %w = or <2 x i8> %x, %y + %z = add <2 x i8> %w, %w + %r = icmp eq <2 x i8> %z, + ret <2 x i1> %r +}