diff --git a/llvm/test/Transforms/InstCombine/and-or-shift.ll b/llvm/test/Transforms/InstCombine/and-or-shift.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/and-or-shift.ll @@ -0,0 +1,271 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes='instcombine' -S | FileCheck %s + +; Fold (-x >> y) & (~x >> y) -> (-x & ~x) >> y + +define i8 @and_ashr_sub_nsw_x_not_x(i8 %x, i8 %y) { +; CHECK-LABEL: @and_ashr_sub_nsw_x_not_x( +; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 0, [[X:%.*]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i8 [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_NOT:%.*]] = ashr i8 [[X]], [[Y]] +; CHECK-NEXT: [[SHR1:%.*]] = xor i8 [[NOT_NOT]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[SHR]], [[SHR1]] +; CHECK-NEXT: ret i8 [[AND]] +; + %sub = sub nsw i8 0, %x + %shr = ashr i8 %sub, %y + %not = xor i8 %x, -1 + %shr1 = ashr i8 %not, %y + %and = and i8 %shr, %shr1 + ret i8 %and +} + +define i8 @and_ashr_sub_nsw_x_not_x_commuted(i8 %x, i8 %y) { +; CHECK-LABEL: @and_ashr_sub_nsw_x_not_x_commuted( +; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 0, [[X:%.*]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i8 [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_NOT:%.*]] = ashr i8 [[X]], [[Y]] +; CHECK-NEXT: [[SHR1:%.*]] = xor i8 [[NOT_NOT]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[SHR]], [[SHR1]] +; CHECK-NEXT: ret i8 [[AND]] +; + %sub = sub nsw i8 0, %x + %shr = ashr i8 %sub, %y + %not = xor i8 %x, -1 + %shr1 = ashr i8 %not, %y + %and = and i8 %shr1, %shr + ret i8 %and +} + +define i8 @and_lshr_sub_x_not_x(i8 %x, i8 %y) { +; CHECK-LABEL: @and_lshr_sub_x_not_x( +; CHECK-NEXT: [[SUB:%.*]] = sub i8 0, [[X:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[X]], -1 +; CHECK-NEXT: [[SHR2:%.*]] = and i8 [[SUB]], [[NOT]] +; CHECK-NEXT: [[AND:%.*]] = lshr i8 [[SHR2]], [[Y:%.*]] +; CHECK-NEXT: ret i8 [[AND]] +; + %sub = sub i8 0, %x + %shr = lshr i8 %sub, %y + %not = xor i8 %x, -1 + %shr1 = lshr i8 %not, %y + %and = and i8 %shr, %shr1 + ret i8 %and +} + +define i8 @and_lshr_sub_x_not_x_commuted(i8 %x, i8 %y) { +; CHECK-LABEL: @and_lshr_sub_x_not_x_commuted( +; CHECK-NEXT: [[SUB:%.*]] = sub i8 0, [[X:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[X]], -1 +; CHECK-NEXT: [[SHR11:%.*]] = and i8 [[NOT]], [[SUB]] +; CHECK-NEXT: [[AND:%.*]] = lshr i8 [[SHR11]], [[Y:%.*]] +; CHECK-NEXT: ret i8 [[AND]] +; + %sub = sub i8 0, %x + %shr = lshr i8 %sub, %y + %not = xor i8 %x, -1 + %shr1 = lshr i8 %not, %y + %and = and i8 %shr1, %shr + ret i8 %and +} + +define <4 x i8> @and_ashr_sub_nsw_x_not_x_vec(<4 x i8> %x, <4 x i8> %y) { +; CHECK-LABEL: @and_ashr_sub_nsw_x_not_x_vec( +; CHECK-NEXT: [[SUB:%.*]] = sub nsw <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i8> [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_NOT:%.*]] = ashr <4 x i8> [[X]], [[Y]] +; CHECK-NEXT: [[SHR1:%.*]] = xor <4 x i8> [[NOT_NOT]], +; CHECK-NEXT: [[AND:%.*]] = and <4 x i8> [[SHR]], [[SHR1]] +; CHECK-NEXT: ret <4 x i8> [[AND]] +; + %sub = sub nsw <4 x i8> , %x + %shr = ashr <4 x i8> %sub, %y + %not = xor <4 x i8> %x, + %shr1 = ashr <4 x i8> %not, %y + %and = and <4 x i8> %shr, %shr1 + ret <4 x i8> %and +} + +define <4 x i8> @and_ashr_sub_nsw_x_not_x_vec_commuted(<4 x i8> %x, <4 x i8> %y) { +; CHECK-LABEL: @and_ashr_sub_nsw_x_not_x_vec_commuted( +; CHECK-NEXT: [[SUB:%.*]] = sub nsw <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i8> [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_NOT:%.*]] = ashr <4 x i8> [[X]], [[Y]] +; CHECK-NEXT: [[SHR1:%.*]] = xor <4 x i8> [[NOT_NOT]], +; CHECK-NEXT: [[AND:%.*]] = and <4 x i8> [[SHR]], [[SHR1]] +; CHECK-NEXT: ret <4 x i8> [[AND]] +; + %sub = sub nsw <4 x i8> , %x + %shr = ashr <4 x i8> %sub, %y + %not = xor <4 x i8> %x, + %shr1 = ashr <4 x i8> %not, %y + %and = and <4 x i8> %shr1, %shr + ret <4 x i8> %and +} + +define <4 x i8> @and_lshr_sub_x_not_x_vec(<4 x i8> %x, <4 x i8> %y) { +; CHECK-LABEL: @and_lshr_sub_x_not_x_vec( +; CHECK-NEXT: [[SUB:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor <4 x i8> [[X]], +; CHECK-NEXT: [[SHR2:%.*]] = and <4 x i8> [[SUB]], [[NOT]] +; CHECK-NEXT: [[AND:%.*]] = lshr <4 x i8> [[SHR2]], [[Y:%.*]] +; CHECK-NEXT: ret <4 x i8> [[AND]] +; + %sub = sub <4 x i8> , %x + %shr = lshr <4 x i8> %sub, %y + %not = xor <4 x i8> %x, + %shr1 = lshr <4 x i8> %not, %y + %and = and <4 x i8> %shr, %shr1 + ret <4 x i8> %and +} + +define <4 x i8> @and_lshr_sub_x_not_x_vec_commuted(<4 x i8> %x, <4 x i8> %y) { +; CHECK-LABEL: @and_lshr_sub_x_not_x_vec_commuted( +; CHECK-NEXT: [[SUB:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor <4 x i8> [[X]], +; CHECK-NEXT: [[SHR11:%.*]] = and <4 x i8> [[NOT]], [[SUB]] +; CHECK-NEXT: [[AND:%.*]] = lshr <4 x i8> [[SHR11]], [[Y:%.*]] +; CHECK-NEXT: ret <4 x i8> [[AND]] +; + %sub = sub <4 x i8> , %x + %shr = lshr <4 x i8> %sub, %y + %not = xor <4 x i8> %x, + %shr1 = lshr <4 x i8> %not, %y + %and = and <4 x i8> %shr1, %shr + ret <4 x i8> %and +} + +; Fold (-a >> b) | (~a >> b) -> (-a | ~a) >> b + +define i8 @or_ashr_sub_nsw_x_not_x(i8 %x, i8 %y) { +; CHECK-LABEL: @or_ashr_sub_nsw_x_not_x( +; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 0, [[X:%.*]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i8 [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_NOT:%.*]] = ashr i8 [[X]], [[Y]] +; CHECK-NEXT: [[SHR1:%.*]] = xor i8 [[NOT_NOT]], -1 +; CHECK-NEXT: [[OR:%.*]] = or i8 [[SHR]], [[SHR1]] +; CHECK-NEXT: ret i8 [[OR]] +; + %sub = sub nsw i8 0, %x + %shr = ashr i8 %sub, %y + %not = xor i8 %x, -1 + %shr1 = ashr i8 %not, %y + %or = or i8 %shr, %shr1 + ret i8 %or +} + +define i8 @or_ashr_sub_nsw_x_not_x_commuted(i8 %x, i8 %y) { +; CHECK-LABEL: @or_ashr_sub_nsw_x_not_x_commuted( +; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 0, [[X:%.*]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i8 [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_NOT:%.*]] = ashr i8 [[X]], [[Y]] +; CHECK-NEXT: [[SHR1:%.*]] = xor i8 [[NOT_NOT]], -1 +; CHECK-NEXT: [[OR:%.*]] = or i8 [[SHR]], [[SHR1]] +; CHECK-NEXT: ret i8 [[OR]] +; + %sub = sub nsw i8 0, %x + %shr = ashr i8 %sub, %y + %not = xor i8 %x, -1 + %shr1 = ashr i8 %not, %y + %or = or i8 %shr1, %shr + ret i8 %or +} + +define i8 @or_lshr_sub_x_not_x(i8 %x, i8 %y) { +; CHECK-LABEL: @or_lshr_sub_x_not_x( +; CHECK-NEXT: [[SUB:%.*]] = sub i8 0, [[X:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[X]], -1 +; CHECK-NEXT: [[SHR2:%.*]] = or i8 [[SUB]], [[NOT]] +; CHECK-NEXT: [[OR:%.*]] = lshr i8 [[SHR2]], [[Y:%.*]] +; CHECK-NEXT: ret i8 [[OR]] +; + %sub = sub i8 0, %x + %shr = lshr i8 %sub, %y + %not = xor i8 %x, -1 + %shr1 = lshr i8 %not, %y + %or = or i8 %shr, %shr1 + ret i8 %or +} + +define i8 @or_lshr_sub_x_not_x_commuted(i8 %x, i8 %y) { +; CHECK-LABEL: @or_lshr_sub_x_not_x_commuted( +; CHECK-NEXT: [[SUB:%.*]] = sub i8 0, [[X:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[X]], -1 +; CHECK-NEXT: [[SHR11:%.*]] = or i8 [[NOT]], [[SUB]] +; CHECK-NEXT: [[OR:%.*]] = lshr i8 [[SHR11]], [[Y:%.*]] +; CHECK-NEXT: ret i8 [[OR]] +; + %sub = sub i8 0, %x + %shr = lshr i8 %sub, %y + %not = xor i8 %x, -1 + %shr1 = lshr i8 %not, %y + %or = or i8 %shr1, %shr + ret i8 %or +} + + +define <4 x i8> @or_ashr_sub_nsw_x_not_x_vec(<4 x i8> %x, <4 x i8> %y) { +; CHECK-LABEL: @or_ashr_sub_nsw_x_not_x_vec( +; CHECK-NEXT: [[SUB:%.*]] = sub nsw <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i8> [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_NOT:%.*]] = ashr <4 x i8> [[X]], [[Y]] +; CHECK-NEXT: [[SHR1:%.*]] = xor <4 x i8> [[NOT_NOT]], +; CHECK-NEXT: [[OR:%.*]] = or <4 x i8> [[SHR]], [[SHR1]] +; CHECK-NEXT: ret <4 x i8> [[OR]] +; + %sub = sub nsw <4 x i8> , %x + %shr = ashr <4 x i8> %sub, %y + %not = xor <4 x i8> %x, + %shr1 = ashr <4 x i8> %not, %y + %or = or <4 x i8> %shr, %shr1 + ret <4 x i8> %or +} + +define <4 x i8> @or_ashr_sub_nsw_x_not_x_vec_commuted(<4 x i8> %x, <4 x i8> %y) { +; CHECK-LABEL: @or_ashr_sub_nsw_x_not_x_vec_commuted( +; CHECK-NEXT: [[SUB:%.*]] = sub nsw <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i8> [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_NOT:%.*]] = ashr <4 x i8> [[X]], [[Y]] +; CHECK-NEXT: [[SHR1:%.*]] = xor <4 x i8> [[NOT_NOT]], +; CHECK-NEXT: [[OR:%.*]] = or <4 x i8> [[SHR]], [[SHR1]] +; CHECK-NEXT: ret <4 x i8> [[OR]] +; + %sub = sub nsw <4 x i8> , %x + %shr = ashr <4 x i8> %sub, %y + %not = xor <4 x i8> %x, + %shr1 = ashr <4 x i8> %not, %y + %or = or <4 x i8> %shr1, %shr + ret <4 x i8> %or +} + +define <4 x i8> @or_lshr_sub_x_not_x_vec(<4 x i8> %x, <4 x i8> %y) { +; CHECK-LABEL: @or_lshr_sub_x_not_x_vec( +; CHECK-NEXT: [[SUB:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor <4 x i8> [[X]], +; CHECK-NEXT: [[SHR2:%.*]] = or <4 x i8> [[SUB]], [[NOT]] +; CHECK-NEXT: [[OR:%.*]] = lshr <4 x i8> [[SHR2]], [[Y:%.*]] +; CHECK-NEXT: ret <4 x i8> [[OR]] +; + %sub = sub <4 x i8> , %x + %shr = lshr <4 x i8> %sub, %y + %not = xor <4 x i8> %x, + %shr1 = lshr <4 x i8> %not, %y + %or = or <4 x i8> %shr, %shr1 + ret <4 x i8> %or +} + +define <4 x i8> @or_lshr_sub_x_not_x_vec_commuted(<4 x i8> %x, <4 x i8> %y) { +; CHECK-LABEL: @or_lshr_sub_x_not_x_vec_commuted( +; CHECK-NEXT: [[SUB:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor <4 x i8> [[X]], +; CHECK-NEXT: [[SHR11:%.*]] = or <4 x i8> [[NOT]], [[SUB]] +; CHECK-NEXT: [[OR:%.*]] = lshr <4 x i8> [[SHR11]], [[Y:%.*]] +; CHECK-NEXT: ret <4 x i8> [[OR]] +; + %sub = sub <4 x i8> , %x + %shr = lshr <4 x i8> %sub, %y + %not = xor <4 x i8> %x, + %shr1 = lshr <4 x i8> %not, %y + %or = or <4 x i8> %shr1, %shr + ret <4 x i8> %or +}