969 lines
33 KiB
LLVM
969 lines
33 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
|
|
|
define i8 @shl_and_and(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_and_and(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shl i8 [[TMP1]], 4
|
|
; CHECK-NEXT: [[BW1:%.*]] = and i8 [[TMP2]], 80
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 4
|
|
%shift2 = shl i8 %y, 4
|
|
%bw2 = and i8 %shift2, 88
|
|
%bw1 = and i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_and_and_fail(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_and_and_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = shl i8 [[X:%.*]], 4
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = shl i8 [[Y:%.*]], 5
|
|
; CHECK-NEXT: [[BW2:%.*]] = and i8 [[SHIFT2]], 64
|
|
; CHECK-NEXT: [[BW1:%.*]] = and i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 4
|
|
%shift2 = shl i8 %y, 5
|
|
%bw2 = and i8 %shift2, 88
|
|
%bw1 = and i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_add_add(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_add_add(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shl i8 [[TMP1]], 2
|
|
; CHECK-NEXT: [[BW1:%.*]] = add i8 [[TMP2]], 48
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 2
|
|
%shift2 = shl i8 %y, 2
|
|
%bw2 = add i8 %shift2, 48
|
|
%bw1 = add i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_add_add_fail(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_add_add_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 2
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 2
|
|
; CHECK-NEXT: [[BW2:%.*]] = add nuw nsw i8 [[SHIFT2]], 48
|
|
; CHECK-NEXT: [[BW1:%.*]] = add nuw i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, 2
|
|
%shift2 = lshr i8 %y, 2
|
|
%bw2 = add i8 %shift2, 48
|
|
%bw1 = add i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_and_and_fail2(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_and_and_fail2(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = shl i8 4, [[X:%.*]]
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = shl i8 4, [[Y:%.*]]
|
|
; CHECK-NEXT: [[BW2:%.*]] = and i8 [[SHIFT2]], 88
|
|
; CHECK-NEXT: [[BW1:%.*]] = and i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 4, %x
|
|
%shift2 = shl i8 4, %y
|
|
%bw2 = and i8 %shift2, 88
|
|
%bw1 = and i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define <2 x i8> @lshr_and_or(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @lshr_and_or(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -64, i8 96>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i8> [[TMP1]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = lshr <2 x i8> [[TMP2]], <i8 4, i8 5>
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = lshr <2 x i8> %x, <i8 4, i8 5>
|
|
%shift2 = lshr <2 x i8> %y, <i8 4, i8 5>
|
|
%bw2 = and <2 x i8> %shift1, <i8 44, i8 99>
|
|
%bw1 = or <2 x i8> %shift2, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define <2 x i8> @lshr_and_or_fail(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @lshr_and_or_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 4, i8 5>
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr <2 x i8> [[Y:%.*]], <i8 5, i8 4>
|
|
; CHECK-NEXT: [[BW2:%.*]] = and <2 x i8> [[SHIFT2]], <i8 44, i8 99>
|
|
; CHECK-NEXT: [[BW1:%.*]] = or <2 x i8> [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = lshr <2 x i8> %x, <i8 4, i8 5>
|
|
%shift2 = lshr <2 x i8> %y, <i8 5, i8 4>
|
|
%bw2 = and <2 x i8> %shift2, <i8 44, i8 99>
|
|
%bw1 = or <2 x i8> %shift1, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define i8 @shl_and_xor(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_and_xor(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], 10
|
|
; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[TMP1]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = shl i8 [[TMP2]], 1
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 1
|
|
%shift2 = shl i8 %y, 1
|
|
%bw2 = and i8 %shift1, 20
|
|
%bw1 = xor i8 %shift2, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_and_add(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_and_add(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[Y:%.*]], 59
|
|
; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = shl i8 [[TMP2]], 1
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 1
|
|
%shift2 = shl i8 %y, 1
|
|
%bw2 = and i8 %shift2, 119
|
|
%bw1 = add i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_xor_add_fail(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_xor_add_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = shl i8 [[X:%.*]], 1
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = shl i8 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[BW2:%.*]] = xor i8 [[SHIFT2]], 119
|
|
; CHECK-NEXT: [[BW1:%.*]] = add i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 1
|
|
%shift2 = shl i8 %y, 1
|
|
%bw2 = xor i8 %shift2, 119
|
|
%bw1 = add i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @lshr_or_and(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @lshr_or_and(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X:%.*]], -64
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = lshr i8 [[TMP2]], 5
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, 5
|
|
%shift2 = lshr i8 %y, 5
|
|
%bw2 = or i8 %shift1, 198
|
|
%bw1 = and i8 %bw2, %shift2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @lshr_or_or_fail(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @lshr_or_or_fail(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], 5
|
|
; CHECK-NEXT: [[BW1:%.*]] = or i8 [[TMP2]], -58
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, 5
|
|
%shift2 = lshr i8 %y, 5
|
|
%bw2 = or i8 %shift2, 198
|
|
%bw1 = or i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define <2 x i8> @shl_xor_and(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @shl_xor_and(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[Y:%.*]], <i8 11, i8 poison>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i8> [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = shl <2 x i8> [[TMP2]], <i8 2, i8 undef>
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = shl <2 x i8> %x, <i8 2, i8 undef>
|
|
%shift2 = shl <2 x i8> %y, <i8 2, i8 undef>
|
|
%bw2 = xor <2 x i8> %shift2, <i8 44, i8 undef>
|
|
%bw1 = and <2 x i8> %bw2, %shift1
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define <2 x i8> @shl_xor_and_fail(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @shl_xor_and_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = shl <2 x i8> [[X:%.*]], <i8 2, i8 undef>
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 undef, i8 2>
|
|
; CHECK-NEXT: [[BW2:%.*]] = xor <2 x i8> [[SHIFT2]], <i8 44, i8 undef>
|
|
; CHECK-NEXT: [[BW1:%.*]] = and <2 x i8> [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = shl <2 x i8> %x, <i8 2, i8 undef>
|
|
%shift2 = shl <2 x i8> %y, <i8 undef, i8 2>
|
|
%bw2 = xor <2 x i8> %shift2, <i8 44, i8 undef>
|
|
%bw1 = and <2 x i8> %shift1, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define i8 @lshr_or_or_no_const(i8 %x, i8 %y, i8 %sh, i8 %mask) {
|
|
; CHECK-LABEL: @lshr_or_or_no_const(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], [[SH:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = or i8 [[TMP2]], [[MASK:%.*]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, %sh
|
|
%shift2 = lshr i8 %y, %sh
|
|
%bw2 = or i8 %shift2, %mask
|
|
%bw1 = or i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @lshr_or_or_no_const_fail(i8 %x, i8 %y, i8 %sh, i8 %mask) {
|
|
; CHECK-LABEL: @lshr_or_or_no_const_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = shl i8 [[X:%.*]], [[SH:%.*]]
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], [[SH]]
|
|
; CHECK-NEXT: [[BW2:%.*]] = or i8 [[SHIFT2]], [[MASK:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = or i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, %sh
|
|
%shift2 = lshr i8 %y, %sh
|
|
%bw2 = or i8 %shift2, %mask
|
|
%bw1 = or i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_xor_xor_no_const(i8 %x, i8 %y, i8 %sh, i8 %mask) {
|
|
; CHECK-LABEL: @shl_xor_xor_no_const(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shl i8 [[TMP1]], [[SH:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = xor i8 [[TMP2]], [[MASK:%.*]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, %sh
|
|
%shift2 = shl i8 %y, %sh
|
|
%bw2 = xor i8 %shift2, %mask
|
|
%bw1 = xor i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_xor_and_no_const_fail(i8 %x, i8 %y, i8 %sh, i8 %mask) {
|
|
; CHECK-LABEL: @shl_xor_and_no_const_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = shl i8 [[X:%.*]], [[SH:%.*]]
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = shl i8 [[Y:%.*]], [[SH]]
|
|
; CHECK-NEXT: [[BW2:%.*]] = xor i8 [[SHIFT2]], [[MASK:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = and i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, %sh
|
|
%shift2 = shl i8 %y, %sh
|
|
%bw2 = xor i8 %shift2, %mask
|
|
%bw1 = and i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define <2 x i8> @shl_and_and_no_const(<2 x i8> %x, <2 x i8> %y, <2 x i8> %sh, <2 x i8> %mask) {
|
|
; CHECK-LABEL: @shl_and_and_no_const(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shl <2 x i8> [[TMP1]], [[SH:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = and <2 x i8> [[TMP2]], [[MASK:%.*]]
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = shl <2 x i8> %x, %sh
|
|
%shift2 = shl <2 x i8> %y, %sh
|
|
%bw2 = and <2 x i8> %shift2, %mask
|
|
%bw1 = and <2 x i8> %shift1, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define i8 @shl_add_add_no_const(i8 %x, i8 %y, i8 %sh, i8 %mask) {
|
|
; CHECK-LABEL: @shl_add_add_no_const(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shl i8 [[TMP1]], [[SH:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = add i8 [[TMP2]], [[MASK:%.*]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, %sh
|
|
%shift2 = shl i8 %y, %sh
|
|
%bw2 = add i8 %shift2, %mask
|
|
%bw1 = add i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @lshr_add_add_no_const_fail(i8 %x, i8 %y, i8 %sh, i8 %mask) {
|
|
; CHECK-LABEL: @lshr_add_add_no_const_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], [[SH:%.*]]
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], [[SH]]
|
|
; CHECK-NEXT: [[BW2:%.*]] = add i8 [[SHIFT2]], [[MASK:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = add i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, %sh
|
|
%shift2 = lshr i8 %y, %sh
|
|
%bw2 = add i8 %shift2, %mask
|
|
%bw1 = add i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define <2 x i8> @lshr_add_and(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @lshr_add_and(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[Y:%.*]], <i8 -8, i8 16>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i8> [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = lshr <2 x i8> [[TMP2]], <i8 3, i8 4>
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = lshr <2 x i8> %x, <i8 3, i8 4>
|
|
%shift2 = lshr <2 x i8> %y, <i8 3, i8 4>
|
|
%bw2 = add <2 x i8> %shift2, <i8 255, i8 1>
|
|
%bw1 = and <2 x i8> %shift1, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define <2 x i8> @lshr_add_or_fail_dif_masks(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @lshr_add_or_fail_dif_masks(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 3, i8 4>
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr <2 x i8> [[Y:%.*]], <i8 undef, i8 3>
|
|
; CHECK-NEXT: [[BW2:%.*]] = add <2 x i8> [[SHIFT2]], <i8 -1, i8 1>
|
|
; CHECK-NEXT: [[BW1:%.*]] = and <2 x i8> [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = lshr <2 x i8> %x, <i8 3, i8 4>
|
|
%shift2 = lshr <2 x i8> %y, <i8 undef, i8 3>
|
|
%bw2 = add <2 x i8> %shift2, <i8 255, i8 1>
|
|
%bw1 = and <2 x i8> %shift1, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define <2 x i8> @shl_or_or_good_mask(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @shl_or_or_good_mask(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i8> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shl <2 x i8> [[TMP1]], <i8 1, i8 1>
|
|
; CHECK-NEXT: [[BW1:%.*]] = or <2 x i8> [[TMP2]], <i8 18, i8 24>
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = shl <2 x i8> %x, <i8 1, i8 1>
|
|
%shift2 = shl <2 x i8> %y, <i8 1, i8 1>
|
|
%bw2 = or <2 x i8> %shift2, <i8 18, i8 24>
|
|
%bw1 = or <2 x i8> %shift1, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define <2 x i8> @shl_or_or_fail_bad_mask(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @shl_or_or_fail_bad_mask(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i8> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shl <2 x i8> [[TMP1]], <i8 1, i8 1>
|
|
; CHECK-NEXT: [[BW1:%.*]] = or <2 x i8> [[TMP2]], <i8 19, i8 24>
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = shl <2 x i8> %x, <i8 1, i8 1>
|
|
%shift2 = shl <2 x i8> %y, <i8 1, i8 1>
|
|
%bw2 = or <2 x i8> %shift2, <i8 19, i8 24>
|
|
%bw1 = or <2 x i8> %shift1, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define i8 @lshr_xor_or_good_mask(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @lshr_xor_or_good_mask(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], 4
|
|
; CHECK-NEXT: [[BW1:%.*]] = or disjoint i8 [[TMP2]], 48
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, 4
|
|
%shift2 = lshr i8 %y, 4
|
|
%bw2 = xor i8 %shift2, 48
|
|
%bw1 = or i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @lshr_xor_or_fail_bad_mask(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @lshr_xor_or_fail_bad_mask(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 6
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 6
|
|
; CHECK-NEXT: [[BW2:%.*]] = xor i8 [[SHIFT2]], -127
|
|
; CHECK-NEXT: [[BW1:%.*]] = or i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, 6
|
|
%shift2 = lshr i8 %y, 6
|
|
%bw2 = xor i8 %shift2, 129
|
|
%bw1 = or i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define <2 x i8> @lshr_or_xor_good_mask(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @lshr_or_xor_good_mask(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i8> [[Y:%.*]], <i8 -64, i8 64>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = xor <2 x i8> [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = lshr <2 x i8> [[TMP2]], <i8 6, i8 6>
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = lshr <2 x i8> %x, <i8 6, i8 6>
|
|
%shift2 = lshr <2 x i8> %y, <i8 6, i8 6>
|
|
%bw2 = or <2 x i8> %shift2, <i8 3, i8 1>
|
|
%bw1 = xor <2 x i8> %shift1, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define <2 x i8> @lshr_or_xor_fail_bad_mask(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @lshr_or_xor_fail_bad_mask(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 6, i8 6>
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr <2 x i8> [[Y:%.*]], <i8 6, i8 6>
|
|
; CHECK-NEXT: [[BW2:%.*]] = or <2 x i8> [[SHIFT2]], <i8 7, i8 1>
|
|
; CHECK-NEXT: [[BW1:%.*]] = xor <2 x i8> [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = lshr <2 x i8> %x, <i8 6, i8 6>
|
|
%shift2 = lshr <2 x i8> %y, <i8 6, i8 6>
|
|
%bw2 = or <2 x i8> %shift2, <i8 7, i8 1>
|
|
%bw1 = xor <2 x i8> %shift1, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define i8 @shl_xor_xor_good_mask(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_xor_xor_good_mask(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shl i8 [[TMP1]], 1
|
|
; CHECK-NEXT: [[BW1:%.*]] = xor i8 [[TMP2]], 88
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 1
|
|
%shift2 = shl i8 %y, 1
|
|
%bw2 = xor i8 %shift2, 88
|
|
%bw1 = xor i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_xor_xor_bad_mask_distribute(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_xor_xor_bad_mask_distribute(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shl i8 [[TMP1]], 1
|
|
; CHECK-NEXT: [[BW1:%.*]] = xor i8 [[TMP2]], -68
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 1
|
|
%shift2 = shl i8 %y, 1
|
|
%bw2 = xor i8 %shift2, 188
|
|
%bw1 = xor i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @shl_add_and(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_add_and(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], 61
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = shl i8 [[TMP2]], 1
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 1
|
|
%shift2 = shl i8 %y, 1
|
|
%bw2 = add i8 %shift2, 123
|
|
%bw1 = and i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @lshr_and_add_fail(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @lshr_and_add_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 1
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[BW2:%.*]] = and i8 [[SHIFT2]], 123
|
|
; CHECK-NEXT: [[BW1:%.*]] = add nuw i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, 1
|
|
%shift2 = lshr i8 %y, 1
|
|
%bw2 = and i8 %shift2, 123
|
|
%bw1 = add i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @lshr_add_or_fail(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @lshr_add_or_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 1
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[BW2:%.*]] = add nuw i8 [[SHIFT2]], 123
|
|
; CHECK-NEXT: [[BW1:%.*]] = or i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, 1
|
|
%shift2 = lshr i8 %y, 1
|
|
%bw2 = add i8 %shift2, 123
|
|
%bw1 = or i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define i8 @lshr_add_xor_fail(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @lshr_add_xor_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = lshr i8 [[X:%.*]], 1
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[BW2:%.*]] = add nuw i8 [[SHIFT2]], 123
|
|
; CHECK-NEXT: [[BW1:%.*]] = xor i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = lshr i8 %x, 1
|
|
%shift2 = lshr i8 %y, 1
|
|
%bw2 = add i8 %shift2, 123
|
|
%bw1 = xor i8 %shift1, %bw2
|
|
ret i8 %bw1
|
|
}
|
|
|
|
define <2 x i8> @lshr_and_add(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @lshr_and_add(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 11, i8 3>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[TMP1]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[BW1:%.*]] = shl <2 x i8> [[TMP2]], <i8 4, i8 5>
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = shl <2 x i8> %x, <i8 4, i8 5>
|
|
%shift2 = shl <2 x i8> %y, <i8 4, i8 5>
|
|
%bw2 = and <2 x i8> %shift1, <i8 189, i8 123>
|
|
%bw1 = add <2 x i8> %shift2, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define <2 x i8> @lshr_or_add_fail(<2 x i8> %x, <2 x i8> %y) {
|
|
; CHECK-LABEL: @lshr_or_add_fail(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = shl <2 x i8> [[X:%.*]], <i8 4, i8 5>
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 4, i8 5>
|
|
; CHECK-NEXT: [[BW2:%.*]] = or <2 x i8> [[SHIFT1]], <i8 -67, i8 123>
|
|
; CHECK-NEXT: [[BW1:%.*]] = add <2 x i8> [[SHIFT2]], [[BW2]]
|
|
; CHECK-NEXT: ret <2 x i8> [[BW1]]
|
|
;
|
|
%shift1 = shl <2 x i8> %x, <i8 4, i8 5>
|
|
%shift2 = shl <2 x i8> %y, <i8 4, i8 5>
|
|
%bw2 = or <2 x i8> %shift1, <i8 189, i8 123>
|
|
%bw1 = add <2 x i8> %shift2, %bw2
|
|
ret <2 x i8> %bw1
|
|
}
|
|
|
|
define i8 @shl_add_and_fail_mismatch_shift(i8 %x, i8 %y) {
|
|
; CHECK-LABEL: @shl_add_and_fail_mismatch_shift(
|
|
; CHECK-NEXT: [[SHIFT1:%.*]] = shl i8 [[X:%.*]], 1
|
|
; CHECK-NEXT: [[SHIFT2:%.*]] = lshr i8 [[Y:%.*]], 1
|
|
; CHECK-NEXT: [[BW2:%.*]] = add nuw i8 [[SHIFT2]], 123
|
|
; CHECK-NEXT: [[BW1:%.*]] = and i8 [[SHIFT1]], [[BW2]]
|
|
; CHECK-NEXT: ret i8 [[BW1]]
|
|
;
|
|
%shift1 = shl i8 %x, 1
|
|
%shift2 = lshr i8 %y, 1
|
|
%bw2 = add i8 %shift2, 123
|
|
%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: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[AND:%.*]] = ashr i8 [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[AND:%.*]] = ashr i8 [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i8> [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[AND:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i8> [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[AND:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i8> [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[AND:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or i8 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = ashr i8 [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or i8 [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = ashr i8 [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or <4 x i8> [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or <4 x i8> [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], <i8 -1, i8 -1, i8 -1, i8 -1>
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or <4 x i8> [[TMP1]], [[X:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = ashr <4 x i8> [[TMP2]], [[SHAMT:%.*]]
|
|
; 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: [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[DOTNOT:%.*]] = ashr i8 [[TMP1]], [[SHAMT:%.*]]
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[DOTNOT]], -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: [[TMP1:%.*]] = xor i8 [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[DOTNOT:%.*]] = ashr i8 [[TMP1]], [[SHAMT:%.*]]
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[DOTNOT]], -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: [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[DOTNOT:%.*]] = ashr <4 x i8> [[TMP1]], [[SHAMT:%.*]]
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor <4 x i8> [[DOTNOT]], <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: [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[DOTNOT:%.*]] = ashr <4 x i8> [[TMP1]], [[SHAMT:%.*]]
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor <4 x i8> [[DOTNOT]], <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: [[TMP1:%.*]] = xor <4 x i8> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: [[DOTNOT:%.*]] = ashr <4 x i8> [[TMP1]], [[SHAMT:%.*]]
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor <4 x i8> [[DOTNOT]], <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 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
|
|
}
|