165 lines
4.9 KiB
LLVM
165 lines
4.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes=instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
|
|
|
|
; Don't do anything for the fully-variable case.
|
|
define i4 @t0(i4 %x, i4 %y, i4 %z) {
|
|
; CHECK-LABEL: @t0(
|
|
; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], [[Z:%.*]]
|
|
; CHECK-NEXT: ret i4 [[I1]]
|
|
;
|
|
%i0 = or i4 %x, %y
|
|
%i1 = xor i4 %i0, %z
|
|
ret i4 %i1
|
|
}
|
|
|
|
; If the second operands are immediate constants, we can perform the fold.
|
|
define i4 @t1(i4 %x) {
|
|
; CHECK-LABEL: @t1(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], 3
|
|
; CHECK-NEXT: [[I1:%.*]] = xor i4 [[TMP1]], 6
|
|
; CHECK-NEXT: ret i4 [[I1]]
|
|
;
|
|
%i0 = or i4 %x, 12 ; 0b1100
|
|
%i1 = xor i4 %i0, 10 ; 0b1010
|
|
ret i4 %i1
|
|
}
|
|
|
|
; Must not have extra uses.
|
|
define i4 @t2(i4 %x) {
|
|
; CHECK-LABEL: @t2(
|
|
; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], -4
|
|
; CHECK-NEXT: call void @use(i4 [[I0]])
|
|
; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], -6
|
|
; CHECK-NEXT: ret i4 [[I1]]
|
|
;
|
|
%i0 = or i4 %x, 12 ; 0b1100
|
|
call void @use(i4 %i0)
|
|
%i1 = xor i4 %i0, 10 ; 0b1010
|
|
ret i4 %i1
|
|
}
|
|
|
|
; Splat constants are fine too.
|
|
define <2 x i4> @t3(<2 x i4> %x) {
|
|
; CHECK-LABEL: @t3(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 3>
|
|
; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 6>
|
|
; CHECK-NEXT: ret <2 x i4> [[I1]]
|
|
;
|
|
%i0 = or <2 x i4> %x, <i4 12, i4 12>
|
|
%i1 = xor <2 x i4> %i0, <i4 10, i4 10>
|
|
ret <2 x i4> %i1
|
|
}
|
|
|
|
; Non-splat constants are fine too.
|
|
define <2 x i4> @t4(<2 x i4> %x) {
|
|
; CHECK-LABEL: @t4(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 5>
|
|
; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 6>
|
|
; CHECK-NEXT: ret <2 x i4> [[I1]]
|
|
;
|
|
%i0 = or <2 x i4> %x, <i4 12, i4 10>
|
|
%i1 = xor <2 x i4> %i0, <i4 10, i4 12>
|
|
ret <2 x i4> %i1
|
|
}
|
|
|
|
; Partially-undef constants are fine.
|
|
define <2 x i4> @t5(<2 x i4> %x) {
|
|
; CHECK-LABEL: @t5(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef>
|
|
; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 undef>
|
|
; CHECK-NEXT: ret <2 x i4> [[I1]]
|
|
;
|
|
%i0 = or <2 x i4> %x, <i4 12, i4 12>
|
|
%i1 = xor <2 x i4> %i0, <i4 10, i4 undef>
|
|
ret <2 x i4> %i1
|
|
}
|
|
define <2 x i4> @t6(<2 x i4> %x) {
|
|
; CHECK-LABEL: @t6(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 0>
|
|
; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 5>
|
|
; CHECK-NEXT: ret <2 x i4> [[I1]]
|
|
;
|
|
%i0 = or <2 x i4> %x, <i4 12, i4 undef>
|
|
%i1 = xor <2 x i4> %i0, <i4 10, i4 10>
|
|
ret <2 x i4> %i1
|
|
}
|
|
define <2 x i4> @t7(<2 x i4> %x) {
|
|
; CHECK-LABEL: @t7(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef>
|
|
; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 undef>
|
|
; CHECK-NEXT: ret <2 x i4> [[I1]]
|
|
;
|
|
%i0 = or <2 x i4> %x, <i4 12, i4 undef>
|
|
%i1 = xor <2 x i4> %i0, <i4 10, i4 undef>
|
|
ret <2 x i4> %i1
|
|
}
|
|
|
|
; Partially-poison constants are fine.
|
|
define <2 x i4> @t8(<2 x i4> %x) {
|
|
; CHECK-LABEL: @t8(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef>
|
|
; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 poison>
|
|
; CHECK-NEXT: ret <2 x i4> [[I1]]
|
|
;
|
|
%i0 = or <2 x i4> %x, <i4 12, i4 12>
|
|
%i1 = xor <2 x i4> %i0, <i4 10, i4 poison>
|
|
ret <2 x i4> %i1
|
|
}
|
|
define <2 x i4> @t9(<2 x i4> %x) {
|
|
; CHECK-LABEL: @t9(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 0>
|
|
; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 5>
|
|
; CHECK-NEXT: ret <2 x i4> [[I1]]
|
|
;
|
|
%i0 = or <2 x i4> %x, <i4 12, i4 poison>
|
|
%i1 = xor <2 x i4> %i0, <i4 10, i4 10>
|
|
ret <2 x i4> %i1
|
|
}
|
|
define <2 x i4> @t10(<2 x i4> %x) {
|
|
; CHECK-LABEL: @t10(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef>
|
|
; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 poison>
|
|
; CHECK-NEXT: ret <2 x i4> [[I1]]
|
|
;
|
|
%i0 = or <2 x i4> %x, <i4 12, i4 poison>
|
|
%i1 = xor <2 x i4> %i0, <i4 10, i4 poison>
|
|
ret <2 x i4> %i1
|
|
}
|
|
|
|
; Do not deal with general constant expressions.
|
|
@G = external global i32
|
|
@G2 = external global i32
|
|
define i4 @t11(i4 %x) {
|
|
; CHECK-LABEL: @t11(
|
|
; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], -4
|
|
; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], ptrtoint (ptr @G2 to i4)
|
|
; CHECK-NEXT: ret i4 [[I1]]
|
|
;
|
|
%i0 = or i4 %x, 12
|
|
%i1 = xor i4 %i0, ptrtoint (ptr @G2 to i4)
|
|
ret i4 %i1
|
|
}
|
|
define i4 @t12(i4 %x) {
|
|
; CHECK-LABEL: @t12(
|
|
; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], ptrtoint (ptr @G to i4)
|
|
; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], -6
|
|
; CHECK-NEXT: ret i4 [[I1]]
|
|
;
|
|
%i0 = or i4 %x, ptrtoint (ptr @G to i4)
|
|
%i1 = xor i4 %i0, 10
|
|
ret i4 %i1
|
|
}
|
|
define i4 @t13(i4 %x) {
|
|
; CHECK-LABEL: @t13(
|
|
; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], ptrtoint (ptr @G to i4)
|
|
; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], ptrtoint (ptr @G2 to i4)
|
|
; CHECK-NEXT: ret i4 [[I1]]
|
|
;
|
|
%i0 = or i4 %x, ptrtoint (ptr @G to i4)
|
|
%i1 = xor i4 %i0, ptrtoint (ptr @G2 to i4)
|
|
ret i4 %i1
|
|
}
|
|
|
|
declare void @use(i4)
|