[llvm] f5130a5 - [InstCombine] Fold (-a >> b) and/or/xor (~a >> b) into (-a and/or/xor ~a) >> b tests

Maksim Kita via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 21 02:50:06 PDT 2023


Author: Maksim Kita
Date: 2023-08-21T12:49:20+03:00
New Revision: f5130a578eb7e4c5c5b0493ca67b7c9f3571476d

URL: https://github.com/llvm/llvm-project/commit/f5130a578eb7e4c5c5b0493ca67b7c9f3571476d
DIFF: https://github.com/llvm/llvm-project/commit/f5130a578eb7e4c5c5b0493ca67b7c9f3571476d.diff

LOG: [InstCombine] Fold (-a >> b) and/or/xor (~a >> b) into (-a and/or/xor ~a) >> b tests

Precommit tests for D157290.

Differential Revision: https://reviews.llvm.org/D157289

Added: 
    

Modified: 
    llvm/test/Transforms/InstCombine/binop-and-shifts.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/InstCombine/binop-and-shifts.ll b/llvm/test/Transforms/InstCombine/binop-and-shifts.ll
index f1814e3a6934d0..d2fa11b0d433c7 100644
--- a/llvm/test/Transforms/InstCombine/binop-and-shifts.ll
+++ b/llvm/test/Transforms/InstCombine/binop-and-shifts.ll
@@ -549,3 +549,431 @@ define i8 @shl_add_and_fail_mismatch_shift(i8 %x, i8 %y) {
   %bw1 = and i8 %shift1, %bw2
   ret i8 %bw1
 }
