Files
clang-p2996/llvm/test/Transforms/InstSimplify/and.ll
Sanjay Patel e36d351d19 [InstSimplify] (x | y) & (x | !y) --> x
https://alive2.llvm.org/ce/z/QagQMn

This fold is handled by instcombine via SimplifyUsingDistributiveLaws(),
but we are missing the sibliing fold for 'logical and' (implemented with
'select'). Retrofitting the code in instcombine looks much harder
than just adding a small adjustment here, and this is potentially more
efficient and beneficial to other passes.
2021-10-06 12:31:25 -04:00

134 lines
3.3 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instsimplify -S | FileCheck %s
define i32 @poison(i32 %x) {
; CHECK-LABEL: @poison(
; CHECK-NEXT: ret i32 poison
;
%v = and i32 %x, poison
ret i32 %v
}
; (X | Y) & (X | ~Y) --> X (commuted 8 ways)
define i8 @or_or_not_commute0(i8 %x, i8 %y) {
; CHECK-LABEL: @or_or_not_commute0(
; CHECK-NEXT: ret i8 [[X:%.*]]
;
%ynot = xor i8 %y, -1
%xory = or i8 %x, %y
%xorynot = or i8 %x, %ynot
%and = and i8 %xory, %xorynot
ret i8 %and
}
define <2 x i5> @or_or_not_commute1(<2 x i5> %x, <2 x i5> %y) {
; CHECK-LABEL: @or_or_not_commute1(
; CHECK-NEXT: ret <2 x i5> [[X:%.*]]
;
%ynot = xor <2 x i5> %y, <i5 -1, i5 -1>
%xory = or <2 x i5> %x, %y
%xorynot = or <2 x i5> %x, %ynot
%and = and <2 x i5> %xorynot, %xory
ret <2 x i5> %and
}
define <2 x i8> @or_or_not_commute2(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @or_or_not_commute2(
; CHECK-NEXT: ret <2 x i8> [[X:%.*]]
;
%ynot = xor <2 x i8> %y, <i8 poison, i8 -1>
%xory = or <2 x i8> %x, %y
%xorynot = or <2 x i8> %ynot, %x
%and = and <2 x i8> %xory, %xorynot
ret <2 x i8> %and
}
define i8 @or_or_not_commute3(i8 %x, i8 %y) {
; CHECK-LABEL: @or_or_not_commute3(
; CHECK-NEXT: ret i8 [[X:%.*]]
;
%ynot = xor i8 %y, -1
%xory = or i8 %x, %y
%xorynot = or i8 %ynot, %x
%and = and i8 %xorynot, %xory
ret i8 %and
}
define i8 @or_or_not_commute4(i8 %x, i8 %y) {
; CHECK-LABEL: @or_or_not_commute4(
; CHECK-NEXT: ret i8 [[X:%.*]]
;
%ynot = xor i8 %y, -1
%xory = or i8 %y, %x
%xorynot = or i8 %x, %ynot
%and = and i8 %xory, %xorynot
ret i8 %and
}
define i8 @or_or_not_commute5(i8 %x, i8 %y) {
; CHECK-LABEL: @or_or_not_commute5(
; CHECK-NEXT: ret i8 [[X:%.*]]
;
%ynot = xor i8 %y, -1
%xory = or i8 %y, %x
%xorynot = or i8 %x, %ynot
%and = and i8 %xorynot, %xory
ret i8 %and
}
define i8 @or_or_not_commute6(i8 %x, i8 %y) {
; CHECK-LABEL: @or_or_not_commute6(
; CHECK-NEXT: ret i8 [[X:%.*]]
;
%ynot = xor i8 %y, -1
%xory = or i8 %y, %x
%xorynot = or i8 %ynot, %x
%and = and i8 %xory, %xorynot
ret i8 %and
}
define i8 @or_or_not_commute7(i8 %x, i8 %y) {
; CHECK-LABEL: @or_or_not_commute7(
; CHECK-NEXT: ret i8 [[X:%.*]]
;
%ynot = xor i8 %y, -1
%xory = or i8 %y, %x
%xorynot = or i8 %ynot, %x
%and = and i8 %xorynot, %xory
ret i8 %and
}
; negative test - wrong logic op
define i8 @or_xor_not(i8 %x, i8 %y) {
; CHECK-LABEL: @or_xor_not(
; CHECK-NEXT: [[YNOT:%.*]] = xor i8 [[Y:%.*]], -1
; CHECK-NEXT: [[XXORY:%.*]] = xor i8 [[Y]], [[X:%.*]]
; CHECK-NEXT: [[XORYNOT:%.*]] = or i8 [[X]], [[YNOT]]
; CHECK-NEXT: [[AND:%.*]] = and i8 [[XORYNOT]], [[XXORY]]
; CHECK-NEXT: ret i8 [[AND]]
;
%ynot = xor i8 %y, -1
%xxory = xor i8 %y, %x
%xorynot = or i8 %x, %ynot
%and = and i8 %xorynot, %xxory
ret i8 %and
}
; negative test - must have common operands
define i8 @or_or_not_no_common_op(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @or_or_not_no_common_op(
; CHECK-NEXT: [[XORZ:%.*]] = or i8 [[Z:%.*]], [[X:%.*]]
; CHECK-NEXT: [[YNOT:%.*]] = xor i8 [[Y:%.*]], -1
; CHECK-NEXT: [[XORYNOT:%.*]] = or i8 [[X]], [[YNOT]]
; CHECK-NEXT: [[AND:%.*]] = and i8 [[XORYNOT]], [[XORZ]]
; CHECK-NEXT: ret i8 [[AND]]
;
%xorz = or i8 %z, %x
%ynot = xor i8 %y, -1
%xorynot = or i8 %x, %ynot
%and = and i8 %xorynot, %xorz
ret i8 %and
}