+
+; Fold (-x >> y) & ((x >> y) ^ -1) -> (-x & ~x) >> y
+
+define i8 @and_ashr_not(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @and_ashr_not(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[AND]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %and = and i8 %x.shift, %y.shift.not
+  ret i8 %and
+}
+
+define i8 @and_ashr_not_commuted(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @and_ashr_not_commuted(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[AND]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %and = and i8 %y.shift.not, %x.shift
+  ret i8 %and
+}
+
+; Negative test: lshr instead of ashr
+
+define i8 @and_ashr_not_fail_lshr_ashr(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @and_ashr_not_fail_lshr_ashr(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[AND]]
+;
+  %x.shift = lshr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %and = and i8 %x.shift, %y.shift.not
+  ret i8 %and
+}
+
+; Negative test: lshr instead of ashr
+
+define i8 @and_ashr_not_fail_ashr_lshr(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @and_ashr_not_fail_ashr_lshr(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[AND]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = lshr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %and = and i8 %x.shift, %y.shift.not
+  ret i8 %and
+}
+
+; Negative test: invalid xor constant
+
+define i8 @and_ashr_not_fail_invalid_xor_constant(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @and_ashr_not_fail_invalid_xor_constant(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -2
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[AND]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -2
+  %and = and i8 %x.shift, %y.shift.not
+  ret i8 %and
+}
+
+define <4 x i8> @and_ashr_not_vec(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @and_ashr_not_vec(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr <4 x i8> [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr <4 x i8> [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor <4 x i8> [[Y_SHIFT]], <i8 -1, i8 -1, i8 -1, i8 -1>
+; CHECK-NEXT:    [[AND:%.*]] = and <4 x i8> [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret <4 x i8> [[AND]]
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
+  %and = and <4 x i8> %x.shift, %y.shift.not
+  ret <4 x i8> %and
+}
+
+define <4 x i8> @and_ashr_not_vec_commuted(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @and_ashr_not_vec_commuted(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr <4 x i8> [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr <4 x i8> [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor <4 x i8> [[Y_SHIFT]], <i8 -1, i8 -1, i8 -1, i8 -1>
+; CHECK-NEXT:    [[AND:%.*]] = and <4 x i8> [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret <4 x i8> [[AND]]
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
+  %and = and <4 x i8> %y.shift.not, %x.shift
+  ret <4 x i8> %and
+}
+
+define <4 x i8> @and_ashr_not_vec_undef_1(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @and_ashr_not_vec_undef_1(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr <4 x i8> [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr <4 x i8> [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor <4 x i8> [[Y_SHIFT]], <i8 -1, i8 undef, i8 undef, i8 undef>
+; CHECK-NEXT:    [[AND:%.*]] = and <4 x i8> [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret <4 x i8> [[AND]]
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 undef, i8 undef, i8 undef>
+  %and = and <4 x i8> %x.shift, %y.shift.not
+  ret <4 x i8> %and
+}
+
+define <4 x i8> @and_ashr_not_vec_undef_2(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @and_ashr_not_vec_undef_2(
+; CHECK-NEXT:    ret <4 x i8> zeroinitializer
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 undef, i8 undef, i8 undef, i8 undef>
+  %and = and <4 x i8> %x.shift, %y.shift.not
+  ret <4 x i8> %and
+}
+
+; Fold (-x >> y) | ((x >> y) ^ -1) -> (-x | ~x) >> y
+
+define i8 @or_ashr_not(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @or_ashr_not(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[OR]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %or = or i8 %x.shift, %y.shift.not
+  ret i8 %or
+}
+
+define i8 @or_ashr_not_commuted(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @or_ashr_not_commuted(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[OR]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %or = or i8 %y.shift.not, %x.shift
+  ret i8 %or
+}
+
+; Negative test: lshr instead of ashr
+
+define i8 @or_ashr_not_fail_lshr_ashr(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @or_ashr_not_fail_lshr_ashr(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[OR]]
+;
+  %x.shift = lshr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %or = or i8 %x.shift, %y.shift.not
+  ret i8 %or
+}
+
+; Negative test: lshr instead of ashr
+
+define i8 @or_ashr_not_fail_ashr_lshr(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @or_ashr_not_fail_ashr_lshr(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[OR]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = lshr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %or = or i8 %x.shift, %y.shift.not
+  ret i8 %or
+}
+
+; Negative test: invalid xor constant
+
+define i8 @or_ashr_not_fail_invalid_xor_constant(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @or_ashr_not_fail_invalid_xor_constant(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -2
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[OR]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -2
+  %or = or i8 %x.shift, %y.shift.not
+  ret i8 %or
+}
+
+define <4 x i8> @or_ashr_not_vec(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @or_ashr_not_vec(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr <4 x i8> [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr <4 x i8> [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor <4 x i8> [[Y_SHIFT]], <i8 -1, i8 -1, i8 -1, i8 -1>
+; CHECK-NEXT:    [[OR:%.*]] = or <4 x i8> [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret <4 x i8> [[OR]]
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
+  %or = or <4 x i8> %x.shift, %y.shift.not
+  ret <4 x i8> %or
+}
+
+define <4 x i8> @or_ashr_not_vec_commuted(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @or_ashr_not_vec_commuted(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr <4 x i8> [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr <4 x i8> [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor <4 x i8> [[Y_SHIFT]], <i8 -1, i8 -1, i8 -1, i8 -1>
+; CHECK-NEXT:    [[OR:%.*]] = or <4 x i8> [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret <4 x i8> [[OR]]
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
+  %or = or <4 x i8> %y.shift.not, %x.shift
+  ret <4 x i8> %or
+}
+
+define <4 x i8> @or_ashr_not_vec_undef_1(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @or_ashr_not_vec_undef_1(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr <4 x i8> [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr <4 x i8> [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor <4 x i8> [[Y_SHIFT]], <i8 -1, i8 undef, i8 undef, i8 undef>
+; CHECK-NEXT:    [[OR:%.*]] = or <4 x i8> [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret <4 x i8> [[OR]]
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 undef, i8 undef, i8 undef>
+  %or = or <4 x i8> %x.shift, %y.shift.not
+  ret <4 x i8> %or
+}
+
+define <4 x i8> @or_ashr_not_vec_undef_2(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @or_ashr_not_vec_undef_2(
+; CHECK-NEXT:    ret <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 undef, i8 undef, i8 undef, i8 undef>
+  %or = or <4 x i8> %x.shift, %y.shift.not
+  ret <4 x i8> %or
+}
+
+; Fold (-x >> y) ^ ((x >> y) ^ -1) -> (-x ^ ~x) >> y
+
+define i8 @xor_ashr_not(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @xor_ashr_not(
+; CHECK-NEXT:    [[Y_SHIFT1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 [[Y_SHIFT1]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[TMP1]], -1
+; CHECK-NEXT:    ret i8 [[XOR]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %xor = xor i8 %x.shift, %y.shift.not
+  ret i8 %xor
+}
+
+define i8 @xor_ashr_not_commuted(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @xor_ashr_not_commuted(
+; CHECK-NEXT:    [[Y_SHIFT1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 [[Y_SHIFT1]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[TMP1]], -1
+; CHECK-NEXT:    ret i8 [[XOR]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %xor = xor i8 %y.shift.not, %x.shift
+  ret i8 %xor
+}
+
+; Negative test: lshr instead of ashr
+
+define i8 @xor_ashr_not_fail_lshr_ashr(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @xor_ashr_not_fail_lshr_ashr(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y_SHIFT]], [[X_SHIFT]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[TMP1]], -1
+; CHECK-NEXT:    ret i8 [[XOR]]
+;
+  %x.shift = lshr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %xor = xor i8 %x.shift, %y.shift.not
+  ret i8 %xor
+}
+
+; Negative test: lshr instead of ashr
+
+define i8 @xor_ashr_not_fail_ashr_lshr(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @xor_ashr_not_fail_ashr_lshr(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y_SHIFT]], [[X_SHIFT]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[TMP1]], -1
+; CHECK-NEXT:    ret i8 [[XOR]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = lshr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %xor = xor i8 %x.shift, %y.shift.not
+  ret i8 %xor
+}
+
+; Negative test: invalid xor constant
+
+define i8 @xor_ashr_not_fail_invalid_xor_constant(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @xor_ashr_not_fail_invalid_xor_constant(
+; CHECK-NEXT:    [[Y_SHIFT1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 [[Y_SHIFT1]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[TMP1]], -2
+; CHECK-NEXT:    ret i8 [[XOR]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -2
+  %xor = xor i8 %x.shift, %y.shift.not
+  ret i8 %xor
+}
+
+define <4 x i8> @xor_ashr_not_vec(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @xor_ashr_not_vec(
+; CHECK-NEXT:    [[Y_SHIFT1:%.*]] = xor <4 x i8> [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr <4 x i8> [[Y_SHIFT1]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor <4 x i8> [[TMP1]], <i8 -1, i8 -1, i8 -1, i8 -1>
+; CHECK-NEXT:    ret <4 x i8> [[XOR]]
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
+  %xor = xor <4 x i8> %x.shift, %y.shift.not
+  ret <4 x i8> %xor
+}
+
+define <4 x i8> @xor_ashr_not_vec_commuted(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @xor_ashr_not_vec_commuted(
+; CHECK-NEXT:    [[Y_SHIFT1:%.*]] = xor <4 x i8> [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr <4 x i8> [[Y_SHIFT1]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor <4 x i8> [[TMP1]], <i8 -1, i8 -1, i8 -1, i8 -1>
+; CHECK-NEXT:    ret <4 x i8> [[XOR]]
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 -1, i8 -1, i8 -1>
+  %xor = xor <4 x i8> %y.shift.not, %x.shift
+  ret <4 x i8> %xor
+}
+
+define <4 x i8> @xor_ashr_not_vec_undef_1(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @xor_ashr_not_vec_undef_1(
+; CHECK-NEXT:    [[Y_SHIFT1:%.*]] = xor <4 x i8> [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr <4 x i8> [[Y_SHIFT1]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor <4 x i8> [[TMP1]], <i8 -1, i8 undef, i8 undef, i8 undef>
+; CHECK-NEXT:    ret <4 x i8> [[XOR]]
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 -1, i8 undef, i8 undef, i8 undef>
+  %xor = xor <4 x i8> %x.shift, %y.shift.not
+  ret <4 x i8> %xor
+}
+
+define <4 x i8> @xor_ashr_not_vec_undef_2(<4 x i8> %x, <4 x i8> %y, <4 x i8> %shamt) {
+; CHECK-LABEL: @xor_ashr_not_vec_undef_2(
+; CHECK-NEXT:    ret <4 x i8> undef
+;
+  %x.shift = ashr <4 x i8> %x, %shamt
+  %y.shift = ashr <4 x i8> %y, %shamt
+  %y.shift.not = xor <4 x i8> %y.shift, <i8 undef, i8 undef, i8 undef, i8 undef>
+  %xor = xor <4 x i8> %x.shift, %y.shift.not
+  ret <4 x i8> %xor
+}
+
+; Negative test: invalid binop
+
+define i8 @binop_ashr_not_fail_invalid_binop(i8 %x, i8 %y, i8 %shamt) {
+; CHECK-LABEL: @binop_ashr_not_fail_invalid_binop(
+; CHECK-NEXT:    [[X_SHIFT:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
+; CHECK-NEXT:    [[Y_SHIFT:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
+; CHECK-NEXT:    [[Y_SHIFT_NOT:%.*]] = xor i8 [[Y_SHIFT]], -1
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X_SHIFT]], [[Y_SHIFT_NOT]]
+; CHECK-NEXT:    ret i8 [[ADD]]
+;
+  %x.shift = ashr i8 %x, %shamt
+  %y.shift = ashr i8 %y, %shamt
+  %y.shift.not = xor i8 %y.shift, -1
+  %add = add i8 %x.shift, %y.shift.not
+  ret i8 %add
+}


        


More information about the llvm-commits mailing list