[llvm] r358552 - Revert "Temporarily Revert "Add basic loop fusion pass.""

Eric Christopher via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 16 21:53:01 PDT 2019


Added: llvm/trunk/test/Transforms/InstSimplify/floating-point-arithmetic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/floating-point-arithmetic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/floating-point-arithmetic.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/floating-point-arithmetic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,1269 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) {
+; CHECK-LABEL: @fsub_negzero_vec_undef_elts(
+; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
+;
+  %r = fsub nsz <2 x float> %x, <float undef, float -0.0>
+  ret <2 x float> %r
+}
+
+; fsub -0.0, (fsub -0.0, X) ==> X
+define float @fsub_-0_-0_x(float %a) {
+; CHECK-LABEL: @fsub_-0_-0_x(
+; CHECK-NEXT:    ret float [[A:%.*]]
+;
+  %t1 = fsub float -0.0, %a
+  %ret = fsub float -0.0, %t1
+  ret float %ret
+}
+
+define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) {
+; CHECK-LABEL: @fsub_-0_-0_x_vec(
+; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
+;
+  %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a
+  %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1
+  ret <2 x float> %ret
+}
+
+define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) {
+; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts(
+; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
+;
+  %t1 = fsub <2 x float> <float undef, float -0.0>, %a
+  %ret = fsub <2 x float> <float -0.0, float undef>, %t1
+  ret <2 x float> %ret
+}
+
+; fsub 0.0, (fsub -0.0, X) != X
+define float @fsub_0_-0_x(float %a) {
+; CHECK-LABEL: @fsub_0_-0_x(
+; CHECK-NEXT:    [[T1:%.*]] = fsub float 0.000000e+00, [[A:%.*]]
+; CHECK-NEXT:    [[RET:%.*]] = fsub float -0.000000e+00, [[T1]]
+; CHECK-NEXT:    ret float [[RET]]
+;
+  %t1 = fsub float 0.0, %a
+  %ret = fsub float -0.0, %t1
+  ret float %ret
+}
+
+; fsub -0.0, (fsub 0.0, X) != X
+define float @fsub_-0_0_x(float %a) {
+; CHECK-LABEL: @fsub_-0_0_x(
+; CHECK-NEXT:    [[T1:%.*]] = fsub float -0.000000e+00, [[A:%.*]]
+; CHECK-NEXT:    [[RET:%.*]] = fsub float 0.000000e+00, [[T1]]
+; CHECK-NEXT:    ret float [[RET]]
+;
+  %t1 = fsub float -0.0, %a
+  %ret = fsub float 0.0, %t1
+  ret float %ret
+}
+
+; fsub X, 0 ==> X
+define float @fsub_x_0(float %x) {
+; CHECK-LABEL: @fsub_x_0(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %r = fsub float %x, 0.0
+  ret float %r
+}
+
+define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) {
+; CHECK-LABEL: @fsub_x_0_vec_undef(
+; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
+;
+  %r = fsub <2 x float> %x, <float undef, float 0.0>
+  ret <2 x float> %r
+}
+
+; fadd X, -0 ==> X
+define float @fadd_x_n0(float %a) {
+; CHECK-LABEL: @fadd_x_n0(
+; CHECK-NEXT:    ret float [[A:%.*]]
+;
+  %ret = fadd float %a, -0.0
+  ret float %ret
+}
+
+define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) {
+; CHECK-LABEL: @fadd_x_n0_vec_undef_elt(
+; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
+;
+  %ret = fadd <2 x float> %a, <float -0.0, float undef>
+  ret <2 x float> %ret
+}
+
+; fmul X, 1.0 ==> X
+define double @fmul_X_1(double %a) {
+; CHECK-LABEL: @fmul_X_1(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %b = fmul double 1.0, %a
+  ret double %b
+}
+
+; PR2642
+define <4 x float> @fmul_X_1_vec(<4 x float> %x) {
+; CHECK-LABEL: @fmul_X_1_vec(
+; CHECK-NEXT:    ret <4 x float> [[X:%.*]]
+;
+  %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
+  ret <4 x float> %m
+}
+
+; fdiv X, 1.0 ==> X
+define float @fdiv_x_1(float %a) {
+; CHECK-LABEL: @fdiv_x_1(
+; CHECK-NEXT:    ret float [[A:%.*]]
+;
+  %ret = fdiv float %a, 1.0
+  ret float %ret
+}
+
+; We can't optimize away the fadd in this test because the input
+; value to the function and subsequently to the fadd may be -0.0.
+; In that one special case, the result of the fadd should be +0.0
+; rather than the first parameter of the fadd.
+
+; Fragile test warning: We need 6 sqrt calls to trigger the bug
+; because the internal logic has a magic recursion limit of 6.
+; This is presented without any explanation or ability to customize.
+
+declare float @sqrtf(float)
+
+define float @PR22688(float %x) {
+; CHECK-LABEL: @PR22688(
+; CHECK-NEXT:    [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]])
+; CHECK-NEXT:    [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]])
+; CHECK-NEXT:    [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]])
+; CHECK-NEXT:    [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]])
+; CHECK-NEXT:    [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00
+; CHECK-NEXT:    ret float [[TMP7]]
+;
+  %1 = call float @sqrtf(float %x)
+  %2 = call float @sqrtf(float %1)
+  %3 = call float @sqrtf(float %2)
+  %4 = call float @sqrtf(float %3)
+  %5 = call float @sqrtf(float %4)
+  %6 = call float @sqrtf(float %5)
+  %7 = fadd float %6, 0.0
+  ret float %7
+}
+
+declare float @llvm.fabs.f32(float)
+declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
+declare float @llvm.sqrt.f32(float)
+
+define float @fabs_select_positive_constants(i32 %c) {
+; CHECK-LABEL: @fabs_select_positive_constants(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
+; CHECK-NEXT:    ret float [[SELECT]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, float 1.0, float 2.0
+  %fabs = call float @llvm.fabs.f32(float %select)
+  ret float %fabs
+}
+
+define <2 x float> @fabs_select_positive_constants_vector(i32 %c) {
+; CHECK-LABEL: @fabs_select_positive_constants_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00>
+; CHECK-NEXT:    ret <2 x float> [[SELECT]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
+  ret <2 x float> %fabs
+}
+
+define float @fabs_select_constant_variable(i32 %c, float %x) {
+; CHECK-LABEL: @fabs_select_constant_variable(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, float 1.0, float %x
+  %fabs = call float @llvm.fabs.f32(float %select)
+  ret float %fabs
+}
+
+define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) {
+; CHECK-LABEL: @fabs_select_constant_variable_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]]
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
+; CHECK-NEXT:    ret <2 x float> [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
+  ret <2 x float> %fabs
+}
+
+define float @fabs_select_neg0_pos0(i32 %c) {
+; CHECK-LABEL: @fabs_select_neg0_pos0(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, float -0.0, float 0.0
+  %fabs = call float @llvm.fabs.f32(float %select)
+  ret float %fabs
+}
+
+define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) {
+; CHECK-LABEL: @fabs_select_neg0_pos0_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
+; CHECK-NEXT:    ret <2 x float> [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0>
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
+  ret <2 x float> %fabs
+}
+
+define float @fabs_select_neg0_neg1(i32 %c) {
+; CHECK-LABEL: @fabs_select_neg0_neg1(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, float -0.0, float -1.0
+  %fabs = call float @llvm.fabs.f32(float %select)
+  ret float %fabs
+}
+
+define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) {
+; CHECK-LABEL: @fabs_select_neg0_neg1_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> <float -1.000000e+00, float -1.000000e+00>
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
+; CHECK-NEXT:    ret <2 x float> [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0>
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
+  ret <2 x float> %fabs
+}
+
+define float @fabs_select_nan_nan(i32 %c) {
+; CHECK-LABEL: @fabs_select_nan_nan(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000
+; CHECK-NEXT:    ret float [[SELECT]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000
+  %fabs = call float @llvm.fabs.f32(float %select)
+  ret float %fabs
+}
+
+define <2 x float> @fabs_select_nan_nan_vector(i32 %c) {
+; CHECK-LABEL: @fabs_select_nan_nan_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
+; CHECK-NEXT:    ret <2 x float> [[SELECT]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
+  ret <2 x float> %fabs
+}
+
+define float @fabs_select_negnan_nan(i32 %c) {
+; CHECK-LABEL: @fabs_select_negnan_nan(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000
+  %fabs = call float @llvm.fabs.f32(float %select)
+  ret float %fabs
+}
+
+define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) {
+; CHECK-LABEL: @fabs_select_negnan_nan_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
+; CHECK-NEXT:    ret <2 x float> [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
+  ret <2 x float> %fabs
+}
+
+define float @fabs_select_negnan_negnan(i32 %c) {
+; CHECK-LABEL: @fabs_select_negnan_negnan(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000
+  %fabs = call float @llvm.fabs.f32(float %select)
+  ret float %fabs
+}
+
+define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) {
+; CHECK-LABEL: @fabs_select_negnan_negnan_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
+; CHECK-NEXT:    ret <2 x float> [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
+  ret <2 x float> %fabs
+}
+
+define float @fabs_select_negnan_negzero(i32 %c) {
+; CHECK-LABEL: @fabs_select_negnan_negzero(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0
+  %fabs = call float @llvm.fabs.f32(float %select)
+  ret float %fabs
+}
+
+define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) {
+; CHECK-LABEL: @fabs_select_negnan_negzero_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00>
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
+; CHECK-NEXT:    ret <2 x float> [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0>
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
+  ret <2 x float> %fabs
+}
+
+define float @fabs_select_negnan_zero(i32 %c) {
+; CHECK-LABEL: @fabs_select_negnan_zero(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0
+  %fabs = call float @llvm.fabs.f32(float %select)
+  ret float %fabs
+}
+
+define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) {
+; CHECK-LABEL: @fabs_select_negnan_zero_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer
+; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
+; CHECK-NEXT:    ret <2 x float> [[FABS]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0>
+  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
+  ret <2 x float> %fabs
+}
+
+; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with
+; an arbitrary sign bit.
+define float @fabs_sqrt(float %a) {
+; CHECK-LABEL: @fabs_sqrt(
+; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %sqrt = call float @llvm.sqrt.f32(float %a)
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+; The fabs can't be eliminated because the nnan sqrt may still return -0.
+define float @fabs_sqrt_nnan(float %a) {
+; CHECK-LABEL: @fabs_sqrt_nnan(
+; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %sqrt = call nnan float @llvm.sqrt.f32(float %a)
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+; The fabs can't be eliminated because the nsz sqrt may still return NaN.
+define float @fabs_sqrt_nsz(float %a) {
+; CHECK-LABEL: @fabs_sqrt_nsz(
+; CHECK-NEXT:    [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]])
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %sqrt = call nsz float @llvm.sqrt.f32(float %a)
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+; The fabs can be eliminated because we're nsz and nnan.
+define float @fabs_sqrt_nnan_nsz(float %a) {
+; CHECK-LABEL: @fabs_sqrt_nnan_nsz(
+; CHECK-NEXT:    [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]])
+; CHECK-NEXT:    ret float [[SQRT]]
+;
+  %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a)
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+; The second fabs can be eliminated because the operand to sqrt cannot be -0.
+define float @fabs_sqrt_nnan_fabs(float %a) {
+; CHECK-LABEL: @fabs_sqrt_nnan_fabs(
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
+; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]])
+; CHECK-NEXT:    ret float [[SQRT]]
+;
+  %b = call float @llvm.fabs.f32(float %a)
+  %sqrt = call nnan float @llvm.sqrt.f32(float %b)
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+define float @fabs_select_positive_constants_vector_extract(i32 %c) {
+; CHECK-LABEL: @fabs_select_positive_constants_vector_extract(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00>
+; CHECK-NEXT:    [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0
+; CHECK-NEXT:    ret float [[EXTRACT]]
+;
+  %cmp = icmp eq i32 %c, 0
+  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
+  %extract = extractelement <2 x float> %select, i32 0
+  %fabs = call float @llvm.fabs.f32(float %extract)
+  ret float %fabs
+}
+
+declare float @llvm.minnum.f32(float, float)
+declare float @llvm.maxnum.f32(float, float)
+declare double @llvm.minnum.f64(double, double)
+declare double @llvm.maxnum.f64(double, double)
+declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>)
+declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)
+
+; From the LangRef for minnum/maxnum:
+; "If either operand is a NaN, returns the other non-NaN operand."
+
+define double @maxnum_nan_op0(double %x) {
+; CHECK-LABEL: @maxnum_nan_op0(
+; CHECK-NEXT:    ret double [[X:%.*]]
+;
+  %r = call double @llvm.maxnum.f64(double 0x7ff8000000000000, double %x)
+  ret double %r
+}
+
+define double @maxnum_nan_op1(double %x) {
+; CHECK-LABEL: @maxnum_nan_op1(
+; CHECK-NEXT:    ret double [[X:%.*]]
+;
+  %r = call double @llvm.maxnum.f64(double %x, double 0x7ff800000000dead)
+  ret double %r
+}
+
+define double @minnum_nan_op0(double %x) {
+; CHECK-LABEL: @minnum_nan_op0(
+; CHECK-NEXT:    ret double [[X:%.*]]
+;
+  %r = call double @llvm.minnum.f64(double 0x7ff8000dead00000, double %x)
+  ret double %r
+}
+
+define double @minnum_nan_op1(double %x) {
+; CHECK-LABEL: @minnum_nan_op1(
+; CHECK-NEXT:    ret double [[X:%.*]]
+;
+  %r = call double @llvm.minnum.f64(double %x, double 0x7ff800dead00dead)
+  ret double %r
+}
+
+define <2 x double> @maxnum_nan_op0_vec(<2 x double> %x) {
+; CHECK-LABEL: @maxnum_nan_op0_vec(
+; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
+;
+  %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x)
+  ret <2 x double> %r
+}
+
+define <2 x double> @maxnum_nan_op1_vec(<2 x double> %x) {
+; CHECK-LABEL: @maxnum_nan_op1_vec(
+; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
+;
+  %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>)
+  ret <2 x double> %r
+}
+
+define <2 x double> @minnum_nan_op0_vec(<2 x double> %x) {
+; CHECK-LABEL: @minnum_nan_op0_vec(
+; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
+;
+  %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x)
+  ret <2 x double> %r
+}
+
+define <2 x double> @minnum_nan_op1_vec(<2 x double> %x) {
+; CHECK-LABEL: @minnum_nan_op1_vec(
+; CHECK-NEXT:    ret <2 x double> [[X:%.*]]
+;
+  %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>)
+  ret <2 x double> %r
+}
+
+define float @maxnum_undef_op1(float %x) {
+; CHECK-LABEL: @maxnum_undef_op1(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %val = call float @llvm.maxnum.f32(float %x, float undef)
+  ret float %val
+}
+
+define float @maxnum_undef_op0(float %x) {
+; CHECK-LABEL: @maxnum_undef_op0(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %val = call float @llvm.maxnum.f32(float undef, float %x)
+  ret float %val
+}
+
+define float @minnum_undef_op1(float %x) {
+; CHECK-LABEL: @minnum_undef_op1(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %val = call float @llvm.minnum.f32(float %x, float undef)
+  ret float %val
+}
+
+define float @minnum_undef_op0(float %x) {
+; CHECK-LABEL: @minnum_undef_op0(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %val = call float @llvm.minnum.f32(float undef, float %x)
+  ret float %val
+}
+
+define float @minnum_undef_undef(float %x) {
+; CHECK-LABEL: @minnum_undef_undef(
+; CHECK-NEXT:    ret float undef
+;
+  %val = call float @llvm.minnum.f32(float undef, float undef)
+  ret float %val
+}
+
+define float @maxnum_undef_undef(float %x) {
+; CHECK-LABEL: @maxnum_undef_undef(
+; CHECK-NEXT:    ret float undef
+;
+  %val = call float @llvm.maxnum.f32(float undef, float undef)
+  ret float %val
+}
+
+define float @minnum_same_args(float %x) {
+; CHECK-LABEL: @minnum_same_args(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %y = call float @llvm.minnum.f32(float %x, float %x)
+  ret float %y
+}
+
+define float @maxnum_same_args(float %x) {
+; CHECK-LABEL: @maxnum_same_args(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %y = call float @llvm.maxnum.f32(float %x, float %x)
+  ret float %y
+}
+
+define float @minnum_x_minnum_x_y(float %x, float %y) {
+; CHECK-LABEL: @minnum_x_minnum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.minnum.f32(float %x, float %y)
+  %b = call float @llvm.minnum.f32(float %x, float %a)
+  ret float %b
+}
+
+define float @minnum_y_minnum_x_y(float %x, float %y) {
+; CHECK-LABEL: @minnum_y_minnum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.minnum.f32(float %x, float %y)
+  %b = call float @llvm.minnum.f32(float %y, float %a)
+  ret float %b
+}
+
+define float @minnum_x_y_minnum_x(float %x, float %y) {
+; CHECK-LABEL: @minnum_x_y_minnum_x(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.minnum.f32(float %x, float %y)
+  %b = call float @llvm.minnum.f32(float %a, float %x)
+  ret float %b
+}
+
+define float @minnum_x_y_minnum_y(float %x, float %y) {
+; CHECK-LABEL: @minnum_x_y_minnum_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.minnum.f32(float %x, float %y)
+  %b = call float @llvm.minnum.f32(float %a, float %y)
+  ret float %b
+}
+
+; negative test
+
+define float @minnum_z_minnum_x_y(float %x, float %y, float %z) {
+; CHECK-LABEL: @minnum_z_minnum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[A]])
+; CHECK-NEXT:    ret float [[B]]
+;
+  %a = call float @llvm.minnum.f32(float %x, float %y)
+  %b = call float @llvm.minnum.f32(float %z, float %a)
+  ret float %b
+}
+
+; negative test
+
+define float @minnum_x_y_minnum_z(float %x, float %y, float %z) {
+; CHECK-LABEL: @minnum_x_y_minnum_z(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minnum.f32(float [[A]], float [[Z:%.*]])
+; CHECK-NEXT:    ret float [[B]]
+;
+  %a = call float @llvm.minnum.f32(float %x, float %y)
+  %b = call float @llvm.minnum.f32(float %a, float %z)
+  ret float %b
+}
+
+; minnum(X, -INF) --> -INF
+
+define float @minnum_neginf(float %x) {
+; CHECK-LABEL: @minnum_neginf(
+; CHECK-NEXT:    ret float 0xFFF0000000000000
+;
+  %val = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000)
+  ret float %val
+}
+
+define <2 x double> @minnum_neginf_commute_vec(<2 x double> %x) {
+; CHECK-LABEL: @minnum_neginf_commute_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>
+;
+  %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x)
+  ret <2 x double> %r
+}
+
+; negative test
+
+define float @minnum_inf(float %x) {
+; CHECK-LABEL: @minnum_inf(
+; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.minnum.f32(float 0x7FF0000000000000, float [[X:%.*]])
+; CHECK-NEXT:    ret float [[VAL]]
+;
+  %val = call float @llvm.minnum.f32(float 0x7FF0000000000000, float %x)
+  ret float %val
+}
+define float @maxnum_x_maxnum_x_y(float %x, float %y) {
+; CHECK-LABEL: @maxnum_x_maxnum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.maxnum.f32(float %x, float %y)
+  %b = call float @llvm.maxnum.f32(float %x, float %a)
+  ret float %b
+}
+
+define float @maxnum_y_maxnum_x_y(float %x, float %y) {
+; CHECK-LABEL: @maxnum_y_maxnum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.maxnum.f32(float %x, float %y)
+  %b = call float @llvm.maxnum.f32(float %y, float %a)
+  ret float %b
+}
+
+define float @maxnum_x_y_maxnum_x(float %x, float %y) {
+; CHECK-LABEL: @maxnum_x_y_maxnum_x(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.maxnum.f32(float %x, float %y)
+  %b = call float @llvm.maxnum.f32(float %a, float %x)
+  ret float %b
+}
+
+define float @maxnum_x_y_maxnum_y(float %x, float %y) {
+; CHECK-LABEL: @maxnum_x_y_maxnum_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.maxnum.f32(float %x, float %y)
+  %b = call float @llvm.maxnum.f32(float %a, float %y)
+  ret float %b
+}
+
+; negative test
+
+define float @maxnum_z_maxnum_x_y(float %x, float %y, float %z) {
+; CHECK-LABEL: @maxnum_z_maxnum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[A]])
+; CHECK-NEXT:    ret float [[B]]
+;
+  %a = call float @llvm.maxnum.f32(float %x, float %y)
+  %b = call float @llvm.maxnum.f32(float %z, float %a)
+  ret float %b
+}
+
+; negative test
+
+define float @maxnum_x_y_maxnum_z(float %x, float %y, float %z) {
+; CHECK-LABEL: @maxnum_x_y_maxnum_z(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[Z:%.*]])
+; CHECK-NEXT:    ret float [[B]]
+;
+  %a = call float @llvm.maxnum.f32(float %x, float %y)
+  %b = call float @llvm.maxnum.f32(float %a, float %z)
+  ret float %b
+}
+
+; maxnum(X, INF) --> INF
+
+define <2 x double> @maxnum_inf(<2 x double> %x) {
+; CHECK-LABEL: @maxnum_inf(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000>
+;
+  %val = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>)
+  ret <2 x double> %val
+}
+
+define float @maxnum_inf_commute(float %x) {
+; CHECK-LABEL: @maxnum_inf_commute(
+; CHECK-NEXT:    ret float 0x7FF0000000000000
+;
+  %val = call float @llvm.maxnum.f32(float 0x7FF0000000000000, float %x)
+  ret float %val
+}
+
+; negative test
+
+define float @maxnum_neginf(float %x) {
+; CHECK-LABEL: @maxnum_neginf(
+; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float [[X:%.*]])
+; CHECK-NEXT:    ret float [[VAL]]
+;
+  %val = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float %x)
+  ret float %val
+}
+
+declare float @llvm.minimum.f32(float, float)
+declare float @llvm.maximum.f32(float, float)
+declare double @llvm.minimum.f64(double, double)
+declare double @llvm.maximum.f64(double, double)
+declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>)
+declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)
+
+; From the LangRef for minimum/maximum:
+; "If either operand is a NaN, returns NaN."
+
+define double @maximum_nan_op0(double %x) {
+; CHECK-LABEL: @maximum_nan_op0(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = call double @llvm.maximum.f64(double 0x7ff8000000000000, double %x)
+  ret double %r
+}
+
+define double @maximum_nan_op1(double %x) {
+; CHECK-LABEL: @maximum_nan_op1(
+; CHECK-NEXT:    ret double 0x7FF800000000DEAD
+;
+  %r = call double @llvm.maximum.f64(double %x, double 0x7ff800000000dead)
+  ret double %r
+}
+
+define double @minimum_nan_op0(double %x) {
+; CHECK-LABEL: @minimum_nan_op0(
+; CHECK-NEXT:    ret double 0x7FF8000DEAD00000
+;
+  %r = call double @llvm.minimum.f64(double 0x7ff8000dead00000, double %x)
+  ret double %r
+}
+
+define double @minimum_nan_op1(double %x) {
+; CHECK-LABEL: @minimum_nan_op1(
+; CHECK-NEXT:    ret double 0x7FF800DEAD00DEAD
+;
+  %r = call double @llvm.minimum.f64(double %x, double 0x7ff800dead00dead)
+  ret double %r
+}
+
+define <2 x double> @maximum_nan_op0_vec(<2 x double> %x) {
+; CHECK-LABEL: @maximum_nan_op0_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
+;
+  %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x)
+  ret <2 x double> %r
+}
+
+define <2 x double> @maximum_nan_op1_vec(<2 x double> %x) {
+; CHECK-LABEL: @maximum_nan_op1_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF800000000DEAD, double 0x7FF8FFFFFFFFFFFF>
+;
+  %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>)
+  ret <2 x double> %r
+}
+
+define <2 x double> @minimum_nan_op0_vec(<2 x double> %x) {
+; CHECK-LABEL: @minimum_nan_op0_vec(
+; CHECK-NEXT:    ret <2 x double> <double undef, double 0x7FF8000DEAD00000>
+;
+  %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x)
+  ret <2 x double> %r
+}
+
+define <2 x double> @minimum_nan_op1_vec(<2 x double> %x) {
+; CHECK-LABEL: @minimum_nan_op1_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF800DEAD00DEAD, double 0x7FF800DEAD00DEAD>
+;
+  %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>)
+  ret <2 x double> %r
+}
+
+define float @maximum_undef_op1(float %x) {
+; CHECK-LABEL: @maximum_undef_op1(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %val = call float @llvm.maximum.f32(float %x, float undef)
+  ret float %val
+}
+
+define float @maximum_undef_op0(float %x) {
+; CHECK-LABEL: @maximum_undef_op0(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %val = call float @llvm.maximum.f32(float undef, float %x)
+  ret float %val
+}
+
+define float @minimum_undef_op1(float %x) {
+; CHECK-LABEL: @minimum_undef_op1(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %val = call float @llvm.minimum.f32(float %x, float undef)
+  ret float %val
+}
+
+define float @minimum_undef_op0(float %x) {
+; CHECK-LABEL: @minimum_undef_op0(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %val = call float @llvm.minimum.f32(float undef, float %x)
+  ret float %val
+}
+
+define float @minimum_undef_undef(float %x) {
+; CHECK-LABEL: @minimum_undef_undef(
+; CHECK-NEXT:    ret float undef
+;
+  %val = call float @llvm.minimum.f32(float undef, float undef)
+  ret float %val
+}
+
+define float @maximum_undef_undef(float %x) {
+; CHECK-LABEL: @maximum_undef_undef(
+; CHECK-NEXT:    ret float undef
+;
+  %val = call float @llvm.maximum.f32(float undef, float undef)
+  ret float %val
+}
+
+define float @minimum_same_args(float %x) {
+; CHECK-LABEL: @minimum_same_args(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %y = call float @llvm.minimum.f32(float %x, float %x)
+  ret float %y
+}
+
+define float @maximum_same_args(float %x) {
+; CHECK-LABEL: @maximum_same_args(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %y = call float @llvm.maximum.f32(float %x, float %x)
+  ret float %y
+}
+
+define float @minimum_x_minimum_x_y(float %x, float %y) {
+; CHECK-LABEL: @minimum_x_minimum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.minimum.f32(float %x, float %y)
+  %b = call float @llvm.minimum.f32(float %x, float %a)
+  ret float %b
+}
+
+define float @minimum_y_minimum_x_y(float %x, float %y) {
+; CHECK-LABEL: @minimum_y_minimum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.minimum.f32(float %x, float %y)
+  %b = call float @llvm.minimum.f32(float %y, float %a)
+  ret float %b
+}
+
+define float @minimum_x_y_minimum_x(float %x, float %y) {
+; CHECK-LABEL: @minimum_x_y_minimum_x(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.minimum.f32(float %x, float %y)
+  %b = call float @llvm.minimum.f32(float %a, float %x)
+  ret float %b
+}
+
+define float @minimum_x_y_minimum_y(float %x, float %y) {
+; CHECK-LABEL: @minimum_x_y_minimum_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.minimum.f32(float %x, float %y)
+  %b = call float @llvm.minimum.f32(float %a, float %y)
+  ret float %b
+}
+
+; negative test
+
+define float @minimum_z_minimum_x_y(float %x, float %y, float %z) {
+; CHECK-LABEL: @minimum_z_minimum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minimum.f32(float [[Z:%.*]], float [[A]])
+; CHECK-NEXT:    ret float [[B]]
+;
+  %a = call float @llvm.minimum.f32(float %x, float %y)
+  %b = call float @llvm.minimum.f32(float %z, float %a)
+  ret float %b
+}
+
+; negative test
+
+define float @minimum_x_y_minimum_z(float %x, float %y, float %z) {
+; CHECK-LABEL: @minimum_x_y_minimum_z(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.minimum.f32(float [[A]], float [[Z:%.*]])
+; CHECK-NEXT:    ret float [[B]]
+;
+  %a = call float @llvm.minimum.f32(float %x, float %y)
+  %b = call float @llvm.minimum.f32(float %a, float %z)
+  ret float %b
+}
+
+; minimum(X, -INF) --> -INF
+
+define float @minimum_neginf(float %x) {
+; CHECK-LABEL: @minimum_neginf(
+; CHECK-NEXT:    ret float 0xFFF0000000000000
+;
+  %val = call float @llvm.minimum.f32(float %x, float 0xFFF0000000000000)
+  ret float %val
+}
+
+define <2 x double> @minimum_neginf_commute_vec(<2 x double> %x) {
+; CHECK-LABEL: @minimum_neginf_commute_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>
+;
+  %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x)
+  ret <2 x double> %r
+}
+
+; negative test
+
+define float @minimum_inf(float %x) {
+; CHECK-LABEL: @minimum_inf(
+; CHECK-NEXT:    [[VAL:%.*]] = call float @llvm.minimum.f32(float 0x7FF0000000000000, float [[X:%.*]])
+; CHECK-NEXT:    ret float [[VAL]]
+;
+  %val = call float @llvm.minimum.f32(float 0x7FF0000000000000, float %x)
+  ret float %val
+}
+define float @maximum_x_maximum_x_y(float %x, float %y) {
+; CHECK-LABEL: @maximum_x_maximum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.maximum.f32(float %x, float %y)
+  %b = call float @llvm.maximum.f32(float %x, float %a)
+  ret float %b
+}
+
+define float @maximum_y_maximum_x_y(float %x, float %y) {
+; CHECK-LABEL: @maximum_y_maximum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.maximum.f32(float %x, float %y)
+  %b = call float @llvm.maximum.f32(float %y, float %a)
+  ret float %b
+}
+
+define float @maximum_x_y_maximum_x(float %x, float %y) {
+; CHECK-LABEL: @maximum_x_y_maximum_x(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.maximum.f32(float %x, float %y)
+  %b = call float @llvm.maximum.f32(float %a, float %x)
+  ret float %b
+}
+
+define float @maximum_x_y_maximum_y(float %x, float %y) {
+; CHECK-LABEL: @maximum_x_y_maximum_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    ret float [[A]]
+;
+  %a = call float @llvm.maximum.f32(float %x, float %y)
+  %b = call float @llvm.maximum.f32(float %a, float %y)
+  ret float %b
+}
+
+; negative test
+
+define float @maximum_z_maximum_x_y(float %x, float %y, float %z) {
+; CHECK-LABEL: @maximum_z_maximum_x_y(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[A]])
+; CHECK-NEXT:    ret float [[B]]
+;
+  %a = call float @llvm.maximum.f32(float %x, float %y)
+  %b = call float @llvm.maximum.f32(float %z, float %a)
+  ret float %b
+}
+
+; negative test
+
+define float @maximum_x_y_maximum_z(float %x, float %y, float %z) {
+; CHECK-LABEL: @maximum_x_y_maximum_z(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maximum.f32(float [[A]], float [[Z:%.*]])
+; CHECK-NEXT:    ret float [[B]]
+;
+  %a = call float @llvm.maximum.f32(float %x, float %y)
+  %b = call float @llvm.maximum.f32(float %a, float %z)
+  ret float %b
+}
+
+; maximum(X, INF) --> INF
+
+define <2 x double> @maximum_inf(<2 x double> %x) {
+; CHECK-LABEL: @maximum_inf(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000>
+;
+  %val = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>)
+  ret <2 x double> %val
+}
+
+define float @maximum_inf_commute(float %x) {
+; CHECK-LABEL: @maximum_inf_commute(
+; CHECK-NEXT:    ret float 0x7FF0000000000000
+;
+  %val = call float @llvm.maximum.f32(float 0x7FF0000000000000, float %x)
+  ret float %val
+}
+
+; Y - (Y - X) --> X
+
+define float @fsub_fsub_common_op(float %x, float %y) {
+; CHECK-LABEL: @fsub_fsub_common_op(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %s = fsub float %y, %x
+  %r = fsub reassoc nsz float %y, %s
+  ret float %r
+}
+
+define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @fsub_fsub_common_op_vec(
+; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
+;
+  %s = fsub <2 x float> %y, %x
+  %r = fsub reassoc nsz <2 x float> %y, %s
+  ret <2 x float> %r
+}
+
+; Negative test - fsub is not commutative.
+; Y - (X - Y) --> (Y - X) + Y (canonicalized)
+
+define float @fsub_fsub_wrong_common_op(float %x, float %y) {
+; CHECK-LABEL: @fsub_fsub_wrong_common_op(
+; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = fsub float %x, %y
+  %r = fsub reassoc nsz float %y, %s
+  ret float %r
+}
+
+; Negative test - negated operand needed.
+; (Y - X) - Y --> -X
+
+define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) {
+; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute(
+; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = fsub float %y, %x
+  %r = fsub reassoc nsz float %s, %y
+  ret float %r
+}
+
+; Negative test - fsub is not commutative.
+; (X - Y) - Y --> ?
+
+define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) {
+; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute(
+; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = fsub float %x, %y
+  %r = fsub reassoc nsz float %s, %y
+  ret float %r
+}
+
+; (Y + X) - Y --> X
+
+define float @fadd_fsub_common_op(float %x, float %y) {
+; CHECK-LABEL: @fadd_fsub_common_op(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %a = fadd float %y, %x
+  %r = fsub reassoc nsz float %a, %y
+  ret float %r
+}
+
+; (X + Y) - Y --> X
+
+define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @fadd_fsub_common_op_commute_vec(
+; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
+;
+  %a = fadd <2 x float> %x, %y
+  %r = fsub reassoc nsz <2 x float> %a, %y
+  ret <2 x float> %r
+}
+
+; Negative test - negated operand needed.
+; Y - (Y + X) --> -X
+
+define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) {
+; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute(
+; CHECK-NEXT:    [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %a = fadd float %y, %x
+  %r = fsub reassoc nsz float %y, %a
+  ret float %r
+}
+
+; Negative test - negated operand needed.
+; Y - (X + Y) --> -X
+
+define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) {
+; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute(
+; CHECK-NEXT:    [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %a = fadd float %x, %y
+  %r = fsub reassoc nsz float %y, %a
+  ret float %r
+}
+
+; Y + (X - Y) --> X
+
+define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @fsub_fadd_common_op_vec(
+; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
+;
+  %s = fsub <2 x float> %x, %y
+  %r = fadd reassoc nsz <2 x float> %y, %s
+  ret <2 x float> %r
+}
+
+; (X - Y) + Y --> X
+
+define float @fsub_fadd_common_op_commute(float %x, float %y) {
+; CHECK-LABEL: @fsub_fadd_common_op_commute(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %s = fsub float %x, %y
+  %r = fadd reassoc nsz float %s, %y
+  ret float %r
+}
+
+; Negative test.
+; Y + (Y - X) --> ?
+
+define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) {
+; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute(
+; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = fsub float %y, %x
+  %r = fadd reassoc nsz float %y, %s
+  ret float %r
+}
+
+; Negative test.
+; (Y - X) + Y --> ?
+
+define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) {
+; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute(
+; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = fsub float %y, %x
+  %r = fadd reassoc nsz float %s, %y
+  ret float %r
+}

Added: llvm/trunk/test/Transforms/InstSimplify/floating-point-compare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/floating-point-compare.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/floating-point-compare.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/floating-point-compare.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,580 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; Infinity
+
+define i1 @inf0(double %arg) {
+; CHECK-LABEL: @inf0(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp ogt double %arg, 0x7FF0000000000000
+  ret i1 %tmp
+}
+
+define i1 @inf1(double %arg) {
+; CHECK-LABEL: @inf1(
+; CHECK-NEXT:    ret i1 true
+;
+  %tmp = fcmp ule double %arg, 0x7FF0000000000000
+  ret i1 %tmp
+}
+
+; Negative infinity
+
+define i1 @ninf0(double %arg) {
+; CHECK-LABEL: @ninf0(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp olt double %arg, 0xFFF0000000000000
+  ret i1 %tmp
+}
+
+define i1 @ninf1(double %arg) {
+; CHECK-LABEL: @ninf1(
+; CHECK-NEXT:    ret i1 true
+;
+  %tmp = fcmp uge double %arg, 0xFFF0000000000000
+  ret i1 %tmp
+}
+
+; NaNs
+
+define i1 @nan0(double %arg) {
+; CHECK-LABEL: @nan0(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp ord double %arg, 0x7FF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nan1(double %arg) {
+; CHECK-LABEL: @nan1(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp oeq double %arg, 0x7FF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nan2(double %arg) {
+; CHECK-LABEL: @nan2(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp olt double %arg, 0x7FF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nan3(double %arg) {
+; CHECK-LABEL: @nan3(
+; CHECK-NEXT:    ret i1 true
+;
+  %tmp = fcmp uno double %arg, 0x7FF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nan4(double %arg) {
+; CHECK-LABEL: @nan4(
+; CHECK-NEXT:    ret i1 true
+;
+  %tmp = fcmp une double %arg, 0x7FF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nan5(double %arg) {
+; CHECK-LABEL: @nan5(
+; CHECK-NEXT:    ret i1 true
+;
+  %tmp = fcmp ult double %arg, 0x7FF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+; Negative NaN.
+
+define i1 @nnan0(double %arg) {
+; CHECK-LABEL: @nnan0(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp ord double %arg, 0xFFF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nnan1(double %arg) {
+; CHECK-LABEL: @nnan1(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp oeq double %arg, 0xFFF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nnan2(double %arg) {
+; CHECK-LABEL: @nnan2(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp olt double %arg, 0xFFF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nnan3(double %arg) {
+; CHECK-LABEL: @nnan3(
+; CHECK-NEXT:    ret i1 true
+;
+  %tmp = fcmp uno double %arg, 0xFFF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nnan4(double %arg) {
+; CHECK-LABEL: @nnan4(
+; CHECK-NEXT:    ret i1 true
+;
+  %tmp = fcmp une double %arg, 0xFFF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+define i1 @nnan5(double %arg) {
+; CHECK-LABEL: @nnan5(
+; CHECK-NEXT:    ret i1 true
+;
+  %tmp = fcmp ult double %arg, 0xFFF00000FFFFFFFF
+  ret i1 %tmp
+}
+
+; Negative zero.
+
+define i1 @nzero0() {
+; CHECK-LABEL: @nzero0(
+; CHECK-NEXT:    ret i1 true
+;
+  %tmp = fcmp oeq double 0.0, -0.0
+  ret i1 %tmp
+}
+
+define i1 @nzero1() {
+; CHECK-LABEL: @nzero1(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp ogt double 0.0, -0.0
+  ret i1 %tmp
+}
+
+; No enlightenment here.
+
+define i1 @one_with_self(double %arg) {
+; CHECK-LABEL: @one_with_self(
+; CHECK-NEXT:    ret i1 false
+;
+  %tmp = fcmp one double %arg, %arg
+  ret i1 %tmp
+}
+
+; These tests choose arbitrarily between float and double,
+; and between uge and olt, to give reasonble coverage
+; without combinatorial explosion.
+
+declare half @llvm.fabs.f16(half)
+declare float @llvm.fabs.f32(float)
+declare double @llvm.fabs.f64(double)
+declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
+declare <3 x float> @llvm.fabs.v3f32(<3 x float>)
+declare <2 x double> @llvm.fabs.v2f64(<2 x double>)
+declare float @llvm.sqrt.f32(float)
+declare double @llvm.powi.f64(double,i32)
+declare float @llvm.exp.f32(float)
+declare float @llvm.minnum.f32(float, float)
+declare float @llvm.maxnum.f32(float, float)
+declare float @llvm.maximum.f32(float, float)
+declare double @llvm.exp2.f64(double)
+declare float @llvm.fma.f32(float,float,float)
+
+declare void @expect_equal(i1,i1)
+
+define i1 @orderedLessZeroTree(float,float,float,float) {
+; CHECK-LABEL: @orderedLessZeroTree(
+; CHECK-NEXT:    ret i1 true
+;
+  %square = fmul float %0, %0
+  %abs = call float @llvm.fabs.f32(float %1)
+  %sqrt = call float @llvm.sqrt.f32(float %2)
+  %fma = call float @llvm.fma.f32(float %3, float %3, float %sqrt)
+  %div = fdiv float %square, %abs
+  %rem = frem float %sqrt, %fma
+  %add = fadd float %div, %rem
+  %uge = fcmp uge float %add, 0.000000e+00
+  ret i1 %uge
+}
+
+define i1 @orderedLessZeroExpExt(float) {
+; CHECK-LABEL: @orderedLessZeroExpExt(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = call float @llvm.exp.f32(float %0)
+  %b = fpext float %a to double
+  %uge = fcmp uge double %b, 0.000000e+00
+  ret i1 %uge
+}
+
+define i1 @orderedLessZeroExp2Trunc(double) {
+; CHECK-LABEL: @orderedLessZeroExp2Trunc(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = call double @llvm.exp2.f64(double %0)
+  %b = fptrunc double %a to float
+  %olt = fcmp olt float %b, 0.000000e+00
+  ret i1 %olt
+}
+
+define i1 @orderedLessZeroPowi(double,double) {
+; CHECK-LABEL: @orderedLessZeroPowi(
+; CHECK-NEXT:    ret i1 false
+;
+  ; Even constant exponent
+  %a = call double @llvm.powi.f64(double %0, i32 2)
+  %square = fmul double %1, %1
+  ; Odd constant exponent with provably non-negative base
+  %b = call double @llvm.powi.f64(double %square, i32 3)
+  %c = fadd double %a, %b
+  %olt = fcmp olt double %b, 0.000000e+00
+  ret i1 %olt
+}
+
+define i1 @UIToFP_is_nan_or_positive_or_zero(i32 %x) {
+; CHECK-LABEL: @UIToFP_is_nan_or_positive_or_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = uitofp i32 %x to float
+  %r = fcmp uge float %a, 0.000000e+00
+  ret i1 %r
+}
+
+define <2 x i1> @UIToFP_is_nan_or_positive_or_zero_vec(<2 x i32> %x) {
+; CHECK-LABEL: @UIToFP_is_nan_or_positive_or_zero_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %a = uitofp <2 x i32> %x to <2 x float>
+  %r = fcmp uge <2 x float> %a, zeroinitializer
+  ret <2 x i1> %r
+}
+
+define i1 @UIToFP_nnan_is_positive_or_zero(i32 %x) {
+; CHECK-LABEL: @UIToFP_nnan_is_positive_or_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = uitofp i32 %x to float
+  %r = fcmp nnan oge float %a, 0.000000e+00
+  ret i1 %r
+}
+
+define <2 x i1> @UIToFP_nnan_is_positive_or_zero_vec(<2 x i32> %x) {
+; CHECK-LABEL: @UIToFP_nnan_is_positive_or_zero_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %a = uitofp <2 x i32> %x to <2 x float>
+  %r = fcmp nnan oge <2 x float> %a, zeroinitializer
+  ret <2 x i1> %r
+}
+
+define i1 @UIToFP_is_not_negative(i32 %x) {
+; CHECK-LABEL: @UIToFP_is_not_negative(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = uitofp i32 %x to float
+  %r = fcmp olt float %a, 0.000000e+00
+  ret i1 %r
+}
+
+define <2 x i1> @UIToFP_is_not_negative_vec(<2 x i32> %x) {
+; CHECK-LABEL: @UIToFP_is_not_negative_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %a = uitofp <2 x i32> %x to <2 x float>
+  %r = fcmp olt <2 x float> %a, zeroinitializer
+  ret <2 x i1> %r
+}
+
+define i1 @UIToFP_nnan_is_not_negative(i32 %x) {
+; CHECK-LABEL: @UIToFP_nnan_is_not_negative(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = uitofp i32 %x to float
+  %r = fcmp nnan ult float %a, 0.000000e+00
+  ret i1 %r
+}
+
+define <2 x i1> @UIToFP_nnan_is_not_negative_vec(<2 x i32> %x) {
+; CHECK-LABEL: @UIToFP_nnan_is_not_negative_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %a = uitofp <2 x i32> %x to <2 x float>
+  %r = fcmp nnan ult <2 x float> %a, zeroinitializer
+  ret <2 x i1> %r
+}
+
+define i1 @fabs_is_nan_or_positive_or_zero(double %x) {
+; CHECK-LABEL: @fabs_is_nan_or_positive_or_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %fabs = tail call double @llvm.fabs.f64(double %x)
+  %cmp = fcmp uge double %fabs, 0.0
+  ret i1 %cmp
+}
+
+define <2 x i1> @fabs_is_nan_or_positive_or_zero_vec(<2 x double> %x) {
+; CHECK-LABEL: @fabs_is_nan_or_positive_or_zero_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %fabs = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
+  %cmp = fcmp uge <2 x double> %fabs, zeroinitializer
+  ret <2 x i1> %cmp
+}
+
+define i1 @fabs_nnan_is_positive_or_zero(double %x) {
+; CHECK-LABEL: @fabs_nnan_is_positive_or_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %fabs = tail call double @llvm.fabs.f64(double %x)
+  %cmp = fcmp nnan oge double %fabs, 0.0
+  ret i1 %cmp
+}
+
+define <2 x i1> @fabs_nnan_is_positive_or_zero_vec(<2 x double> %x) {
+; CHECK-LABEL: @fabs_nnan_is_positive_or_zero_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %fabs = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
+  %cmp = fcmp nnan oge <2 x double> %fabs, zeroinitializer
+  ret <2 x i1> %cmp
+}
+
+define i1 @fabs_is_not_negative(double %x) {
+; CHECK-LABEL: @fabs_is_not_negative(
+; CHECK-NEXT:    ret i1 false
+;
+  %fabs = tail call double @llvm.fabs.f64(double %x)
+  %cmp = fcmp olt double %fabs, 0.0
+  ret i1 %cmp
+}
+
+define <2 x i1> @fabs_is_not_negative_vec(<2 x double> %x) {
+; CHECK-LABEL: @fabs_is_not_negative_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %fabs = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
+  %cmp = fcmp olt <2 x double> %fabs, zeroinitializer
+  ret <2 x i1> %cmp
+}
+
+define i1 @fabs_nnan_is_not_negative(double %x) {
+; CHECK-LABEL: @fabs_nnan_is_not_negative(
+; CHECK-NEXT:    ret i1 false
+;
+  %fabs = tail call double @llvm.fabs.f64(double %x)
+  %cmp = fcmp nnan ult double %fabs, 0.0
+  ret i1 %cmp
+}
+
+define <2 x i1> @fabs_nnan_is_not_negative_vec(<2 x double> %x) {
+; CHECK-LABEL: @fabs_nnan_is_not_negative_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %fabs = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
+  %cmp = fcmp nnan ult <2 x double> %fabs, zeroinitializer
+  ret <2 x i1> %cmp
+}
+
+define <2 x i1> @fabs_is_not_negative_negzero(<2 x float> %V) {
+; CHECK-LABEL: @fabs_is_not_negative_negzero(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %abs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %V)
+  %cmp = fcmp olt <2 x float> %abs, <float -0.0, float -0.0>
+  ret <2 x i1> %cmp
+}
+
+define <2 x i1> @fabs_is_not_negative_poszero(<2 x float> %V) {
+; CHECK-LABEL: @fabs_is_not_negative_poszero(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %abs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %V)
+  %cmp = fcmp olt <2 x float> %abs, <float 0.0, float 0.0>
+  ret <2 x i1> %cmp
+}
+
+define <2 x i1> @fabs_is_not_negative_anyzero(<2 x float> %V) {
+; CHECK-LABEL: @fabs_is_not_negative_anyzero(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %abs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %V)
+  %cmp = fcmp olt <2 x float> %abs, <float 0.0, float -0.0>
+  ret <2 x i1> %cmp
+}
+
+define <3 x i1> @fabs_is_not_negative_negzero_undef(<3 x float> %V) {
+; CHECK-LABEL: @fabs_is_not_negative_negzero_undef(
+; CHECK-NEXT:    ret <3 x i1> zeroinitializer
+;
+  %abs = call <3 x float> @llvm.fabs.v3f32(<3 x float> %V)
+  %cmp = fcmp olt <3 x float> %abs, <float -0.0, float -0.0, float undef>
+  ret <3 x i1> %cmp
+}
+
+define <3 x i1> @fabs_is_not_negative_poszero_undef(<3 x float> %V) {
+; CHECK-LABEL: @fabs_is_not_negative_poszero_undef(
+; CHECK-NEXT:    ret <3 x i1> zeroinitializer
+;
+  %abs = call <3 x float> @llvm.fabs.v3f32(<3 x float> %V)
+  %cmp = fcmp olt <3 x float> %abs, <float 0.0, float 0.0, float undef>
+  ret <3 x i1> %cmp
+}
+
+define <3 x i1> @fabs_is_not_negative_anyzero_undef(<3 x float> %V) {
+; CHECK-LABEL: @fabs_is_not_negative_anyzero_undef(
+; CHECK-NEXT:    ret <3 x i1> zeroinitializer
+;
+  %abs = call <3 x float> @llvm.fabs.v3f32(<3 x float> %V)
+  %cmp = fcmp olt <3 x float> %abs, <float 0.0, float -0.0, float undef>
+  ret <3 x i1> %cmp
+}
+
+define i1 @orderedLessZeroSelect(float, float) {
+; CHECK-LABEL: @orderedLessZeroSelect(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = call float @llvm.exp.f32(float %0)
+  %b = call float @llvm.fabs.f32(float %1)
+  %c = fcmp olt float %0, %1
+  %d = select i1 %c, float %a, float %b
+  %e = fadd float %d, 1.0
+  %uge = fcmp uge float %e, 0.000000e+00
+  ret i1 %uge
+}
+
+define i1 @orderedLessZeroMinNum(float, float) {
+; CHECK-LABEL: @orderedLessZeroMinNum(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = call float @llvm.exp.f32(float %0)
+  %b = call float @llvm.fabs.f32(float %1)
+  %c = call float @llvm.minnum.f32(float %a, float %b)
+  %uge = fcmp uge float %c, 0.000000e+00
+  ret i1 %uge
+}
+
+; PR37776: https://bugs.llvm.org/show_bug.cgi?id=37776
+; exp() may return nan, leaving %1 as the unknown result, so we can't simplify.
+
+define i1 @orderedLessZeroMaxNum(float, float) {
+; CHECK-LABEL: @orderedLessZeroMaxNum(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.exp.f32(float [[TMP0:%.*]])
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[TMP1:%.*]])
+; CHECK-NEXT:    [[UGE:%.*]] = fcmp uge float [[B]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[UGE]]
+;
+  %a = call float @llvm.exp.f32(float %0)
+  %b = call float @llvm.maxnum.f32(float %a, float %1)
+  %uge = fcmp uge float %b, 0.000000e+00
+  ret i1 %uge
+}
+
+; But using maximum, we can simplify, since the NaN would be propagated
+
+define i1 @orderedLessZeroMaximum(float, float) {
+; CHECK-LABEL: @orderedLessZeroMaximum(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = call float @llvm.exp.f32(float %0)
+  %b = call float @llvm.maximum.f32(float %a, float %1)
+  %uge = fcmp uge float %b, 0.000000e+00
+  ret i1 %uge
+}
+
+define i1 @known_positive_olt_with_negative_constant(double %a) {
+; CHECK-LABEL: @known_positive_olt_with_negative_constant(
+; CHECK-NEXT:    ret i1 false
+;
+  %call = call double @llvm.fabs.f64(double %a)
+  %cmp = fcmp olt double %call, -1.0
+  ret i1 %cmp
+}
+
+define <2 x i1> @known_positive_ole_with_negative_constant_splat_vec(<2 x i32> %a) {
+; CHECK-LABEL: @known_positive_ole_with_negative_constant_splat_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %call = uitofp <2 x i32> %a to <2 x double>
+  %cmp = fcmp ole <2 x double> %call, <double -2.0, double -2.0>
+  ret <2 x i1> %cmp
+}
+
+define i1 @known_positive_ugt_with_negative_constant(i32 %a) {
+; CHECK-LABEL: @known_positive_ugt_with_negative_constant(
+; CHECK-NEXT:    ret i1 true
+;
+  %call = uitofp i32 %a to float
+  %cmp = fcmp ugt float %call, -3.0
+  ret i1 %cmp
+}
+
+define <2 x i1> @known_positive_uge_with_negative_constant_splat_vec(<2 x float> %a) {
+; CHECK-LABEL: @known_positive_uge_with_negative_constant_splat_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
+  %cmp = fcmp uge <2 x float> %call, <float -4.0, float -4.0>
+  ret <2 x i1> %cmp
+}
+
+define i1 @known_positive_oeq_with_negative_constant(half %a) {
+; CHECK-LABEL: @known_positive_oeq_with_negative_constant(
+; CHECK-NEXT:    ret i1 false
+;
+  %call = call half @llvm.fabs.f16(half %a)
+  %cmp = fcmp oeq half %call, -5.0
+  ret i1 %cmp
+}
+
+define <2 x i1> @known_positive_une_with_negative_constant_splat_vec(<2 x i32> %a) {
+; CHECK-LABEL: @known_positive_une_with_negative_constant_splat_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %call = uitofp <2 x i32> %a to <2 x half>
+  %cmp = fcmp une <2 x half> %call, <half -6.0, half -6.0>
+  ret <2 x i1> %cmp
+}
+
+define i1 @nonans1(double %in1, double %in2) {
+; CHECK-LABEL: @nonans1(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = fcmp nnan uno double %in1, %in2
+  ret i1 %cmp
+}
+
+define i1 @nonans2(double %in1, double %in2) {
+; CHECK-LABEL: @nonans2(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = fcmp nnan ord double %in1, %in2
+  ret i1 %cmp
+}
+
+define <2 x i1> @orderedCompareWithNaNVector(<2 x double> %A) {
+; CHECK-LABEL: @orderedCompareWithNaNVector(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %cmp = fcmp olt <2 x double> %A, <double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF>
+  ret <2 x i1> %cmp
+}
+
+define <2 x i1> @orderedCompareWithNaNVector_undef_elt(<2 x double> %A) {
+; CHECK-LABEL: @orderedCompareWithNaNVector_undef_elt(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %cmp = fcmp olt <2 x double> %A, <double 0xFFFFFFFFFFFFFFFF, double undef>
+  ret <2 x i1> %cmp
+}
+
+define <2 x i1> @unorderedCompareWithNaNVector_undef_elt(<2 x double> %A) {
+; CHECK-LABEL: @unorderedCompareWithNaNVector_undef_elt(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %cmp = fcmp ult <2 x double> %A, <double undef, double 0xFFFFFFFFFFFFFFFF>
+  ret <2 x i1> %cmp
+}

Added: llvm/trunk/test/Transforms/InstSimplify/fold-builtin-fma.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/fold-builtin-fma.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/fold-builtin-fma.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/fold-builtin-fma.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,119 @@
+; RUN: opt -instsimplify -S < %s | FileCheck %s
+
+; Fixes PR20832
+; Make sure that we correctly fold a fused multiply-add where operands
+; are all finite constants and addend is zero.
+
+declare double @llvm.fma.f64(double, double, double)
+
+
+define double @PR20832()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0.0)
+  ret double %1
+}
+; CHECK-LABEL: @PR20832(
+; CHECK: ret double 5.600000e+01
+
+; Test builtin fma with all finite non-zero constants.
+define double @test_all_finite()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 5.0)
+  ret double %1
+}
+; CHECK-LABEL: @test_all_finite(
+; CHECK: ret double 6.100000e+01
+
+; Test builtin fma with a +/-NaN addend.
+define double @test_NaN_addend()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0x7FF8000000000000)
+  ret double %1
+}
+; CHECK-LABEL: @test_NaN_addend(
+; CHECK: ret double 0x7FF8000000000000
+
+define double @test_NaN_addend_2()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0xFFF8000000000000)
+  ret double %1
+}
+; CHECK-LABEL: @test_NaN_addend_2(
+; CHECK: ret double 0xFFF8000000000000
+
+; Test builtin fma with a +/-Inf addend.
+define double @test_Inf_addend()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0x7FF0000000000000)
+  ret double %1
+}
+; CHECK-LABEL: @test_Inf_addend(
+; CHECK: ret double 0x7FF0000000000000
+
+define double @test_Inf_addend_2()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 8.0, double 0xFFF0000000000000)
+  ret double %1
+}
+; CHECK-LABEL: @test_Inf_addend_2(
+; CHECK: ret double 0xFFF0000000000000
+
+; Test builtin fma with one of the operands to the multiply being +/-NaN.
+define double @test_NaN_1()  {
+  %1 = call double @llvm.fma.f64(double 0x7FF8000000000000, double 8.0, double 0.0)
+  ret double %1
+}
+; CHECK-LABEL: @test_NaN_1(
+; CHECK: ret double 0x7FF8000000000000
+
+
+define double @test_NaN_2()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 0x7FF8000000000000, double 0.0)
+  ret double %1
+}
+; CHECK-LABEL: @test_NaN_2(
+; CHECK: ret double 0x7FF8000000000000
+
+
+define double @test_NaN_3()  {
+  %1 = call double @llvm.fma.f64(double 0xFFF8000000000000, double 8.0, double 0.0)
+  ret double %1
+}
+; CHECK-LABEL: @test_NaN_3(
+; CHECK: ret double 0x7FF8000000000000
+
+
+define double @test_NaN_4()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 0xFFF8000000000000, double 0.0)
+  ret double %1
+}
+; CHECK-LABEL: @test_NaN_4(
+; CHECK: ret double 0x7FF8000000000000
+
+
+; Test builtin fma with one of the operands to the multiply being +/-Inf.
+define double @test_Inf_1()  {
+  %1 = call double @llvm.fma.f64(double 0x7FF0000000000000, double 8.0, double 0.0)
+  ret double %1
+}
+; CHECK-LABEL: @test_Inf_1(
+; CHECK: ret double 0x7FF0000000000000
+
+
+define double @test_Inf_2()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 0x7FF0000000000000, double 0.0)
+  ret double %1
+}
+; CHECK-LABEL: @test_Inf_2(
+; CHECK: ret double 0x7FF0000000000000
+
+
+define double @test_Inf_3()  {
+  %1 = call double @llvm.fma.f64(double 0xFFF0000000000000, double 8.0, double 0.0)
+  ret double %1
+}
+; CHECK-LABEL: @test_Inf_3(
+; CHECK: ret double 0xFFF0000000000000
+
+
+define double @test_Inf_4()  {
+  %1 = call double @llvm.fma.f64(double 7.0, double 0xFFF0000000000000, double 0.0)
+  ret double %1
+}
+; CHECK-LABEL: @test_Inf_4(
+; CHECK: ret double 0xFFF0000000000000
+

Added: llvm/trunk/test/Transforms/InstSimplify/fold-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/fold-intrinsics.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/fold-intrinsics.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/fold-intrinsics.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+declare double @llvm.powi.f64(double, i32) nounwind readonly
+declare i32 @llvm.bswap.i32(i32)
+
+; A
+define i32 @test_bswap(i32 %a) nounwind {
+; CHECK-LABEL: @test_bswap(
+; CHECK-NEXT:    ret i32 %a
+;
+  %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a )
+  %tmp4 = tail call i32 @llvm.bswap.i32( i32 %tmp2 )
+  ret i32 %tmp4
+}
+
+define void @powi(double %V, double *%P) {
+  %B = tail call double @llvm.powi.f64(double %V, i32 0) nounwind
+  store volatile double %B, double* %P
+
+  %C = tail call double @llvm.powi.f64(double %V, i32 1) nounwind
+  store volatile double %C, double* %P
+
+  ret void
+; CHECK-LABEL: @powi(
+; CHECK: store volatile double 1.0
+; CHECK: store volatile double %V
+}

Added: llvm/trunk/test/Transforms/InstSimplify/fp-nan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/fp-nan.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/fp-nan.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/fp-nan.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,201 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; Default NaN constant
+
+define double @fadd_nan_op0(double %x) {
+; CHECK-LABEL: @fadd_nan_op0(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fadd double 0x7FF8000000000000, %x
+  ret double %r
+}
+
+; Sign bit is set
+
+define double @fadd_nan_op1(double %x) {
+; CHECK-LABEL: @fadd_nan_op1(
+; CHECK-NEXT:    ret double 0xFFF8000000000000
+;
+  %r = fadd double %x, 0xFFF8000000000000
+  ret double %r
+}
+
+; Non-zero payload
+
+define float @fsub_nan_op0(float %x) {
+; CHECK-LABEL: @fsub_nan_op0(
+; CHECK-NEXT:    ret float 0x7FFFFF0000000000
+;
+  %r = fsub float 0x7FFFFF0000000000, %x
+  ret float %r
+}
+
+; Signaling
+
+define float @fsub_nan_op1(float %x) {
+; CHECK-LABEL: @fsub_nan_op1(
+; CHECK-NEXT:    ret float 0x7FF1000000000000
+;
+  %r = fsub float %x, 0x7FF1000000000000
+  ret float %r
+}
+
+; Signaling and signed
+
+define double @fmul_nan_op0(double %x) {
+; CHECK-LABEL: @fmul_nan_op0(
+; CHECK-NEXT:    ret double 0xFFF0000000000001
+;
+  %r = fmul double 0xFFF0000000000001, %x
+  ret double %r
+}
+
+; Vector type
+
+define <2 x float> @fmul_nan_op1(<2 x float> %x) {
+; CHECK-LABEL: @fmul_nan_op1(
+; CHECK-NEXT:    ret <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
+;
+  %r = fmul <2 x float> %x, <float 0x7FF8000000000000, float 0x7FF8000000000000>
+  ret <2 x float> %r
+}
+
+; Vector signed and non-zero payload
+
+define <2 x double> @fdiv_nan_op0(<2 x double> %x) {
+; CHECK-LABEL: @fdiv_nan_op0(
+; CHECK-NEXT:    ret <2 x double> <double 0xFFF800000000000F, double 0xFFF800000000000F>
+;
+  %r = fdiv <2 x double> <double 0xFFF800000000000F, double 0xFFF800000000000F>, %x
+  ret <2 x double>  %r
+}
+
+; Vector with different NaN constant elements
+
+define <2 x half> @fdiv_nan_op1(<2 x half> %x) {
+; CHECK-LABEL: @fdiv_nan_op1(
+; CHECK-NEXT:    ret <2 x half> <half 0xH7FFF, half 0xHFF00>
+;
+  %r = fdiv <2 x half> %x, <half 0xH7FFF, half 0xHFF00>
+  ret <2 x half> %r
+}
+
+; Vector with undef element
+
+define <2 x double> @frem_nan_op0(<2 x double> %x) {
+; CHECK-LABEL: @frem_nan_op0(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>
+;
+  %r = frem <2 x double> <double 0xFFFF000000000000, double undef>, %x
+  ret <2 x double> %r
+}
+
+define float @frem_nan_op1(float %x) {
+; CHECK-LABEL: @frem_nan_op1(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = frem float %x, 0x7FF8000000000000
+  ret float %r
+}
+
+; Special-case: fneg must only change the sign bit (this is handled by constant folding).
+
+define double @fneg_nan_1(double %x) {
+; CHECK-LABEL: @fneg_nan_1(
+; CHECK-NEXT:    ret double 0xFFFABCDEF0123456
+;
+  %r = fsub double -0.0, 0x7FFABCDEF0123456
+  ret double %r
+}
+
+define <2 x double> @fneg_nan_2(<2 x double> %x) {
+; CHECK-LABEL: @fneg_nan_2(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF1234567890ABC, double 0xFFF0000000000001>
+;
+  %r = fsub <2 x double> <double -0.0, double -0.0>, <double 0xFFF1234567890ABC, double 0x7FF0000000000001>
+  ret <2 x double> %r
+}
+
+; Repeat all tests with fast-math-flags. Alternate 'nnan' and 'fast' for more coverage.
+
+define float @fadd_nan_op0_nnan(float %x) {
+; CHECK-LABEL: @fadd_nan_op0_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fadd nnan float 0x7FF8000000000000, %x
+  ret float %r
+}
+
+define float @fadd_nan_op1_fast(float %x) {
+; CHECK-LABEL: @fadd_nan_op1_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fadd fast float %x, 0x7FF8000000000000
+  ret float %r
+}
+
+define float @fsub_nan_op0_fast(float %x) {
+; CHECK-LABEL: @fsub_nan_op0_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fsub fast float 0x7FF8000000000000, %x
+  ret float %r
+}
+
+define float @fsub_nan_op1_nnan(float %x) {
+; CHECK-LABEL: @fsub_nan_op1_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fsub nnan float %x, 0x7FF8000000000000
+  ret float %r
+}
+
+define float @fmul_nan_op0_nnan(float %x) {
+; CHECK-LABEL: @fmul_nan_op0_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fmul nnan float 0x7FF8000000000000, %x
+  ret float %r
+}
+
+define float @fmul_nan_op1_fast(float %x) {
+; CHECK-LABEL: @fmul_nan_op1_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fmul fast float %x, 0x7FF8000000000000
+  ret float %r
+}
+
+define float @fdiv_nan_op0_fast(float %x) {
+; CHECK-LABEL: @fdiv_nan_op0_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fdiv fast float 0x7FF8000000000000, %x
+  ret float %r
+}
+
+define float @fdiv_nan_op1_nnan(float %x) {
+; CHECK-LABEL: @fdiv_nan_op1_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fdiv nnan float %x, 0x7FF8000000000000
+  ret float %r
+}
+
+define float @frem_nan_op0_nnan(float %x) {
+; CHECK-LABEL: @frem_nan_op0_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = frem nnan float 0x7FF8000000000000, %x
+  ret float %r
+}
+
+define float @frem_nan_op1_fast(float %x) {
+; CHECK-LABEL: @frem_nan_op1_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = frem fast float %x, 0x7FF8000000000000
+  ret float %r
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/fp-undef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/fp-undef.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/fp-undef.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/fp-undef.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,533 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define float @fadd_undef_op0(float %x) {
+; CHECK-LABEL: @fadd_undef_op0(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fadd float undef, %x
+  ret float %r
+}
+
+define float @fadd_undef_op1(float %x) {
+; CHECK-LABEL: @fadd_undef_op1(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fadd float %x, undef
+  ret float %r
+}
+
+define float @fsub_undef_op0(float %x) {
+; CHECK-LABEL: @fsub_undef_op0(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fsub float undef, %x
+  ret float %r
+}
+
+define float @fsub_undef_op1(float %x) {
+; CHECK-LABEL: @fsub_undef_op1(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fsub float %x, undef
+  ret float %r
+}
+
+define float @fmul_undef_op0(float %x) {
+; CHECK-LABEL: @fmul_undef_op0(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fmul float undef, %x
+  ret float %r
+}
+
+define float @fmul_undef_op1(float %x) {
+; CHECK-LABEL: @fmul_undef_op1(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fmul float %x, undef
+  ret float %r
+}
+
+define float @fdiv_undef_op0(float %x) {
+; CHECK-LABEL: @fdiv_undef_op0(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fdiv float undef, %x
+  ret float %r
+}
+
+define float @fdiv_undef_op1(float %x) {
+; CHECK-LABEL: @fdiv_undef_op1(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fdiv float %x, undef
+  ret float %r
+}
+
+define float @frem_undef_op0(float %x) {
+; CHECK-LABEL: @frem_undef_op0(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = frem float undef, %x
+  ret float %r
+}
+
+define float @frem_undef_op1(float %x) {
+; CHECK-LABEL: @frem_undef_op1(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = frem float %x, undef
+  ret float %r
+}
+
+; Repeat all tests with fast-math-flags. Alternate 'nnan' and 'fast' for more coverage.
+
+define float @fadd_undef_op0_nnan(float %x) {
+; CHECK-LABEL: @fadd_undef_op0_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fadd nnan float undef, %x
+  ret float %r
+}
+
+define float @fadd_undef_op1_fast(float %x) {
+; CHECK-LABEL: @fadd_undef_op1_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fadd fast float %x, undef
+  ret float %r
+}
+
+define float @fsub_undef_op0_fast(float %x) {
+; CHECK-LABEL: @fsub_undef_op0_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fsub fast float undef, %x
+  ret float %r
+}
+
+define float @fsub_undef_op1_nnan(float %x) {
+; CHECK-LABEL: @fsub_undef_op1_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fsub nnan float %x, undef
+  ret float %r
+}
+
+define float @fmul_undef_op0_nnan(float %x) {
+; CHECK-LABEL: @fmul_undef_op0_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fmul nnan float undef, %x
+  ret float %r
+}
+
+define float @fmul_undef_op1_fast(float %x) {
+; CHECK-LABEL: @fmul_undef_op1_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fmul fast float %x, undef
+  ret float %r
+}
+
+define float @fdiv_undef_op0_fast(float %x) {
+; CHECK-LABEL: @fdiv_undef_op0_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fdiv fast float undef, %x
+  ret float %r
+}
+
+define float @fdiv_undef_op1_nnan(float %x) {
+; CHECK-LABEL: @fdiv_undef_op1_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fdiv nnan float %x, undef
+  ret float %r
+}
+
+define float @frem_undef_op0_nnan(float %x) {
+; CHECK-LABEL: @frem_undef_op0_nnan(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = frem nnan float undef, %x
+  ret float %r
+}
+
+define float @frem_undef_op1_fast(float %x) {
+; CHECK-LABEL: @frem_undef_op1_fast(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = frem fast float %x, undef
+  ret float %r
+}
+
+; Constant folding - undef undef.
+
+define double @fadd_undef_undef(double %x) {
+; CHECK-LABEL: @fadd_undef_undef(
+; CHECK-NEXT:    ret double undef
+;
+  %r = fadd double undef, undef
+  ret double %r
+}
+
+define double @fsub_undef_undef(double %x) {
+; CHECK-LABEL: @fsub_undef_undef(
+; CHECK-NEXT:    ret double undef
+;
+  %r = fsub double undef, undef
+  ret double %r
+}
+
+define double @fmul_undef_undef(double %x) {
+; CHECK-LABEL: @fmul_undef_undef(
+; CHECK-NEXT:    ret double undef
+;
+  %r = fmul double undef, undef
+  ret double %r
+}
+
+define double @fdiv_undef_undef(double %x) {
+; CHECK-LABEL: @fdiv_undef_undef(
+; CHECK-NEXT:    ret double undef
+;
+  %r = fdiv double undef, undef
+  ret double %r
+}
+
+define double @frem_undef_undef(double %x) {
+; CHECK-LABEL: @frem_undef_undef(
+; CHECK-NEXT:    ret double undef
+;
+  %r = frem double undef, undef
+  ret double %r
+}
+
+; Constant folding.
+
+define float @fadd_undef_op0_nnan_constant(float %x) {
+; CHECK-LABEL: @fadd_undef_op0_nnan_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fadd nnan float undef, 1.0
+  ret float %r
+}
+
+define float @fadd_undef_op1_constant(float %x) {
+; CHECK-LABEL: @fadd_undef_op1_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fadd float 2.0, undef
+  ret float %r
+}
+
+define float @fsub_undef_op0_fast_constant(float %x) {
+; CHECK-LABEL: @fsub_undef_op0_fast_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fsub fast float undef, 3.0
+  ret float %r
+}
+
+define float @fsub_undef_op1_constant(float %x) {
+; CHECK-LABEL: @fsub_undef_op1_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fsub float 4.0, undef
+  ret float %r
+}
+
+define float @fmul_undef_op0_nnan_constant(float %x) {
+; CHECK-LABEL: @fmul_undef_op0_nnan_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fmul nnan float undef, 5.0
+  ret float %r
+}
+
+define float @fmul_undef_op1_constant(float %x) {
+; CHECK-LABEL: @fmul_undef_op1_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fmul float 6.0, undef
+  ret float %r
+}
+
+define float @fdiv_undef_op0_fast_constant(float %x) {
+; CHECK-LABEL: @fdiv_undef_op0_fast_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fdiv fast float undef, 7.0
+  ret float %r
+}
+
+define float @fdiv_undef_op1_constant(float %x) {
+; CHECK-LABEL: @fdiv_undef_op1_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = fdiv float 8.0, undef
+  ret float %r
+}
+
+define float @frem_undef_op0_nnan_constant(float %x) {
+; CHECK-LABEL: @frem_undef_op0_nnan_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = frem nnan float undef, 9.0
+  ret float %r
+}
+
+define float @frem_undef_op1_constant(float %x) {
+; CHECK-LABEL: @frem_undef_op1_constant(
+; CHECK-NEXT:    ret float 0x7FF8000000000000
+;
+  %r = frem float 10.0, undef
+  ret float %r
+}
+
+; Constant folding - special constants: NaN.
+
+define double @fadd_undef_op0_constant_nan(double %x) {
+; CHECK-LABEL: @fadd_undef_op0_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fadd double undef, 0x7FF8000000000000
+  ret double %r
+}
+
+define double @fadd_undef_op1_fast_constant_nan(double %x) {
+; CHECK-LABEL: @fadd_undef_op1_fast_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fadd fast double 0xFFF0000000000001, undef
+  ret double %r
+}
+
+define double @fsub_undef_op0_constant_nan(double %x) {
+; CHECK-LABEL: @fsub_undef_op0_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fsub double undef, 0xFFF8000000000010
+  ret double %r
+}
+
+define double @fsub_undef_op1_nnan_constant_nan(double %x) {
+; CHECK-LABEL: @fsub_undef_op1_nnan_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fsub nnan double 0x7FF0000000000011, undef
+  ret double %r
+}
+
+define double @fmul_undef_op0_constant_nan(double %x) {
+; CHECK-LABEL: @fmul_undef_op0_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fmul double undef, 0x7FF8000000000100
+  ret double %r
+}
+
+define double @fmul_undef_op1_fast_constant_nan(double %x) {
+; CHECK-LABEL: @fmul_undef_op1_fast_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fmul fast double 0xFFF0000000000101, undef
+  ret double %r
+}
+
+define double @fdiv_undef_op0_constant_nan(double %x) {
+; CHECK-LABEL: @fdiv_undef_op0_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fdiv double undef, 0xFFF8000000000110
+  ret double %r
+}
+
+define double @fdiv_undef_op1_nnan_constant_nan(double %x) {
+; CHECK-LABEL: @fdiv_undef_op1_nnan_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fdiv nnan double 0x7FF0000000000111, undef
+  ret double %r
+}
+
+define double @frem_undef_op0_constant_nan(double %x) {
+; CHECK-LABEL: @frem_undef_op0_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = frem double undef, 0x7FF8000000001000
+  ret double %r
+}
+
+define double @frem_undef_op1_fast_constant_nan(double %x) {
+; CHECK-LABEL: @frem_undef_op1_fast_constant_nan(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = frem fast double 0xFFF0000000001001, undef
+  ret double %r
+}
+
+; Constant folding - special constants: Inf.
+
+define double @fadd_undef_op0_constant_inf(double %x) {
+; CHECK-LABEL: @fadd_undef_op0_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fadd double undef, 0x7FF0000000000000
+  ret double %r
+}
+
+define double @fadd_undef_op1_fast_constant_inf(double %x) {
+; CHECK-LABEL: @fadd_undef_op1_fast_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fadd fast double 0xFFF0000000000000, undef
+  ret double %r
+}
+
+define double @fsub_undef_op0_constant_inf(double %x) {
+; CHECK-LABEL: @fsub_undef_op0_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fsub double undef, 0xFFF0000000000000
+  ret double %r
+}
+
+define double @fsub_undef_op1_ninf_constant_inf(double %x) {
+; CHECK-LABEL: @fsub_undef_op1_ninf_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fsub ninf double 0x7FF0000000000000, undef
+  ret double %r
+}
+
+define double @fmul_undef_op0_constant_inf(double %x) {
+; CHECK-LABEL: @fmul_undef_op0_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fmul double undef, 0x7FF0000000000000
+  ret double %r
+}
+
+define double @fmul_undef_op1_fast_constant_inf(double %x) {
+; CHECK-LABEL: @fmul_undef_op1_fast_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fmul fast double 0xFFF0000000000000, undef
+  ret double %r
+}
+
+define double @fdiv_undef_op0_constant_inf(double %x) {
+; CHECK-LABEL: @fdiv_undef_op0_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fdiv double undef, 0xFFF0000000000000
+  ret double %r
+}
+
+define double @fdiv_undef_op1_ninf_constant_inf(double %x) {
+; CHECK-LABEL: @fdiv_undef_op1_ninf_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = fdiv ninf double 0x7FF0000000000000, undef
+  ret double %r
+}
+
+define double @frem_undef_op0_constant_inf(double %x) {
+; CHECK-LABEL: @frem_undef_op0_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = frem double undef, 0x7FF0000000000000
+  ret double %r
+}
+
+define double @frem_undef_op1_fast_constant_inf(double %x) {
+; CHECK-LABEL: @frem_undef_op1_fast_constant_inf(
+; CHECK-NEXT:    ret double 0x7FF8000000000000
+;
+  %r = frem fast double 0xFFF0000000000000, undef
+  ret double %r
+}
+
+define <2 x double> @fadd_undef_op1_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @fadd_undef_op1_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
+;
+  %r = fadd <2 x double> <double 42.0, double undef>, undef
+  ret <2 x double> %r
+}
+
+define <2 x double> @fadd_undef_op0_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @fadd_undef_op0_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double undef, double 0x7FF8000000000000>
+;
+  %r = fadd <2 x double> undef, <double undef, double 42.0>
+  ret <2 x double> %r
+}
+
+define <2 x double> @fsub_undef_op1_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @fsub_undef_op1_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double undef, double 0x7FF8000000000000>
+;
+  %r = fsub <2 x double> <double undef, double 42.0>, undef
+  ret <2 x double> %r
+}
+
+define <2 x double> @fsub_undef_op0_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @fsub_undef_op0_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
+;
+  %r = fsub <2 x double> undef, <double 42.0, double undef>
+  ret <2 x double> %r
+}
+
+define <2 x double> @fmul_undef_op1_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @fmul_undef_op1_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
+;
+  %r = fmul <2 x double> <double 42.0, double undef>, undef
+  ret <2 x double> %r
+}
+
+define <2 x double> @fmul_undef_op0_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @fmul_undef_op0_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double undef, double 0x7FF8000000000000>
+;
+  %r = fmul <2 x double> undef, <double undef, double 42.0>
+  ret <2 x double> %r
+}
+
+define <2 x double> @fdiv_undef_op1_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @fdiv_undef_op1_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
+;
+  %r = fdiv <2 x double> <double 42.0, double undef>, undef
+  ret <2 x double> %r
+}
+
+define <2 x double> @fdiv_undef_op0_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @fdiv_undef_op0_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double undef, double 0x7FF8000000000000>
+;
+  %r = fdiv <2 x double> undef, <double undef, double 42.0>
+  ret <2 x double> %r
+}
+
+define <2 x double> @frem_undef_op1_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @frem_undef_op1_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double undef, double 0x7FF8000000000000>
+;
+  %r = frem <2 x double> <double undef, double 42.0>, undef
+  ret <2 x double> %r
+}
+
+define <2 x double> @frem_undef_op0_constant_vec(<2 x double> %x) {
+; CHECK-LABEL: @frem_undef_op0_constant_vec(
+; CHECK-NEXT:    ret <2 x double> <double 0x7FF8000000000000, double undef>
+;
+  %r = frem <2 x double> undef, <double 42.0, double undef>
+  ret <2 x double> %r
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/gep.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/gep.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/gep.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,105 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.A = type { [7 x i8] }
+
+define %struct.A* @test1(%struct.A* %b, %struct.A* %e) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    ret %struct.A* [[E:%.*]]
+;
+  %e_ptr = ptrtoint %struct.A* %e to i64
+  %b_ptr = ptrtoint %struct.A* %b to i64
+  %sub = sub i64 %e_ptr, %b_ptr
+  %sdiv = sdiv exact i64 %sub, 7
+  %gep = getelementptr inbounds %struct.A, %struct.A* %b, i64 %sdiv
+  ret %struct.A* %gep
+}
+
+define i8* @test2(i8* %b, i8* %e) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:    ret i8* [[E:%.*]]
+;
+  %e_ptr = ptrtoint i8* %e to i64
+  %b_ptr = ptrtoint i8* %b to i64
+  %sub = sub i64 %e_ptr, %b_ptr
+  %gep = getelementptr inbounds i8, i8* %b, i64 %sub
+  ret i8* %gep
+}
+
+define i64* @test3(i64* %b, i64* %e) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    ret i64* [[E:%.*]]
+;
+  %e_ptr = ptrtoint i64* %e to i64
+  %b_ptr = ptrtoint i64* %b to i64
+  %sub = sub i64 %e_ptr, %b_ptr
+  %ashr = ashr exact i64 %sub, 3
+  %gep = getelementptr inbounds i64, i64* %b, i64 %ashr
+  ret i64* %gep
+}
+
+define %struct.A* @test4(%struct.A* %b) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:    ret %struct.A* null
+;
+  %b_ptr = ptrtoint %struct.A* %b to i64
+  %sub = sub i64 0, %b_ptr
+  %sdiv = sdiv exact i64 %sub, 7
+  %gep = getelementptr inbounds %struct.A, %struct.A* %b, i64 %sdiv
+  ret %struct.A* %gep
+}
+
+define i8* @test5(i8* %b) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:    ret i8* null
+;
+  %b_ptr = ptrtoint i8* %b to i64
+  %sub = sub i64 0, %b_ptr
+  %gep = getelementptr inbounds i8, i8* %b, i64 %sub
+  ret i8* %gep
+}
+
+define i64* @test6(i64* %b) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:    ret i64* null
+;
+  %b_ptr = ptrtoint i64* %b to i64
+  %sub = sub i64 0, %b_ptr
+  %ashr = ashr exact i64 %sub, 3
+  %gep = getelementptr inbounds i64, i64* %b, i64 %ashr
+  ret i64* %gep
+}
+
+define i8* @test7(i8* %b, i8** %e) {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT:    [[E_PTR:%.*]] = ptrtoint i8** [[E:%.*]] to i64
+; CHECK-NEXT:    [[B_PTR:%.*]] = ptrtoint i8* [[B:%.*]] to i64
+; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[E_PTR]], [[B_PTR]]
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, i8* [[B]], i64 [[SUB]]
+; CHECK-NEXT:    ret i8* [[GEP]]
+;
+  %e_ptr = ptrtoint i8** %e to i64
+  %b_ptr = ptrtoint i8* %b to i64
+  %sub = sub i64 %e_ptr, %b_ptr
+  %gep = getelementptr inbounds i8, i8* %b, i64 %sub
+  ret i8* %gep
+}
+
+define <8 x i64*> @undef_vec1() {
+; CHECK-LABEL: @undef_vec1(
+; CHECK-NEXT:    ret <8 x i64*> undef
+;
+  %el = getelementptr inbounds i64, i64* undef, <8 x i64> undef
+  ret <8 x i64*> %el
+}
+
+define <8 x i64*> @undef_vec2() {
+; CHECK-LABEL: @undef_vec2(
+; CHECK-NEXT:    ret <8 x i64*> undef
+;
+  %el = getelementptr i64, <8 x i64*> undef, <8 x i64> undef
+  ret <8 x i64*> %el
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,403 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; This is canonical form for this IR.
+
+define i1 @abs_nsw_is_positive(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sgt i32 %abs, -1
+  ret i1 %r
+}
+
+; Test non-canonical predicate and non-canonical form of abs().
+
+define i1 @abs_nsw_is_positive_sge(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_sge(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sge i32 %abs, 0
+  ret i1 %r
+}
+
+; This is a range-based analysis. Any negative constant works.
+
+define i1 @abs_nsw_is_positive_reduced_range(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_reduced_range(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sgt i32 %abs, -42
+  ret i1 %r
+}
+
+; Negative test - we need 'nsw' in the abs().
+
+define i1 @abs_is_positive_reduced_range(i32 %x) {
+; CHECK-LABEL: @abs_is_positive_reduced_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[ABS]], 42
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sgt i32 %abs, 42
+  ret i1 %r
+}
+
+; Negative test - range intersection is not subset.
+
+define i1 @abs_nsw_is_positive_wrong_range(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_wrong_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[ABS]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sgt i32 %abs, 0
+  ret i1 %r
+}
+
+; This is canonical form for this IR.
+
+define i1 @abs_nsw_is_not_negative(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp slt i32 %abs, 0
+  ret i1 %r
+}
+
+; Test non-canonical predicate and non-canonical form of abs().
+
+define i1 @abs_nsw_is_not_negative_sle(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_sle(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sle i32 %abs, -1
+  ret i1 %r
+}
+
+; This is a range-based analysis. Any negative constant works.
+
+define i1 @abs_nsw_is_not_negative_reduced_range(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_reduced_range(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp slt i32 %abs, -24
+  ret i1 %r
+}
+
+; Negative test - we need 'nsw' in the abs().
+
+define i1 @abs_is_not_negative_reduced_range(i32 %x) {
+; CHECK-LABEL: @abs_is_not_negative_reduced_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[ABS]], 42
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp slt i32 %abs, 42
+  ret i1 %r
+}
+
+; Negative test - range intersection is not empty.
+
+define i1 @abs_nsw_is_not_negative_wrong_range(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_wrong_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sle i32 [[ABS]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sle i32 %abs, 0
+  ret i1 %r
+}
+
+; Even if we don't have nsw, the range is still limited in the unsigned domain.
+define i1 @abs_positive_or_signed_min(i32 %x) {
+; CHECK-LABEL: @abs_positive_or_signed_min(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp ult i32 %abs, 2147483649
+  ret i1 %r
+}
+
+define i1 @abs_positive_or_signed_min_reduced_range(i32 %x) {
+; CHECK-LABEL: @abs_positive_or_signed_min_reduced_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ult i32 [[ABS]], -2147483648
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp ult i32 %abs, 2147483648
+  ret i1 %r
+}
+
+; This is canonical form for this IR. For nabs(), we don't require 'nsw'
+
+define i1 @nabs_is_negative_or_0(i32 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp slt i32 %nabs, 1
+  ret i1 %r
+}
+
+; Test non-canonical predicate and non-canonical form of nabs().
+
+define i1 @nabs_is_negative_or_0_sle(i32 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0_sle(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sle i32 %nabs, 0
+  ret i1 %r
+}
+
+; This is a range-based analysis. Any positive constant works.
+
+define i1 @nabs_is_negative_or_0_reduced_range(i32 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0_reduced_range(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp slt i32 %nabs, 421
+  ret i1 %r
+}
+
+; Negative test - range intersection is not subset.
+
+define i1 @nabs_is_negative_or_0_wrong_range(i32 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0_wrong_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[NABS]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp slt i32 %nabs, 0
+  ret i1 %r
+}
+
+; This is canonical form for this IR. For nabs(), we don't require 'nsw'
+
+define i1 @nabs_is_not_over_0(i32 %x) {
+; CHECK-LABEL: @nabs_is_not_over_0(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sgt i32 %nabs, 0
+  ret i1 %r
+}
+
+; Test non-canonical predicate and non-canonical form of nabs().
+
+define i1 @nabs_is_not_over_0_sle(i32 %x) {
+; CHECK-LABEL: @nabs_is_not_over_0_sle(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sge i32 %nabs, 1
+  ret i1 %r
+}
+
+; This is a range-based analysis. Any positive constant works.
+
+define i1 @nabs_is_not_over_0_reduced_range(i32 %x) {
+; CHECK-LABEL: @nabs_is_not_over_0_reduced_range(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sgt i32 %nabs, 4223
+  ret i1 %r
+}
+
+; Negative test - range intersection is not subset.
+
+define i1 @nabs_is_not_over_0_wrong_range(i32 %x) {
+; CHECK-LABEL: @nabs_is_not_over_0_wrong_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[NABS]], -1
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sgt i32 %nabs, -1
+  ret i1 %r
+}
+
+; More miscellaneous tests for predicates/types.
+
+; Equality predicates are ok.
+
+define i1 @abs_nsw_is_positive_eq(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_eq(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp eq i32 %abs, -8
+  ret i1 %r
+}
+
+; An unsigned compare may work.
+
+define i1 @abs_nsw_is_positive_ult(i8 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_ult(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i8 %x, 0
+  %negx = sub nsw i8 0, %x
+  %abs = select i1 %cmp, i8 %negx, i8 %x
+  %r = icmp ult i8 %abs, 139
+  ret i1 %r
+}
+
+; An unsigned compare may work.
+
+define i1 @abs_nsw_is_not_negative_ugt(i8 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_ugt(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i8 %x, 0
+  %negx = sub nsw i8 0, %x
+  %abs = select i1 %cmp, i8 %negx, i8 %x
+  %r = icmp ugt i8 %abs, 127
+  ret i1 %r
+}
+
+; Vector types are ok.
+
+define <2 x i1> @abs_nsw_is_not_negative_vec_splat(<2 x i32> %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_vec_splat(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %cmp = icmp slt <2 x i32> %x, zeroinitializer
+  %negx = sub nsw <2 x i32> zeroinitializer, %x
+  %abs = select <2 x i1> %cmp, <2 x i32> %negx, <2 x i32> %x
+  %r = icmp slt <2 x i32> %abs, <i32 -8, i32 -8>
+  ret <2 x i1> %r
+}
+
+; Equality predicates are ok.
+
+define i1 @nabs_is_negative_or_0_ne(i8 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i8 %x, 0
+  %negx = sub i8 0, %x
+  %nabs = select i1 %cmp, i8 %x, i8 %negx
+  %r = icmp ne i8 %nabs, 12
+  ret i1 %r
+}
+
+; Vector types are ok.
+
+define <3 x i1> @nabs_is_not_over_0_sle_vec_splat(<3 x i33> %x) {
+; CHECK-LABEL: @nabs_is_not_over_0_sle_vec_splat(
+; CHECK-NEXT:    ret <3 x i1> zeroinitializer
+;
+  %cmp = icmp slt <3 x i33> %x, <i33 1, i33 1, i33 1>
+  %negx = sub <3 x i33> zeroinitializer, %x
+  %nabs = select <3 x i1> %cmp, <3 x i33> %x, <3 x i33> %negx
+  %r = icmp sge <3 x i33> %nabs, <i33 1, i33 1, i33 1>
+  ret <3 x i1> %r
+}
+
+; Negative test - intersection does not equal absolute value range.
+; PR39510 - https://bugs.llvm.org/show_bug.cgi?id=39510
+
+define i1 @abs_no_intersection(i32 %a) {
+; CHECK-LABEL: @abs_no_intersection(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i32 [[COND]], 2
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %a, 0
+  %sub = sub nsw i32 0, %a
+  %cond = select i1 %cmp, i32 %sub, i32 %a
+  %r = icmp ne i32 %cond, 2
+  ret i1 %r
+}
+
+; Negative test - intersection does not equal absolute value range.
+
+define i1 @nabs_no_intersection(i32 %a) {
+; CHECK-LABEL: @nabs_no_intersection(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[A]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i32 [[COND]], -2
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp sgt i32 %a, 0
+  %sub = sub i32 0, %a
+  %cond = select i1 %cmp, i32 %sub, i32 %a
+  %r = icmp ne i32 %cond, -2
+  ret i1 %r
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/icmp-bool-constant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/icmp-bool-constant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/icmp-bool-constant.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/icmp-bool-constant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,196 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; Test all integer predicates with bool types and true/false constants.
+; Use vectors to provide test coverage that is not duplicated in other folds.
+
+define <2 x i1> @eq_t(<2 x i1> %a) {
+; CHECK-LABEL: @eq_t(
+; CHECK-NEXT:    ret <2 x i1> %a
+;
+  %r = icmp eq <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @eq_t_undef_elt(<2 x i1> %a) {
+; CHECK-LABEL: @eq_t_undef_elt(
+; CHECK-NEXT:    ret <2 x i1> [[A:%.*]]
+;
+  %r = icmp eq <2 x i1> %a, <i1 undef, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @eq_f(<2 x i1> %a) {
+; CHECK-LABEL: @eq_f(
+; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i1> %a, zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %r = icmp eq <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ne_t(<2 x i1> %a) {
+; CHECK-LABEL: @ne_t(
+; CHECK-NEXT:    [[R:%.*]] = icmp ne <2 x i1> %a, <i1 true, i1 true>
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %r = icmp ne <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ne_f(<2 x i1> %a) {
+; CHECK-LABEL: @ne_f(
+; CHECK-NEXT:    ret <2 x i1> %a
+;
+  %r = icmp ne <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ugt_t(<2 x i1> %a) {
+; CHECK-LABEL: @ugt_t(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %r = icmp ugt <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ugt_t_undef_elt(<2 x i1> %a) {
+; CHECK-LABEL: @ugt_t_undef_elt(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %r = icmp ugt <2 x i1> %a, <i1 true, i1 undef>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ugt_f(<2 x i1> %a) {
+; CHECK-LABEL: @ugt_f(
+; CHECK-NEXT:    ret <2 x i1> %a
+;
+  %r = icmp ugt <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ult_t(<2 x i1> %a) {
+; CHECK-LABEL: @ult_t(
+; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i1> %a, <i1 true, i1 true>
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %r = icmp ult <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ult_f(<2 x i1> %a) {
+; CHECK-LABEL: @ult_f(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %r = icmp ult <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @sgt_t(<2 x i1> %a) {
+; CHECK-LABEL: @sgt_t(
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt <2 x i1> %a, <i1 true, i1 true>
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %r = icmp sgt <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @sgt_f(<2 x i1> %a) {
+; CHECK-LABEL: @sgt_f(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %r = icmp sgt <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @slt_t(<2 x i1> %a) {
+; CHECK-LABEL: @slt_t(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %r = icmp slt <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @slt_f(<2 x i1> %a) {
+; CHECK-LABEL: @slt_f(
+; CHECK-NEXT:    ret <2 x i1> %a
+;
+  %r = icmp slt <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @uge_t(<2 x i1> %a) {
+; CHECK-LABEL: @uge_t(
+; CHECK-NEXT:    ret <2 x i1> %a
+;
+  %r = icmp uge <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @uge_f(<2 x i1> %a) {
+; CHECK-LABEL: @uge_f(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %r = icmp uge <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ule_t(<2 x i1> %a) {
+; CHECK-LABEL: @ule_t(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %r = icmp ule <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ule_f(<2 x i1> %a) {
+; CHECK-LABEL: @ule_f(
+; CHECK-NEXT:    [[R:%.*]] = icmp ule <2 x i1> %a, zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %r = icmp ule <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @sge_t(<2 x i1> %a) {
+; CHECK-LABEL: @sge_t(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %r = icmp sge <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @sge_t_undef_elt(<2 x i1> %a) {
+; CHECK-LABEL: @sge_t_undef_elt(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %r = icmp sge <2 x i1> %a, <i1 true, i1 undef>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @sge_f(<2 x i1> %a) {
+; CHECK-LABEL: @sge_f(
+; CHECK-NEXT:    [[R:%.*]] = icmp sge <2 x i1> %a, zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %r = icmp sge <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @sle_t(<2 x i1> %a) {
+; CHECK-LABEL: @sle_t(
+; CHECK-NEXT:    ret <2 x i1> %a
+;
+  %r = icmp sle <2 x i1> %a, <i1 true, i1 true>
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @sle_f(<2 x i1> %a) {
+; CHECK-LABEL: @sle_f(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %r = icmp sle <2 x i1> %a, <i1 false, i1 false>
+  ret <2 x i1> %r
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/icmp-constant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/icmp-constant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/icmp-constant.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/icmp-constant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,760 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; Fold icmp with a constant operand.
+
+define i1 @tautological_ule(i8 %x) {
+; CHECK-LABEL: @tautological_ule(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp ule i8 %x, 255
+  ret i1 %cmp
+}
+
+define <2 x i1> @tautological_ule_vec(<2 x i8> %x) {
+; CHECK-LABEL: @tautological_ule_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %cmp = icmp ule <2 x i8> %x, <i8 255, i8 255>
+  ret <2 x i1> %cmp
+}
+
+define i1 @tautological_ugt(i8 %x) {
+; CHECK-LABEL: @tautological_ugt(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp ugt i8 %x, 255
+  ret i1 %cmp
+}
+
+define <2 x i1> @tautological_ugt_vec(<2 x i8> %x) {
+; CHECK-LABEL: @tautological_ugt_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %cmp = icmp ugt <2 x i8> %x, <i8 255, i8 255>
+  ret <2 x i1> %cmp
+}
+
+; 'urem x, C2' produces [0, C2)
+define i1 @urem3(i32 %X) {
+; CHECK-LABEL: @urem3(
+; CHECK-NEXT:    ret i1 true
+;
+  %A = urem i32 %X, 10
+  %B = icmp ult i32 %A, 15
+  ret i1 %B
+}
+
+define <2 x i1> @urem3_vec(<2 x i32> %X) {
+; CHECK-LABEL: @urem3_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %A = urem <2 x i32> %X, <i32 10, i32 10>
+  %B = icmp ult <2 x i32> %A, <i32 15, i32 15>
+  ret <2 x i1> %B
+}
+
+;'srem x, C2' produces (-|C2|, |C2|)
+define i1 @srem1(i32 %X) {
+; CHECK-LABEL: @srem1(
+; CHECK-NEXT:    ret i1 false
+;
+  %A = srem i32 %X, -5
+  %B = icmp sgt i32 %A, 5
+  ret i1 %B
+}
+
+define <2 x i1> @srem1_vec(<2 x i32> %X) {
+; CHECK-LABEL: @srem1_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %A = srem <2 x i32> %X, <i32 -5, i32 -5>
+  %B = icmp sgt <2 x i32> %A, <i32 5, i32 5>
+  ret <2 x i1> %B
+}
+
+;'udiv C2, x' produces [0, C2]
+define i1 @udiv5(i32 %X) {
+; CHECK-LABEL: @udiv5(
+; CHECK-NEXT:    ret i1 false
+;
+  %A = udiv i32 123, %X
+  %C = icmp ugt i32 %A, 124
+  ret i1 %C
+}
+
+define <2 x i1> @udiv5_vec(<2 x i32> %X) {
+; CHECK-LABEL: @udiv5_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %A = udiv <2 x i32> <i32 123, i32 123>, %X
+  %C = icmp ugt <2 x i32> %A, <i32 124, i32 124>
+  ret <2 x i1> %C
+}
+
+; 'udiv x, C2' produces [0, UINT_MAX / C2]
+define i1 @udiv1(i32 %X) {
+; CHECK-LABEL: @udiv1(
+; CHECK-NEXT:    ret i1 true
+;
+  %A = udiv i32 %X, 1000000
+  %B = icmp ult i32 %A, 5000
+  ret i1 %B
+}
+
+define <2 x i1> @udiv1_vec(<2 x i32> %X) {
+; CHECK-LABEL: @udiv1_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %A = udiv <2 x i32> %X, <i32 1000000, i32 1000000>
+  %B = icmp ult <2 x i32> %A, <i32 5000, i32 5000>
+  ret <2 x i1> %B
+}
+
+; 'sdiv C2, x' produces [-|C2|, |C2|]
+define i1 @compare_dividend(i32 %a) {
+; CHECK-LABEL: @compare_dividend(
+; CHECK-NEXT:    ret i1 false
+;
+  %div = sdiv i32 2, %a
+  %cmp = icmp eq i32 %div, 3
+  ret i1 %cmp
+}
+
+define <2 x i1> @compare_dividend_vec(<2 x i32> %a) {
+; CHECK-LABEL: @compare_dividend_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %div = sdiv <2 x i32> <i32 2, i32 2>, %a
+  %cmp = icmp eq <2 x i32> %div, <i32 3, i32 3>
+  ret <2 x i1> %cmp
+}
+
+; 'sdiv x, C2' produces [INT_MIN / C2, INT_MAX / C2]
+;    where C2 != -1 and C2 != 0 and C2 != 1
+define i1 @sdiv1(i32 %X) {
+; CHECK-LABEL: @sdiv1(
+; CHECK-NEXT:    ret i1 true
+;
+  %A = sdiv i32 %X, 1000000
+  %B = icmp slt i32 %A, 3000
+  ret i1 %B
+}
+
+define <2 x i1> @sdiv1_vec(<2 x i32> %X) {
+; CHECK-LABEL: @sdiv1_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %A = sdiv <2 x i32> %X, <i32 1000000, i32 1000000>
+  %B = icmp slt <2 x i32> %A, <i32 3000, i32 3000>
+  ret <2 x i1> %B
+}
+
+; 'shl nuw C2, x' produces [C2, C2 << CLZ(C2)]
+define i1 @shl5(i32 %X) {
+; CHECK-LABEL: @shl5(
+; CHECK-NEXT:    ret i1 true
+;
+  %sub = shl nuw i32 4, %X
+  %cmp = icmp ugt i32 %sub, 3
+  ret i1 %cmp
+}
+
+define <2 x i1> @shl5_vec(<2 x i32> %X) {
+; CHECK-LABEL: @shl5_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %sub = shl nuw <2 x i32> <i32 4, i32 4>, %X
+  %cmp = icmp ugt <2 x i32> %sub, <i32 3, i32 3>
+  ret <2 x i1> %cmp
+}
+
+; 'shl nsw C2, x' produces [C2 << CLO(C2)-1, C2]
+define i1 @shl2(i32 %X) {
+; CHECK-LABEL: @shl2(
+; CHECK-NEXT:    ret i1 false
+;
+  %sub = shl nsw i32 -1, %X
+  %cmp = icmp eq i32 %sub, 31
+  ret i1 %cmp
+}
+
+define <2 x i1> @shl2_vec(<2 x i32> %X) {
+; CHECK-LABEL: @shl2_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %sub = shl nsw <2 x i32> <i32 -1, i32 -1>, %X
+  %cmp = icmp eq <2 x i32> %sub, <i32 31, i32 31>
+  ret <2 x i1> %cmp
+}
+
+; 'shl nsw C2, x' produces [C2 << CLO(C2)-1, C2]
+define i1 @shl4(i32 %X) {
+; CHECK-LABEL: @shl4(
+; CHECK-NEXT:    ret i1 true
+;
+  %sub = shl nsw i32 -1, %X
+  %cmp = icmp sle i32 %sub, -1
+  ret i1 %cmp
+}
+
+define <2 x i1> @shl4_vec(<2 x i32> %X) {
+; CHECK-LABEL: @shl4_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %sub = shl nsw <2 x i32> <i32 -1, i32 -1>, %X
+  %cmp = icmp sle <2 x i32> %sub, <i32 -1, i32 -1>
+  ret <2 x i1> %cmp
+}
+
+; 'shl nsw C2, x' produces [C2, C2 << CLZ(C2)-1]
+define i1 @icmp_shl_nsw_1(i64 %a) {
+; CHECK-LABEL: @icmp_shl_nsw_1(
+; CHECK-NEXT:    ret i1 true
+;
+  %shl = shl nsw i64 1, %a
+  %cmp = icmp sge i64 %shl, 0
+  ret i1 %cmp
+}
+
+define <2 x i1> @icmp_shl_nsw_1_vec(<2 x i64> %a) {
+; CHECK-LABEL: @icmp_shl_nsw_1_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %shl = shl nsw <2 x i64> <i64 1, i64 1>, %a
+  %cmp = icmp sge <2 x i64> %shl, zeroinitializer
+  ret <2 x i1> %cmp
+}
+
+; 'shl nsw C2, x' produces [C2 << CLO(C2)-1, C2]
+define i1 @icmp_shl_nsw_neg1(i64 %a) {
+; CHECK-LABEL: @icmp_shl_nsw_neg1(
+; CHECK-NEXT:    ret i1 false
+;
+  %shl = shl nsw i64 -1, %a
+  %cmp = icmp sge i64 %shl, 3
+  ret i1 %cmp
+}
+
+define <2 x i1> @icmp_shl_nsw_neg1_vec(<2 x i64> %a) {
+; CHECK-LABEL: @icmp_shl_nsw_neg1_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %shl = shl nsw <2 x i64> <i64 -1, i64 -1>, %a
+  %cmp = icmp sge <2 x i64> %shl, <i64 3, i64 3>
+  ret <2 x i1> %cmp
+}
+
+; 'lshr x, C2' produces [0, UINT_MAX >> C2]
+define i1 @lshr2(i32 %x) {
+; CHECK-LABEL: @lshr2(
+; CHECK-NEXT:    ret i1 false
+;
+  %s = lshr i32 %x, 30
+  %c = icmp ugt i32 %s, 8
+  ret i1 %c
+}
+
+define <2 x i1> @lshr2_vec(<2 x i32> %x) {
+; CHECK-LABEL: @lshr2_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %s = lshr <2 x i32> %x, <i32 30, i32 30>
+  %c = icmp ugt <2 x i32> %s, <i32 8, i32 8>
+  ret <2 x i1> %c
+}
+
+; 'lshr C2, x' produces [C2 >> (Width-1), C2]
+define i1 @exact_lshr_ugt_false(i32 %a) {
+; CHECK-LABEL: @exact_lshr_ugt_false(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr exact i32 30, %a
+  %cmp = icmp ult i32 %shr, 15
+  ret i1 %cmp
+}
+
+define <2 x i1> @exact_lshr_ugt_false_vec(<2 x i32> %a) {
+; CHECK-LABEL: @exact_lshr_ugt_false_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %shr = lshr exact <2 x i32> <i32 30, i32 30>, %a
+  %cmp = icmp ult <2 x i32> %shr, <i32 15, i32 15>
+  ret <2 x i1> %cmp
+}
+
+; 'lshr C2, x' produces [C2 >> (Width-1), C2]
+define i1 @lshr_sgt_false(i32 %a) {
+; CHECK-LABEL: @lshr_sgt_false(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr i32 1, %a
+  %cmp = icmp sgt i32 %shr, 1
+  ret i1 %cmp
+}
+
+define <2 x i1> @lshr_sgt_false_vec(<2 x i32> %a) {
+; CHECK-LABEL: @lshr_sgt_false_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %shr = lshr <2 x i32> <i32 1, i32 1>, %a
+  %cmp = icmp sgt <2 x i32> %shr, <i32 1, i32 1>
+  ret <2 x i1> %cmp
+}
+
+; 'ashr x, C2' produces [INT_MIN >> C2, INT_MAX >> C2]
+define i1 @ashr2(i32 %x) {
+; CHECK-LABEL: @ashr2(
+; CHECK-NEXT:    ret i1 false
+;
+  %s = ashr i32 %x, 30
+  %c = icmp slt i32 %s, -5
+  ret i1 %c
+}
+
+define <2 x i1> @ashr2_vec(<2 x i32> %x) {
+; CHECK-LABEL: @ashr2_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %s = ashr <2 x i32> %x, <i32 30, i32 30>
+  %c = icmp slt <2 x i32> %s, <i32 -5, i32 -5>
+  ret <2 x i1> %c
+}
+
+; 'ashr C2, x' produces [C2, C2 >> (Width-1)]
+define i1 @ashr_sgt_false(i32 %a) {
+; CHECK-LABEL: @ashr_sgt_false(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr i32 -30, %a
+  %cmp = icmp sgt i32 %shr, -1
+  ret i1 %cmp
+}
+
+define <2 x i1> @ashr_sgt_false_vec(<2 x i32> %a) {
+; CHECK-LABEL: @ashr_sgt_false_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %shr = ashr <2 x i32> <i32 -30, i32 -30>, %a
+  %cmp = icmp sgt <2 x i32> %shr, <i32 -1, i32 -1>
+  ret <2 x i1> %cmp
+}
+
+; 'ashr C2, x' produces [C2, C2 >> (Width-1)]
+define i1 @exact_ashr_sgt_false(i32 %a) {
+; CHECK-LABEL: @exact_ashr_sgt_false(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr exact i32 -30, %a
+  %cmp = icmp sgt i32 %shr, -15
+  ret i1 %cmp
+}
+
+define <2 x i1> @exact_ashr_sgt_false_vec(<2 x i32> %a) {
+; CHECK-LABEL: @exact_ashr_sgt_false_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %shr = ashr exact <2 x i32> <i32 -30, i32 -30>, %a
+  %cmp = icmp sgt <2 x i32> %shr, <i32 -15, i32 -15>
+  ret <2 x i1> %cmp
+}
+
+; 'or x, C2' produces [C2, UINT_MAX]
+define i1 @or1(i32 %X) {
+; CHECK-LABEL: @or1(
+; CHECK-NEXT:    ret i1 false
+;
+  %A = or i32 %X, 62
+  %B = icmp ult i32 %A, 50
+  ret i1 %B
+}
+
+define <2 x i1> @or1_vec(<2 x i32> %X) {
+; CHECK-LABEL: @or1_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %A = or <2 x i32> %X, <i32 62, i32 62>
+  %B = icmp ult <2 x i32> %A, <i32 50, i32 50>
+  ret <2 x i1> %B
+}
+
+; Single bit OR.
+define i1 @or2_true(i8 %x) {
+; CHECK-LABEL: @or2_true(
+; CHECK-NEXT:    [[Y:%.*]] = or i8 [[X:%.*]], 64
+; CHECK-NEXT:    [[Z:%.*]] = icmp sge i8 [[Y]], -64
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = or i8 %x, 64
+  %z = icmp sge i8 %y, -64
+  ret i1 %z
+}
+
+define i1 @or2_unknown(i8 %x) {
+; CHECK-LABEL: @or2_unknown(
+; CHECK-NEXT:    [[Y:%.*]] = or i8 [[X:%.*]], 64
+; CHECK-NEXT:    [[Z:%.*]] = icmp sgt i8 [[Y]], -64
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = or i8 %x, 64
+  %z = icmp sgt i8 %y, -64
+  ret i1 %z
+}
+
+; Multi bit OR.
+; 78 = 0b01001110; -50 = 0b11001110
+define i1 @or3_true(i8 %x) {
+; CHECK-LABEL: @or3_true(
+; CHECK-NEXT:    [[Y:%.*]] = or i8 [[X:%.*]], 78
+; CHECK-NEXT:    [[Z:%.*]] = icmp sge i8 [[Y]], -50
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = or i8 %x, 78
+  %z = icmp sge i8 %y, -50
+  ret i1 %z
+}
+
+define i1 @or3_unknown(i8 %x) {
+; CHECK-LABEL: @or3_unknown(
+; CHECK-NEXT:    [[Y:%.*]] = or i8 [[X:%.*]], 78
+; CHECK-NEXT:    [[Z:%.*]] = icmp sgt i8 [[Y]], -50
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = or i8 %x, 78
+  %z = icmp sgt i8 %y, -50
+  ret i1 %z
+}
+
+; OR with sign bit.
+define i1 @or4_true(i8 %x) {
+; CHECK-LABEL: @or4_true(
+; CHECK-NEXT:    ret i1 true
+;
+  %y = or i8 %x, -64
+  %z = icmp sge i8 %y, -64
+  ret i1 %z
+}
+
+define i1 @or4_unknown(i8 %x) {
+; CHECK-LABEL: @or4_unknown(
+; CHECK-NEXT:    [[Y:%.*]] = or i8 [[X:%.*]], -64
+; CHECK-NEXT:    [[Z:%.*]] = icmp sgt i8 [[Y]], -64
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = or i8 %x, -64
+  %z = icmp sgt i8 %y, -64
+  ret i1 %z
+}
+
+; If sign bit is set, signed & unsigned ranges are the same.
+define i1 @or5_true(i8 %x) {
+; CHECK-LABEL: @or5_true(
+; CHECK-NEXT:    ret i1 true
+;
+  %y = or i8 %x, -64
+  %z = icmp uge i8 %y, -64
+  ret i1 %z
+}
+
+define i1 @or5_unknown(i8 %x) {
+; CHECK-LABEL: @or5_unknown(
+; CHECK-NEXT:    [[Y:%.*]] = or i8 [[X:%.*]], -64
+; CHECK-NEXT:    [[Z:%.*]] = icmp ugt i8 [[Y]], -64
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = or i8 %x, -64
+  %z = icmp ugt i8 %y, -64
+  ret i1 %z
+}
+
+; 'and x, C2' produces [0, C2]
+define i1 @and1(i32 %X) {
+; CHECK-LABEL: @and1(
+; CHECK-NEXT:    ret i1 false
+;
+  %A = and i32 %X, 62
+  %B = icmp ugt i32 %A, 70
+  ret i1 %B
+}
+
+define <2 x i1> @and1_vec(<2 x i32> %X) {
+; CHECK-LABEL: @and1_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %A = and <2 x i32> %X, <i32 62, i32 62>
+  %B = icmp ugt <2 x i32> %A, <i32 70, i32 70>
+  ret <2 x i1> %B
+}
+
+; If the sign bit is not set, signed and unsigned ranges are the same.
+define i1 @and2(i32 %X) {
+; CHECK-LABEL: @and2(
+; CHECK-NEXT:    ret i1 false
+;
+  %A = and i32 %X, 62
+  %B = icmp sgt i32 %A, 70
+  ret i1 %B
+}
+
+; -75 = 0b10110101, 53 = 0b00110101
+define i1 @and3_true1(i8 %x) {
+; CHECK-LABEL: @and3_true1(
+; CHECK-NEXT:    [[Y:%.*]] = and i8 [[X:%.*]], -75
+; CHECK-NEXT:    [[Z:%.*]] = icmp sge i8 [[Y]], -75
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = and i8 %x, -75
+  %z = icmp sge i8 %y, -75
+  ret i1 %z
+}
+
+define i1 @and3_unknown1(i8 %x) {
+; CHECK-LABEL: @and3_unknown1(
+; CHECK-NEXT:    [[Y:%.*]] = and i8 [[X:%.*]], -75
+; CHECK-NEXT:    [[Z:%.*]] = icmp sgt i8 [[Y]], -75
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = and i8 %x, -75
+  %z = icmp sgt i8 %y, -75
+  ret i1 %z
+}
+
+define i1 @and3_true2(i8 %x) {
+; CHECK-LABEL: @and3_true2(
+; CHECK-NEXT:    [[Y:%.*]] = and i8 [[X:%.*]], -75
+; CHECK-NEXT:    [[Z:%.*]] = icmp sle i8 [[Y]], 53
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = and i8 %x, -75
+  %z = icmp sle i8 %y, 53
+  ret i1 %z
+}
+
+define i1 @and3_unknown2(i8 %x) {
+; CHECK-LABEL: @and3_unknown2(
+; CHECK-NEXT:    [[Y:%.*]] = and i8 [[X:%.*]], -75
+; CHECK-NEXT:    [[Z:%.*]] = icmp slt i8 [[Y]], 53
+; CHECK-NEXT:    ret i1 [[Z]]
+;
+  %y = and i8 %x, -75
+  %z = icmp slt i8 %y, 53
+  ret i1 %z
+}
+
+; 'add nuw x, C2' produces [C2, UINT_MAX]
+define i1 @tautological9(i32 %x) {
+; CHECK-LABEL: @tautological9(
+; CHECK-NEXT:    ret i1 true
+;
+  %add = add nuw i32 %x, 13
+  %cmp = icmp ne i32 %add, 12
+  ret i1 %cmp
+}
+
+define <2 x i1> @tautological9_vec(<2 x i32> %x) {
+; CHECK-LABEL: @tautological9_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %add = add nuw <2 x i32> %x, <i32 13, i32 13>
+  %cmp = icmp ne <2 x i32> %add, <i32 12, i32 12>
+  ret <2 x i1> %cmp
+}
+
+; The upper bound of the 'add' is 0.
+
+define i1 @add_nsw_neg_const1(i32 %x) {
+; CHECK-LABEL: @add_nsw_neg_const1(
+; CHECK-NEXT:    ret i1 false
+;
+  %add = add nsw i32 %x, -2147483647
+  %cmp = icmp sgt i32 %add, 0
+  ret i1 %cmp
+}
+
+; InstCombine can fold this, but not InstSimplify.
+
+define i1 @add_nsw_neg_const2(i32 %x) {
+; CHECK-LABEL: @add_nsw_neg_const2(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[X:%.*]], -2147483647
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[ADD]], -1
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %add = add nsw i32 %x, -2147483647
+  %cmp = icmp sgt i32 %add, -1
+  ret i1 %cmp
+}
+
+; The upper bound of the 'add' is 1 (move the constants to prove we're doing range-based analysis).
+
+define i1 @add_nsw_neg_const3(i32 %x) {
+; CHECK-LABEL: @add_nsw_neg_const3(
+; CHECK-NEXT:    ret i1 false
+;
+  %add = add nsw i32 %x, -2147483646
+  %cmp = icmp sgt i32 %add, 1
+  ret i1 %cmp
+}
+
+; InstCombine can fold this, but not InstSimplify.
+
+define i1 @add_nsw_neg_const4(i32 %x) {
+; CHECK-LABEL: @add_nsw_neg_const4(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[X:%.*]], -2147483646
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[ADD]], 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %add = add nsw i32 %x, -2147483646
+  %cmp = icmp sgt i32 %add, 0
+  ret i1 %cmp
+}
+
+; The upper bound of the 'add' is 2147483647 - 42 = 2147483605 (move the constants again and try a different cmp predicate).
+
+define i1 @add_nsw_neg_const5(i32 %x) {
+; CHECK-LABEL: @add_nsw_neg_const5(
+; CHECK-NEXT:    ret i1 true
+;
+  %add = add nsw i32 %x, -42
+  %cmp = icmp ne i32 %add, 2147483606
+  ret i1 %cmp
+}
+
+; InstCombine can fold this, but not InstSimplify.
+
+define i1 @add_nsw_neg_const6(i32 %x) {
+; CHECK-LABEL: @add_nsw_neg_const6(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[X:%.*]], -42
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[ADD]], 2147483605
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %add = add nsw i32 %x, -42
+  %cmp = icmp ne i32 %add, 2147483605
+  ret i1 %cmp
+}
+
+; The lower bound of the 'add' is -1.
+
+define i1 @add_nsw_pos_const1(i32 %x) {
+; CHECK-LABEL: @add_nsw_pos_const1(
+; CHECK-NEXT:    ret i1 false
+;
+  %add = add nsw i32 %x, 2147483647
+  %cmp = icmp slt i32 %add, -1
+  ret i1 %cmp
+}
+
+; InstCombine can fold this, but not InstSimplify.
+
+define i1 @add_nsw_pos_const2(i32 %x) {
+; CHECK-LABEL: @add_nsw_pos_const2(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[X:%.*]], 2147483647
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[ADD]], 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %add = add nsw i32 %x, 2147483647
+  %cmp = icmp slt i32 %add, 0
+  ret i1 %cmp
+}
+
+; The lower bound of the 'add' is -2 (move the constants to prove we're doing range-based analysis).
+
+define i1 @add_nsw_pos_const3(i32 %x) {
+; CHECK-LABEL: @add_nsw_pos_const3(
+; CHECK-NEXT:    ret i1 false
+;
+  %add = add nsw i32 %x, 2147483646
+  %cmp = icmp slt i32 %add, -2
+  ret i1 %cmp
+}
+
+; InstCombine can fold this, but not InstSimplify.
+
+define i1 @add_nsw_pos_const4(i32 %x) {
+; CHECK-LABEL: @add_nsw_pos_const4(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[X:%.*]], 2147483646
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[ADD]], -1
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %add = add nsw i32 %x, 2147483646
+  %cmp = icmp slt i32 %add, -1
+  ret i1 %cmp
+}
+
+; The lower bound of the 'add' is -2147483648 + 42 = -2147483606 (move the constants again and change the cmp predicate).
+
+define i1 @add_nsw_pos_const5(i32 %x) {
+; CHECK-LABEL: @add_nsw_pos_const5(
+; CHECK-NEXT:    ret i1 false
+;
+  %add = add nsw i32 %x, 42
+  %cmp = icmp eq i32 %add, -2147483607
+  ret i1 %cmp
+}
+
+; InstCombine can fold this, but not InstSimplify.
+
+define i1 @add_nsw_pos_const6(i32 %x) {
+; CHECK-LABEL: @add_nsw_pos_const6(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[X:%.*]], 42
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[ADD]], -2147483606
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %add = add nsw i32 %x, 42
+  %cmp = icmp eq i32 %add, -2147483606
+  ret i1 %cmp
+}
+
+; Verify that vectors work too.
+
+define <2 x i1> @add_nsw_pos_const5_splat_vec(<2 x i32> %x) {
+; CHECK-LABEL: @add_nsw_pos_const5_splat_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %add = add nsw <2 x i32> %x, <i32 42, i32 42>
+  %cmp = icmp ne <2 x i32> %add, <i32 -2147483607, i32 -2147483607>
+  ret <2 x i1> %cmp
+}
+
+; PR34838 - https://bugs.llvm.org/show_bug.cgi?id=34838
+; The shift is known to create poison, so we can simplify the cmp.
+
+define i1 @ne_shl_by_constant_produces_poison(i8 %x) {
+; CHECK-LABEL: @ne_shl_by_constant_produces_poison(
+; CHECK-NEXT:    ret i1 true
+;
+  %zx = zext i8 %x to i16      ; zx  = 0x00xx
+  %xor = xor i16 %zx, 32767    ; xor = 0x7fyy
+  %sub = sub nsw i16 %zx, %xor ; sub = 0x80zz  (the top bit is known one)
+  %poison = shl nsw i16 %sub, 2    ; oops! this shl can't be nsw; that's POISON
+  %cmp = icmp ne i16 %poison, 1
+  ret i1 %cmp
+}
+
+define i1 @eq_shl_by_constant_produces_poison(i8 %x) {
+; CHECK-LABEL: @eq_shl_by_constant_produces_poison(
+; CHECK-NEXT:    ret i1 false
+;
+  %clear_high_bit = and i8 %x, 127                 ; 0x7f
+  %set_next_high_bits = or i8 %clear_high_bit, 112 ; 0x70
+  %poison = shl nsw i8 %set_next_high_bits, 3
+  %cmp = icmp eq i8 %poison, 15
+  ret i1 %cmp
+}
+
+; Shift-by-variable that produces poison is more complicated but still possible.
+; We guarantee that the shift will change the sign of the shifted value (and
+; therefore produce poison) by limiting its range from 1 to 3.
+
+define i1 @eq_shl_by_variable_produces_poison(i8 %x) {
+; CHECK-LABEL: @eq_shl_by_variable_produces_poison(
+; CHECK-NEXT:    ret i1 false
+;
+  %clear_high_bit = and i8 %x, 127                 ; 0x7f
+  %set_next_high_bits = or i8 %clear_high_bit, 112 ; 0x70
+  %notundef_shiftamt = and i8 %x, 3
+  %nonzero_shiftamt = or i8 %notundef_shiftamt, 1
+  %poison = shl nsw i8 %set_next_high_bits, %nonzero_shiftamt
+  %cmp = icmp eq i8 %poison, 15
+  ret i1 %cmp
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/icmp-ranges.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/icmp-ranges.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/icmp-ranges.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/icmp-ranges.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,5470 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; Cycle through all pairs of predicates to test
+; simplification of range-intersection or range-union.
+
+; eq
+; x == 13 && x == 17
+
+define i1 @and_eq_eq(i8 %x) {
+; CHECK-LABEL: @and_eq_eq(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 && x != 17
+
+define i1 @and_eq_ne(i8 %x) {
+; CHECK-LABEL: @and_eq_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 && x >=s 17
+
+define i1 @and_eq_sge(i8 %x) {
+; CHECK-LABEL: @and_eq_sge(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 && x >s 17
+
+define i1 @and_eq_sgt(i8 %x) {
+; CHECK-LABEL: @and_eq_sgt(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 && x <=s 17
+
+define i1 @and_eq_sle(i8 %x) {
+; CHECK-LABEL: @and_eq_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 && x <s 17
+
+define i1 @and_eq_slt(i8 %x) {
+; CHECK-LABEL: @and_eq_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 && x >=u 17
+
+define i1 @and_eq_uge(i8 %x) {
+; CHECK-LABEL: @and_eq_uge(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 && x >u 17
+
+define i1 @and_eq_ugt(i8 %x) {
+; CHECK-LABEL: @and_eq_ugt(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 && x <=u 17
+
+define i1 @and_eq_ule(i8 %x) {
+; CHECK-LABEL: @and_eq_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 && x <u 17
+
+define i1 @and_eq_ult(i8 %x) {
+; CHECK-LABEL: @and_eq_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; ne
+; x != 13 && x == 17
+
+define i1 @and_ne_eq(i8 %x) {
+; CHECK-LABEL: @and_ne_eq(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 && x != 17
+
+define i1 @and_ne_ne(i8 %x) {
+; CHECK-LABEL: @and_ne_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 && x >=s 17
+
+define i1 @and_ne_sge(i8 %x) {
+; CHECK-LABEL: @and_ne_sge(
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 && x >s 17
+
+define i1 @and_ne_sgt(i8 %x) {
+; CHECK-LABEL: @and_ne_sgt(
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 && x <=s 17
+
+define i1 @and_ne_sle(i8 %x) {
+; CHECK-LABEL: @and_ne_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 && x <s 17
+
+define i1 @and_ne_slt(i8 %x) {
+; CHECK-LABEL: @and_ne_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 && x >=u 17
+
+define i1 @and_ne_uge(i8 %x) {
+; CHECK-LABEL: @and_ne_uge(
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 && x >u 17
+
+define i1 @and_ne_ugt(i8 %x) {
+; CHECK-LABEL: @and_ne_ugt(
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 && x <=u 17
+
+define i1 @and_ne_ule(i8 %x) {
+; CHECK-LABEL: @and_ne_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 && x <u 17
+
+define i1 @and_ne_ult(i8 %x) {
+; CHECK-LABEL: @and_ne_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; sge
+; x >=s 13 && x == 17
+
+define i1 @and_sge_eq(i8 %x) {
+; CHECK-LABEL: @and_sge_eq(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 && x != 17
+
+define i1 @and_sge_ne(i8 %x) {
+; CHECK-LABEL: @and_sge_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 && x >=s 17
+
+define i1 @and_sge_sge(i8 %x) {
+; CHECK-LABEL: @and_sge_sge(
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 && x >s 17
+
+define i1 @and_sge_sgt(i8 %x) {
+; CHECK-LABEL: @and_sge_sgt(
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 && x <=s 17
+
+define i1 @and_sge_sle(i8 %x) {
+; CHECK-LABEL: @and_sge_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 && x <s 17
+
+define i1 @and_sge_slt(i8 %x) {
+; CHECK-LABEL: @and_sge_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 && x >=u 17
+
+define i1 @and_sge_uge(i8 %x) {
+; CHECK-LABEL: @and_sge_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 && x >u 17
+
+define i1 @and_sge_ugt(i8 %x) {
+; CHECK-LABEL: @and_sge_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 && x <=u 17
+
+define i1 @and_sge_ule(i8 %x) {
+; CHECK-LABEL: @and_sge_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 && x <u 17
+
+define i1 @and_sge_ult(i8 %x) {
+; CHECK-LABEL: @and_sge_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; sgt
+; x >s 13 && x == 17
+
+define i1 @and_sgt_eq(i8 %x) {
+; CHECK-LABEL: @and_sgt_eq(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 && x != 17
+
+define i1 @and_sgt_ne(i8 %x) {
+; CHECK-LABEL: @and_sgt_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 && x >=s 17
+
+define i1 @and_sgt_sge(i8 %x) {
+; CHECK-LABEL: @and_sgt_sge(
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 && x >s 17
+
+define i1 @and_sgt_sgt(i8 %x) {
+; CHECK-LABEL: @and_sgt_sgt(
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 && x <=s 17
+
+define i1 @and_sgt_sle(i8 %x) {
+; CHECK-LABEL: @and_sgt_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 && x <s 17
+
+define i1 @and_sgt_slt(i8 %x) {
+; CHECK-LABEL: @and_sgt_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 && x >=u 17
+
+define i1 @and_sgt_uge(i8 %x) {
+; CHECK-LABEL: @and_sgt_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 && x >u 17
+
+define i1 @and_sgt_ugt(i8 %x) {
+; CHECK-LABEL: @and_sgt_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 && x <=u 17
+
+define i1 @and_sgt_ule(i8 %x) {
+; CHECK-LABEL: @and_sgt_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 && x <u 17
+
+define i1 @and_sgt_ult(i8 %x) {
+; CHECK-LABEL: @and_sgt_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; sle
+; x <=s 13 && x == 17
+
+define i1 @and_sle_eq(i8 %x) {
+; CHECK-LABEL: @and_sle_eq(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 && x != 17
+
+define i1 @and_sle_ne(i8 %x) {
+; CHECK-LABEL: @and_sle_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 && x >=s 17
+
+define i1 @and_sle_sge(i8 %x) {
+; CHECK-LABEL: @and_sle_sge(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 && x >s 17
+
+define i1 @and_sle_sgt(i8 %x) {
+; CHECK-LABEL: @and_sle_sgt(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 && x <=s 17
+
+define i1 @and_sle_sle(i8 %x) {
+; CHECK-LABEL: @and_sle_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 && x <s 17
+
+define i1 @and_sle_slt(i8 %x) {
+; CHECK-LABEL: @and_sle_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 && x >=u 17
+
+define i1 @and_sle_uge(i8 %x) {
+; CHECK-LABEL: @and_sle_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 && x >u 17
+
+define i1 @and_sle_ugt(i8 %x) {
+; CHECK-LABEL: @and_sle_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 && x <=u 17
+
+define i1 @and_sle_ule(i8 %x) {
+; CHECK-LABEL: @and_sle_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 && x <u 17
+
+define i1 @and_sle_ult(i8 %x) {
+; CHECK-LABEL: @and_sle_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; slt
+; x <s 13 && x == 17
+
+define i1 @and_slt_eq(i8 %x) {
+; CHECK-LABEL: @and_slt_eq(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 && x != 17
+
+define i1 @and_slt_ne(i8 %x) {
+; CHECK-LABEL: @and_slt_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 && x >=s 17
+
+define i1 @and_slt_sge(i8 %x) {
+; CHECK-LABEL: @and_slt_sge(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 && x >s 17
+
+define i1 @and_slt_sgt(i8 %x) {
+; CHECK-LABEL: @and_slt_sgt(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 && x <=s 17
+
+define i1 @and_slt_sle(i8 %x) {
+; CHECK-LABEL: @and_slt_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 && x <s 17
+
+define i1 @and_slt_slt(i8 %x) {
+; CHECK-LABEL: @and_slt_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 && x >=u 17
+
+define i1 @and_slt_uge(i8 %x) {
+; CHECK-LABEL: @and_slt_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 && x >u 17
+
+define i1 @and_slt_ugt(i8 %x) {
+; CHECK-LABEL: @and_slt_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 && x <=u 17
+
+define i1 @and_slt_ule(i8 %x) {
+; CHECK-LABEL: @and_slt_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 && x <u 17
+
+define i1 @and_slt_ult(i8 %x) {
+; CHECK-LABEL: @and_slt_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; uge
+; x >=u 13 && x == 17
+
+define i1 @and_uge_eq(i8 %x) {
+; CHECK-LABEL: @and_uge_eq(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 && x != 17
+
+define i1 @and_uge_ne(i8 %x) {
+; CHECK-LABEL: @and_uge_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 && x >=s 17
+
+define i1 @and_uge_sge(i8 %x) {
+; CHECK-LABEL: @and_uge_sge(
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 && x >s 17
+
+define i1 @and_uge_sgt(i8 %x) {
+; CHECK-LABEL: @and_uge_sgt(
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 && x <=s 17
+
+define i1 @and_uge_sle(i8 %x) {
+; CHECK-LABEL: @and_uge_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 && x <s 17
+
+define i1 @and_uge_slt(i8 %x) {
+; CHECK-LABEL: @and_uge_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 && x >=u 17
+
+define i1 @and_uge_uge(i8 %x) {
+; CHECK-LABEL: @and_uge_uge(
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 && x >u 17
+
+define i1 @and_uge_ugt(i8 %x) {
+; CHECK-LABEL: @and_uge_ugt(
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 && x <=u 17
+
+define i1 @and_uge_ule(i8 %x) {
+; CHECK-LABEL: @and_uge_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 && x <u 17
+
+define i1 @and_uge_ult(i8 %x) {
+; CHECK-LABEL: @and_uge_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; ugt
+; x >u 13 && x == 17
+
+define i1 @and_ugt_eq(i8 %x) {
+; CHECK-LABEL: @and_ugt_eq(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 && x != 17
+
+define i1 @and_ugt_ne(i8 %x) {
+; CHECK-LABEL: @and_ugt_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 && x >=s 17
+
+define i1 @and_ugt_sge(i8 %x) {
+; CHECK-LABEL: @and_ugt_sge(
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 && x >s 17
+
+define i1 @and_ugt_sgt(i8 %x) {
+; CHECK-LABEL: @and_ugt_sgt(
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 && x <=s 17
+
+define i1 @and_ugt_sle(i8 %x) {
+; CHECK-LABEL: @and_ugt_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 && x <s 17
+
+define i1 @and_ugt_slt(i8 %x) {
+; CHECK-LABEL: @and_ugt_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 && x >=u 17
+
+define i1 @and_ugt_uge(i8 %x) {
+; CHECK-LABEL: @and_ugt_uge(
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 && x >u 17
+
+define i1 @and_ugt_ugt(i8 %x) {
+; CHECK-LABEL: @and_ugt_ugt(
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 && x <=u 17
+
+define i1 @and_ugt_ule(i8 %x) {
+; CHECK-LABEL: @and_ugt_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 && x <u 17
+
+define i1 @and_ugt_ult(i8 %x) {
+; CHECK-LABEL: @and_ugt_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; ule
+; x <=u 13 && x == 17
+
+define i1 @and_ule_eq(i8 %x) {
+; CHECK-LABEL: @and_ule_eq(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 && x != 17
+
+define i1 @and_ule_ne(i8 %x) {
+; CHECK-LABEL: @and_ule_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 && x >=s 17
+
+define i1 @and_ule_sge(i8 %x) {
+; CHECK-LABEL: @and_ule_sge(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 && x >s 17
+
+define i1 @and_ule_sgt(i8 %x) {
+; CHECK-LABEL: @and_ule_sgt(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 && x <=s 17
+
+define i1 @and_ule_sle(i8 %x) {
+; CHECK-LABEL: @and_ule_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 && x <s 17
+
+define i1 @and_ule_slt(i8 %x) {
+; CHECK-LABEL: @and_ule_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 && x >=u 17
+
+define i1 @and_ule_uge(i8 %x) {
+; CHECK-LABEL: @and_ule_uge(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 && x >u 17
+
+define i1 @and_ule_ugt(i8 %x) {
+; CHECK-LABEL: @and_ule_ugt(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 && x <=u 17
+
+define i1 @and_ule_ule(i8 %x) {
+; CHECK-LABEL: @and_ule_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 && x <u 17
+
+define i1 @and_ule_ult(i8 %x) {
+; CHECK-LABEL: @and_ule_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; ult
+; x <u 13 && x == 17
+
+define i1 @and_ult_eq(i8 %x) {
+; CHECK-LABEL: @and_ult_eq(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 && x != 17
+
+define i1 @and_ult_ne(i8 %x) {
+; CHECK-LABEL: @and_ult_ne(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 && x >=s 17
+
+define i1 @and_ult_sge(i8 %x) {
+; CHECK-LABEL: @and_ult_sge(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 && x >s 17
+
+define i1 @and_ult_sgt(i8 %x) {
+; CHECK-LABEL: @and_ult_sgt(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 && x <=s 17
+
+define i1 @and_ult_sle(i8 %x) {
+; CHECK-LABEL: @and_ult_sle(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 && x <s 17
+
+define i1 @and_ult_slt(i8 %x) {
+; CHECK-LABEL: @and_ult_slt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 && x >=u 17
+
+define i1 @and_ult_uge(i8 %x) {
+; CHECK-LABEL: @and_ult_uge(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 && x >u 17
+
+define i1 @and_ult_ugt(i8 %x) {
+; CHECK-LABEL: @and_ult_ugt(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 && x <=u 17
+
+define i1 @and_ult_ule(i8 %x) {
+; CHECK-LABEL: @and_ult_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 && x <u 17
+
+define i1 @and_ult_ult(i8 %x) {
+; CHECK-LABEL: @and_ult_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; eq
+; x == 23 && x == 17
+
+define i1 @and_eq_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_eq_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 && x != 17
+
+define i1 @and_eq_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 && x >=s 17
+
+define i1 @and_eq_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 && x >s 17
+
+define i1 @and_eq_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 && x <=s 17
+
+define i1 @and_eq_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_sle_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 && x <s 17
+
+define i1 @and_eq_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_slt_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 && x >=u 17
+
+define i1 @and_eq_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 && x >u 17
+
+define i1 @and_eq_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 && x <=u 17
+
+define i1 @and_eq_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_ule_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 && x <u 17
+
+define i1 @and_eq_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_eq_ult_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; ne
+; x != 23 && x == 17
+
+define i1 @and_ne_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_eq_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 && x != 17
+
+define i1 @and_ne_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 && x >=s 17
+
+define i1 @and_ne_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 && x >s 17
+
+define i1 @and_ne_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 && x <=s 17
+
+define i1 @and_ne_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_sle_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 && x <s 17
+
+define i1 @and_ne_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_slt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 && x >=u 17
+
+define i1 @and_ne_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 && x >u 17
+
+define i1 @and_ne_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 && x <=u 17
+
+define i1 @and_ne_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_ule_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 && x <u 17
+
+define i1 @and_ne_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_ne_ult_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; sge
+; x >=s 23 && x == 17
+
+define i1 @and_sge_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_eq_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 && x != 17
+
+define i1 @and_sge_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 && x >=s 17
+
+define i1 @and_sge_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 && x >s 17
+
+define i1 @and_sge_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 && x <=s 17
+
+define i1 @and_sge_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_sle_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 && x <s 17
+
+define i1 @and_sge_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_slt_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 && x >=u 17
+
+define i1 @and_sge_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 && x >u 17
+
+define i1 @and_sge_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 && x <=u 17
+
+define i1 @and_sge_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_ule_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 && x <u 17
+
+define i1 @and_sge_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_sge_ult_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; sgt
+; x >s 23 && x == 17
+
+define i1 @and_sgt_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_eq_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 && x != 17
+
+define i1 @and_sgt_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 && x >=s 17
+
+define i1 @and_sgt_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 && x >s 17
+
+define i1 @and_sgt_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 && x <=s 17
+
+define i1 @and_sgt_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_sle_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 && x <s 17
+
+define i1 @and_sgt_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_slt_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 && x >=u 17
+
+define i1 @and_sgt_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 && x >u 17
+
+define i1 @and_sgt_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 && x <=u 17
+
+define i1 @and_sgt_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_ule_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 && x <u 17
+
+define i1 @and_sgt_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_sgt_ult_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; sle
+; x <=s 23 && x == 17
+
+define i1 @and_sle_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_eq_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 && x != 17
+
+define i1 @and_sle_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 && x >=s 17
+
+define i1 @and_sle_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 && x >s 17
+
+define i1 @and_sle_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 && x <=s 17
+
+define i1 @and_sle_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_sle_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 && x <s 17
+
+define i1 @and_sle_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_slt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 && x >=u 17
+
+define i1 @and_sle_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 && x >u 17
+
+define i1 @and_sle_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 && x <=u 17
+
+define i1 @and_sle_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_ule_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 && x <u 17
+
+define i1 @and_sle_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_sle_ult_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; slt
+; x <s 23 && x == 17
+
+define i1 @and_slt_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_eq_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 && x != 17
+
+define i1 @and_slt_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 && x >=s 17
+
+define i1 @and_slt_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 && x >s 17
+
+define i1 @and_slt_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 && x <=s 17
+
+define i1 @and_slt_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_sle_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 && x <s 17
+
+define i1 @and_slt_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_slt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 && x >=u 17
+
+define i1 @and_slt_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 && x >u 17
+
+define i1 @and_slt_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 && x <=u 17
+
+define i1 @and_slt_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_ule_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 && x <u 17
+
+define i1 @and_slt_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_slt_ult_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; uge
+; x >=u 23 && x == 17
+
+define i1 @and_uge_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_eq_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 && x != 17
+
+define i1 @and_uge_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 && x >=s 17
+
+define i1 @and_uge_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 && x >s 17
+
+define i1 @and_uge_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 && x <=s 17
+
+define i1 @and_uge_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 && x <s 17
+
+define i1 @and_uge_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 && x >=u 17
+
+define i1 @and_uge_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 && x >u 17
+
+define i1 @and_uge_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 && x <=u 17
+
+define i1 @and_uge_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_ule_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 && x <u 17
+
+define i1 @and_uge_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_uge_ult_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; ugt
+; x >u 23 && x == 17
+
+define i1 @and_ugt_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_eq_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 && x != 17
+
+define i1 @and_ugt_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 && x >=s 17
+
+define i1 @and_ugt_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 && x >s 17
+
+define i1 @and_ugt_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 && x <=s 17
+
+define i1 @and_ugt_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 && x <s 17
+
+define i1 @and_ugt_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 && x >=u 17
+
+define i1 @and_ugt_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 && x >u 17
+
+define i1 @and_ugt_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 && x <=u 17
+
+define i1 @and_ugt_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_ule_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 && x <u 17
+
+define i1 @and_ugt_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_ugt_ult_swap(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; ule
+; x <=u 23 && x == 17
+
+define i1 @and_ule_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_eq_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 && x != 17
+
+define i1 @and_ule_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 && x >=s 17
+
+define i1 @and_ule_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 && x >s 17
+
+define i1 @and_ule_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 && x <=s 17
+
+define i1 @and_ule_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 && x <s 17
+
+define i1 @and_ule_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 && x >=u 17
+
+define i1 @and_ule_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 && x >u 17
+
+define i1 @and_ule_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 && x <=u 17
+
+define i1 @and_ule_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_ule_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 && x <u 17
+
+define i1 @and_ule_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_ule_ult_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; ult
+; x <u 23 && x == 17
+
+define i1 @and_ult_eq_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_eq_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 && x != 17
+
+define i1 @and_ult_ne_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_ne_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 && x >=s 17
+
+define i1 @and_ult_sge_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 && x >s 17
+
+define i1 @and_ult_sgt_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 && x <=s 17
+
+define i1 @and_ult_sle_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 && x <s 17
+
+define i1 @and_ult_slt_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 && x >=u 17
+
+define i1 @and_ult_uge_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_uge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 && x >u 17
+
+define i1 @and_ult_ugt_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_ugt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 && x <=u 17
+
+define i1 @and_ult_ule_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_ule_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 && x <u 17
+
+define i1 @and_ult_ult_swap(i8 %x) {
+; CHECK-LABEL: @and_ult_ult_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+
+; eq
+; x == 13 || x == 17
+
+define i1 @or_eq_eq(i8 %x) {
+; CHECK-LABEL: @or_eq_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 || x != 17
+
+define i1 @or_eq_ne(i8 %x) {
+; CHECK-LABEL: @or_eq_ne(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 || x >=s 17
+
+define i1 @or_eq_sge(i8 %x) {
+; CHECK-LABEL: @or_eq_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 || x >s 17
+
+define i1 @or_eq_sgt(i8 %x) {
+; CHECK-LABEL: @or_eq_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 || x <=s 17
+
+define i1 @or_eq_sle(i8 %x) {
+; CHECK-LABEL: @or_eq_sle(
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 || x <s 17
+
+define i1 @or_eq_slt(i8 %x) {
+; CHECK-LABEL: @or_eq_slt(
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 || x >=u 17
+
+define i1 @or_eq_uge(i8 %x) {
+; CHECK-LABEL: @or_eq_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 || x >u 17
+
+define i1 @or_eq_ugt(i8 %x) {
+; CHECK-LABEL: @or_eq_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 || x <=u 17
+
+define i1 @or_eq_ule(i8 %x) {
+; CHECK-LABEL: @or_eq_ule(
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 13 || x <u 17
+
+define i1 @or_eq_ult(i8 %x) {
+; CHECK-LABEL: @or_eq_ult(
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; ne
+; x != 13 || x == 17
+
+define i1 @or_ne_eq(i8 %x) {
+; CHECK-LABEL: @or_ne_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 || x != 17
+
+define i1 @or_ne_ne(i8 %x) {
+; CHECK-LABEL: @or_ne_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 || x >=s 17
+
+define i1 @or_ne_sge(i8 %x) {
+; CHECK-LABEL: @or_ne_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 || x >s 17
+
+define i1 @or_ne_sgt(i8 %x) {
+; CHECK-LABEL: @or_ne_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 || x <=s 17
+
+define i1 @or_ne_sle(i8 %x) {
+; CHECK-LABEL: @or_ne_sle(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 || x <s 17
+
+define i1 @or_ne_slt(i8 %x) {
+; CHECK-LABEL: @or_ne_slt(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 || x >=u 17
+
+define i1 @or_ne_uge(i8 %x) {
+; CHECK-LABEL: @or_ne_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 || x >u 17
+
+define i1 @or_ne_ugt(i8 %x) {
+; CHECK-LABEL: @or_ne_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 || x <=u 17
+
+define i1 @or_ne_ule(i8 %x) {
+; CHECK-LABEL: @or_ne_ule(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 13 || x <u 17
+
+define i1 @or_ne_ult(i8 %x) {
+; CHECK-LABEL: @or_ne_ult(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; sge
+; x >=s 13 || x == 17
+
+define i1 @or_sge_eq(i8 %x) {
+; CHECK-LABEL: @or_sge_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 || x != 17
+
+define i1 @or_sge_ne(i8 %x) {
+; CHECK-LABEL: @or_sge_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 || x >=s 17
+
+define i1 @or_sge_sge(i8 %x) {
+; CHECK-LABEL: @or_sge_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 || x >s 17
+
+define i1 @or_sge_sgt(i8 %x) {
+; CHECK-LABEL: @or_sge_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 || x <=s 17
+
+define i1 @or_sge_sle(i8 %x) {
+; CHECK-LABEL: @or_sge_sle(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 || x <s 17
+
+define i1 @or_sge_slt(i8 %x) {
+; CHECK-LABEL: @or_sge_slt(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 || x >=u 17
+
+define i1 @or_sge_uge(i8 %x) {
+; CHECK-LABEL: @or_sge_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 || x >u 17
+
+define i1 @or_sge_ugt(i8 %x) {
+; CHECK-LABEL: @or_sge_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 || x <=u 17
+
+define i1 @or_sge_ule(i8 %x) {
+; CHECK-LABEL: @or_sge_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 13 || x <u 17
+
+define i1 @or_sge_ult(i8 %x) {
+; CHECK-LABEL: @or_sge_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; sgt
+; x >s 13 || x == 17
+
+define i1 @or_sgt_eq(i8 %x) {
+; CHECK-LABEL: @or_sgt_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 || x != 17
+
+define i1 @or_sgt_ne(i8 %x) {
+; CHECK-LABEL: @or_sgt_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 || x >=s 17
+
+define i1 @or_sgt_sge(i8 %x) {
+; CHECK-LABEL: @or_sgt_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 || x >s 17
+
+define i1 @or_sgt_sgt(i8 %x) {
+; CHECK-LABEL: @or_sgt_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 || x <=s 17
+
+define i1 @or_sgt_sle(i8 %x) {
+; CHECK-LABEL: @or_sgt_sle(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 || x <s 17
+
+define i1 @or_sgt_slt(i8 %x) {
+; CHECK-LABEL: @or_sgt_slt(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 || x >=u 17
+
+define i1 @or_sgt_uge(i8 %x) {
+; CHECK-LABEL: @or_sgt_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 || x >u 17
+
+define i1 @or_sgt_ugt(i8 %x) {
+; CHECK-LABEL: @or_sgt_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 || x <=u 17
+
+define i1 @or_sgt_ule(i8 %x) {
+; CHECK-LABEL: @or_sgt_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 13 || x <u 17
+
+define i1 @or_sgt_ult(i8 %x) {
+; CHECK-LABEL: @or_sgt_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; sle
+; x <=s 13 || x == 17
+
+define i1 @or_sle_eq(i8 %x) {
+; CHECK-LABEL: @or_sle_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 || x != 17
+
+define i1 @or_sle_ne(i8 %x) {
+; CHECK-LABEL: @or_sle_ne(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 || x >=s 17
+
+define i1 @or_sle_sge(i8 %x) {
+; CHECK-LABEL: @or_sle_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 || x >s 17
+
+define i1 @or_sle_sgt(i8 %x) {
+; CHECK-LABEL: @or_sle_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 || x <=s 17
+
+define i1 @or_sle_sle(i8 %x) {
+; CHECK-LABEL: @or_sle_sle(
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 || x <s 17
+
+define i1 @or_sle_slt(i8 %x) {
+; CHECK-LABEL: @or_sle_slt(
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 || x >=u 17
+
+define i1 @or_sle_uge(i8 %x) {
+; CHECK-LABEL: @or_sle_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 || x >u 17
+
+define i1 @or_sle_ugt(i8 %x) {
+; CHECK-LABEL: @or_sle_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 || x <=u 17
+
+define i1 @or_sle_ule(i8 %x) {
+; CHECK-LABEL: @or_sle_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 13 || x <u 17
+
+define i1 @or_sle_ult(i8 %x) {
+; CHECK-LABEL: @or_sle_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sle i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; slt
+; x <s 13 || x == 17
+
+define i1 @or_slt_eq(i8 %x) {
+; CHECK-LABEL: @or_slt_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 || x != 17
+
+define i1 @or_slt_ne(i8 %x) {
+; CHECK-LABEL: @or_slt_ne(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 || x >=s 17
+
+define i1 @or_slt_sge(i8 %x) {
+; CHECK-LABEL: @or_slt_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 || x >s 17
+
+define i1 @or_slt_sgt(i8 %x) {
+; CHECK-LABEL: @or_slt_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 || x <=s 17
+
+define i1 @or_slt_sle(i8 %x) {
+; CHECK-LABEL: @or_slt_sle(
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 || x <s 17
+
+define i1 @or_slt_slt(i8 %x) {
+; CHECK-LABEL: @or_slt_slt(
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 || x >=u 17
+
+define i1 @or_slt_uge(i8 %x) {
+; CHECK-LABEL: @or_slt_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 || x >u 17
+
+define i1 @or_slt_ugt(i8 %x) {
+; CHECK-LABEL: @or_slt_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 || x <=u 17
+
+define i1 @or_slt_ule(i8 %x) {
+; CHECK-LABEL: @or_slt_ule(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 13 || x <u 17
+
+define i1 @or_slt_ult(i8 %x) {
+; CHECK-LABEL: @or_slt_ult(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp slt i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; uge
+; x >=u 13 || x == 17
+
+define i1 @or_uge_eq(i8 %x) {
+; CHECK-LABEL: @or_uge_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 || x != 17
+
+define i1 @or_uge_ne(i8 %x) {
+; CHECK-LABEL: @or_uge_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 || x >=s 17
+
+define i1 @or_uge_sge(i8 %x) {
+; CHECK-LABEL: @or_uge_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 || x >s 17
+
+define i1 @or_uge_sgt(i8 %x) {
+; CHECK-LABEL: @or_uge_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 || x <=s 17
+
+define i1 @or_uge_sle(i8 %x) {
+; CHECK-LABEL: @or_uge_sle(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 || x <s 17
+
+define i1 @or_uge_slt(i8 %x) {
+; CHECK-LABEL: @or_uge_slt(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 || x >=u 17
+
+define i1 @or_uge_uge(i8 %x) {
+; CHECK-LABEL: @or_uge_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 || x >u 17
+
+define i1 @or_uge_ugt(i8 %x) {
+; CHECK-LABEL: @or_uge_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 || x <=u 17
+
+define i1 @or_uge_ule(i8 %x) {
+; CHECK-LABEL: @or_uge_ule(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 13 || x <u 17
+
+define i1 @or_uge_ult(i8 %x) {
+; CHECK-LABEL: @or_uge_ult(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp uge i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; ugt
+; x >u 13 || x == 17
+
+define i1 @or_ugt_eq(i8 %x) {
+; CHECK-LABEL: @or_ugt_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 || x != 17
+
+define i1 @or_ugt_ne(i8 %x) {
+; CHECK-LABEL: @or_ugt_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 || x >=s 17
+
+define i1 @or_ugt_sge(i8 %x) {
+; CHECK-LABEL: @or_ugt_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 || x >s 17
+
+define i1 @or_ugt_sgt(i8 %x) {
+; CHECK-LABEL: @or_ugt_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 || x <=s 17
+
+define i1 @or_ugt_sle(i8 %x) {
+; CHECK-LABEL: @or_ugt_sle(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 || x <s 17
+
+define i1 @or_ugt_slt(i8 %x) {
+; CHECK-LABEL: @or_ugt_slt(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 || x >=u 17
+
+define i1 @or_ugt_uge(i8 %x) {
+; CHECK-LABEL: @or_ugt_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 || x >u 17
+
+define i1 @or_ugt_ugt(i8 %x) {
+; CHECK-LABEL: @or_ugt_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 13
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 || x <=u 17
+
+define i1 @or_ugt_ule(i8 %x) {
+; CHECK-LABEL: @or_ugt_ule(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 13 || x <u 17
+
+define i1 @or_ugt_ult(i8 %x) {
+; CHECK-LABEL: @or_ugt_ult(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ugt i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; ule
+; x <=u 13 || x == 17
+
+define i1 @or_ule_eq(i8 %x) {
+; CHECK-LABEL: @or_ule_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 || x != 17
+
+define i1 @or_ule_ne(i8 %x) {
+; CHECK-LABEL: @or_ule_ne(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 || x >=s 17
+
+define i1 @or_ule_sge(i8 %x) {
+; CHECK-LABEL: @or_ule_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 || x >s 17
+
+define i1 @or_ule_sgt(i8 %x) {
+; CHECK-LABEL: @or_ule_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 || x <=s 17
+
+define i1 @or_ule_sle(i8 %x) {
+; CHECK-LABEL: @or_ule_sle(
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 || x <s 17
+
+define i1 @or_ule_slt(i8 %x) {
+; CHECK-LABEL: @or_ule_slt(
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 || x >=u 17
+
+define i1 @or_ule_uge(i8 %x) {
+; CHECK-LABEL: @or_ule_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 || x >u 17
+
+define i1 @or_ule_ugt(i8 %x) {
+; CHECK-LABEL: @or_ule_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 || x <=u 17
+
+define i1 @or_ule_ule(i8 %x) {
+; CHECK-LABEL: @or_ule_ule(
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 13 || x <u 17
+
+define i1 @or_ule_ult(i8 %x) {
+; CHECK-LABEL: @or_ule_ult(
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ule i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; ult
+; x <u 13 || x == 17
+
+define i1 @or_ult_eq(i8 %x) {
+; CHECK-LABEL: @or_ult_eq(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 || x != 17
+
+define i1 @or_ult_ne(i8 %x) {
+; CHECK-LABEL: @or_ult_ne(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 || x >=s 17
+
+define i1 @or_ult_sge(i8 %x) {
+; CHECK-LABEL: @or_ult_sge(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 || x >s 17
+
+define i1 @or_ult_sgt(i8 %x) {
+; CHECK-LABEL: @or_ult_sgt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 || x <=s 17
+
+define i1 @or_ult_sle(i8 %x) {
+; CHECK-LABEL: @or_ult_sle(
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 || x <s 17
+
+define i1 @or_ult_slt(i8 %x) {
+; CHECK-LABEL: @or_ult_slt(
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 || x >=u 17
+
+define i1 @or_ult_uge(i8 %x) {
+; CHECK-LABEL: @or_ult_uge(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 || x >u 17
+
+define i1 @or_ult_ugt(i8 %x) {
+; CHECK-LABEL: @or_ult_ugt(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 13
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 || x <=u 17
+
+define i1 @or_ult_ule(i8 %x) {
+; CHECK-LABEL: @or_ult_ule(
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 13 || x <u 17
+
+define i1 @or_ult_ult(i8 %x) {
+; CHECK-LABEL: @or_ult_ult(
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ult i8 %x, 13
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; eq
+; x == 23 || x == 17
+
+define i1 @or_eq_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 || x != 17
+
+define i1 @or_eq_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_ne_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 || x >=s 17
+
+define i1 @or_eq_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_sge_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 || x >s 17
+
+define i1 @or_eq_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_sgt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 || x <=s 17
+
+define i1 @or_eq_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 || x <s 17
+
+define i1 @or_eq_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 || x >=u 17
+
+define i1 @or_eq_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_uge_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 || x >u 17
+
+define i1 @or_eq_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_ugt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 || x <=u 17
+
+define i1 @or_eq_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x == 23 || x <u 17
+
+define i1 @or_eq_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_eq_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp eq i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; ne
+; x != 23 || x == 17
+
+define i1 @or_ne_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 || x != 17
+
+define i1 @or_ne_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_ne_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 || x >=s 17
+
+define i1 @or_ne_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_sge_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 || x >s 17
+
+define i1 @or_ne_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_sgt_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 || x <=s 17
+
+define i1 @or_ne_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 || x <s 17
+
+define i1 @or_ne_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 || x >=u 17
+
+define i1 @or_ne_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_uge_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 || x >u 17
+
+define i1 @or_ne_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_ugt_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 || x <=u 17
+
+define i1 @or_ne_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x != 23 || x <u 17
+
+define i1 @or_ne_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_ne_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ne i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; sge
+; x >=s 23 || x == 17
+
+define i1 @or_sge_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 || x != 17
+
+define i1 @or_sge_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_ne_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 || x >=s 17
+
+define i1 @or_sge_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_sge_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 || x >s 17
+
+define i1 @or_sge_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_sgt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 || x <=s 17
+
+define i1 @or_sge_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 || x <s 17
+
+define i1 @or_sge_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 || x >=u 17
+
+define i1 @or_sge_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_uge_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 || x >u 17
+
+define i1 @or_sge_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_ugt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 || x <=u 17
+
+define i1 @or_sge_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=s 23 || x <u 17
+
+define i1 @or_sge_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_sge_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sge i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; sgt
+; x >s 23 || x == 17
+
+define i1 @or_sgt_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 || x != 17
+
+define i1 @or_sgt_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_ne_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 || x >=s 17
+
+define i1 @or_sgt_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_sge_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 || x >s 17
+
+define i1 @or_sgt_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_sgt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 || x <=s 17
+
+define i1 @or_sgt_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 || x <s 17
+
+define i1 @or_sgt_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 || x >=u 17
+
+define i1 @or_sgt_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_uge_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 || x >u 17
+
+define i1 @or_sgt_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_ugt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 || x <=u 17
+
+define i1 @or_sgt_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >s 23 || x <u 17
+
+define i1 @or_sgt_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_sgt_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sgt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp sgt i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; sle
+; x <=s 23 || x == 17
+
+define i1 @or_sle_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 || x != 17
+
+define i1 @or_sle_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_ne_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 || x >=s 17
+
+define i1 @or_sle_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_sge_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 || x >s 17
+
+define i1 @or_sle_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_sgt_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 || x <=s 17
+
+define i1 @or_sle_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 || x <s 17
+
+define i1 @or_sle_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 || x >=u 17
+
+define i1 @or_sle_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_uge_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 || x >u 17
+
+define i1 @or_sle_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_ugt_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 || x <=u 17
+
+define i1 @or_sle_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=s 23 || x <u 17
+
+define i1 @or_sle_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_sle_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp sle i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp sle i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; slt
+; x <s 23 || x == 17
+
+define i1 @or_slt_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 || x != 17
+
+define i1 @or_slt_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_ne_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 || x >=s 17
+
+define i1 @or_slt_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_sge_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 || x >s 17
+
+define i1 @or_slt_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_sgt_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 || x <=s 17
+
+define i1 @or_slt_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 || x <s 17
+
+define i1 @or_slt_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 || x >=u 17
+
+define i1 @or_slt_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_uge_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 || x >u 17
+
+define i1 @or_slt_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_ugt_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 || x <=u 17
+
+define i1 @or_slt_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <s 23 || x <u 17
+
+define i1 @or_slt_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_slt_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp slt i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp slt i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; uge
+; x >=u 23 || x == 17
+
+define i1 @or_uge_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 || x != 17
+
+define i1 @or_uge_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_ne_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 || x >=s 17
+
+define i1 @or_uge_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 || x >s 17
+
+define i1 @or_uge_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 || x <=s 17
+
+define i1 @or_uge_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 || x <s 17
+
+define i1 @or_uge_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 || x >=u 17
+
+define i1 @or_uge_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_uge_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 || x >u 17
+
+define i1 @or_uge_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_ugt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 || x <=u 17
+
+define i1 @or_uge_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >=u 23 || x <u 17
+
+define i1 @or_uge_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_uge_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp uge i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp uge i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; ugt
+; x >u 23 || x == 17
+
+define i1 @or_ugt_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 || x != 17
+
+define i1 @or_ugt_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_ne_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 || x >=s 17
+
+define i1 @or_ugt_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 || x >s 17
+
+define i1 @or_ugt_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 || x <=s 17
+
+define i1 @or_ugt_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 || x <s 17
+
+define i1 @or_ugt_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 || x >=u 17
+
+define i1 @or_ugt_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_uge_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp uge i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 || x >u 17
+
+define i1 @or_ugt_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_ugt_swap(
+; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 %x, 17
+; CHECK-NEXT:    ret i1 [[B]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 || x <=u 17
+
+define i1 @or_ugt_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ule i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x >u 23 || x <u 17
+
+define i1 @or_ugt_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_ugt_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ugt i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ugt i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; ule
+; x <=u 23 || x == 17
+
+define i1 @or_ule_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 || x != 17
+
+define i1 @or_ule_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_ne_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 || x >=s 17
+
+define i1 @or_ule_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 || x >s 17
+
+define i1 @or_ule_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 || x <=s 17
+
+define i1 @or_ule_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 || x <s 17
+
+define i1 @or_ule_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 || x >=u 17
+
+define i1 @or_ule_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_uge_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 || x >u 17
+
+define i1 @or_ule_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_ugt_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 || x <=u 17
+
+define i1 @or_ule_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <=u 23 || x <u 17
+
+define i1 @or_ule_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_ule_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ule i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ule i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; ult
+; x <u 23 || x == 17
+
+define i1 @or_ult_eq_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_eq_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp eq i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 || x != 17
+
+define i1 @or_ult_ne_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_ne_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp ne i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 || x >=s 17
+
+define i1 @or_ult_sge_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_sge_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sge i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp sge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 || x >s 17
+
+define i1 @or_ult_sgt_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_sgt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp sgt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 || x <=s 17
+
+define i1 @or_ult_sle_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_sle_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp sle i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp sle i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 || x <s 17
+
+define i1 @or_ult_slt_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_slt_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 %x, 17
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp slt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 || x >=u 17
+
+define i1 @or_ult_uge_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_uge_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp uge i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 || x >u 17
+
+define i1 @or_ult_ugt_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_ugt_swap(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp ugt i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 || x <=u 17
+
+define i1 @or_ult_ule_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_ule_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp ule i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; x <u 23 || x <u 17
+
+define i1 @or_ult_ult_swap(i8 %x) {
+; CHECK-LABEL: @or_ult_ult_swap(
+; CHECK-NEXT:    [[A:%.*]] = icmp ult i8 %x, 23
+; CHECK-NEXT:    ret i1 [[A]]
+;
+  %a = icmp ult i8 %x, 23
+  %b = icmp ult i8 %x, 17
+  %c = or i1 %a, %b
+  ret i1 %c
+}
+
+; Special case - slt is uge
+; x <u 31 && x <s 0
+
+define i1 @empty2(i32 %x) {
+; CHECK-LABEL: @empty2(
+; CHECK-NEXT:    ret i1 false
+;
+  %a = icmp ult i32 %x, 31
+  %b = icmp slt i32 %x, 0
+  %c = and i1 %a, %b
+  ret i1 %c
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/implies.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/implies.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/implies.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/implies.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,257 @@
+; NOTE: Assertions have been autogenerated by update_test_checks.py
+; RUN: opt -S %s -instsimplify | FileCheck %s
+
+; A ==> A -> true
+define i1 @test(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test(
+; CHECK:         ret i1 true
+;
+  %var29 = icmp slt i32 %i, %length.i
+  %res = icmp uge i1 %var29, %var29
+  ret i1 %res
+}
+
+; i +_{nsw} C_{>0} <s L ==> i <s L -> true
+define i1 @test2(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test2(
+; CHECK:         ret i1 true
+;
+  %iplus1 = add nsw i32 %i, 1
+  %var29 = icmp slt i32 %i, %length.i
+  %var30 = icmp slt i32 %iplus1, %length.i
+  %res = icmp ule i1 %var30, %var29
+  ret i1 %res
+}
+
+; i + C_{>0} <s L ==> i <s L -> unknown without the nsw
+define i1 @test2_neg(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test2_neg(
+; CHECK:         [[IPLUS1:%.*]] = add i32 %i, 1
+; CHECK-NEXT:    [[VAR29:%.*]] = icmp slt i32 %i, %length.i
+; CHECK-NEXT:    [[VAR30:%.*]] = icmp slt i32 [[IPLUS1]], %length.i
+; CHECK-NEXT:    [[RES:%.*]] = icmp ule i1 [[VAR30]], [[VAR29]]
+; CHECK-NEXT:    ret i1 [[RES]]
+;
+  %iplus1 = add i32 %i, 1
+  %var29 = icmp slt i32 %i, %length.i
+  %var30 = icmp slt i32 %iplus1, %length.i
+  %res = icmp ule i1 %var30, %var29
+  ret i1 %res
+}
+
+; sle is not implication
+define i1 @test2_neg2(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test2_neg2(
+; CHECK:         [[IPLUS1:%.*]] = add i32 %i, 1
+; CHECK-NEXT:    [[VAR29:%.*]] = icmp slt i32 %i, %length.i
+; CHECK-NEXT:    [[VAR30:%.*]] = icmp slt i32 [[IPLUS1]], %length.i
+; CHECK-NEXT:    [[RES:%.*]] = icmp sle i1 [[VAR30]], [[VAR29]]
+; CHECK-NEXT:    ret i1 [[RES]]
+;
+  %iplus1 = add i32 %i, 1
+  %var29 = icmp slt i32 %i, %length.i
+  %var30 = icmp slt i32 %iplus1, %length.i
+  %res = icmp sle i1 %var30, %var29
+  ret i1 %res
+}
+
+; The binary operator has to be an add
+define i1 @test2_neg3(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test2_neg3(
+; CHECK:         [[IPLUS1:%.*]] = sub nsw i32 %i, 1
+; CHECK-NEXT:    [[VAR29:%.*]] = icmp slt i32 %i, %length.i
+; CHECK-NEXT:    [[VAR30:%.*]] = icmp slt i32 [[IPLUS1]], %length.i
+; CHECK-NEXT:    [[RES:%.*]] = icmp ule i1 [[VAR30]], [[VAR29]]
+; CHECK-NEXT:    ret i1 [[RES]]
+;
+  %iplus1 = sub nsw i32 %i, 1
+  %var29 = icmp slt i32 %i, %length.i
+  %var30 = icmp slt i32 %iplus1, %length.i
+  %res = icmp ule i1 %var30, %var29
+  ret i1 %res
+}
+
+; i +_{nsw} C_{>0} <s L ==> i <s L -> true
+; With an inverted conditional (ule B A rather than canonical ugt A B
+define i1 @test3(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test3(
+; CHECK:         ret i1 true
+;
+  %iplus1 = add nsw i32 %i, 1
+  %var29 = icmp slt i32 %i, %length.i
+  %var30 = icmp slt i32 %iplus1, %length.i
+  %res = icmp uge i1 %var29, %var30
+  ret i1 %res
+}
+
+; i +_{nuw} C <u L ==> i <u L
+define i1 @test4(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test4(
+; CHECK:         ret i1 true
+;
+  %iplus1 = add nuw i32 %i, 1
+  %var29 = icmp ult i32 %i, %length.i
+  %var30 = icmp ult i32 %iplus1, %length.i
+  %res = icmp ule i1 %var30, %var29
+  ret i1 %res
+}
+
+; A ==> A for vectors
+define <4 x i1> @test5(<4 x i1> %vec) {
+; CHECK-LABEL: @test5(
+; CHECK:         ret <4 x i1> <i1 true, i1 true, i1 true, i1 true>
+;
+  %res = icmp ule <4 x i1> %vec, %vec
+  ret <4 x i1> %res
+}
+
+; Don't crash on vector inputs - pr25040
+define <4 x i1> @test6(<4 x i1> %a, <4 x i1> %b) {
+; CHECK-LABEL: @test6(
+; CHECK:         [[RES:%.*]] = icmp ule <4 x i1> %a, %b
+; CHECK-NEXT:    ret <4 x i1> [[RES]]
+;
+  %res = icmp ule <4 x i1> %a, %b
+  ret <4 x i1> %res
+}
+
+; i +_{nsw} 1 <s L  ==> i < L +_{nsw} 1
+define i1 @test7(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test7(
+; CHECK:         ret i1 true
+;
+  %iplus1 = add nsw i32 %i, 1
+  %len.plus.one = add nsw i32 %length.i, 1
+  %var29 = icmp slt i32 %i, %len.plus.one
+  %var30 = icmp slt i32 %iplus1, %length.i
+  %res = icmp ule i1 %var30, %var29
+  ret i1 %res
+}
+
+; i +_{nuw} 1 <u L  ==> i < L +_{nuw} 1
+define i1 @test8(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test8(
+; CHECK:         ret i1 true
+;
+  %iplus1 = add nuw i32 %i, 1
+  %len.plus.one = add nuw i32 %length.i, 1
+  %var29 = icmp ult i32 %i, %len.plus.one
+  %var30 = icmp ult i32 %iplus1, %length.i
+  %res = icmp ule i1 %var30, %var29
+  ret i1 %res
+}
+
+; i +_{nuw} C <u L ==> i < L, even if C is negative
+define i1 @test9(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test9(
+; CHECK:         ret i1 true
+;
+  %iplus1 = add nuw i32 %i, -100
+  %var29 = icmp ult i32 %i, %length.i
+  %var30 = icmp ult i32 %iplus1, %length.i
+  %res = icmp ule i1 %var30, %var29
+  ret i1 %res
+}
+
+define i1 @test10(i32 %length.i, i32 %x.full) {
+; CHECK-LABEL: @test10(
+; CHECK:         ret i1 true
+;
+  %x = and i32 %x.full, 4294901760  ;; 4294901760 == 0xffff0000
+  %large = or i32 %x, 100
+  %small = or i32 %x, 90
+  %known = icmp ult i32 %large, %length.i
+  %to.prove = icmp ult i32 %small, %length.i
+  %res = icmp ule i1 %known, %to.prove
+  ret i1 %res
+}
+
+define i1 @test11(i32 %length.i, i32 %x) {
+; CHECK-LABEL: @test11(
+; CHECK:         [[LARGE:%.*]] = or i32 %x, 100
+; CHECK-NEXT:    [[SMALL:%.*]] = or i32 %x, 90
+; CHECK-NEXT:    [[KNOWN:%.*]] = icmp ult i32 [[LARGE]], %length.i
+; CHECK-NEXT:    [[TO_PROVE:%.*]] = icmp ult i32 [[SMALL]], %length.i
+; CHECK-NEXT:    [[RES:%.*]] = icmp ule i1 [[KNOWN]], [[TO_PROVE]]
+; CHECK-NEXT:    ret i1 [[RES]]
+;
+  %large = or i32 %x, 100
+  %small = or i32 %x, 90
+  %known = icmp ult i32 %large, %length.i
+  %to.prove = icmp ult i32 %small, %length.i
+  %res = icmp ule i1 %known, %to.prove
+  ret i1 %res
+}
+
+define i1 @test12(i32 %length.i, i32 %x.full) {
+; CHECK-LABEL: @test12(
+; CHECK:         [[X:%.*]] = and i32 [[X:%.*]].full, -65536
+; CHECK-NEXT:    [[LARGE:%.*]] = or i32 [[X]], 65536
+; CHECK-NEXT:    [[SMALL:%.*]] = or i32 [[X]], 90
+; CHECK-NEXT:    [[KNOWN:%.*]] = icmp ult i32 [[LARGE]], %length.i
+; CHECK-NEXT:    [[TO_PROVE:%.*]] = icmp ult i32 [[SMALL]], %length.i
+; CHECK-NEXT:    [[RES:%.*]] = icmp ule i1 [[KNOWN]], [[TO_PROVE]]
+; CHECK-NEXT:    ret i1 [[RES]]
+;
+  %x = and i32 %x.full, 4294901760  ;; 4294901760 == 0xffff0000
+  %large = or i32 %x, 65536 ;; 65536 == 0x00010000
+  %small = or i32 %x, 90
+  %known = icmp ult i32 %large, %length.i
+  %to.prove = icmp ult i32 %small, %length.i
+  %res = icmp ule i1 %known, %to.prove
+  ret i1 %res
+}
+
+define i1 @test13(i32 %length.i, i32 %x) {
+; CHECK-LABEL: @test13(
+; CHECK:         ret i1 true
+;
+  %large = add nuw i32 %x, 100
+  %small = add nuw i32 %x, 90
+  %known = icmp ult i32 %large, %length.i
+  %to.prove = icmp ult i32 %small, %length.i
+  %res = icmp ule i1 %known, %to.prove
+  ret i1 %res
+}
+
+define i1 @test14(i32 %length.i, i32 %x.full) {
+; CHECK-LABEL: @test14(
+; CHECK:         ret i1 true
+;
+  %x = and i32 %x.full, 4294905615  ;; 4294905615 == 0xffff0f0f
+  %large = or i32 %x, 8224 ;; == 0x2020
+  %small = or i32 %x, 4112 ;; == 0x1010
+  %known = icmp ult i32 %large, %length.i
+  %to.prove = icmp ult i32 %small, %length.i
+  %res = icmp ule i1 %known, %to.prove
+  ret i1 %res
+}
+
+define i1 @test15(i32 %length.i, i32 %x) {
+; CHECK-LABEL: @test15(
+; CHECK:         [[LARGE:%.*]] = add nuw i32 %x, 100
+; CHECK-NEXT:    [[SMALL:%.*]] = add nuw i32 %x, 110
+; CHECK-NEXT:    [[KNOWN:%.*]] = icmp ult i32 [[LARGE]], %length.i
+; CHECK-NEXT:    [[TO_PROVE:%.*]] = icmp ult i32 [[SMALL]], %length.i
+; CHECK-NEXT:    [[RES:%.*]] = icmp ule i1 [[KNOWN]], [[TO_PROVE]]
+; CHECK-NEXT:    ret i1 [[RES]]
+;
+  %large = add nuw i32 %x, 100
+  %small = add nuw i32 %x, 110
+  %known = icmp ult i32 %large, %length.i
+  %to.prove = icmp ult i32 %small, %length.i
+  %res = icmp ule i1 %known, %to.prove
+  ret i1 %res
+}
+
+; X >=(s) Y == X ==> Y (i1 1 becomes -1 for reasoning)
+define i1 @test_sge(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test_sge(
+; CHECK:         ret i1 true
+;
+  %iplus1 = add nsw nuw i32 %i, 1
+  %var29 = icmp ult i32 %i, %length.i
+  %var30 = icmp ult i32 %iplus1, %length.i
+  %res = icmp sge i1 %var30, %var29
+  ret i1 %res
+}

Added: llvm/trunk/test/Transforms/InstSimplify/insertelement.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/insertelement.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/insertelement.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/insertelement.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+
+define <4 x i32> @test1(<4 x i32> %A) {
+  %I = insertelement <4 x i32> %A, i32 5, i64 4294967296
+  ; CHECK: ret <4 x i32> undef
+  ret <4 x i32> %I
+}
+
+define <4 x i32> @test2(<4 x i32> %A) {
+  %I = insertelement <4 x i32> %A, i32 5, i64 4
+  ; CHECK: ret <4 x i32> undef
+  ret <4 x i32> %I
+}
+
+define <4 x i32> @test3(<4 x i32> %A) {
+  %I = insertelement <4 x i32> %A, i32 5, i64 1
+  ; CHECK: ret <4 x i32> %I
+  ret <4 x i32> %I
+}
+
+define <4 x i32> @test4(<4 x i32> %A) {
+  %I = insertelement <4 x i32> %A, i32 5, i128 100
+  ; CHECK: ret <4 x i32> undef
+  ret <4 x i32> %I
+}
+
+define <4 x i32> @test5(<4 x i32> %A) {
+  %I = insertelement <4 x i32> %A, i32 5, i64 undef
+  ; CHECK: ret <4 x i32> undef
+  ret <4 x i32> %I
+}

Added: llvm/trunk/test/Transforms/InstSimplify/known-never-nan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/known-never-nan.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/known-never-nan.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/known-never-nan.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,372 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -instsimplify | FileCheck %s
+
+declare double @func()
+
+define i1 @nnan_call() {
+; CHECK-LABEL: @nnan_call(
+; CHECK-NEXT:    [[OP:%.*]] = call nnan double @func()
+; CHECK-NEXT:    ret i1 true
+;
+  %op = call nnan double @func()
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_fabs_src(double %arg) {
+; CHECK-LABEL: @nnan_fabs_src(
+; CHECK-NEXT:    ret i1 false
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.fabs.f64(double %nnan)
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_canonicalize_src(double %arg) {
+; CHECK-LABEL: @nnan_canonicalize_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.canonicalize.f64(double %nnan)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_copysign_src(double %arg0, double %arg1) {
+; CHECK-LABEL: @nnan_copysign_src(
+; CHECK-NEXT:    ret i1 false
+;
+  %nnan = fadd nnan double %arg0, 1.0
+  %op = call double @llvm.copysign.f64(double %nnan, double %arg1)
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @fabs_sqrt_src(double %arg0, double %arg1) {
+; CHECK-LABEL: @fabs_sqrt_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg0, 1.0
+  %fabs = call double @llvm.fabs.f64(double %nnan)
+  %op = call double @llvm.sqrt.f64(double %fabs)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @fabs_sqrt_src_maybe_nan(double %arg0, double %arg1) {
+; CHECK-LABEL: @fabs_sqrt_src_maybe_nan(
+; CHECK-NEXT:    [[FABS:%.*]] = call double @llvm.fabs.f64(double [[ARG0:%.*]])
+; CHECK-NEXT:    [[OP:%.*]] = call double @llvm.sqrt.f64(double [[FABS]])
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %fabs = call double @llvm.fabs.f64(double %arg0)
+  %op = call double @llvm.sqrt.f64(double %fabs)
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @exp_nnan_src(double %arg) {
+; CHECK-LABEL: @exp_nnan_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.exp.f64(double %nnan)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @exp2_nnan_src(double %arg) {
+; CHECK-LABEL: @exp2_nnan_src(
+; CHECK-NEXT:    ret i1 false
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.exp2.f64(double %nnan)
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @floor_nnan_src(double %arg) {
+; CHECK-LABEL: @floor_nnan_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.floor.f64(double %nnan)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @ceil_nnan_src(double %arg) {
+; CHECK-LABEL: @ceil_nnan_src(
+; CHECK-NEXT:    ret i1 false
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.ceil.f64(double %nnan)
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @trunc_nnan_src(double %arg) {
+; CHECK-LABEL: @trunc_nnan_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.trunc.f64(double %nnan)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @rint_nnan_src(double %arg) {
+; CHECK-LABEL: @rint_nnan_src(
+; CHECK-NEXT:    ret i1 false
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.rint.f64(double %nnan)
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nearbyint_nnan_src(double %arg) {
+; CHECK-LABEL: @nearbyint_nnan_src(
+; CHECK-NEXT:    ret i1 true
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.nearbyint.f64(double %nnan)
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @round_nnan_src(double %arg) {
+; CHECK-LABEL: @round_nnan_src(
+; CHECK-NEXT:    ret i1 false
+;
+  %nnan = fadd nnan double %arg, 1.0
+  %op = call double @llvm.round.f64(double %nnan)
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @known_nan_select(i1 %cond, double %arg0, double %arg1) {
+; CHECK-LABEL: @known_nan_select(
+; CHECK-NEXT:    ret i1 true
+;
+  %lhs = fadd nnan double %arg0, 1.0
+  %rhs = fadd nnan double %arg1, 2.0
+  %op = select i1 %cond, double %lhs, double %rhs
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @select_maybe_nan_lhs(i1 %cond, double %lhs, double %arg1) {
+; CHECK-LABEL: @select_maybe_nan_lhs(
+; CHECK-NEXT:    [[RHS:%.*]] = fadd nnan double [[ARG1:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[OP:%.*]] = select i1 [[COND:%.*]], double [[LHS:%.*]], double [[RHS]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %rhs = fadd nnan double %arg1, 1.0
+  %op = select i1 %cond, double %lhs, double %rhs
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @select_maybe_nan_rhs(i1 %cond, double %arg0, double %rhs) {
+; CHECK-LABEL: @select_maybe_nan_rhs(
+; CHECK-NEXT:    [[LHS:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[OP:%.*]] = select i1 [[COND:%.*]], double [[LHS]], double [[RHS:%.*]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %lhs = fadd nnan double %arg0, 1.0
+  %op = select i1 %cond, double %lhs, double %rhs
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_fadd(double %arg0, double %arg1) {
+; CHECK-LABEL: @nnan_fadd(
+; CHECK-NEXT:    [[NNAN_ARG0:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[NNAN_ARG1:%.*]] = fadd nnan double [[ARG0]], 2.000000e+00
+; CHECK-NEXT:    [[OP:%.*]] = fadd double [[NNAN_ARG0]], [[NNAN_ARG1]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %nnan.arg0 = fadd nnan double %arg0, 1.0
+  %nnan.arg1 = fadd nnan double %arg0, 2.0
+  %op = fadd double %nnan.arg0, %nnan.arg1
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_fadd_maybe_nan_lhs(double %arg0, double %arg1) {
+; CHECK-LABEL: @nnan_fadd_maybe_nan_lhs(
+; CHECK-NEXT:    [[NNAN_ARG1:%.*]] = fadd nnan double [[ARG1:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[OP:%.*]] = fadd double [[ARG0:%.*]], [[NNAN_ARG1]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %nnan.arg1 = fadd nnan double %arg1, 1.0
+  %op = fadd double %arg0, %nnan.arg1
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_fadd_maybe_nan_rhs(double %arg0, double %arg1) {
+; CHECK-LABEL: @nnan_fadd_maybe_nan_rhs(
+; CHECK-NEXT:    [[NNAN_ARG0:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[OP:%.*]] = fadd double [[NNAN_ARG0]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %nnan.arg0 = fadd nnan double %arg0, 1.0
+  %op = fadd double %nnan.arg0, %arg1
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_fmul(double %arg0, double %arg1) {
+; CHECK-LABEL: @nnan_fmul(
+; CHECK-NEXT:    [[NNAN_ARG0:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[NNAN_ARG1:%.*]] = fadd nnan double [[ARG0]], 2.000000e+00
+; CHECK-NEXT:    [[OP:%.*]] = fmul double [[NNAN_ARG0]], [[NNAN_ARG1]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %nnan.arg0 = fadd nnan double %arg0, 1.0
+  %nnan.arg1 = fadd nnan double %arg0, 2.0
+  %op = fmul double %nnan.arg0, %nnan.arg1
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_fsub(double %arg0, double %arg1) {
+; CHECK-LABEL: @nnan_fsub(
+; CHECK-NEXT:    [[NNAN_ARG0:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[NNAN_ARG1:%.*]] = fadd nnan double [[ARG0]], 2.000000e+00
+; CHECK-NEXT:    [[OP:%.*]] = fsub double [[NNAN_ARG0]], [[NNAN_ARG1]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %nnan.arg0 = fadd nnan double %arg0, 1.0
+  %nnan.arg1 = fadd nnan double %arg0, 2.0
+  %op = fsub double %nnan.arg0, %nnan.arg1
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_fneg() {
+; CHECK-LABEL: @nnan_fneg(
+; CHECK-NEXT:    [[NNAN:%.*]] = call nnan double @func()
+; CHECK-NEXT:    [[OP:%.*]] = fsub double -0.000000e+00, [[NNAN]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %nnan = call nnan double @func()
+  %op = fsub double -0.0, %nnan
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @sitofp(i32 %arg0) {
+; CHECK-LABEL: @sitofp(
+; CHECK-NEXT:    ret i1 false
+;
+  %op = sitofp i32 %arg0 to double
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @uitofp(i32 %arg0) {
+; CHECK-LABEL: @uitofp(
+; CHECK-NEXT:    ret i1 true
+;
+  %op = uitofp i32 %arg0 to double
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @fpext(float %arg0) {
+; CHECK-LABEL: @fpext(
+; CHECK-NEXT:    ret i1 false
+;
+  %arg0.nnan = fadd nnan float %arg0, 1.0
+  %op = fpext float %arg0.nnan to double
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @fpext_maybe_nan(float %arg0) {
+; CHECK-LABEL: @fpext_maybe_nan(
+; CHECK-NEXT:    [[OP:%.*]] = fpext float [[ARG0:%.*]] to double
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %op = fpext float %arg0 to double
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @fptrunc(double %arg0) {
+; CHECK-LABEL: @fptrunc(
+; CHECK-NEXT:    ret i1 false
+;
+  %arg0.nnan = fadd nnan double %arg0, 1.0
+  %op = fptrunc double %arg0.nnan to float
+  %tmp = fcmp uno float %op, %op
+  ret i1 %tmp
+}
+
+define i1 @fptrunc_maybe_nan(double %arg0) {
+; CHECK-LABEL: @fptrunc_maybe_nan(
+; CHECK-NEXT:    [[OP:%.*]] = fptrunc double [[ARG0:%.*]] to float
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord float [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %op = fptrunc double %arg0 to float
+  %tmp = fcmp ord float %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_fdiv(double %arg0, double %arg1) {
+; CHECK-LABEL: @nnan_fdiv(
+; CHECK-NEXT:    [[NNAN_ARG0:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[NNAN_ARG1:%.*]] = fadd nnan double [[ARG0]], 2.000000e+00
+; CHECK-NEXT:    [[OP:%.*]] = fdiv double [[NNAN_ARG0]], [[NNAN_ARG1]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp uno double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %nnan.arg0 = fadd nnan double %arg0, 1.0
+  %nnan.arg1 = fadd nnan double %arg0, 2.0
+  %op = fdiv double %nnan.arg0, %nnan.arg1
+  %tmp = fcmp uno double %op, %op
+  ret i1 %tmp
+}
+
+define i1 @nnan_frem(double %arg0, double %arg1) {
+; CHECK-LABEL: @nnan_frem(
+; CHECK-NEXT:    [[NNAN_ARG0:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[NNAN_ARG1:%.*]] = fadd nnan double [[ARG0]], 2.000000e+00
+; CHECK-NEXT:    [[OP:%.*]] = frem double [[NNAN_ARG0]], [[NNAN_ARG1]]
+; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[OP]], [[OP]]
+; CHECK-NEXT:    ret i1 [[TMP]]
+;
+  %nnan.arg0 = fadd nnan double %arg0, 1.0
+  %nnan.arg1 = fadd nnan double %arg0, 2.0
+  %op = frem double %nnan.arg0, %nnan.arg1
+  %tmp = fcmp ord double %op, %op
+  ret i1 %tmp
+}
+
+declare double @llvm.sqrt.f64(double)
+declare double @llvm.fabs.f64(double)
+declare double @llvm.canonicalize.f64(double)
+declare double @llvm.copysign.f64(double, double)
+declare double @llvm.exp.f64(double)
+declare double @llvm.exp2.f64(double)
+declare double @llvm.floor.f64(double)
+declare double @llvm.ceil.f64(double)
+declare double @llvm.trunc.f64(double)
+declare double @llvm.rint.f64(double)
+declare double @llvm.nearbyint.f64(double)
+declare double @llvm.round.f64(double)

Added: llvm/trunk/test/Transforms/InstSimplify/load-relative-32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/load-relative-32.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/load-relative-32.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/load-relative-32.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-unknown-linux-gnu"
+
+ at a = external global i8
+
+ at c1 = constant [3 x i32] [i32 0, i32 0,
+i32 sub (i32 ptrtoint (i8* @a to i32), i32 ptrtoint (i32* getelementptr ([3 x i32], [3 x i32]* @c1, i32 0, i32 2) to i32))
+]
+
+; CHECK: @f1
+define i8* @f1() {
+  ; CHECK: ret i8* @a
+  %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([3 x i32], [3 x i32]* @c1, i32 0, i32 2) to i8*), i32 0)
+  ret i8* %l
+}
+
+declare i8* @llvm.load.relative.i32(i8*, i32)

Added: llvm/trunk/test/Transforms/InstSimplify/load-relative.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/load-relative.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/load-relative.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/load-relative.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,75 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at a = external global i8
+ at b = external global i8
+
+ at c1 = constant i32 trunc (i64 sub (i64 ptrtoint (i8* @a to i64), i64 ptrtoint (i32* @c1 to i64)) to i32)
+ at c2 = constant [7 x i32] [i32 0, i32 0,
+i32 trunc (i64 sub (i64 ptrtoint (i8* @a to i64), i64 ptrtoint (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i32 0, i32 2) to i64)) to i32),
+i32 trunc (i64 sub (i64 ptrtoint (i8* @b to i64), i64 ptrtoint (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i32 0, i32 2) to i64)) to i32),
+i32 trunc (i64 add (i64 ptrtoint (i8* @b to i64), i64 ptrtoint (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i32 0, i32 2) to i64)) to i32),
+i32 trunc (i64 sub (i64 ptrtoint (i8* @b to i64), i64 1) to i32),
+i32 trunc (i64 sub (i64 0, i64 ptrtoint (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i32 0, i32 2) to i64)) to i32)
+]
+
+; CHECK: @f1
+define i8* @f1() {
+  ; CHECK: ret i8* @a
+  %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* @c1 to i8*), i32 0)
+  ret i8* %l
+}
+
+; CHECK: @f2
+define i8* @f2() {
+  ; CHECK: ret i8* @a
+  %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 0)
+  ret i8* %l
+}
+
+; CHECK: @f3
+define i8* @f3() {
+  ; CHECK: ret i8* @b
+  %l = call i8* @llvm.load.relative.i64(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i64 4)
+  ret i8* %l
+}
+
+; CHECK: @f4
+define i8* @f4() {
+  ; CHECK: ret i8* %
+  %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 1)
+  ret i8* %l
+}
+
+; CHECK: @f5
+define i8* @f5() {
+  ; CHECK: ret i8* %
+  %l = call i8* @llvm.load.relative.i32(i8* zeroinitializer, i32 0)
+  ret i8* %l
+}
+
+; CHECK: @f6
+define i8* @f6() {
+  ; CHECK: ret i8* %
+  %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 8)
+  ret i8* %l
+}
+
+; CHECK: @f7
+define i8* @f7() {
+  ; CHECK: ret i8* %
+  %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 12)
+  ret i8* %l
+}
+
+; CHECK: @f8
+define i8* @f8() {
+  ; CHECK: ret i8* %
+  %l = call i8* @llvm.load.relative.i32(i8* bitcast (i32* getelementptr ([7 x i32], [7 x i32]* @c2, i64 0, i64 2) to i8*), i32 16)
+  ret i8* %l
+}
+
+declare i8* @llvm.load.relative.i32(i8*, i32)
+declare i8* @llvm.load.relative.i64(i8*, i64)

Added: llvm/trunk/test/Transforms/InstSimplify/load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/load.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; NOTE: Assertions have been autogenerated by update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+ at zeroinit = constant {} zeroinitializer
+ at undef = constant {} undef
+
+define i32 @crash_on_zeroinit() {
+; CHECK-LABEL: @crash_on_zeroinit(
+; CHECK:         ret i32 0
+;
+  %load = load i32, i32* bitcast ({}* @zeroinit to i32*)
+  ret i32 %load
+}
+
+define i32 @crash_on_undef() {
+; CHECK-LABEL: @crash_on_undef(
+; CHECK:         ret i32 undef
+;
+  %load = load i32, i32* bitcast ({}* @undef to i32*)
+  ret i32 %load
+}
+
+ at GV = private constant [8 x i32] [i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49]
+
+define <8 x i32> @partial_load() {
+; CHECK-LABEL: @partial_load(
+; CHECK:         ret <8 x i32> <i32 0, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48>
+  %load = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr ([8 x i32], [8 x i32]* @GV, i64 0, i64 -1) to <8 x i32>*)
+  ret <8 x i32> %load
+}

Added: llvm/trunk/test/Transforms/InstSimplify/log-exp-intrinsic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/log-exp-intrinsic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/log-exp-intrinsic.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/log-exp-intrinsic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,192 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+declare double @llvm.log.f64(double)
+declare double @llvm.exp.f64(double)
+declare double @llvm.log2.f64(double)
+declare double @llvm.exp2.f64(double)
+
+define double @log_reassoc_exp_strict(double %a) {
+; CHECK-LABEL: @log_reassoc_exp_strict(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %1 = call double @llvm.exp.f64(double %a)
+  %2 = call reassoc double @llvm.log.f64(double %1)
+  ret double %2
+}
+
+define double @log_strict_exp_reassoc(double %a) {
+; CHECK-LABEL: @log_strict_exp_reassoc(
+; CHECK-NEXT:    [[TMP1:%.*]] = call reassoc double @llvm.exp.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.log.f64(double [[TMP1]])
+; CHECK-NEXT:    ret double [[TMP2]]
+;
+  %1 = call reassoc double @llvm.exp.f64(double %a)
+  %2 = call double @llvm.log.f64(double %1)
+  ret double %2
+}
+
+define double @log_exp_log_exp(double %a) {
+; CHECK-LABEL: @log_exp_log_exp(
+; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.exp.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.log.f64(double [[TMP1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = call double @llvm.exp.f64(double [[TMP2]])
+; CHECK-NEXT:    [[TMP4:%.*]] = call double @llvm.log.f64(double [[TMP3]])
+; CHECK-NEXT:    ret double [[TMP4]]
+;
+  %1 = call double @llvm.exp.f64(double %a)
+  %2 = call double @llvm.log.f64(double %1)
+  %3 = call double @llvm.exp.f64(double %2)
+  %4 = call double @llvm.log.f64(double %3)
+  ret double %4
+}
+
+define double @log_exp_log_exp_reassoc(double %a) {
+; CHECK-LABEL: @log_exp_log_exp_reassoc(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %1 = call double @llvm.exp.f64(double %a)
+  %2 = call reassoc double @llvm.log.f64(double %1)
+  %3 = call double @llvm.exp.f64(double %2)
+  %4 = call reassoc double @llvm.log.f64(double %3)
+  ret double %4
+}
+
+define double @log2_reassoc_exp2_strict(double %a) {
+; CHECK-LABEL: @log2_reassoc_exp2_strict(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %1 = call double @llvm.exp2.f64(double %a)
+  %2 = call reassoc double @llvm.log2.f64(double %1)
+  ret double %2
+}
+
+define double @log2_strict_exp2_reassoc(double %a) {
+; CHECK-LABEL: @log2_strict_exp2_reassoc(
+; CHECK-NEXT:    [[TMP1:%.*]] = call reassoc double @llvm.exp2.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.log2.f64(double [[TMP1]])
+; CHECK-NEXT:    ret double [[TMP2]]
+;
+  %1 = call reassoc double @llvm.exp2.f64(double %a)
+  %2 = call double @llvm.log2.f64(double %1)
+  ret double %2
+}
+
+define double @log2_exp2_log2_exp2(double %a) {
+; CHECK-LABEL: @log2_exp2_log2_exp2(
+; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.exp2.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.log2.f64(double [[TMP1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = call double @llvm.exp2.f64(double [[TMP2]])
+; CHECK-NEXT:    [[TMP4:%.*]] = call double @llvm.log2.f64(double [[TMP3]])
+; CHECK-NEXT:    ret double [[TMP4]]
+;
+  %1 = call double @llvm.exp2.f64(double %a)
+  %2 = call double @llvm.log2.f64(double %1)
+  %3 = call double @llvm.exp2.f64(double %2)
+  %4 = call double @llvm.log2.f64(double %3)
+  ret double %4
+}
+
+define double @log2_exp2_log2_exp2_reassoc(double %a) {
+; CHECK-LABEL: @log2_exp2_log2_exp2_reassoc(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %1 = call double @llvm.exp2.f64(double %a)
+  %2 = call reassoc double @llvm.log2.f64(double %1)
+  %3 = call double @llvm.exp2.f64(double %2)
+  %4 = call reassoc double @llvm.log2.f64(double %3)
+  ret double %4
+}
+
+define double @exp_reassoc_log_strict(double %a) {
+; CHECK-LABEL: @exp_reassoc_log_strict(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %1 = call double @llvm.log.f64(double %a)
+  %2 = call reassoc double @llvm.exp.f64(double %1)
+  ret double %2
+}
+
+define double @exp_strict_log_reassoc(double %a) {
+; CHECK-LABEL: @exp_strict_log_reassoc(
+; CHECK-NEXT:    [[TMP1:%.*]] = call reassoc double @llvm.log.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.exp.f64(double [[TMP1]])
+; CHECK-NEXT:    ret double [[TMP2]]
+;
+  %1 = call reassoc double @llvm.log.f64(double %a)
+  %2 = call double @llvm.exp.f64(double %1)
+  ret double %2
+}
+
+define double @exp_log_exp_log(double %a) {
+; CHECK-LABEL: @exp_log_exp_log(
+; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.log.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.exp.f64(double [[TMP1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = call double @llvm.log.f64(double [[TMP2]])
+; CHECK-NEXT:    [[TMP4:%.*]] = call double @llvm.exp.f64(double [[TMP3]])
+; CHECK-NEXT:    ret double [[TMP4]]
+;
+  %1 = call double @llvm.log.f64(double %a)
+  %2 = call double @llvm.exp.f64(double %1)
+  %3 = call double @llvm.log.f64(double %2)
+  %4 = call double @llvm.exp.f64(double %3)
+  ret double %4
+}
+
+define double @exp_log_exp_log_reassoc(double %a) {
+; CHECK-LABEL: @exp_log_exp_log_reassoc(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %1 = call double @llvm.log.f64(double %a)
+  %2 = call reassoc double @llvm.exp.f64(double %1)
+  %3 = call double @llvm.log.f64(double %2)
+  %4 = call reassoc double @llvm.exp.f64(double %3)
+  ret double %4
+}
+
+define double @exp2_reassoc_log2_strict(double %a) {
+; CHECK-LABEL: @exp2_reassoc_log2_strict(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %1 = call double @llvm.log2.f64(double %a)
+  %2 = call reassoc double @llvm.exp2.f64(double %1)
+  ret double %2
+}
+
+define double @exp2_strict_log2_reassoc(double %a) {
+; CHECK-LABEL: @exp2_strict_log2_reassoc(
+; CHECK-NEXT:    [[TMP1:%.*]] = call reassoc double @llvm.log2.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.exp2.f64(double [[TMP1]])
+; CHECK-NEXT:    ret double [[TMP2]]
+;
+  %1 = call reassoc double @llvm.log2.f64(double %a)
+  %2 = call double @llvm.exp2.f64(double %1)
+  ret double %2
+}
+
+define double @exp2_log2_exp2_log2(double %a) {
+; CHECK-LABEL: @exp2_log2_exp2_log2(
+; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.log2.f64(double [[A:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.exp2.f64(double [[TMP1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = call double @llvm.log2.f64(double [[TMP2]])
+; CHECK-NEXT:    [[TMP4:%.*]] = call double @llvm.exp2.f64(double [[TMP3]])
+; CHECK-NEXT:    ret double [[TMP4]]
+;
+  %1 = call double @llvm.log2.f64(double %a)
+  %2 = call double @llvm.exp2.f64(double %1)
+  %3 = call double @llvm.log2.f64(double %2)
+  %4 = call double @llvm.exp2.f64(double %3)
+  ret double %4
+}
+
+define double @exp2_log2_exp2_log2_reassoc(double %a) {
+; CHECK-LABEL: @exp2_log2_exp2_log2_reassoc(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %1 = call double @llvm.log2.f64(double %a)
+  %2 = call reassoc double @llvm.exp2.f64(double %1)
+  %3 = call double @llvm.log2.f64(double %2)
+  %4 = call reassoc double @llvm.exp2.f64(double %3)
+  ret double %4
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/log10-pow10-intrinsic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/log10-pow10-intrinsic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/log10-pow10-intrinsic.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/log10-pow10-intrinsic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+
+declare double @llvm.log10.f64(double)
+declare double @llvm.pow.f64(double, double)
+
+define double @log10_pow10(double %x) {
+; CHECK-LABEL: @log10_pow10(
+; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.pow.f64(double 1.000000e+01, double [[X:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.log10.f64(double [[TMP1]])
+; CHECK-NEXT:    ret double [[TMP2]]
+;
+  %tmp = call double @llvm.pow.f64(double 1.000000e+01, double %x)
+  %tmp1 = call double @llvm.log10.f64(double %tmp)
+  ret double %tmp1
+}
+
+define double @log10_strict_pow10_reassoc(double %x) {
+; CHECK-LABEL: @log10_strict_pow10_reassoc(
+; CHECK-NEXT:    [[TMP1:%.*]] = call reassoc double @llvm.pow.f64(double 1.000000e+01, double [[X:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.log10.f64(double [[TMP1]])
+; CHECK-NEXT:    ret double [[TMP2]]
+;
+  %tmp = call reassoc double @llvm.pow.f64(double 1.000000e+01, double %x)
+  %tmp1 = call double @llvm.log10.f64(double %tmp)
+  ret double %tmp1
+}
+
+define double @log10_reassoc_pow10_strict(double %x) {
+; CHECK-LABEL: @log10_reassoc_pow10_strict(
+; CHECK-NEXT:    ret double [[X:%.*]]
+;
+  %tmp = call double @llvm.pow.f64(double 1.000000e+01, double %x)
+  %tmp1 = call reassoc double @llvm.log10.f64(double %tmp)
+  ret double %tmp1
+}
+
+define double @log10_pow10_reassoc(double %x) {
+; CHECK-LABEL: @log10_pow10_reassoc(
+; CHECK-NEXT:    ret double [[X:%.*]]
+;
+  %tmp = call reassoc double @llvm.pow.f64(double 1.000000e+01, double %x)
+  %tmp1 = call reassoc double @llvm.log10.f64(double %tmp)
+  ret double %tmp1
+}

Added: llvm/trunk/test/Transforms/InstSimplify/log2-pow2-intrinsic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/log2-pow2-intrinsic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/log2-pow2-intrinsic.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/log2-pow2-intrinsic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+
+declare double @llvm.log2.f64(double)
+declare double @llvm.pow.f64(double, double)
+
+define double @log2_pow2(double %x) {
+; CHECK-LABEL: @log2_pow2(
+; CHECK-NEXT:    [[TMP:%.*]] = call double @llvm.pow.f64(double 2.000000e+00, double [[X:%.*]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.log2.f64(double [[TMP]])
+; CHECK-NEXT:    ret double [[TMP1]]
+;
+  %tmp = call double @llvm.pow.f64(double 2.000000e+00, double %x)
+  %tmp1 = call double @llvm.log2.f64(double %tmp)
+  ret double %tmp1
+}
+
+define double @log2_strict_pow2_reassoc(double %x) {
+; CHECK-LABEL: @log2_strict_pow2_reassoc(
+; CHECK-NEXT:    [[TMP:%.*]] = call reassoc double @llvm.pow.f64(double 2.000000e+00, double [[X:%.*]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.log2.f64(double [[TMP]])
+; CHECK-NEXT:    ret double [[TMP1]]
+;
+  %tmp = call reassoc double @llvm.pow.f64(double 2.000000e+00, double %x)
+  %tmp1 = call double @llvm.log2.f64(double %tmp)
+  ret double %tmp1
+}
+
+define double @log2_reassoc_pow2_strict(double %x) {
+; CHECK-LABEL: @log2_reassoc_pow2_strict(
+; CHECK-NEXT:    ret double [[X:%.*]]
+;
+  %tmp = call double @llvm.pow.f64(double 2.000000e+00, double %x)
+  %tmp1 = call reassoc double @llvm.log2.f64(double %tmp)
+  ret double %tmp1
+}
+
+define double @log2_pow2_reassoc(double %x) {
+; CHECK-LABEL: @log2_pow2_reassoc(
+; CHECK-NEXT:    ret double [[X:%.*]]
+;
+  %tmp = call reassoc double @llvm.pow.f64(double 2.000000e+00, double %x)
+  %tmp1 = call reassoc double @llvm.log2.f64(double %tmp)
+  ret double %tmp1
+}

Added: llvm/trunk/test/Transforms/InstSimplify/logic-of-fcmps.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/logic-of-fcmps.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/logic-of-fcmps.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/logic-of-fcmps.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,183 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; Cycle through commuted variants where one operand of fcmp ord/uno is
+; known not-a-NAN and the other is repeated in the logically-connected fcmp.
+
+define i1 @ord1(float %x, float %y) {
+; CHECK-LABEL: @ord1(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord float %x, %y
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = fcmp ord float 0.0, %x
+  %cmp2 = fcmp ord float %x, %y
+  %r = and i1 %cmp1, %cmp2
+  ret i1 %r
+}
+
+define i1 @ord2(double %x, double %y) {
+; CHECK-LABEL: @ord2(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord double %y, %x
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = fcmp ord double 42.0, %x
+  %cmp2 = fcmp ord double %y, %x
+  %r = and i1 %cmp1, %cmp2
+  ret i1 %r
+}
+
+define <2 x i1> @ord3(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @ord3(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord <2 x float> %x, %y
+; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
+;
+  %cmp1 = fcmp ord <2 x float> %x, zeroinitializer
+  %cmp2 = fcmp ord <2 x float> %x, %y
+  %r = and <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ord4(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: @ord4(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord <2 x double> %y, %x
+; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
+;
+  %cmp1 = fcmp ord <2 x double> %x, <double 42.0, double 42.0>
+  %cmp2 = fcmp ord <2 x double> %y, %x
+  %r = and <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %r
+}
+
+define i1 @ord5(float %x, float %y) {
+; CHECK-LABEL: @ord5(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord float %x, %y
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %nnan = fdiv nnan float %x, %y
+  %cmp1 = fcmp ord float %x, %y
+  %cmp2 = fcmp ord float %nnan, %x
+  %r = and i1 %cmp1, %cmp2
+  ret i1 %r
+}
+
+define i1 @ord6(double %x, double %y) {
+; CHECK-LABEL: @ord6(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord double %y, %x
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = fcmp ord double %y, %x
+  %cmp2 = fcmp ord double 42.0, %x
+  %r = and i1 %cmp1, %cmp2
+  ret i1 %r
+}
+
+define <2 x i1> @ord7(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @ord7(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord <2 x float> %x, %y
+; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
+;
+  %cmp1 = fcmp ord <2 x float> %x, %y
+  %cmp2 = fcmp ord <2 x float> %x, zeroinitializer
+  %r = and <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @ord8(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: @ord8(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord <2 x double> %y, %x
+; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
+;
+  %cmp1 = fcmp ord <2 x double> %y, %x
+  %cmp2 = fcmp ord <2 x double> %x, <double 0.0, double 42.0>
+  %r = and <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %r
+}
+
+define i1 @uno1(float %x, float %y) {
+; CHECK-LABEL: @uno1(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno float %x, %y
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = fcmp uno float 0.0, %x
+  %cmp2 = fcmp uno float %x, %y
+  %r = or i1 %cmp1, %cmp2
+  ret i1 %r
+}
+
+define i1 @uno2(double %x, double %y) {
+; CHECK-LABEL: @uno2(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno double %y, %x
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = fcmp uno double 42.0, %x
+  %cmp2 = fcmp uno double %y, %x
+  %r = or i1 %cmp1, %cmp2
+  ret i1 %r
+}
+
+define <2 x i1> @uno3(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @uno3(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno <2 x float> %x, %y
+; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
+;
+  %cmp1 = fcmp uno <2 x float> %x, zeroinitializer
+  %cmp2 = fcmp uno <2 x float> %x, %y
+  %r = or <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @uno4(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: @uno4(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno <2 x double> %y, %x
+; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
+;
+  %cmp1 = fcmp uno <2 x double> %x, <double 42.0, double 42.0>
+  %cmp2 = fcmp uno <2 x double> %y, %x
+  %r = or <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %r
+}
+
+define i1 @uno5(float %x, float %y) {
+; CHECK-LABEL: @uno5(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno float %x, %y
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = fcmp uno float %x, %y
+  %cmp2 = fcmp uno float 0.0, %x
+  %r = or i1 %cmp1, %cmp2
+  ret i1 %r
+}
+
+define i1 @uno6(double %x, double %y) {
+; CHECK-LABEL: @uno6(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno double %y, %x
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = fcmp uno double %y, %x
+  %cmp2 = fcmp uno double 42.0, %x
+  %r = or i1 %cmp1, %cmp2
+  ret i1 %r
+}
+
+define <2 x i1> @uno7(<2 x float> %x, <2 x float> %y) {
+; CHECK-LABEL: @uno7(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno <2 x float> %x, %y
+; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
+;
+  %nnan = fdiv nnan <2 x float> %x, %y
+  %cmp1 = fcmp uno <2 x float> %x, %y
+  %cmp2 = fcmp uno <2 x float> %x, %nnan
+  %r = or <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %r
+}
+
+define <2 x i1> @uno8(<2 x double> %x, <2 x double> %y) {
+; CHECK-LABEL: @uno8(
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno <2 x double> %y, %x
+; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
+;
+  %cmp1 = fcmp uno <2 x double> %y, %x
+  %cmp2 = fcmp uno <2 x double> %x, <double 0x7ff0000000000000, double 42.0>
+  %r = or <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %r
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/maxmin.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/maxmin.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/maxmin.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/maxmin.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,302 @@
+; NOTE: Assertions have been autogenerated by update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i1 @max1(i32 %x, i32 %y) {
+; CHECK-LABEL: @max1(
+; CHECK:         ret i1 false
+;
+  %c = icmp sgt i32 %x, %y
+  %m = select i1 %c, i32 %x, i32 %y
+  %r = icmp slt i32 %m, %x
+  ret i1 %r
+}
+
+define i1 @max2(i32 %x, i32 %y) {
+; CHECK-LABEL: @max2(
+; CHECK:         ret i1 true
+;
+  %c = icmp sge i32 %x, %y
+  %m = select i1 %c, i32 %x, i32 %y
+  %r = icmp sge i32 %m, %x
+  ret i1 %r
+}
+
+define i1 @max3(i32 %x, i32 %y) {
+; CHECK-LABEL: @max3(
+; CHECK:         ret i1 false
+;
+  %c = icmp ugt i32 %x, %y
+  %m = select i1 %c, i32 %x, i32 %y
+  %r = icmp ult i32 %m, %x
+  ret i1 %r
+}
+
+define i1 @max4(i32 %x, i32 %y) {
+; CHECK-LABEL: @max4(
+; CHECK:         ret i1 true
+;
+  %c = icmp uge i32 %x, %y
+  %m = select i1 %c, i32 %x, i32 %y
+  %r = icmp uge i32 %m, %x
+  ret i1 %r
+}
+
+define i1 @max5(i32 %x, i32 %y) {
+; CHECK-LABEL: @max5(
+; CHECK:         ret i1 false
+;
+  %c = icmp sgt i32 %x, %y
+  %m = select i1 %c, i32 %x, i32 %y
+  %r = icmp sgt i32 %x, %m
+  ret i1 %r
+}
+
+define i1 @max6(i32 %x, i32 %y) {
+; CHECK-LABEL: @max6(
+; CHECK:         ret i1 true
+;
+  %c = icmp sge i32 %x, %y
+  %m = select i1 %c, i32 %x, i32 %y
+  %r = icmp sle i32 %x, %m
+  ret i1 %r
+}
+
+define i1 @max7(i32 %x, i32 %y) {
+; CHECK-LABEL: @max7(
+; CHECK:         ret i1 false
+;
+  %c = icmp ugt i32 %x, %y
+  %m = select i1 %c, i32 %x, i32 %y
+  %r = icmp ugt i32 %x, %m
+  ret i1 %r
+}
+
+define i1 @max8(i32 %x, i32 %y) {
+; CHECK-LABEL: @max8(
+; CHECK:         ret i1 true
+;
+  %c = icmp uge i32 %x, %y
+  %m = select i1 %c, i32 %x, i32 %y
+  %r = icmp ule i32 %x, %m
+  ret i1 %r
+}
+
+define i1 @min1(i32 %x, i32 %y) {
+; CHECK-LABEL: @min1(
+; CHECK:         ret i1 false
+;
+  %c = icmp sgt i32 %x, %y
+  %m = select i1 %c, i32 %y, i32 %x
+  %r = icmp sgt i32 %m, %x
+  ret i1 %r
+}
+
+define i1 @min2(i32 %x, i32 %y) {
+; CHECK-LABEL: @min2(
+; CHECK:         ret i1 true
+;
+  %c = icmp sge i32 %x, %y
+  %m = select i1 %c, i32 %y, i32 %x
+  %r = icmp sle i32 %m, %x
+  ret i1 %r
+}
+
+define i1 @min3(i32 %x, i32 %y) {
+; CHECK-LABEL: @min3(
+; CHECK:         ret i1 false
+;
+  %c = icmp ugt i32 %x, %y
+  %m = select i1 %c, i32 %y, i32 %x
+  %r = icmp ugt i32 %m, %x
+  ret i1 %r
+}
+
+define i1 @min4(i32 %x, i32 %y) {
+; CHECK-LABEL: @min4(
+; CHECK:         ret i1 true
+;
+  %c = icmp uge i32 %x, %y
+  %m = select i1 %c, i32 %y, i32 %x
+  %r = icmp ule i32 %m, %x
+  ret i1 %r
+}
+
+define i1 @min5(i32 %x, i32 %y) {
+; CHECK-LABEL: @min5(
+; CHECK:         ret i1 false
+;
+  %c = icmp sgt i32 %x, %y
+  %m = select i1 %c, i32 %y, i32 %x
+  %r = icmp slt i32 %x, %m
+  ret i1 %r
+}
+
+define i1 @min6(i32 %x, i32 %y) {
+; CHECK-LABEL: @min6(
+; CHECK:         ret i1 true
+;
+  %c = icmp sge i32 %x, %y
+  %m = select i1 %c, i32 %y, i32 %x
+  %r = icmp sge i32 %x, %m
+  ret i1 %r
+}
+
+define i1 @min7(i32 %x, i32 %y) {
+; CHECK-LABEL: @min7(
+; CHECK:         ret i1 false
+;
+  %c = icmp ugt i32 %x, %y
+  %m = select i1 %c, i32 %y, i32 %x
+  %r = icmp ult i32 %x, %m
+  ret i1 %r
+}
+
+define i1 @min8(i32 %x, i32 %y) {
+; CHECK-LABEL: @min8(
+; CHECK:         ret i1 true
+;
+  %c = icmp uge i32 %x, %y
+  %m = select i1 %c, i32 %y, i32 %x
+  %r = icmp uge i32 %x, %m
+  ret i1 %r
+}
+
+define i1 @maxmin1(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @maxmin1(
+; CHECK:         ret i1 true
+;
+  %c1 = icmp sge i32 %x, %y
+  %max = select i1 %c1, i32 %x, i32 %y
+  %c2 = icmp sge i32 %x, %z
+  %min = select i1 %c2, i32 %z, i32 %x
+  %c = icmp sge i32 %max, %min
+  ret i1 %c
+}
+
+define i1 @maxmin2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @maxmin2(
+; CHECK:         ret i1 false
+;
+  %c1 = icmp sge i32 %x, %y
+  %max = select i1 %c1, i32 %x, i32 %y
+  %c2 = icmp sge i32 %x, %z
+  %min = select i1 %c2, i32 %z, i32 %x
+  %c = icmp sgt i32 %min, %max
+  ret i1 %c
+}
+
+define i1 @maxmin3(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @maxmin3(
+; CHECK:         ret i1 true
+;
+  %c1 = icmp sge i32 %x, %y
+  %max = select i1 %c1, i32 %x, i32 %y
+  %c2 = icmp sge i32 %x, %z
+  %min = select i1 %c2, i32 %z, i32 %x
+  %c = icmp sle i32 %min, %max
+  ret i1 %c
+}
+
+define i1 @maxmin4(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @maxmin4(
+; CHECK:         ret i1 false
+;
+  %c1 = icmp sge i32 %x, %y
+  %max = select i1 %c1, i32 %x, i32 %y
+  %c2 = icmp sge i32 %x, %z
+  %min = select i1 %c2, i32 %z, i32 %x
+  %c = icmp slt i32 %max, %min
+  ret i1 %c
+}
+
+define i1 @maxmin5(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @maxmin5(
+; CHECK:         ret i1 true
+;
+  %c1 = icmp uge i32 %x, %y
+  %max = select i1 %c1, i32 %x, i32 %y
+  %c2 = icmp uge i32 %x, %z
+  %min = select i1 %c2, i32 %z, i32 %x
+  %c = icmp uge i32 %max, %min
+  ret i1 %c
+}
+
+define i1 @maxmin6(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @maxmin6(
+; CHECK:         ret i1 false
+;
+  %c1 = icmp uge i32 %x, %y
+  %max = select i1 %c1, i32 %x, i32 %y
+  %c2 = icmp uge i32 %x, %z
+  %min = select i1 %c2, i32 %z, i32 %x
+  %c = icmp ugt i32 %min, %max
+  ret i1 %c
+}
+
+define i1 @maxmin7(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @maxmin7(
+; CHECK:         ret i1 true
+;
+  %c1 = icmp uge i32 %x, %y
+  %max = select i1 %c1, i32 %x, i32 %y
+  %c2 = icmp uge i32 %x, %z
+  %min = select i1 %c2, i32 %z, i32 %x
+  %c = icmp ule i32 %min, %max
+  ret i1 %c
+}
+
+define i1 @maxmin8(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @maxmin8(
+; CHECK:         ret i1 false
+;
+  %c1 = icmp uge i32 %x, %y
+  %max = select i1 %c1, i32 %x, i32 %y
+  %c2 = icmp uge i32 %x, %z
+  %min = select i1 %c2, i32 %z, i32 %x
+  %c = icmp ult i32 %max, %min
+  ret i1 %c
+}
+
+define i1 @eqcmp1(i32 %x, i32 %y) {
+; CHECK-LABEL: @eqcmp1(
+; CHECK:         [[C:%.*]] = icmp sge i32 %x, %y
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %c = icmp sge i32 %x, %y
+  %max = select i1 %c, i32 %x, i32 %y
+  %r = icmp eq i32 %max, %x
+  ret i1 %r
+}
+
+define i1 @eqcmp2(i32 %x, i32 %y) {
+; CHECK-LABEL: @eqcmp2(
+; CHECK:         [[C:%.*]] = icmp sge i32 %x, %y
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %c = icmp sge i32 %x, %y
+  %max = select i1 %c, i32 %x, i32 %y
+  %r = icmp eq i32 %x, %max
+  ret i1 %r
+}
+
+define i1 @eqcmp3(i32 %x, i32 %y) {
+; CHECK-LABEL: @eqcmp3(
+; CHECK:         [[C:%.*]] = icmp uge i32 %x, %y
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %c = icmp uge i32 %x, %y
+  %max = select i1 %c, i32 %x, i32 %y
+  %r = icmp eq i32 %max, %x
+  ret i1 %r
+}
+
+define i1 @eqcmp4(i32 %x, i32 %y) {
+; CHECK-LABEL: @eqcmp4(
+; CHECK:         [[C:%.*]] = icmp uge i32 %x, %y
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %c = icmp uge i32 %x, %y
+  %max = select i1 %c, i32 %x, i32 %y
+  %r = icmp eq i32 %x, %max
+  ret i1 %r
+}

Added: llvm/trunk/test/Transforms/InstSimplify/mul.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/mul.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/mul.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/mul.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define <2 x i1> @test1(<2 x i1> %a) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %b = and <2 x i1> %a, <i1 true, i1 false>
+  %res = mul <2 x i1> %b, <i1 false, i1 true>
+  ret <2 x i1> %res
+}
+
+define i32 @mul_by_1(i32 %A) {
+; CHECK-LABEL: @mul_by_1(
+; CHECK-NEXT:    ret i32 [[A:%.*]]
+;
+  %B = mul i32 %A, 1
+  ret i32 %B
+}
+
+define i32 @mul_by_0(i32 %A) {
+; CHECK-LABEL: @mul_by_0(
+; CHECK-NEXT:    ret i32 0
+;
+  %B = mul i32 %A, 0
+  ret i32 %B
+}
+
+define <16 x i8> @mul_by_0_vec(<16 x i8> %a) {
+; CHECK-LABEL: @mul_by_0_vec(
+; CHECK-NEXT:    ret <16 x i8> zeroinitializer
+;
+  %b = mul <16 x i8> %a, zeroinitializer
+  ret <16 x i8> %b
+}
+
+define <2 x i8> @mul_by_0_vec_undef_elt(<2 x i8> %a) {
+; CHECK-LABEL: @mul_by_0_vec_undef_elt(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %b = mul <2 x i8> %a, <i8 undef, i8 0>
+  ret <2 x i8> %b
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/negate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/negate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/negate.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/negate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @negate_nuw(i32 %x) {
+; CHECK-LABEL: @negate_nuw(
+; CHECK-NEXT:    ret i32 0
+;
+  %neg = sub nuw i32 0, %x
+  ret i32 %neg
+}
+
+define <2 x i32> @negate_nuw_vec(<2 x i32> %x) {
+; CHECK-LABEL: @negate_nuw_vec(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %neg = sub nuw <2 x i32> zeroinitializer, %x
+  ret <2 x i32> %neg
+}
+
+define <2 x i32> @negate_nuw_vec_undef_elt(<2 x i32> %x) {
+; CHECK-LABEL: @negate_nuw_vec_undef_elt(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %neg = sub nuw <2 x i32> <i32 0, i32 undef>, %x
+  ret <2 x i32> %neg
+}
+
+define i8 @negate_zero_or_minsigned_nsw(i8 %x) {
+; CHECK-LABEL: @negate_zero_or_minsigned_nsw(
+; CHECK-NEXT:    ret i8 0
+;
+  %signbit = and i8 %x, 128
+  %neg = sub nsw i8 0, %signbit
+  ret i8 %neg
+}
+
+define <2 x i8> @negate_zero_or_minsigned_nsw_vec(<2 x i8> %x) {
+; CHECK-LABEL: @negate_zero_or_minsigned_nsw_vec(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %signbit = shl <2 x i8> %x, <i8 7, i8 7>
+  %neg = sub nsw <2 x i8> zeroinitializer, %signbit
+  ret <2 x i8> %neg
+}
+
+define <2 x i8> @negate_zero_or_minsigned_nsw_vec_undef_elt(<2 x i8> %x) {
+; CHECK-LABEL: @negate_zero_or_minsigned_nsw_vec_undef_elt(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %signbit = shl <2 x i8> %x, <i8 7, i8 7>
+  %neg = sub nsw <2 x i8> <i8 undef, i8 0>, %signbit
+  ret <2 x i8> %neg
+}
+
+define i8 @negate_zero_or_minsigned(i8 %x) {
+; CHECK-LABEL: @negate_zero_or_minsigned(
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = shl i8 [[X:%.*]], 7
+; CHECK-NEXT:    ret i8 [[SIGNBIT]]
+;
+  %signbit = shl i8 %x, 7
+  %neg = sub i8 0, %signbit
+  ret i8 %neg
+}
+
+define <2 x i8> @negate_zero_or_minsigned_vec(<2 x i8> %x) {
+; CHECK-LABEL: @negate_zero_or_minsigned_vec(
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = and <2 x i8> [[X:%.*]], <i8 -128, i8 -128>
+; CHECK-NEXT:    ret <2 x i8> [[SIGNBIT]]
+;
+  %signbit = and <2 x i8> %x, <i8 128, i8 128>
+  %neg = sub <2 x i8> zeroinitializer, %signbit
+  ret <2 x i8> %neg
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/noalias-ptr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/noalias-ptr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/noalias-ptr.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/noalias-ptr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,259 @@
+; RUN: opt -instsimplify -S < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at g1 = global i32 0, align 4
+ at g2 = internal global i32 0, align 4
+ at g3 = unnamed_addr global i32 0, align 4
+ at g4 = hidden global i32 0, align 4
+ at g5 = protected global i32 0, align 4
+ at g6 = thread_local unnamed_addr global i32 0, align 4
+
+; Make sure we can simplify away a pointer comparison between
+; dynamically-allocated memory and a local stack allocation.
+;   void p()
+;   {
+;     int *mData;
+;     int mStackData[10];
+;     mData = new int[12];
+;     if (mData != mStackData) {
+;       delete[] mData;
+;     }
+;   }
+
+define void @_Z2p1v() #0 {
+  %mStackData = alloca [10 x i32], align 16
+  %1 = bitcast [10 x i32]* %mStackData to i8*
+  %2 = tail call noalias i8* @_Znam(i64 48) #4
+  %3 = bitcast i8* %2 to i32*
+  %4 = getelementptr inbounds [10 x i32], [10 x i32]* %mStackData, i64 0, i64 0
+  %5 = icmp eq i32* %3, %4
+  br i1 %5, label %7, label %6
+
+; CHECK-LABEL: @_Z2p1v
+; CHECK-NOT: icmp
+; CHECK: ret void
+
+; <label>:6                                       ; preds = %0
+  call void @_ZdaPv(i8* %2) #5
+  br label %7
+
+; <label>:7                                       ; preds = %0, %6
+  ret void
+}
+
+; Also check a more-complicated case with multiple underlying objects.
+
+define void @_Z2p2bb(i1 zeroext %b1, i1 zeroext %b2) #0 {
+  %mStackData = alloca [10 x i32], align 16
+  %1 = bitcast [10 x i32]* %mStackData to i8*
+  %2 = getelementptr inbounds [10 x i32], [10 x i32]* %mStackData, i64 0, i64 0
+  %3 = select i1 %b1, i32* %2, i32* @g2
+  %4 = tail call noalias i8* @_Znam(i64 48) #4
+  %5 = tail call noalias i8* @_Znam(i64 48) #4
+  %.v = select i1 %b2, i8* %4, i8* %5
+  %6 = bitcast i8* %.v to i32*
+  %7 = icmp eq i32* %6, %3
+  br i1 %7, label %9, label %8
+
+; CHECK-LABEL: @_Z2p2bb
+; CHECK-NOT: icmp
+; CHECK: ret void
+
+; <label>:8                                       ; preds = %0
+  call void @_ZdaPv(i8* %4) #5
+  call void @_ZdaPv(i8* %5) #5
+  br label %9
+
+; <label>:9                                       ; preds = %0, %8
+  ret void
+}
+
+define void @_Z2p4bb(i1 zeroext %b1, i1 zeroext %b2) #0 {
+  %mStackData = alloca [10 x i32], align 16
+  %1 = bitcast [10 x i32]* %mStackData to i8*
+  %2 = getelementptr inbounds [10 x i32], [10 x i32]* %mStackData, i64 0, i64 0
+  %3 = select i1 %b1, i32* %2, i32* @g3
+  %4 = tail call noalias i8* @_Znam(i64 48) #4
+  %5 = tail call noalias i8* @_Znam(i64 48) #4
+  %.v = select i1 %b2, i8* %4, i8* %5
+  %6 = bitcast i8* %.v to i32*
+  %7 = icmp eq i32* %6, %3
+  br i1 %7, label %9, label %8
+
+; CHECK-LABEL: @_Z2p4bb
+; CHECK-NOT: icmp
+; CHECK: ret void
+
+; <label>:8                                       ; preds = %0
+  call void @_ZdaPv(i8* %4) #5
+  call void @_ZdaPv(i8* %5) #5
+  br label %9
+
+; <label>:9                                       ; preds = %0, %8
+  ret void
+}
+
+define void @_Z2p5bb(i1 zeroext %b1, i1 zeroext %b2) #0 {
+  %mStackData = alloca [10 x i32], align 16
+  %1 = bitcast [10 x i32]* %mStackData to i8*
+  %2 = getelementptr inbounds [10 x i32], [10 x i32]* %mStackData, i64 0, i64 0
+  %3 = select i1 %b1, i32* %2, i32* @g4
+  %4 = tail call noalias i8* @_Znam(i64 48) #4
+  %5 = tail call noalias i8* @_Znam(i64 48) #4
+  %.v = select i1 %b2, i8* %4, i8* %5
+  %6 = bitcast i8* %.v to i32*
+  %7 = icmp eq i32* %6, %3
+  br i1 %7, label %9, label %8
+
+; CHECK-LABEL: @_Z2p5bb
+; CHECK-NOT: icmp
+; CHECK: ret void
+
+; <label>:8                                       ; preds = %0
+  call void @_ZdaPv(i8* %4) #5
+  call void @_ZdaPv(i8* %5) #5
+  br label %9
+
+; <label>:9                                       ; preds = %0, %8
+  ret void
+}
+
+define void @_Z2p6bb(i1 zeroext %b1, i1 zeroext %b2) #0 {
+  %mStackData = alloca [10 x i32], align 16
+  %1 = bitcast [10 x i32]* %mStackData to i8*
+  %2 = getelementptr inbounds [10 x i32], [10 x i32]* %mStackData, i64 0, i64 0
+  %3 = select i1 %b1, i32* %2, i32* @g5
+  %4 = tail call noalias i8* @_Znam(i64 48) #4
+  %5 = tail call noalias i8* @_Znam(i64 48) #4
+  %.v = select i1 %b2, i8* %4, i8* %5
+  %6 = bitcast i8* %.v to i32*
+  %7 = icmp eq i32* %6, %3
+  br i1 %7, label %9, label %8
+
+; CHECK-LABEL: @_Z2p6bb
+; CHECK-NOT: icmp
+; CHECK: ret void
+
+; <label>:8                                       ; preds = %0
+  call void @_ZdaPv(i8* %4) #5
+  call void @_ZdaPv(i8* %5) #5
+  br label %9
+
+; <label>:9                                       ; preds = %0, %8
+  ret void
+}
+
+; Here's another case involving multiple underlying objects, but this time we
+; must keep the comparison (it might involve a regular pointer-typed function
+; argument).
+
+define void @_Z4nopebbPi(i1 zeroext %b1, i1 zeroext %b2, i32* readnone %q) #0 {
+  %mStackData = alloca [10 x i32], align 16
+  %1 = bitcast [10 x i32]* %mStackData to i8*
+  %2 = getelementptr inbounds [10 x i32], [10 x i32]* %mStackData, i64 0, i64 0
+  %3 = select i1 %b1, i32* %2, i32* %q
+  %4 = tail call noalias i8* @_Znam(i64 48) #4
+  %5 = tail call noalias i8* @_Znam(i64 48) #4
+  %.v = select i1 %b2, i8* %4, i8* %5
+  %6 = bitcast i8* %.v to i32*
+  %7 = icmp eq i32* %6, %3
+  br i1 %7, label %9, label %8
+
+; CHECK-LABEL: @_Z4nopebbPi
+; CHECK: icmp
+; CHECK: ret void
+
+; <label>:8                                       ; preds = %0
+  call void @_ZdaPv(i8* %4) #5
+  call void @_ZdaPv(i8* %5) #5
+  br label %9
+
+; <label>:9                                       ; preds = %0, %8
+  ret void
+}
+
+define void @_Z2p3bb(i1 zeroext %b1, i1 zeroext %b2) #0 {
+  %mStackData = alloca [10 x i32], align 16
+  %1 = bitcast [10 x i32]* %mStackData to i8*
+  %2 = getelementptr inbounds [10 x i32], [10 x i32]* %mStackData, i64 0, i64 0
+  %3 = select i1 %b1, i32* %2, i32* @g1
+  %4 = tail call noalias i8* @_Znam(i64 48) #4
+  %5 = tail call noalias i8* @_Znam(i64 48) #4
+  %.v = select i1 %b2, i8* %4, i8* %5
+  %6 = bitcast i8* %.v to i32*
+  %7 = icmp eq i32* %6, %3
+  br i1 %7, label %9, label %8
+
+; CHECK-LABEL: @_Z2p3bb
+; CHECK: icmp
+; CHECK: ret void
+
+; <label>:8                                       ; preds = %0
+  call void @_ZdaPv(i8* %4) #5
+  call void @_ZdaPv(i8* %5) #5
+  br label %9
+
+; <label>:9                                       ; preds = %0, %8
+  ret void
+}
+
+define void @_Z2p7bb(i1 zeroext %b1, i1 zeroext %b2) #0 {
+  %mStackData = alloca [10 x i32], align 16
+  %1 = bitcast [10 x i32]* %mStackData to i8*
+  %2 = getelementptr inbounds [10 x i32], [10 x i32]* %mStackData, i64 0, i64 0
+  %3 = select i1 %b1, i32* %2, i32* @g6
+  %4 = tail call noalias i8* @_Znam(i64 48) #4
+  %5 = tail call noalias i8* @_Znam(i64 48) #4
+  %.v = select i1 %b2, i8* %4, i8* %5
+  %6 = bitcast i8* %.v to i32*
+  %7 = icmp eq i32* %6, %3
+  br i1 %7, label %9, label %8
+
+; CHECK-LABEL: @_Z2p7bb
+; CHECK: icmp
+; CHECK: ret void
+
+; <label>:8                                       ; preds = %0
+  call void @_ZdaPv(i8* %4) #5
+  call void @_ZdaPv(i8* %5) #5
+  br label %9
+
+; <label>:9                                       ; preds = %0, %8
+  ret void
+}
+
+define void @_Z2p2v(i32 %c) #0 {
+  %mStackData = alloca [10 x i32], i32 %c, align 16
+  %1 = bitcast [10 x i32]* %mStackData to i8*
+  %2 = tail call noalias i8* @_Znam(i64 48) #4
+  %3 = bitcast i8* %2 to i32*
+  %4 = getelementptr inbounds [10 x i32], [10 x i32]* %mStackData, i64 0, i64 0
+  %5 = icmp eq i32* %3, %4
+  br i1 %5, label %7, label %6
+
+; CHECK-LABEL: @_Z2p2v
+; CHECK: icmp
+; CHECK: ret void
+
+; <label>:6                                       ; preds = %0
+  call void @_ZdaPv(i8* %2) #5
+  br label %7
+
+; <label>:7                                       ; preds = %0, %6
+  ret void
+}
+
+; Function Attrs: nobuiltin
+declare noalias i8* @_Znam(i64) #2
+
+; Function Attrs: nobuiltin nounwind
+declare void @_ZdaPv(i8*) #3
+
+attributes #0 = { uwtable }
+attributes #1 = { nounwind }
+attributes #2 = { nobuiltin }
+attributes #3 = { nobuiltin nounwind }
+attributes #4 = { builtin }
+attributes #5 = { builtin nounwind }
+

Added: llvm/trunk/test/Transforms/InstSimplify/or-icmps-same-ops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/or-icmps-same-ops.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/or-icmps-same-ops.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/or-icmps-same-ops.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,1239 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; There are 10 * 10 combinations of icmp predicates that can be OR'd together.
+; The majority of these can be simplified to always true or just one of the icmps.
+
+define i1 @eq_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_eq(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @eq_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @eq_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_sge(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @eq_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_sgt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @eq_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_sle(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @eq_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_slt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @eq_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_uge(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @eq_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_ugt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @eq_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_ule(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @eq_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @eq_ult(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp eq i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+;
+
+define i1 @ne_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_eq(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ne_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_ne(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ne_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_sge(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ne_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_sgt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ne_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_sle(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ne_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_slt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ne_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_uge(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ne_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_ugt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ne_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_ule(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ne_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @ne_ult(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp ne i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+;
+
+define i1 @sge_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_eq(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sge_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sge_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_sge(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sge_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_sgt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sge_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_sle(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sge_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_slt(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sge_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_uge(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sge_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_ugt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sge_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_ule(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sge_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @sge_ult(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sge i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+;
+
+define i1 @sgt_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_eq(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sgt_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_ne(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sgt_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_sge(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sgt_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_sgt(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sgt_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_sle(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sgt_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_slt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sgt_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_uge(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sgt_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_ugt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sgt_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_ule(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sgt_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @sgt_ult(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+;
+
+define i1 @sle_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_eq(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sle_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sle_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_sge(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sle_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_sgt(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sle_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_sle(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sle_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_slt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sle_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_uge(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sle_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_ugt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sle_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_ule(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @sle_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @sle_ult(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp sle i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+;
+
+define i1 @slt_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_eq(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @slt_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_ne(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @slt_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_sge(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @slt_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_sgt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @slt_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_sle(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @slt_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_slt(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @slt_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_uge(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @slt_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_ugt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @slt_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_ule(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @slt_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @slt_ult(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+;
+
+define i1 @uge_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_eq(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @uge_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @uge_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_sge(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @uge_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_sgt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @uge_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_sle(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @uge_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_slt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @uge_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_uge(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @uge_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_ugt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @uge_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_ule(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @uge_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_ult(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp uge i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+;
+
+define i1 @ugt_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_eq(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ugt_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_ne(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ugt_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_sge(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ugt_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_sgt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ugt_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_sle(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ugt_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_slt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ugt_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_uge(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ugt_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_ugt(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ugt_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_ule(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ugt_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_ult(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+;
+
+define i1 @ule_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_eq(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ule_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ule_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_sge(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ule_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_sgt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ule_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_sle(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ule_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_slt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ule_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_uge(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ule_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_ugt(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ule_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_ule(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ule_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_ult(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP1]]
+;
+  %cmp1 = icmp ule i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+;
+
+define i1 @ult_eq(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_eq(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp eq i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_ne(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_ne(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp ne i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_sge(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_sge(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp sge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_sgt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_sle(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_sle(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp sle i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_slt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_slt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_uge(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_uge(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp uge i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_ugt(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_ugt(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 %a, %b
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_ule(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_ule(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp ule i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_ult(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_ult(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp ult i8 %a, %b
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+; Check a couple of vector variants to make sure those work too.
+
+define <2 x i1> @ult_uge_vec(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: @ult_uge_vec(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %cmp1 = icmp ult <2 x i8> %a, %b
+  %cmp2 = icmp uge <2 x i8> %a, %b
+  %or = or <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %or
+}
+
+define <2 x i1> @ult_ule_vec(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: @ult_ule_vec(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule <2 x i8> %a, %b
+; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
+;
+  %cmp1 = icmp ult <2 x i8> %a, %b
+  %cmp2 = icmp ule <2 x i8> %a, %b
+  %or = or <2 x i1> %cmp1, %cmp2
+  ret <2 x i1> %or
+}
+
+define i1 @ult_ne_swap(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_ne_swap(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i8 %b, %a
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp ne i8 %b, %a
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+
+define i1 @ult_ule_swap(i8 %a, i8 %b) {
+; CHECK-LABEL: @ult_ule_swap(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp uge i8 %b, %a
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp uge i8 %b, %a
+  %or = or i1 %cmp1, %cmp2
+  ret i1 %or
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/or.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/or.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/or.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/or.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,221 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @test1(i32 %A) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    ret i32 %A
+;
+  %B = or i32 %A, 0
+  ret i32 %B
+}
+
+define i32 @all_ones(i32 %A) {
+; CHECK-LABEL: @all_ones(
+; CHECK-NEXT:    ret i32 -1
+;
+  %B = or i32 %A, -1
+  ret i32 %B
+}
+
+define <3 x i8> @all_ones_vec_with_undef_elt(<3 x i8> %A) {
+; CHECK-LABEL: @all_ones_vec_with_undef_elt(
+; CHECK-NEXT:    ret <3 x i8> <i8 -1, i8 -1, i8 -1>
+;
+  %B = or <3 x i8> %A, <i8 -1, i8 undef, i8 -1>
+  ret <3 x i8> %B
+}
+
+define i1 @test3(i1 %A) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    ret i1 %A
+;
+  %B = or i1 %A, false
+  ret i1 %B
+}
+
+define i1 @test4(i1 %A) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:    ret i1 true
+;
+  %B = or i1 %A, true
+  ret i1 %B
+}
+
+define i1 @test5(i1 %A) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:    ret i1 %A
+;
+  %B = or i1 %A, %A
+  ret i1 %B
+}
+
+define i32 @test6(i32 %A) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:    ret i32 %A
+;
+  %B = or i32 %A, %A
+  ret i32 %B
+}
+
+; A | ~A == -1
+define i32 @test7(i32 %A) {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT:    ret i32 -1
+;
+  %NotA = xor i32 %A, -1
+  %B = or i32 %A, %NotA
+  ret i32 %B
+}
+
+define i8 @test8(i8 %A) {
+; CHECK-LABEL: @test8(
+; CHECK-NEXT:    ret i8 -1
+;
+  %B = or i8 %A, -2
+  %C = or i8 %B, 1
+  ret i8 %C
+}
+
+; Test that (A|c1)|(B|c2) == (A|B)|(c1|c2)
+define i8 @test9(i8 %A, i8 %B) {
+; CHECK-LABEL: @test9(
+; CHECK-NEXT:    ret i8 -1
+;
+  %C = or i8 %A, 1
+  %D = or i8 %B, -2
+  %E = or i8 %C, %D
+  ret i8 %E
+}
+
+define i8 @test10(i8 %A) {
+; CHECK-LABEL: @test10(
+; CHECK-NEXT:    ret i8 -2
+;
+  %B = or i8 %A, 1
+  %C = and i8 %B, -2
+  ; (X & C1) | C2 --> (X | C2) & (C1|C2)
+  %D = or i8 %C, -2
+  ret i8 %D
+}
+
+define i8 @test11(i8 %A) {
+; CHECK-LABEL: @test11(
+; CHECK-NEXT:    ret i8 -1
+;
+  %B = or i8 %A, -2
+  %C = xor i8 %B, 13
+  ; (X ^ C1) | C2 --> (X | C2) ^ (C1&~C2)
+  %D = or i8 %C, 1
+  %E = xor i8 %D, 12
+  ret i8 %E
+}
+
+; Test the case where integer BitWidth <= 64 && BitWidth % 2 != 0.
+define i39 @test1_apint(i39 %V, i39 %M) {
+; CHECK-LABEL: @test1_apint(
+; CHECK:         [[N:%.*]] = and i39 %M, -274877906944
+; CHECK-NEXT:    [[A:%.*]] = add i39 %V, [[N]]
+; CHECK-NEXT:    ret i39 [[A]]
+;
+    ;; If we have: ((V + N) & C1) | (V & C2)
+    ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0
+    ;; replace with V+N.
+    %C1 = xor i39 274877906943, -1 ;; C2 = 274877906943
+    %N = and i39 %M, 274877906944
+    %A = add i39 %V, %N
+    %B = and i39 %A, %C1
+    %D = and i39 %V, 274877906943
+    %R = or i39 %B, %D
+    ret i39 %R
+}
+
+define i7 @test2_apint(i7 %X) {
+; CHECK-LABEL: @test2_apint(
+; CHECK:         ret i7 %X
+;
+    %Y = or i7 %X, 0
+    ret i7 %Y
+}
+
+define i17 @test3_apint(i17 %X) {
+; CHECK-LABEL: @test3_apint(
+; CHECK:         ret i17 -1
+;
+    %Y = or i17 %X, -1
+    ret i17 %Y
+}
+
+; Test the case where Integer BitWidth > 64 && BitWidth <= 1024.
+define i399 @test4_apint(i399 %V, i399 %M) {
+; CHECK-LABEL: @test4_apint(
+; CHECK:         [[N:%.*]] = and i399 %M, 18446742974197923840
+; CHECK-NEXT:    [[A:%.*]] = add i399 %V, [[N]]
+; CHECK-NEXT:    ret i399 [[A]]
+;
+    ;; If we have: ((V + N) & C1) | (V & C2)
+    ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0
+    ;; replace with V+N.
+    %C1 = xor i399 274877906943, -1 ;; C2 = 274877906943
+    %N = and i399 %M, 18446742974197923840
+    %A = add i399 %V, %N
+    %B = and i399 %A, %C1
+    %D = and i399 %V, 274877906943
+    %R = or i399 %D, %B
+    ret i399 %R
+}
+
+define i777 @test5_apint(i777 %X) {
+; CHECK-LABEL: @test5_apint(
+; CHECK:         ret i777 %X
+;
+    %Y = or i777 %X, 0
+    ret i777 %Y
+}
+
+define i117 @test6_apint(i117 %X) {
+; CHECK-LABEL: @test6_apint(
+; CHECK:         ret i117 -1
+;
+    %Y = or i117 %X, -1
+    ret i117 %Y
+}
+
+; Test the case where integer BitWidth <= 64 && BitWidth % 2 != 0.
+; Vector version of test1_apint with the add commuted
+define <2 x i39> @test7_apint(<2 x i39> %V, <2 x i39> %M) {
+; CHECK-LABEL: @test7_apint(
+; CHECK-NEXT:    [[N:%.*]] = and <2 x i39> [[M:%.*]], <i39 -274877906944, i39 -274877906944>
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i39> [[N]], [[V:%.*]]
+; CHECK-NEXT:    ret <2 x i39> [[A]]
+;
+  ;; If we have: ((V + N) & C1) | (V & C2)
+  ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0
+  ;; replace with V+N.
+  %C1 = xor <2 x i39> <i39 274877906943, i39 274877906943>, <i39 -1, i39 -1> ;; C2 = 274877906943
+  %N = and <2 x i39> %M, <i39 274877906944, i39 274877906944>
+  %A = add <2 x i39> %N, %V
+  %B = and <2 x i39> %A, %C1
+  %D = and <2 x i39> %V, <i39 274877906943, i39 274877906943>
+  %R = or <2 x i39> %B, %D
+  ret <2 x i39> %R
+}
+
+; Test the case where Integer BitWidth > 64 && BitWidth <= 1024.
+; Vector version of test4_apint with the add and the or commuted
+define <2 x i399> @test8_apint(<2 x i399> %V, <2 x i399> %M) {
+; CHECK-LABEL: @test8_apint(
+; CHECK-NEXT:    [[N:%.*]] = and <2 x i399> [[M:%.*]], <i399 18446742974197923840, i399 18446742974197923840>
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i399> [[N]], [[V:%.*]]
+; CHECK-NEXT:    ret <2 x i399> [[A]]
+;
+  ;; If we have: ((V + N) & C1) | (V & C2)
+  ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0
+  ;; replace with V+N.
+  %C1 = xor <2 x i399> <i399 274877906943, i399 274877906943>, <i399 -1, i399 -1> ;; C2 = 274877906943
+  %N = and <2 x i399> %M, <i399 18446742974197923840, i399 18446742974197923840>
+  %A = add <2 x i399> %N, %V
+  %B = and <2 x i399> %A, %C1
+  %D = and <2 x i399> %V, <i399 274877906943, i399 274877906943>
+  %R = or <2 x i399> %D, %B
+  ret <2 x i399> %R
+}

Added: llvm/trunk/test/Transforms/InstSimplify/past-the-end.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/past-the-end.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/past-the-end.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/past-the-end.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,93 @@
+; NOTE: Assertions have been autogenerated by update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+target datalayout = "p:32:32"
+
+; Check some past-the-end subtleties.
+
+ at opte_a = global i32 0
+ at opte_b = global i32 0
+
+; Comparing base addresses of two distinct globals. Never equal.
+
+define zeroext i1 @no_offsets() {
+; CHECK-LABEL: @no_offsets(
+; CHECK:         ret i1 false
+;
+  %t = icmp eq i32* @opte_a, @opte_b
+  ret i1 %t
+}
+
+; Comparing past-the-end addresses of two distinct globals. Never equal.
+
+define zeroext i1 @both_past_the_end() {
+; CHECK-LABEL: @both_past_the_end(
+; CHECK:         ret i1 icmp eq (i32* getelementptr inbounds (i32, i32* @opte_a, i32 1), i32* getelementptr inbounds (i32, i32* @opte_b, i32 1))
+;
+  %x = getelementptr i32, i32* @opte_a, i32 1
+  %y = getelementptr i32, i32* @opte_b, i32 1
+  %t = icmp eq i32* %x, %y
+  ret i1 %t
+  ; TODO: refine this
+}
+
+; Comparing past-the-end addresses of one global to the base address
+; of another. Can't fold this.
+
+define zeroext i1 @just_one_past_the_end() {
+; CHECK-LABEL: @just_one_past_the_end(
+; CHECK:         ret i1 icmp eq (i32* getelementptr inbounds (i32, i32* @opte_a, i32 1), i32* @opte_b)
+;
+  %x = getelementptr i32, i32* @opte_a, i32 1
+  %t = icmp eq i32* %x, @opte_b
+  ret i1 %t
+}
+
+; Comparing base addresses of two distinct allocas. Never equal.
+
+define zeroext i1 @no_alloca_offsets() {
+; CHECK-LABEL: @no_alloca_offsets(
+; CHECK:         ret i1 false
+;
+  %m = alloca i32
+  %n = alloca i32
+  %t = icmp eq i32* %m, %n
+  ret i1 %t
+}
+
+; Comparing past-the-end addresses of two distinct allocas. Never equal.
+
+define zeroext i1 @both_past_the_end_alloca() {
+; CHECK-LABEL: @both_past_the_end_alloca(
+; CHECK:         [[M:%.*]] = alloca i32
+; CHECK-NEXT:    [[N:%.*]] = alloca i32
+; CHECK-NEXT:    [[X:%.*]] = getelementptr i32, i32* [[M]], i32 1
+; CHECK-NEXT:    [[Y:%.*]] = getelementptr i32, i32* [[N]], i32 1
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32* [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+  %m = alloca i32
+  %n = alloca i32
+  %x = getelementptr i32, i32* %m, i32 1
+  %y = getelementptr i32, i32* %n, i32 1
+  %t = icmp eq i32* %x, %y
+  ret i1 %t
+  ; TODO: refine this
+}
+
+; Comparing past-the-end addresses of one alloca to the base address
+; of another. Can't fold this.
+
+define zeroext i1 @just_one_past_the_end_alloca() {
+; CHECK-LABEL: @just_one_past_the_end_alloca(
+; CHECK:         [[M:%.*]] = alloca i32
+; CHECK-NEXT:    [[N:%.*]] = alloca i32
+; CHECK-NEXT:    [[X:%.*]] = getelementptr i32, i32* [[M]], i32 1
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32* [[X]], [[N]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+  %m = alloca i32
+  %n = alloca i32
+  %x = getelementptr i32, i32* %m, i32 1
+  %t = icmp eq i32* %x, %n
+  ret i1 %t
+}

Added: llvm/trunk/test/Transforms/InstSimplify/phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/phi.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; NOTE: Assertions have been autogenerated by update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; PR12189
+define i1 @test1(i32 %x) {
+; CHECK-LABEL: @test1(
+; CHECK:         ret i1 %e
+;
+  br i1 true, label %a, label %b
+
+a:
+  %aa = or i32 %x, 10
+  br label %c
+
+b:
+  %bb = or i32 %x, 10
+  br label %c
+
+c:
+  %cc = phi i32 [ %bb, %b ], [%aa, %a ]
+  %d = urem i32 %cc, 2
+  %e = icmp eq i32 %d, 0
+  ret i1 %e
+}

Added: llvm/trunk/test/Transforms/InstSimplify/pr28725.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/pr28725.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/pr28725.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/pr28725.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+%S = type { i16, i32 }
+
+define <2 x i16> @test1() {
+entry:
+  %b = insertelement <2 x i16> <i16 undef, i16 0>, i16 extractvalue (%S select (i1 icmp eq (i16 extractelement (<2 x i16> bitcast (<1 x i32> <i32 1> to <2 x i16>), i32 0), i16 0), %S zeroinitializer, %S { i16 0, i32 1 }), 0), i32 0
+  ret <2 x i16> %b
+}
+
+; InstCombine will be able to fold this into zeroinitializer
+; CHECK-LABEL: @test1(
+; CHECK: ret <2 x i16> <i16 extractvalue (%S select (i1 icmp eq (i16 extractelement (<2 x i16> bitcast (<1 x i32> <i32 1> to <2 x i16>), i32 0), i16 0), %S zeroinitializer, %S { i16 0, i32 1 }), 0), i16 0>

Added: llvm/trunk/test/Transforms/InstSimplify/pr33957.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/pr33957.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/pr33957.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/pr33957.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -loop-unroll -S %s | FileCheck %s
+
+%struct.bar = type { i32 }
+
+ at global = external constant [78 x %struct.bar], align 4
+
+define void @patatino(i32 %x) {
+; CHECK-LABEL: @patatino(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br i1 true, label [[BB1_PREHEADER:%.*]], label [[BB3:%.*]]
+; CHECK:       bb1.preheader:
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret void
+;
+bb:
+  br i1 true, label %bb1, label %bb3
+
+bb1:
+  %tmp = getelementptr inbounds [78 x %struct.bar], [78 x %struct.bar]* @global, i32 0, <4 x i32> undef
+  %tmp2 = getelementptr inbounds %struct.bar, <4 x %struct.bar*> %tmp, i32 1
+  br i1 true, label %bb3, label %bb1
+
+bb3:
+  ret void
+}

Added: llvm/trunk/test/Transforms/InstSimplify/ptr_diff.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/ptr_diff.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/ptr_diff.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/ptr_diff.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,84 @@
+; NOTE: Assertions have been autogenerated by update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i64 @ptrdiff1(i8* %ptr) {
+; CHECK-LABEL: @ptrdiff1(
+; CHECK:         ret i64 42
+;
+  %first = getelementptr inbounds i8, i8* %ptr, i32 0
+  %last = getelementptr inbounds i8, i8* %ptr, i32 42
+  %first.int = ptrtoint i8* %first to i64
+  %last.int = ptrtoint i8* %last to i64
+  %diff = sub i64 %last.int, %first.int
+  ret i64 %diff
+}
+
+define i64 @ptrdiff2(i8* %ptr) {
+; CHECK-LABEL: @ptrdiff2(
+; CHECK:         ret i64 42
+;
+  %first1 = getelementptr inbounds i8, i8* %ptr, i32 0
+  %first2 = getelementptr inbounds i8, i8* %first1, i32 1
+  %first3 = getelementptr inbounds i8, i8* %first2, i32 2
+  %first4 = getelementptr inbounds i8, i8* %first3, i32 4
+  %last1 = getelementptr inbounds i8, i8* %first2, i32 48
+  %last2 = getelementptr inbounds i8, i8* %last1, i32 8
+  %last3 = getelementptr inbounds i8, i8* %last2, i32 -4
+  %last4 = getelementptr inbounds i8, i8* %last3, i32 -4
+  %first.int = ptrtoint i8* %first4 to i64
+  %last.int = ptrtoint i8* %last4 to i64
+  %diff = sub i64 %last.int, %first.int
+  ret i64 %diff
+}
+
+define i64 @ptrdiff3(i8* %ptr) {
+; Don't bother with non-inbounds GEPs.
+; CHECK-LABEL: @ptrdiff3(
+; CHECK:         [[LAST:%.*]] = getelementptr i8, i8* %ptr, i32 42
+; CHECK-NEXT:    [[FIRST_INT:%.*]] = ptrtoint i8* %ptr to i64
+; CHECK-NEXT:    [[LAST_INT:%.*]] = ptrtoint i8* [[LAST]] to i64
+; CHECK-NEXT:    [[DIFF:%.*]] = sub i64 [[LAST_INT]], [[FIRST_INT]]
+; CHECK-NEXT:    ret i64 [[DIFF]]
+;
+  %first = getelementptr i8, i8* %ptr, i32 0
+  %last = getelementptr i8, i8* %ptr, i32 42
+  %first.int = ptrtoint i8* %first to i64
+  %last.int = ptrtoint i8* %last to i64
+  %diff = sub i64 %last.int, %first.int
+  ret i64 %diff
+}
+
+define <4 x i32> @ptrdiff4(<4 x i8*> %arg) nounwind {
+; Handle simple cases of vectors of pointers.
+; CHECK-LABEL: @ptrdiff4(
+; CHECK:         ret <4 x i32> zeroinitializer
+;
+  %p1 = ptrtoint <4 x i8*> %arg to <4 x i32>
+  %bc = bitcast <4 x i8*> %arg to <4 x i32*>
+  %p2 = ptrtoint <4 x i32*> %bc to <4 x i32>
+  %sub = sub <4 x i32> %p1, %p2
+  ret <4 x i32> %sub
+}
+
+%struct.ham = type { i32, [2 x [2 x i32]] }
+
+ at global = internal global %struct.ham zeroinitializer, align 4
+
+define i32 @ptrdiff5() nounwind {
+; CHECK-LABEL: @ptrdiff5(
+; CHECK:       bb:
+; CHECK-NEXT:    ret i32 0
+;
+bb:
+  %tmp = getelementptr inbounds %struct.ham, %struct.ham* @global, i32 0, i32 1
+  %tmp1 = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %tmp, i32 0, i32 0
+  %tmp2 = bitcast [2 x i32]* %tmp1 to i32*
+  %tmp3 = ptrtoint i32* %tmp2 to i32
+  %tmp4 = getelementptr inbounds %struct.ham, %struct.ham* @global, i32 0, i32 1
+  %tmp5 = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %tmp4, i32 0, i32 0
+  %tmp6 = ptrtoint [2 x i32]* %tmp5 to i32
+  %tmp7 = sub i32 %tmp3, %tmp6
+  ret i32 %tmp7
+}

Added: llvm/trunk/test/Transforms/InstSimplify/reassociate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/reassociate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/reassociate.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/reassociate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,266 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @add1(i32 %x) {
+; CHECK-LABEL: @add1(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+; (X + -1) + 1 -> X
+  %l = add i32 %x, -1
+  %r = add i32 %l, 1
+  ret i32 %r
+}
+
+define i32 @and1(i32 %x, i32 %y) {
+; CHECK-LABEL: @and1(
+; CHECK-NEXT:    [[L:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[L]]
+;
+; (X & Y) & X -> X & Y
+  %l = and i32 %x, %y
+  %r = and i32 %l, %x
+  ret i32 %r
+}
+
+define i32 @and2(i32 %x, i32 %y) {
+; CHECK-LABEL: @and2(
+; CHECK-NEXT:    [[R:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+; X & (X & Y) -> X & Y
+  %r = and i32 %x, %y
+  %l = and i32 %x, %r
+  ret i32 %l
+}
+
+define i32 @or1(i32 %x, i32 %y) {
+; CHECK-LABEL: @or1(
+; CHECK-NEXT:    [[L:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[L]]
+;
+; (X | Y) | X -> X | Y
+  %l = or i32 %x, %y
+  %r = or i32 %l, %x
+  ret i32 %r
+}
+
+define i32 @or2(i32 %x, i32 %y) {
+; CHECK-LABEL: @or2(
+; CHECK-NEXT:    [[R:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+; X | (X | Y) -> X | Y
+  %r = or i32 %x, %y
+  %l = or i32 %x, %r
+  ret i32 %l
+}
+
+define i32 @xor1(i32 %x, i32 %y) {
+; CHECK-LABEL: @xor1(
+; CHECK-NEXT:    ret i32 [[Y:%.*]]
+;
+; (X ^ Y) ^ X = Y
+  %l = xor i32 %x, %y
+  %r = xor i32 %l, %x
+  ret i32 %r
+}
+
+define i32 @xor2(i32 %x, i32 %y) {
+; CHECK-LABEL: @xor2(
+; CHECK-NEXT:    ret i32 [[Y:%.*]]
+;
+; X ^ (X ^ Y) = Y
+  %r = xor i32 %x, %y
+  %l = xor i32 %x, %r
+  ret i32 %l
+}
+
+define i32 @sub1(i32 %x, i32 %y) {
+; CHECK-LABEL: @sub1(
+; CHECK-NEXT:    ret i32 [[Y:%.*]]
+;
+  %d = sub i32 %x, %y
+  %r = sub i32 %x, %d
+  ret i32 %r
+}
+
+define i32 @sub2(i32 %x) {
+; CHECK-LABEL: @sub2(
+; CHECK-NEXT:    ret i32 -1
+;
+; X - (X + 1) -> -1
+  %xp1 = add i32 %x, 1
+  %r = sub i32 %x, %xp1
+  ret i32 %r
+}
+
+define i32 @sub3(i32 %x, i32 %y) {
+; CHECK-LABEL: @sub3(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+; ((X + 1) + Y) - (Y + 1) -> X
+  %xp1 = add i32 %x, 1
+  %lhs = add i32 %xp1, %y
+  %rhs = add i32 %y, 1
+  %r = sub i32 %lhs, %rhs
+  ret i32 %r
+}
+
+; (no overflow X * Y) / Y -> X
+
+define i32 @mulnsw_sdiv(i32 %x, i32 %y) {
+; CHECK-LABEL: @mulnsw_sdiv(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+  %mul = mul nsw i32 %x, %y
+  %r = sdiv i32 %mul, %y
+  ret i32 %r
+}
+
+define <2 x i32> @mulnsw_sdiv_commute(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @mulnsw_sdiv_commute(
+; CHECK-NEXT:    ret <2 x i32> [[X:%.*]]
+;
+  %mul = mul nsw <2 x i32> %y, %x
+  %r = sdiv <2 x i32> %mul, %y
+  ret <2 x i32> %r
+}
+
+; (no overflow X * Y) / Y -> X
+
+define <2 x i8> @mulnuw_udiv(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @mulnuw_udiv(
+; CHECK-NEXT:    ret <2 x i8> [[X:%.*]]
+;
+  %mul = mul nuw <2 x i8> %x, %y
+  %r = udiv <2 x i8> %mul, %y
+  ret <2 x i8> %r
+}
+
+define i32 @mulnuw_udiv_commute(i32 %x, i32 %y) {
+; CHECK-LABEL: @mulnuw_udiv_commute(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+  %mul = mul nuw i32 %y, %x
+  %r = udiv i32 %mul, %y
+  ret i32 %r
+}
+
+; (((X / Y) * Y) / Y) -> X / Y
+
+define i32 @sdiv_mul_sdiv(i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv_mul_sdiv(
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %div = sdiv i32 %x, %y
+  %mul = mul i32 %div, %y
+  %r = sdiv i32 %mul, %y
+  ret i32 %r
+}
+
+define i32 @sdiv_mul_sdiv_commute(i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv_mul_sdiv_commute(
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %div = sdiv i32 %x, %y
+  %mul = mul i32 %y, %div
+  %r = sdiv i32 %mul, %y
+  ret i32 %r
+}
+
+; (((X / Y) * Y) / Y) -> X / Y
+
+define i32 @udiv_mul_udiv(i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv_mul_udiv(
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %div = udiv i32 %x, %y
+  %mul = mul i32 %div, %y
+  %r = udiv i32 %mul, %y
+  ret i32 %r
+}
+
+define i32 @udiv_mul_udiv_commute(i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv_mul_udiv_commute(
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %div = udiv i32 %x, %y
+  %mul = mul i32 %y, %div
+  %r = udiv i32 %mul, %y
+  ret i32 %r
+}
+
+define i32 @sdiv3(i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv3(
+; CHECK-NEXT:    ret i32 0
+;
+; (X rem Y) / Y -> 0
+  %rem = srem i32 %x, %y
+  %div = sdiv i32 %rem, %y
+  ret i32 %div
+}
+
+define i32 @sdiv4(i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv4(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+; (X / Y) * Y -> X if the division is exact
+  %div = sdiv exact i32 %x, %y
+  %mul = mul i32 %div, %y
+  ret i32 %mul
+}
+
+define i32 @sdiv5(i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv5(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+; Y * (X / Y) -> X if the division is exact
+  %div = sdiv exact i32 %x, %y
+  %mul = mul i32 %y, %div
+  ret i32 %mul
+}
+
+define i32 @udiv3(i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv3(
+; CHECK-NEXT:    ret i32 0
+;
+; (X rem Y) / Y -> 0
+  %rem = urem i32 %x, %y
+  %div = udiv i32 %rem, %y
+  ret i32 %div
+}
+
+define i32 @udiv4(i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv4(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+; (X / Y) * Y -> X if the division is exact
+  %div = udiv exact i32 %x, %y
+  %mul = mul i32 %div, %y
+  ret i32 %mul
+}
+
+define i32 @udiv5(i32 %x, i32 %y) {
+; CHECK-LABEL: @udiv5(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+; Y * (X / Y) -> X if the division is exact
+  %div = udiv exact i32 %x, %y
+  %mul = mul i32 %y, %div
+  ret i32 %mul
+}
+
+define i16 @trunc1(i32 %x) {
+; CHECK-LABEL: @trunc1(
+; CHECK-NEXT:    ret i16 1
+;
+  %y = add i32 %x, 1
+  %tx = trunc i32 %x to i16
+  %ty = trunc i32 %y to i16
+  %d = sub i16 %ty, %tx
+  ret i16 %d
+}

Added: llvm/trunk/test/Transforms/InstSimplify/rem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/rem.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/rem.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/rem.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,327 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @zero_dividend(i32 %A) {
+; CHECK-LABEL: @zero_dividend(
+; CHECK-NEXT:    ret i32 0
+;
+  %B = urem i32 0, %A
+  ret i32 %B
+}
+
+define <2 x i32> @zero_dividend_vector(<2 x i32> %A) {
+; CHECK-LABEL: @zero_dividend_vector(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %B = srem <2 x i32> zeroinitializer, %A
+  ret <2 x i32> %B
+}
+
+define <2 x i32> @zero_dividend_vector_undef_elt(<2 x i32> %A) {
+; CHECK-LABEL: @zero_dividend_vector_undef_elt(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %B = urem <2 x i32> <i32 undef, i32 0>, %A
+  ret <2 x i32> %B
+}
+
+; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
+
+define <2 x i8> @srem_zero_elt_vec_constfold(<2 x i8> %x) {
+; CHECK-LABEL: @srem_zero_elt_vec_constfold(
+; CHECK-NEXT:    ret <2 x i8> undef
+;
+  %rem = srem <2 x i8> <i8 1, i8 2>, <i8 0, i8 -42>
+  ret <2 x i8> %rem
+}
+
+define <2 x i8> @urem_zero_elt_vec_constfold(<2 x i8> %x) {
+; CHECK-LABEL: @urem_zero_elt_vec_constfold(
+; CHECK-NEXT:    ret <2 x i8> undef
+;
+  %rem = urem <2 x i8> <i8 1, i8 2>, <i8 42, i8 0>
+  ret <2 x i8> %rem
+}
+
+define <2 x i8> @srem_zero_elt_vec(<2 x i8> %x) {
+; CHECK-LABEL: @srem_zero_elt_vec(
+; CHECK-NEXT:    ret <2 x i8> undef
+;
+  %rem = srem <2 x i8> %x, <i8 -42, i8 0>
+  ret <2 x i8> %rem
+}
+
+define <2 x i8> @urem_zero_elt_vec(<2 x i8> %x) {
+; CHECK-LABEL: @urem_zero_elt_vec(
+; CHECK-NEXT:    ret <2 x i8> undef
+;
+  %rem = urem <2 x i8> %x, <i8 0, i8 42>
+  ret <2 x i8> %rem
+}
+
+define <2 x i8> @srem_undef_elt_vec(<2 x i8> %x) {
+; CHECK-LABEL: @srem_undef_elt_vec(
+; CHECK-NEXT:    ret <2 x i8> undef
+;
+  %rem = srem <2 x i8> %x, <i8 -42, i8 undef>
+  ret <2 x i8> %rem
+}
+
+define <2 x i8> @urem_undef_elt_vec(<2 x i8> %x) {
+; CHECK-LABEL: @urem_undef_elt_vec(
+; CHECK-NEXT:    ret <2 x i8> undef
+;
+  %rem = urem <2 x i8> %x, <i8 undef, i8 42>
+  ret <2 x i8> %rem
+}
+
+; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
+; Thus, we can simplify this: if any element of 'y' is 0, we can do anything.
+; Therefore, assume that all elements of 'y' must be 1.
+
+define <2 x i1> @srem_bool_vec(<2 x i1> %x, <2 x i1> %y) {
+; CHECK-LABEL: @srem_bool_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %rem = srem <2 x i1> %x, %y
+  ret <2 x i1> %rem
+}
+
+define <2 x i1> @urem_bool_vec(<2 x i1> %x, <2 x i1> %y) {
+; CHECK-LABEL: @urem_bool_vec(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %rem = urem <2 x i1> %x, %y
+  ret <2 x i1> %rem
+}
+
+define <2 x i32> @zext_bool_urem_divisor_vec(<2 x i1> %x, <2 x i32> %y) {
+; CHECK-LABEL: @zext_bool_urem_divisor_vec(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %ext = zext <2 x i1> %x to <2 x i32>
+  %r = urem <2 x i32> %y, %ext
+  ret <2 x i32> %r
+}
+
+define i32 @zext_bool_srem_divisor(i1 %x, i32 %y) {
+; CHECK-LABEL: @zext_bool_srem_divisor(
+; CHECK-NEXT:    ret i32 0
+;
+  %ext = zext i1 %x to i32
+  %r = srem i32 %y, %ext
+  ret i32 %r
+}
+
+define i32 @select1(i32 %x, i1 %b) {
+; CHECK-LABEL: @select1(
+; CHECK-NEXT:    ret i32 0
+;
+  %rhs = select i1 %b, i32 %x, i32 1
+  %rem = srem i32 %x, %rhs
+  ret i32 %rem
+}
+
+define i32 @select2(i32 %x, i1 %b) {
+; CHECK-LABEL: @select2(
+; CHECK-NEXT:    ret i32 0
+;
+  %rhs = select i1 %b, i32 %x, i32 1
+  %rem = urem i32 %x, %rhs
+  ret i32 %rem
+}
+
+define i32 @rem1(i32 %x, i32 %n) {
+; CHECK-LABEL: @rem1(
+; CHECK-NEXT:    [[MOD:%.*]] = srem i32 [[X:%.*]], [[N:%.*]]
+; CHECK-NEXT:    ret i32 [[MOD]]
+;
+  %mod = srem i32 %x, %n
+  %mod1 = srem i32 %mod, %n
+  ret i32 %mod1
+}
+
+define i32 @rem2(i32 %x, i32 %n) {
+; CHECK-LABEL: @rem2(
+; CHECK-NEXT:    [[MOD:%.*]] = urem i32 [[X:%.*]], [[N:%.*]]
+; CHECK-NEXT:    ret i32 [[MOD]]
+;
+  %mod = urem i32 %x, %n
+  %mod1 = urem i32 %mod, %n
+  ret i32 %mod1
+}
+
+define i32 @rem3(i32 %x, i32 %n) {
+; CHECK-LABEL: @rem3(
+; CHECK-NEXT:    [[MOD:%.*]] = srem i32 [[X:%.*]], [[N:%.*]]
+; CHECK-NEXT:    [[MOD1:%.*]] = urem i32 [[MOD]], [[N]]
+; CHECK-NEXT:    ret i32 [[MOD1]]
+;
+  %mod = srem i32 %x, %n
+  %mod1 = urem i32 %mod, %n
+  ret i32 %mod1
+}
+
+define i32 @urem_dividend_known_smaller_than_constant_divisor(i32 %x) {
+; CHECK-LABEL: @urem_dividend_known_smaller_than_constant_divisor(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 250
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %and = and i32 %x, 250
+  %r = urem i32 %and, 251
+  ret i32 %r
+}
+
+define i32 @not_urem_dividend_known_smaller_than_constant_divisor(i32 %x) {
+; CHECK-LABEL: @not_urem_dividend_known_smaller_than_constant_divisor(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 251
+; CHECK-NEXT:    [[R:%.*]] = urem i32 [[AND]], 251
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %and = and i32 %x, 251
+  %r = urem i32 %and, 251
+  ret i32 %r
+}
+
+define i32 @urem_constant_dividend_known_smaller_than_divisor(i32 %x) {
+; CHECK-LABEL: @urem_constant_dividend_known_smaller_than_divisor(
+; CHECK-NEXT:    ret i32 250
+;
+  %or = or i32 %x, 251
+  %r = urem i32 250, %or
+  ret i32 %r
+}
+
+define i32 @not_urem_constant_dividend_known_smaller_than_divisor(i32 %x) {
+; CHECK-LABEL: @not_urem_constant_dividend_known_smaller_than_divisor(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], 251
+; CHECK-NEXT:    [[R:%.*]] = urem i32 251, [[OR]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %or = or i32 %x, 251
+  %r = urem i32 251, %or
+  ret i32 %r
+}
+
+; This would require computing known bits on both x and y. Is it worth doing?
+
+define i32 @urem_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
+; CHECK-LABEL: @urem_dividend_known_smaller_than_divisor(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 250
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], 251
+; CHECK-NEXT:    [[R:%.*]] = urem i32 [[AND]], [[OR]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %and = and i32 %x, 250
+  %or = or i32 %y, 251
+  %r = urem i32 %and, %or
+  ret i32 %r
+}
+
+define i32 @not_urem_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
+; CHECK-LABEL: @not_urem_dividend_known_smaller_than_divisor(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 251
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], 251
+; CHECK-NEXT:    [[R:%.*]] = urem i32 [[AND]], [[OR]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %and = and i32 %x, 251
+  %or = or i32 %y, 251
+  %r = urem i32 %and, %or
+  ret i32 %r
+}
+
+declare i32 @external()
+
+define i32 @rem4() {
+; CHECK-LABEL: @rem4(
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 @external(), !range !0
+; CHECK-NEXT:    ret i32 [[CALL]]
+;
+  %call = call i32 @external(), !range !0
+  %urem = urem i32 %call, 3
+  ret i32 %urem
+}
+
+!0 = !{i32 0, i32 3}
+
+define i32 @rem5(i32 %x, i32 %y) {
+; CHECK-LABEL: @rem5(
+; CHECK-NEXT:    ret i32 0
+;
+  %shl = shl nsw i32 %x, %y
+  %mod = srem i32 %shl, %x
+  ret i32 %mod
+}
+
+define <2 x i32> @rem6(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @rem6(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %shl = shl nsw <2 x i32> %x, %y
+  %mod = srem <2 x i32> %shl, %x
+  ret <2 x i32> %mod
+}
+
+; make sure the previous fold doesn't take place for wrapped shifts
+
+define i32 @rem7(i32 %x, i32 %y) {
+; CHECK-LABEL: @rem7(
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[MOD:%.*]] = srem i32 [[SHL]], [[X]]
+; CHECK-NEXT:    ret i32 [[MOD]]
+;
+  %shl = shl i32 %x, %y
+  %mod = srem i32 %shl, %x
+  ret i32 %mod
+}
+
+define i32 @rem8(i32 %x, i32 %y) {
+; CHECK-LABEL: @rem8(
+; CHECK-NEXT:    ret i32 0
+;
+  %shl = shl nuw i32 %x, %y
+  %mod = urem i32 %shl, %x
+  ret i32 %mod
+}
+
+define <2 x i32> @rem9(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @rem9(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %shl = shl nuw <2 x i32> %x, %y
+  %mod = urem <2 x i32> %shl, %x
+  ret <2 x i32> %mod
+}
+
+; make sure the previous fold doesn't take place for wrapped shifts
+
+define i32 @rem10(i32 %x, i32 %y) {
+; CHECK-LABEL: @rem10(
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[MOD:%.*]] = urem i32 [[SHL]], [[X]]
+; CHECK-NEXT:    ret i32 [[MOD]]
+;
+  %shl = shl i32 %x, %y
+  %mod = urem i32 %shl, %x
+  ret i32 %mod
+}
+
+define i32 @srem_with_sext_bool_divisor(i1 %x, i32 %y) {
+; CHECK-LABEL: @srem_with_sext_bool_divisor(
+; CHECK-NEXT:    ret i32 0
+;
+  %s = sext i1 %x to i32
+  %r = srem i32 %y, %s
+  ret i32 %r
+}
+
+define <2 x i32> @srem_with_sext_bool_divisor_vec(<2 x i1> %x, <2 x i32> %y) {
+; CHECK-LABEL: @srem_with_sext_bool_divisor_vec(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %s = sext <2 x i1> %x to <2 x i32>
+  %r = srem <2 x i32> %y, %s
+  ret <2 x i32> %r
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/require-dominator.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/require-dominator.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/require-dominator.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/require-dominator.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt < %s -instsimplify
+
+; instsimplify pass should explicitly require DominatorTreeAnalysis
+; This test will segfault if DominatorTree is not available
+
+target triple = "x86_64-grtev4-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define void @foo(i16 *) #1 align 2 {
+  br i1 undef, label %exit, label %2
+
+; <label>:2:
+  %3 = tail call i8* @_Znwm(i64 56) #10
+  %4 = bitcast i8* %3 to i16*
+  %p = load i16*, i16** undef, align 8
+  %5 = icmp eq i16* %p, %4
+  br i1 %5, label %exit, label %6
+
+; <label>:6:
+  %7 = icmp eq i16* %p, null
+  br i1 %7, label %exit, label %8
+
+; <label>:8:
+  br label %exit
+
+exit:
+  ret void
+}
+
+; Function Attrs: nobuiltin
+declare i8* @_Znwm(i64)

Added: llvm/trunk/test/Transforms/InstSimplify/returned.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/returned.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/returned.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/returned.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt -instsimplify -S < %s | FileCheck %s
+
+define i1 @bitcast() {
+; CHECK-LABEL: @bitcast(
+  %a = alloca i32
+  %b = alloca i64
+  %x = bitcast i32* %a to i8*
+  %z = bitcast i64* %b to i8*
+  %y = call i8* @func1(i8* %z)
+  %cmp = icmp eq i8* %x, %y
+  ret i1 %cmp
+; CHECK-NEXT: ret i1 false
+}
+
+%gept = type { i32, i32 }
+
+define i1 @gep3() {
+; CHECK-LABEL: @gep3(
+  %x = alloca %gept, align 8
+  %a = getelementptr %gept, %gept* %x, i64 0, i32 0
+  %y = call %gept* @func2(%gept* %x)
+  %b = getelementptr %gept, %gept* %y, i64 0, i32 1
+  %equal = icmp eq i32* %a, %b
+  ret i1 %equal
+; CHECK-NEXT: ret i1 false
+}
+
+declare i8* @func1(i8* returned) nounwind readnone
+declare %gept* @func2(%gept* returned) nounwind readnone
+

Added: llvm/trunk/test/Transforms/InstSimplify/round-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/round-intrinsics.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/round-intrinsics.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/round-intrinsics.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,131 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -instsimplify %s | FileCheck %s
+
+define float @sitofp_floor(i32 %arg) {
+; CHECK-LABEL: @sitofp_floor(
+; CHECK-NEXT:    [[CVT:%.*]] = sitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = sitofp i32 %arg to float
+  %round = call float @llvm.floor.f32(float %cvt)
+  ret float %round
+}
+
+define float @uitofp_floor(i32 %arg) {
+; CHECK-LABEL: @uitofp_floor(
+; CHECK-NEXT:    [[CVT:%.*]] = uitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = uitofp i32 %arg to float
+  %round = call float @llvm.floor.f32(float %cvt)
+  ret float %round
+}
+
+define float @sitofp_trunc(i32 %arg) {
+; CHECK-LABEL: @sitofp_trunc(
+; CHECK-NEXT:    [[CVT:%.*]] = sitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = sitofp i32 %arg to float
+  %round = call float @llvm.trunc.f32(float %cvt)
+  ret float %round
+}
+
+define float @uitofp_trunc(i32 %arg) {
+; CHECK-LABEL: @uitofp_trunc(
+; CHECK-NEXT:    [[CVT:%.*]] = uitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = uitofp i32 %arg to float
+  %round = call float @llvm.trunc.f32(float %cvt)
+  ret float %round
+}
+
+define float @sitofp_ceil(i32 %arg) {
+; CHECK-LABEL: @sitofp_ceil(
+; CHECK-NEXT:    [[CVT:%.*]] = sitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = sitofp i32 %arg to float
+  %round = call float @llvm.ceil.f32(float %cvt)
+  ret float %round
+}
+
+define float @uitofp_ceil(i32 %arg) {
+; CHECK-LABEL: @uitofp_ceil(
+; CHECK-NEXT:    [[CVT:%.*]] = uitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = uitofp i32 %arg to float
+  %round = call float @llvm.ceil.f32(float %cvt)
+  ret float %round
+}
+
+define float @sitofp_round(i32 %arg) {
+; CHECK-LABEL: @sitofp_round(
+; CHECK-NEXT:    [[CVT:%.*]] = sitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = sitofp i32 %arg to float
+  %round = call float @llvm.round.f32(float %cvt)
+  ret float %round
+}
+
+define float @uitofp_round(i32 %arg) {
+; CHECK-LABEL: @uitofp_round(
+; CHECK-NEXT:    [[CVT:%.*]] = uitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = uitofp i32 %arg to float
+  %round = call float @llvm.round.f32(float %cvt)
+  ret float %round
+}
+
+define float @sitofp_nearbyint(i32 %arg) {
+; CHECK-LABEL: @sitofp_nearbyint(
+; CHECK-NEXT:    [[CVT:%.*]] = sitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = sitofp i32 %arg to float
+  %nearbyint = call float @llvm.nearbyint.f32(float %cvt)
+  ret float %nearbyint
+}
+
+define float @uitofp_nearbyint(i32 %arg) {
+; CHECK-LABEL: @uitofp_nearbyint(
+; CHECK-NEXT:    [[CVT:%.*]] = uitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = uitofp i32 %arg to float
+  %nearbyint = call float @llvm.nearbyint.f32(float %cvt)
+  ret float %nearbyint
+}
+
+define float @sitofp_rint(i32 %arg) {
+; CHECK-LABEL: @sitofp_rint(
+; CHECK-NEXT:    [[CVT:%.*]] = sitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = sitofp i32 %arg to float
+  %rint = call float @llvm.rint.f32(float %cvt)
+  ret float %rint
+}
+
+define float @uitofp_rint(i32 %arg) {
+; CHECK-LABEL: @uitofp_rint(
+; CHECK-NEXT:    [[CVT:%.*]] = uitofp i32 [[ARG:%.*]] to float
+; CHECK-NEXT:    ret float [[CVT]]
+;
+  %cvt = uitofp i32 %arg to float
+  %rint = call float @llvm.rint.f32(float %cvt)
+  ret float %rint
+}
+
+declare float @llvm.floor.f32(float) #0
+declare float @llvm.trunc.f32(float) #0
+declare float @llvm.ceil.f32(float) #0
+declare float @llvm.round.f32(float) #0
+declare float @llvm.nearbyint.f32(float) #0
+declare float @llvm.rint.f32(float) #0
+
+attributes #0 = { nounwind readnone speculatable }

Added: llvm/trunk/test/Transforms/InstSimplify/saturating-add-sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/saturating-add-sub.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/saturating-add-sub.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/saturating-add-sub.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,666 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+declare i3 @llvm.uadd.sat.i3(i3, i3)
+declare i8 @llvm.uadd.sat.i8(i8, i8)
+declare <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8>, <2 x i8>)
+declare <2 x i9> @llvm.uadd.sat.v2i9(<2 x i9>, <2 x i9>)
+
+declare i8 @llvm.sadd.sat.i8(i8, i8)
+declare <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8>, <2 x i8>)
+
+declare i8 @llvm.usub.sat.i8(i8, i8)
+declare i8 @llvm.ssub.sat.i8(i8, i8)
+declare <2 x i8> @llvm.usub.sat.v2i8(<2 x i8>, <2 x i8>)
+declare <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8>, <2 x i8>)
+
+define i8 @uadd_scalar_0(i8 %a) {
+; CHECK-LABEL: @uadd_scalar_0(
+; CHECK-NEXT:    ret i8 [[A:%.*]]
+;
+  %x1 = call i8 @llvm.uadd.sat.i8(i8 %a, i8 0)
+  ret i8 %x1
+}
+
+define <2 x i8> @uadd_vector_0(<2 x i8> %a) {
+; CHECK-LABEL: @uadd_vector_0(
+; CHECK-NEXT:    ret <2 x i8> [[A:%.*]]
+;
+  %x1v = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a, <2 x i8> zeroinitializer)
+  ret <2 x i8> %x1v
+}
+
+define i3 @uadd_scalar_0_commute(i3 %a) {
+; CHECK-LABEL: @uadd_scalar_0_commute(
+; CHECK-NEXT:    ret i3 [[A:%.*]]
+;
+  %x2 = call i3 @llvm.uadd.sat.i3(i3 0, i3 %a)
+  ret i3 %x2
+}
+
+define <2 x i8> @uadd_vector_0_commute(<2 x i8> %a) {
+; CHECK-LABEL: @uadd_vector_0_commute(
+; CHECK-NEXT:    ret <2 x i8> [[A:%.*]]
+;
+  %x2v = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> <i8 0, i8 undef>, <2 x i8> %a)
+  ret <2 x i8> %x2v
+}
+
+define i8 @uadd_scalar_maxval(i8 %a) {
+; CHECK-LABEL: @uadd_scalar_maxval(
+; CHECK-NEXT:    ret i8 -1
+;
+  %x3 = call i8 @llvm.uadd.sat.i8(i8 %a, i8 255)
+  ret i8 %x3
+}
+
+define <2 x i9> @uadd_vector_maxval(<2 x i9> %a) {
+; CHECK-LABEL: @uadd_vector_maxval(
+; CHECK-NEXT:    ret <2 x i9> <i9 -1, i9 -1>
+;
+  %x3v = call <2 x i9> @llvm.uadd.sat.v2i9(<2 x i9> %a, <2 x i9> <i9 511, i9 511>)
+  ret <2 x i9> %x3v
+}
+
+define i3 @uadd_scalar_maxval_commute(i3 %a) {
+; CHECK-LABEL: @uadd_scalar_maxval_commute(
+; CHECK-NEXT:    ret i3 -1
+;
+  %x4 = call i3 @llvm.uadd.sat.i3(i3 7, i3 %a)
+  ret i3 %x4
+}
+
+define <2 x i8> @uadd_vector_maxval_commute(<2 x i8> %a) {
+; CHECK-LABEL: @uadd_vector_maxval_commute(
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
+;
+  %x4v = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> <i8 255, i8 255>, <2 x i8> %a)
+  ret <2 x i8> %x4v
+}
+
+define i8 @uadd_scalar_undef(i8 %a) {
+; CHECK-LABEL: @uadd_scalar_undef(
+; CHECK-NEXT:    ret i8 -1
+;
+  %x5 = call i8 @llvm.uadd.sat.i8(i8 %a, i8 undef)
+  ret i8 %x5
+}
+
+define <2 x i8> @uadd_vector_undef(<2 x i8> %a) {
+; CHECK-LABEL: @uadd_vector_undef(
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
+;
+  %x5v = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 undef, i8 undef>)
+  ret <2 x i8> %x5v
+}
+
+define i8 @uadd_scalar_undef_commute(i8 %a) {
+; CHECK-LABEL: @uadd_scalar_undef_commute(
+; CHECK-NEXT:    ret i8 -1
+;
+  %x6 = call i8 @llvm.uadd.sat.i8(i8 undef, i8 %a)
+  ret i8 %x6
+}
+
+define <2 x i8> @uadd_vector_undef_commute(<2 x i8> %a) {
+; CHECK-LABEL: @uadd_vector_undef_commute(
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
+;
+  %x5v = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> undef, <2 x i8> %a)
+  ret <2 x i8> %x5v
+}
+
+define i8 @sadd_scalar_0(i8 %a) {
+; CHECK-LABEL: @sadd_scalar_0(
+; CHECK-NEXT:    ret i8 [[A:%.*]]
+;
+  %y1 = call i8 @llvm.sadd.sat.i8(i8 %a, i8 0)
+  ret i8 %y1
+}
+
+define <2 x i8> @sadd_vector_0(<2 x i8> %a) {
+; CHECK-LABEL: @sadd_vector_0(
+; CHECK-NEXT:    ret <2 x i8> [[A:%.*]]
+;
+  %y1v = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 undef, i8 0>)
+  ret <2 x i8> %y1v
+}
+
+define i8 @sadd_scalar_0_commute(i8 %a) {
+; CHECK-LABEL: @sadd_scalar_0_commute(
+; CHECK-NEXT:    ret i8 [[A:%.*]]
+;
+  %y2 = call i8 @llvm.sadd.sat.i8(i8 0, i8 %a)
+  ret i8 %y2
+}
+
+define <2 x i8> @sadd_vector_0_commute(<2 x i8> %a) {
+; CHECK-LABEL: @sadd_vector_0_commute(
+; CHECK-NEXT:    ret <2 x i8> [[A:%.*]]
+;
+  %y2v = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> zeroinitializer, <2 x i8> %a)
+  ret <2 x i8> %y2v
+}
+
+define i8 @sadd_scalar_maxval(i8 %a) {
+; CHECK-LABEL: @sadd_scalar_maxval(
+; CHECK-NEXT:    [[Y3:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 127)
+; CHECK-NEXT:    ret i8 [[Y3]]
+;
+  %y3 = call i8 @llvm.sadd.sat.i8(i8 %a, i8 127)
+  ret i8 %y3
+}
+
+define <2 x i8> @sadd_vector_maxval(<2 x i8> %a) {
+; CHECK-LABEL: @sadd_vector_maxval(
+; CHECK-NEXT:    [[Y3V:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 127, i8 127>)
+; CHECK-NEXT:    ret <2 x i8> [[Y3V]]
+;
+  %y3v = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 127, i8 127>)
+  ret <2 x i8> %y3v
+}
+
+define i8 @sadd_scalar_maxval_commute(i8 %a) {
+; CHECK-LABEL: @sadd_scalar_maxval_commute(
+; CHECK-NEXT:    [[Y4:%.*]] = call i8 @llvm.sadd.sat.i8(i8 127, i8 [[A:%.*]])
+; CHECK-NEXT:    ret i8 [[Y4]]
+;
+  %y4 = call i8 @llvm.sadd.sat.i8(i8 127, i8 %a)
+  ret i8 %y4
+}
+
+define <2 x i8> @sadd_vector_maxval_commute(<2 x i8> %a) {
+; CHECK-LABEL: @sadd_vector_maxval_commute(
+; CHECK-NEXT:    [[Y4V:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> <i8 undef, i8 127>, <2 x i8> [[A:%.*]])
+; CHECK-NEXT:    ret <2 x i8> [[Y4V]]
+;
+  %y4v = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> <i8 undef, i8 127>, <2 x i8> %a)
+  ret <2 x i8> %y4v
+}
+
+define i8 @sadd_scalar_undef(i8 %a) {
+; CHECK-LABEL: @sadd_scalar_undef(
+; CHECK-NEXT:    ret i8 -1
+;
+  %y5 = call i8 @llvm.sadd.sat.i8(i8 %a, i8 undef)
+  ret i8 %y5
+}
+
+define <2 x i8> @sadd_vector_undef(<2 x i8> %a) {
+; CHECK-LABEL: @sadd_vector_undef(
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
+;
+  %y5v = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %a, <2 x i8> undef)
+  ret <2 x i8> %y5v
+}
+
+define i8 @sadd_scalar_undef_commute(i8 %a) {
+; CHECK-LABEL: @sadd_scalar_undef_commute(
+; CHECK-NEXT:    ret i8 -1
+;
+  %y6 = call i8 @llvm.sadd.sat.i8(i8 undef, i8 %a)
+  ret i8 %y6
+}
+
+define <2 x i8> @sadd_vector_undef_commute(<2 x i8> %a) {
+; CHECK-LABEL: @sadd_vector_undef_commute(
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
+;
+  %y6v = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> undef, <2 x i8> %a)
+  ret <2 x i8> %y6v
+}
+
+define i8 @usub_scalar_0(i8 %a) {
+; CHECK-LABEL: @usub_scalar_0(
+; CHECK-NEXT:    ret i8 [[A:%.*]]
+;
+  %x1 = call i8 @llvm.usub.sat.i8(i8 %a, i8 0)
+  ret i8 %x1
+}
+
+define <2 x i8> @usub_vector_0(<2 x i8> %a) {
+; CHECK-LABEL: @usub_vector_0(
+; CHECK-NEXT:    ret <2 x i8> [[A:%.*]]
+;
+  %x1v = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 0, i8 0>)
+  ret <2 x i8> %x1v
+}
+
+define i8 @usub_scalar_0_commute(i8 %a) {
+; CHECK-LABEL: @usub_scalar_0_commute(
+; CHECK-NEXT:    ret i8 0
+;
+  %x2 = call i8 @llvm.usub.sat.i8(i8 0, i8 %a)
+  ret i8 %x2
+}
+
+define <2 x i8> @usub_vector_0_commute(<2 x i8> %a) {
+; CHECK-LABEL: @usub_vector_0_commute(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %x2v = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> <i8 0, i8 0>, <2 x i8> %a)
+  ret <2 x i8> %x2v
+}
+
+define i8 @usub_scalar_maxval(i8 %a) {
+; CHECK-LABEL: @usub_scalar_maxval(
+; CHECK-NEXT:    ret i8 0
+;
+  %x3 = call i8 @llvm.usub.sat.i8(i8 %a, i8 255)
+  ret i8 %x3
+}
+
+define <2 x i8> @usub_vector_maxval(<2 x i8> %a) {
+; CHECK-LABEL: @usub_vector_maxval(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %x3v = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 255, i8 255>)
+  ret <2 x i8> %x3v
+}
+
+define i8 @usub_scalar_undef(i8 %a) {
+; CHECK-LABEL: @usub_scalar_undef(
+; CHECK-NEXT:    ret i8 0
+;
+  %x4 = call i8 @llvm.usub.sat.i8(i8 %a, i8 undef)
+  ret i8 %x4
+}
+
+define <2 x i8> @usub_vector_undef(<2 x i8> %a) {
+; CHECK-LABEL: @usub_vector_undef(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %x4v = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 undef, i8 undef>)
+  ret <2 x i8> %x4v
+}
+
+define i8 @usub_scalar_undef_commute(i8 %a) {
+; CHECK-LABEL: @usub_scalar_undef_commute(
+; CHECK-NEXT:    ret i8 0
+;
+  %x5 = call i8 @llvm.usub.sat.i8(i8 undef, i8 %a)
+  ret i8 %x5
+}
+
+define <2 x i8> @usub_vector_undef_commute(<2 x i8> %a) {
+; CHECK-LABEL: @usub_vector_undef_commute(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %x5v = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> <i8 undef, i8 undef>, <2 x i8> %a)
+  ret <2 x i8> %x5v
+}
+
+define i8 @usub_scalar_same(i8 %a) {
+; CHECK-LABEL: @usub_scalar_same(
+; CHECK-NEXT:    ret i8 0
+;
+  %x6 = call i8 @llvm.usub.sat.i8(i8 %a, i8 %a)
+  ret i8 %x6
+}
+
+define <2 x i8> @usub_vector_same(<2 x i8> %a) {
+; CHECK-LABEL: @usub_vector_same(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %x6v = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a, <2 x i8> %a)
+  ret <2 x i8> %x6v
+}
+
+define i8 @ssub_scalar_0(i8 %a) {
+; CHECK-LABEL: @ssub_scalar_0(
+; CHECK-NEXT:    ret i8 [[A:%.*]]
+;
+  %y1 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 0)
+  ret i8 %y1
+}
+
+define <2 x i8> @ssub_vector_0(<2 x i8> %a) {
+; CHECK-LABEL: @ssub_vector_0(
+; CHECK-NEXT:    ret <2 x i8> [[A:%.*]]
+;
+  %y1v = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 0, i8 0>)
+  ret <2 x i8> %y1v
+}
+
+define i8 @ssub_scalar_0_commute(i8 %a) {
+; CHECK-LABEL: @ssub_scalar_0_commute(
+; CHECK-NEXT:    [[Y2:%.*]] = call i8 @llvm.ssub.sat.i8(i8 0, i8 [[A:%.*]])
+; CHECK-NEXT:    ret i8 [[Y2]]
+;
+  %y2 = call i8 @llvm.ssub.sat.i8(i8 0, i8 %a)
+  ret i8 %y2
+}
+
+define <2 x i8> @ssub_vector_0_commute(<2 x i8> %a) {
+; CHECK-LABEL: @ssub_vector_0_commute(
+; CHECK-NEXT:    [[Y2V:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> zeroinitializer, <2 x i8> [[A:%.*]])
+; CHECK-NEXT:    ret <2 x i8> [[Y2V]]
+;
+  %y2v = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> <i8 0, i8 0>, <2 x i8> %a)
+  ret <2 x i8> %y2v
+}
+
+define i8 @ssub_scalar_maxval(i8 %a) {
+; CHECK-LABEL: @ssub_scalar_maxval(
+; CHECK-NEXT:    [[Y3:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 127)
+; CHECK-NEXT:    ret i8 [[Y3]]
+;
+  %y3 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 127)
+  ret i8 %y3
+}
+
+define <2 x i8> @ssub_vector_maxval(<2 x i8> %a) {
+; CHECK-LABEL: @ssub_vector_maxval(
+; CHECK-NEXT:    [[Y3V:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 127, i8 127>)
+; CHECK-NEXT:    ret <2 x i8> [[Y3V]]
+;
+  %y3v = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 127, i8 127>)
+  ret <2 x i8> %y3v
+}
+
+define i8 @ssub_scalar_undef(i8 %a) {
+; CHECK-LABEL: @ssub_scalar_undef(
+; CHECK-NEXT:    ret i8 0
+;
+  %y4 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 undef)
+  ret i8 %y4
+}
+
+define <2 x i8> @ssub_vector_undef(<2 x i8> %a) {
+; CHECK-LABEL: @ssub_vector_undef(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %y4v = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> undef)
+  ret <2 x i8> %y4v
+}
+
+define i8 @ssub_scalar_undef_commute(i8 %a) {
+; CHECK-LABEL: @ssub_scalar_undef_commute(
+; CHECK-NEXT:    ret i8 0
+;
+  %y5 = call i8 @llvm.ssub.sat.i8(i8 undef, i8 %a)
+  ret i8 %y5
+}
+
+define <2 x i8> @ssub_vector_undef_commute(<2 x i8> %a) {
+; CHECK-LABEL: @ssub_vector_undef_commute(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %y5v = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> <i8 undef, i8 undef>, <2 x i8> %a)
+  ret <2 x i8> %y5v
+}
+
+define i8 @ssub_scalar_same(i8 %a) {
+; CHECK-LABEL: @ssub_scalar_same(
+; CHECK-NEXT:    ret i8 0
+;
+  %y6 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 %a)
+  ret i8 %y6
+}
+
+define <2 x i8> @ssub_vector_same(<2 x i8> %a) {
+; CHECK-LABEL: @ssub_vector_same(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %y6v = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> %a)
+  ret <2 x i8> %y6v
+}
+
+define i1 @uadd_icmp_op0_known(i8 %a) {
+; CHECK-LABEL: @uadd_icmp_op0_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.uadd.sat.i8(i8 10, i8 %a)
+  %c = icmp uge i8 %b, 10
+  ret i1 %c
+}
+
+define i1 @uadd_icmp_op0_unknown(i8 %a) {
+; CHECK-LABEL: @uadd_icmp_op0_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.uadd.sat.i8(i8 10, i8 [[A:%.*]])
+; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 [[B]], 10
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.uadd.sat.i8(i8 10, i8 %a)
+  %c = icmp ugt i8 %b, 10
+  ret i1 %c
+}
+
+define i1 @uadd_icmp_op1_known(i8 %a) {
+; CHECK-LABEL: @uadd_icmp_op1_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.uadd.sat.i8(i8 %a, i8 10)
+  %c = icmp uge i8 %b, 10
+  ret i1 %c
+}
+
+define i1 @uadd_icmp_op1_unknown(i8 %a) {
+; CHECK-LABEL: @uadd_icmp_op1_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A:%.*]], i8 10)
+; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 [[B]], 10
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.uadd.sat.i8(i8 %a, i8 10)
+  %c = icmp ugt i8 %b, 10
+  ret i1 %c
+}
+
+define i1 @sadd_icmp_op0_pos_known(i8 %a) {
+; CHECK-LABEL: @sadd_icmp_op0_pos_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.sadd.sat.i8(i8 10, i8 %a)
+  %c = icmp sge i8 %b, -118
+  ret i1 %c
+}
+
+define i1 @sadd_icmp_op0_pos_unknown(i8 %a) {
+; CHECK-LABEL: @sadd_icmp_op0_pos_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.sadd.sat.i8(i8 10, i8 [[A:%.*]])
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[B]], -118
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.sadd.sat.i8(i8 10, i8 %a)
+  %c = icmp sgt i8 %b, -118
+  ret i1 %c
+}
+
+define i1 @sadd_icmp_op0_neg_known(i8 %a) {
+; CHECK-LABEL: @sadd_icmp_op0_neg_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.sadd.sat.i8(i8 -10, i8 %a)
+  %c = icmp sle i8 %b, 117
+  ret i1 %c
+}
+
+define i1 @sadd_icmp_op0_neg_unknown(i8 %a) {
+; CHECK-LABEL: @sadd_icmp_op0_neg_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.sadd.sat.i8(i8 -10, i8 [[A:%.*]])
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[B]], 117
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.sadd.sat.i8(i8 -10, i8 %a)
+  %c = icmp slt i8 %b, 117
+  ret i1 %c
+}
+
+define i1 @sadd_icmp_op1_pos_known(i8 %a) {
+; CHECK-LABEL: @sadd_icmp_op1_pos_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.sadd.sat.i8(i8 %a, i8 10)
+  %c = icmp sge i8 %b, -118
+  ret i1 %c
+}
+
+define i1 @sadd_icmp_op1_pos_unknown(i8 %a) {
+; CHECK-LABEL: @sadd_icmp_op1_pos_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 10)
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[B]], -118
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.sadd.sat.i8(i8 %a, i8 10)
+  %c = icmp sgt i8 %b, -118
+  ret i1 %c
+}
+
+define i1 @sadd_icmp_op1_neg_known(i8 %a) {
+; CHECK-LABEL: @sadd_icmp_op1_neg_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.sadd.sat.i8(i8 %a, i8 -10)
+  %c = icmp sle i8 %b, 117
+  ret i1 %c
+}
+
+define i1 @sadd_icmp_op1_neg_unknown(i8 %a) {
+; CHECK-LABEL: @sadd_icmp_op1_neg_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -10)
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[B]], 117
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.sadd.sat.i8(i8 %a, i8 -10)
+  %c = icmp slt i8 %b, 117
+  ret i1 %c
+}
+
+define i1 @usub_icmp_op0_known(i8 %a) {
+; CHECK-LABEL: @usub_icmp_op0_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.usub.sat.i8(i8 10, i8 %a)
+  %c = icmp ule i8 %b, 10
+  ret i1 %c
+}
+
+define i1 @usub_icmp_op0_unknown(i8 %a) {
+; CHECK-LABEL: @usub_icmp_op0_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.usub.sat.i8(i8 10, i8 [[A:%.*]])
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[B]], 10
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.usub.sat.i8(i8 10, i8 %a)
+  %c = icmp ult i8 %b, 10
+  ret i1 %c
+}
+
+define i1 @usub_icmp_op1_known(i8 %a) {
+; CHECK-LABEL: @usub_icmp_op1_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.usub.sat.i8(i8 %a, i8 10)
+  %c = icmp ule i8 %b, 245
+  ret i1 %c
+}
+
+define i1 @usub_icmp_op1_unknown(i8 %a) {
+; CHECK-LABEL: @usub_icmp_op1_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 10)
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[B]], -11
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.usub.sat.i8(i8 %a, i8 10)
+  %c = icmp ult i8 %b, 245
+  ret i1 %c
+}
+
+define i1 @ssub_icmp_op0_pos_known(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op0_pos_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 10, i8 %a)
+  %c = icmp sge i8 %b, -117
+  ret i1 %c
+}
+
+define i1 @ssub_icmp_op0_pos_unknown(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op0_pos_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.ssub.sat.i8(i8 10, i8 [[A:%.*]])
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[B]], -117
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 10, i8 %a)
+  %c = icmp sgt i8 %b, -117
+  ret i1 %c
+}
+
+define i1 @ssub_icmp_op0_neg_known(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op0_neg_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 -10, i8 %a)
+  %c = icmp sle i8 %b, 118
+  ret i1 %c
+}
+
+define i1 @ssub_icmp_op0_neg_unknown(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op0_neg_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.ssub.sat.i8(i8 -10, i8 [[A:%.*]])
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[B]], 118
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 -10, i8 %a)
+  %c = icmp slt i8 %b, 118
+  ret i1 %c
+}
+
+; Peculiar case: ssub.sat(0, x) is never signed min.
+define i1 @ssub_icmp_op0_zero(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op0_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 0, i8 %a)
+  %c = icmp ne i8 %b, -128
+  ret i1 %c
+}
+
+define i1 @ssub_icmp_op1_pos_known(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op1_pos_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 %a, i8 10)
+  %c = icmp sle i8 %b, 117
+  ret i1 %c
+}
+
+define i1 @ssub_icmp_op1_pos_unknown(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op1_pos_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 10)
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[B]], 117
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 %a, i8 10)
+  %c = icmp slt i8 %b, 117
+  ret i1 %c
+}
+
+define i1 @ssub_icmp_op1_neg_known(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op1_neg_known(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 %a, i8 -10)
+  %c = icmp sge i8 %b, -118
+  ret i1 %c
+}
+
+define i1 @ssub_icmp_op1_neg_unknown(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op1_neg_unknown(
+; CHECK-NEXT:    [[B:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 -10)
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[B]], -118
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 %a, i8 -10)
+  %c = icmp sgt i8 %b, -118
+  ret i1 %c
+}
+
+define i1 @ssub_icmp_op1_smin(i8 %a) {
+; CHECK-LABEL: @ssub_icmp_op1_smin(
+; CHECK-NEXT:    ret i1 true
+;
+  %b = call i8 @llvm.ssub.sat.i8(i8 %a, i8 -128)
+  %c = icmp sge i8 %b, 0
+  ret i1 %c
+}

Added: llvm/trunk/test/Transforms/InstSimplify/sdiv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/sdiv.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/sdiv.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/sdiv.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,179 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @negated_operand(i32 %x) {
+; CHECK-LABEL: @negated_operand(
+; CHECK-NEXT:    ret i32 -1
+;
+  %negx = sub nsw i32 0, %x
+  %div = sdiv i32 %negx, %x
+  ret i32 %div
+}
+
+define <2 x i32> @negated_operand_commute_vec(<2 x i32> %x) {
+; CHECK-LABEL: @negated_operand_commute_vec(
+; CHECK-NEXT:    ret <2 x i32> <i32 -1, i32 -1>
+;
+  %negx = sub nsw <2 x i32> zeroinitializer, %x
+  %div = sdiv <2 x i32> %negx, %x
+  ret <2 x i32> %div
+}
+
+define i32 @knownnegation(i32 %x, i32 %y) {
+; CHECK-LABEL: @knownnegation(
+; CHECK-NEXT:    ret i32 -1
+;
+  %xy = sub nsw i32 %x, %y
+  %yx = sub nsw i32 %y, %x
+  %div = sdiv i32 %xy, %yx
+  ret i32 %div
+}
+
+define <2 x i32> @knownnegation_commute_vec(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @knownnegation_commute_vec(
+; CHECK-NEXT:    ret <2 x i32> <i32 -1, i32 -1>
+;
+  %xy = sub nsw <2 x i32> %x, %y
+  %yx = sub nsw <2 x i32> %y, %x
+  %div = sdiv <2 x i32> %xy, %yx
+  ret <2 x i32> %div
+}
+
+define i32 @negated_operand_2(i32 %t) {
+; CHECK-LABEL: @negated_operand_2(
+; CHECK-NEXT:    ret i32 -1
+;
+  %x = sub i32 %t, 5 
+  %negx = sub nsw i32 0, %x
+  %div = sdiv i32 %negx, %x
+  ret i32 %div
+}
+
+define i32 @negated_operand_commute(i32 %x) {
+; CHECK-LABEL: @negated_operand_commute(
+; CHECK-NEXT:    ret i32 -1
+;
+  %negx = sub nsw i32 0, %x
+  %div = sdiv i32 %x, %negx
+  ret i32 %div
+}
+
+define i32 @negated_operand_bad(i32 %x) {
+; CHECK-LABEL: @negated_operand_bad(
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[NEGX]], [[X]]
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %negx = sub i32 0, %x ; not nsw
+  %div = sdiv i32 %negx, %x
+  ret i32 %div
+}
+
+define i32 @knownnegation_bad_1(i32 %x, i32 %y) {
+; CHECK-LABEL: @knownnegation_bad_1(
+; CHECK-NEXT:    [[XY:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[YX:%.*]] = sub i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[XY]], [[YX]]
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %xy = sub nsw i32 %x, %y
+  %yx = sub i32 %y, %x ; not nsw
+  %div = sdiv i32 %xy, %yx
+  ret i32 %div
+}
+
+define i32 @knownnegation_bad_2(i32 %x, i32 %y) {
+; CHECK-LABEL: @knownnegation_bad_2(
+; CHECK-NEXT:    [[XY:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[YX:%.*]] = sub nsw i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[XY]], [[YX]]
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %xy = sub i32 %x, %y ; not nsw
+  %yx = sub nsw i32 %y, %x
+  %div = sdiv i32 %xy, %yx
+  ret i32 %div
+}
+
+define i32 @knownnegation_bad_3(i32 %x, i32 %y) {
+; CHECK-LABEL: @knownnegation_bad_3(
+; CHECK-NEXT:    [[XY:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[YX:%.*]] = sub i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[XY]], [[YX]]
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %xy = sub i32 %x, %y ; not nsw
+  %yx = sub i32 %y, %x ; not nsw
+  %div = sdiv i32 %xy, %yx
+  ret i32 %div
+}
+
+define <2 x i32> @negated_operand_commute_vec_bad(<2 x i32> %x) {
+; CHECK-LABEL: @negated_operand_commute_vec_bad(
+; CHECK-NEXT:    [[NEGX:%.*]] = sub <2 x i32> zeroinitializer, [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv <2 x i32> [[NEGX]], [[X]]
+; CHECK-NEXT:    ret <2 x i32> [[DIV]]
+;
+  %negx = sub <2 x i32> zeroinitializer, %x ; not nsw
+  %div = sdiv <2 x i32> %negx, %x
+  ret <2 x i32> %div
+}
+
+define <2 x i32> @knownnegation_commute_vec_bad1(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @knownnegation_commute_vec_bad1(
+; CHECK-NEXT:    [[XY:%.*]] = sub nsw <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[YX:%.*]] = sub <2 x i32> [[Y]], [[X]]
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv <2 x i32> [[XY]], [[YX]]
+; CHECK-NEXT:    ret <2 x i32> [[DIV]]
+;
+  %xy = sub nsw <2 x i32> %x, %y
+  %yx = sub <2 x i32> %y, %x ; not nsw
+  %div = sdiv <2 x i32> %xy, %yx
+  ret <2 x i32> %div
+}
+
+define <2 x i32> @knownnegation_commute_vec_bad2(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @knownnegation_commute_vec_bad2(
+; CHECK-NEXT:    [[XY:%.*]] = sub <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[YX:%.*]] = sub nsw <2 x i32> [[Y]], [[X]]
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv <2 x i32> [[XY]], [[YX]]
+; CHECK-NEXT:    ret <2 x i32> [[DIV]]
+;
+  %xy = sub <2 x i32> %x, %y ; not nsw
+  %yx = sub nsw <2 x i32> %y, %x
+  %div = sdiv <2 x i32> %xy, %yx
+  ret <2 x i32> %div
+}
+
+define <2 x i32> @knownnegation_commute_vec_bad3(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @knownnegation_commute_vec_bad3(
+; CHECK-NEXT:    [[XY:%.*]] = sub <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[YX:%.*]] = sub <2 x i32> [[Y]], [[X]]
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv <2 x i32> [[XY]], [[YX]]
+; CHECK-NEXT:    ret <2 x i32> [[DIV]]
+;
+  %xy = sub <2 x i32> %x, %y ; not nsw
+  %yx = sub <2 x i32> %y, %x ; not nsw
+  %div = sdiv <2 x i32> %xy, %yx
+  ret <2 x i32> %div
+}
+
+define <3 x i32> @negated_operand_vec_undef(<3 x i32> %x) {
+; CHECK-LABEL: @negated_operand_vec_undef(
+; CHECK-NEXT:    ret <3 x i32> <i32 -1, i32 -1, i32 -1>
+;
+  %negx = sub nsw <3 x i32> <i32 0, i32 undef, i32 0>, %x
+  %div = sdiv <3 x i32> %negx, %x
+  ret <3 x i32> %div
+}
+
+define <2 x i32> @negated_operand_vec_nonsplat(<2 x i32> %x) {
+; CHECK-LABEL: @negated_operand_vec_nonsplat(
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw <2 x i32> <i32 0, i32 1>, [[X:%.*]]
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv <2 x i32> [[NEGX]], [[X]]
+; CHECK-NEXT:    ret <2 x i32> [[DIV]]
+;
+  %negx = sub nsw <2 x i32> <i32 0, i32 1>, %x ; not 0, don't fold
+  %div = sdiv <2 x i32> %negx, %x
+  ret <2 x i32> %div
+}

Added: llvm/trunk/test/Transforms/InstSimplify/select-and-cmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/select-and-cmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/select-and-cmp.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/select-and-cmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,339 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @select_and_icmp(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define <2 x i8> @select_and_icmp_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @select_and_icmp_vec(
+; CHECK-NEXT:    ret <2 x i8> [[X:%.*]]
+;
+  %A = icmp eq <2 x i8> %x, %z
+  %B = icmp eq <2 x i8> %y, %z
+  %C = and <2 x i1> %A, %B
+  %D = select <2 x i1> %C, <2 x i8> %z, <2 x i8> %x
+  ret <2 x i8> %D
+}
+
+define i32 @select_and_icmp2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp2(
+; CHECK-NEXT:    ret i32 [[Y:%.*]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %y
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_alt(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_alt(
+; CHECK-NEXT:    ret i32 [[Z:%.*]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_alt2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_alt2(
+; CHECK-NEXT:    ret i32 [[Z:%.*]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %y, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_inv_alt(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_inv_alt(
+; CHECK-NEXT:    ret i32 [[Z:%.*]]
+;
+  %A = icmp eq i32 %z, %x
+  %B = icmp eq i32 %z, %y
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_inv_icmp_alt(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_inv_icmp_alt(
+; CHECK-NEXT:    ret i32 [[Z:%.*]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %B, %A
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_inv_icmp(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_inv_icmp(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %B , %A
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define <2 x i8> @select_and_icmp_alt_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @select_and_icmp_alt_vec(
+; CHECK-NEXT:    ret <2 x i8> [[Z:%.*]]
+;
+  %A = icmp eq <2 x i8> %x, %z
+  %B = icmp eq <2 x i8> %y, %z
+  %C = and <2 x i1> %A, %B
+  %D = select <2 x i1> %C, <2 x i8> %x, <2 x i8> %z
+  ret <2 x i8> %D
+}
+
+
+define i32 @select_and_icmp_inv(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_inv(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+  %A = icmp eq i32 %z, %x
+  %B = icmp eq i32 %z, %y
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+; Negative tests
+define i32 @select_and_icmp_pred_bad_1(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_pred_bad_1(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_pred_bad_2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_pred_bad_2(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_pred_bad_3(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_pred_bad_3(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_pred_bad_4(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_pred_bad_4(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_bad_true_val(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_and_icmp_bad_true_val(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[K:%.*]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %k, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_bad_false_val(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_and_icmp_bad_false_val(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[K:%.*]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %k
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_bad_op(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_and_icmp_bad_op(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[K:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X:%.*]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %k, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_bad_op_2(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_and_icmp_bad_op_2(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[K:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %k
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_alt_bad_1(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_alt_bad_1(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_alt_bad_2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_alt_bad_2(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_alt_bad_3(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_alt_bad_3(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_alt_bad_4(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_alt_bad_4(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_alt_bad_5(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_and_icmp_alt_bad_5(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[K:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %k
+  %B = icmp eq i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_alt_bad_true_val(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_and_icmp_alt_bad_true_val(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[K:%.*]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %k, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_alt_bad_false_val(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_and_icmp_alt_bad_false_val(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[K:%.*]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %k
+  ret i32 %D
+}

Added: llvm/trunk/test/Transforms/InstSimplify/select-implied.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/select-implied.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/select-implied.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/select-implied.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,276 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; A == B implies A >u B is false.
+
+define void @test1(i32 %a, i32 %b) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @foo(i32 10)
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %end
+
+taken:
+  %cmp2 = icmp ugt i32 %a, %b
+  %c = select i1 %cmp2, i32 0, i32 10
+  call void @foo(i32 %c)
+  br label %end
+
+end:
+  ret void
+}
+
+; If A == B is false then A != B is true.
+
+define void @test2(i32 %a, i32 %b) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @foo(i32 20)
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %end, label %taken
+
+taken:
+  %cmp2 = icmp ne i32 %a, %b
+  %c = select i1 %cmp2, i32 20, i32 0
+  call void @foo(i32 %c)
+  br label %end
+
+end:
+  ret void
+}
+
+; A >u 10 implies A >u 10 is true.
+
+define void @test3(i32 %a) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10
+; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @foo(i32 30)
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp1 = icmp ugt i32 %a, 10
+  br i1 %cmp1, label %taken, label %end
+
+taken:
+  %cmp2 = icmp ugt i32 %a, 10
+  %c = select i1 %cmp2, i32 30, i32 0
+  call void @foo(i32 %c)
+  br label %end
+
+end:
+  ret void
+}
+
+define i8 @PR23333(i8 addrspace(1)* %ptr) {
+; CHECK-LABEL: @PR23333(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 addrspace(1)* [[PTR:%.*]], null
+; CHECK-NEXT:    br i1 [[CMP]], label [[TAKEN:%.*]], label [[END:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    ret i8 1
+; CHECK:       end:
+; CHECK-NEXT:    ret i8 0
+;
+  %cmp = icmp eq i8 addrspace(1)* %ptr, null
+  br i1 %cmp, label %taken, label %end
+
+taken:
+  %cmp2 = icmp ne i8 addrspace(1)* %ptr, null
+  %res = select i1 %cmp2, i8 2, i8 1
+  ret i8 %res
+
+end:
+  ret i8 0
+}
+
+; We know the condition of the select is true based on a dominating condition.
+; Therefore, we can replace %cond with %len. 
+; TODO: len == 8 is known false in bb. This is handled by other passes, but should it be handled here? 
+
+define void @test4(i32 %len) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @bar(i32 [[LEN:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[LEN]], 4
+; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[B1:%.*]]
+; CHECK:       bb:
+; CHECK-NEXT:    [[CMP11:%.*]] = icmp eq i32 [[LEN]], 8
+; CHECK-NEXT:    br i1 [[CMP11]], label [[B0:%.*]], label [[B1]]
+; CHECK:       b0:
+; CHECK-NEXT:    call void @foo(i32 [[LEN]])
+; CHECK-NEXT:    br label [[B1]]
+; CHECK:       b1:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[LEN]], [[BB]] ], [ undef, [[B0]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    br label [[RET:%.*]]
+; CHECK:       ret:
+; CHECK-NEXT:    call void @foo(i32 [[TMP1]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = call i32 @bar(i32 %len);
+  %cmp = icmp ult i32 %len, 4
+  br i1 %cmp, label %bb, label %b1
+bb:
+  %cond = select i1 %cmp, i32 %len, i32 8
+  %cmp11 = icmp eq i32 %cond, 8
+  br i1 %cmp11, label %b0, label %b1
+
+b0:
+  call void @foo(i32 %len)
+  br label %b1
+
+b1:
+  %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ]
+  br label %ret
+
+ret:
+  call void @foo(i32 %1)
+  ret void
+}
+
+; A >u 10 implies A >u 9 is true.
+
+define void @test5(i32 %a) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10
+; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @foo(i32 30)
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp1 = icmp ugt i32 %a, 10
+  br i1 %cmp1, label %taken, label %end
+
+taken:
+  %cmp2 = icmp ugt i32 %a, 9
+  %c = select i1 %cmp2, i32 30, i32 0
+  call void @foo(i32 %c)
+  br label %end
+
+end:
+  ret void
+}
+
+declare void @foo(i32)
+declare i32 @bar(i32)
+
+define i32 @test_and(i32 %a, i32 %b) {
+; CHECK-LABEL: @test_and(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[TPATH:%.*]], label [[END:%.*]]
+; CHECK:       tpath:
+; CHECK-NEXT:    ret i32 313
+; CHECK:       end:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %cmp1 = icmp ne i32 %a, 0
+  %cmp2 = icmp ne i32 %b, 0
+  %and = and i1 %cmp1, %cmp2
+  br i1 %and, label %tpath, label %end
+
+tpath:
+  %cmp3 = icmp eq i32 %a, 0 ;; <-- implied false
+  %c = select i1 %cmp3, i32 0, i32 313
+  ret i32 %c
+
+end:
+  ret i32 0
+}
+
+; cmp1 and cmp2 are false on the 'fpath' path and thus cmp3 is true.
+
+define i32 @test_or1(i32 %a, i32 %b) {
+; CHECK-LABEL: @test_or1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    br i1 [[OR]], label [[END:%.*]], label [[FPATH:%.*]]
+; CHECK:       fpath:
+; CHECK-NEXT:    ret i32 37
+; CHECK:       end:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %cmp1 = icmp eq i32 %a, 0
+  %cmp2 = icmp eq i32 %b, 0
+  %or = or i1 %cmp1, %cmp2
+  br i1 %or, label %end, label %fpath
+
+fpath:
+  %cmp3 = icmp ne i32 %a, 0  ;; <-- implied true
+  %c = select i1 %cmp3, i32 37, i32 0
+  ret i32 %c
+
+end:
+  ret i32 0
+}
+
+; LHS ==> RHS by definition (true -> true)
+
+define void @test6(i32 %a, i32 %b) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @foo(i32 10)
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %end
+
+taken:
+  %c = select i1 %cmp1, i32 10, i32 0
+  call void @foo(i32 %c)
+  br label %end
+
+end:
+  ret void
+}
+
+; LHS ==> RHS by definition (false -> false)
+
+define void @test7(i32 %a, i32 %b) {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @foo(i32 11)
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %end, label %taken
+
+taken:
+  %c = select i1 %cmp1, i32 0, i32 11
+  call void @foo(i32 %c)
+  br label %end
+
+end:
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/select-or-cmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/select-or-cmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/select-or-cmp.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/select-or-cmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,339 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @select_or_icmp(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp(
+; CHECK-NEXT:    ret i32 [[Z:%.*]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define <2 x i8> @select_or_icmp_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @select_or_icmp_vec(
+; CHECK-NEXT:    ret <2 x i8> [[Z:%.*]]
+;
+  %A = icmp ne <2 x i8> %x, %z
+  %B = icmp ne <2 x i8> %y, %z
+  %C = or <2 x i1> %A, %B
+  %D = select <2 x i1> %C, <2 x i8> %z, <2 x i8> %x
+  ret <2 x i8> %D
+}
+
+define i32 @select_or_icmp2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp2(
+; CHECK-NEXT:    ret i32 [[Z:%.*]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %y
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_alt(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp_alt(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_alt2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp_alt2(
+; CHECK-NEXT:    ret i32 [[Y:%.*]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %y, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_inv_alt(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp_inv_alt(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+  %A = icmp ne i32 %z, %x
+  %B = icmp ne i32 %z, %y
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_or_inv_icmp_alt(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_inv_icmp_alt(
+; CHECK-NEXT:    ret i32 [[X:%.*]]
+;
+  %A = icmp ne i32 %z, %x
+  %B = icmp ne i32 %z, %y
+  %C = or i1 %B, %A
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define <2 x i8> @select_or_icmp_alt_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @select_or_icmp_alt_vec(
+; CHECK-NEXT:    ret <2 x i8> [[X:%.*]]
+;
+  %A = icmp ne <2 x i8> %x, %z
+  %B = icmp ne <2 x i8> %y, %z
+  %C = or <2 x i1> %A, %B
+  %D = select <2 x i1> %C, <2 x i8> %x, <2 x i8> %z
+  ret <2 x i8> %D
+}
+
+define i32 @select_or_inv_icmp(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_inv_icmp(
+; CHECK-NEXT:    ret i32 [[Z:%.*]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %B , %A
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_inv(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp_inv(
+; CHECK-NEXT:    ret i32 [[Z:%.*]]
+;
+  %A = icmp ne i32 %z, %x
+  %B = icmp ne i32 %z, %y
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+; Negative tests
+define i32 @select_and_icmp_pred_bad_1(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_pred_bad_1(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_pred_bad_2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_pred_bad_2(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_pred_bad_3(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_pred_bad_3(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_and_icmp_pred_bad_4(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_and_icmp_pred_bad_4(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_bad_true_val(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_or_icmp_bad_true_val(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[K:%.*]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %k, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_bad_false_val(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_or_icmp_bad_false_val(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[K:%.*]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %k
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_bad_op(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_or_icmp_bad_op(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[K:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X:%.*]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %k, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+
+define i32 @select_or_icmp_bad_op_2(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_or_icmp_bad_op_2(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[K:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[Z]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %k
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %z, i32 %x
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_alt_bad_1(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp_alt_bad_1(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_alt_bad_2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp_alt_bad_2(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_alt_bad_3(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp_alt_bad_3(
+; CHECK-NEXT:    [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp eq i32 %x, %z
+  %B = icmp eq i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_alt_bad_4(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @select_or_icmp_alt_bad_4(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = and i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_alt_bad_5(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_or_icmp_alt_bad_5(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[K:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %k
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_alt_bad_true_val(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_or_icmp_alt_bad_true_val(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[K:%.*]], i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %k, i32 %z
+  ret i32 %D
+}
+
+define i32 @select_or_icmp_alt_bad_false_val(i32 %x, i32 %y, i32 %z, i32 %k) {
+; CHECK-LABEL: @select_or_icmp_alt_bad_false_val(
+; CHECK-NEXT:    [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]]
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[A]], [[B]]
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[K:%.*]]
+; CHECK-NEXT:    ret i32 [[D]]
+;
+  %A = icmp ne i32 %x, %z
+  %B = icmp ne i32 %y, %z
+  %C = or i1 %A, %B
+  %D = select i1 %C, i32 %x, i32 %k
+  ret i32 %D
+}

Added: llvm/trunk/test/Transforms/InstSimplify/select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/select.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/select.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/select.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,566 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define <2 x i8> @vsel_tvec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @vsel_tvec(
+; CHECK-NEXT:    ret <2 x i8> %x
+;
+  %s = select <2 x i1><i1 true, i1 true>, <2 x i8> %x, <2 x i8> %y
+  ret <2 x i8> %s
+}
+
+define <2 x i8> @vsel_fvec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @vsel_fvec(
+; CHECK-NEXT:    ret <2 x i8> %y
+;
+  %s = select <2 x i1><i1 false, i1 false>, <2 x i8> %x, <2 x i8> %y
+  ret <2 x i8> %s
+}
+
+define <2 x i8> @vsel_mixedvec() {
+; CHECK-LABEL: @vsel_mixedvec(
+; CHECK-NEXT:    ret <2 x i8> <i8 0, i8 3>
+;
+  %s = select <2 x i1><i1 true, i1 false>, <2 x i8> <i8 0, i8 1>, <2 x i8> <i8 2, i8 3>
+  ret <2 x i8> %s
+}
+
+; FIXME: Allow for undef elements in a constant vector condition.
+
+define <3 x i8> @vsel_undef_true_op(<3 x i8> %x, <3 x i8> %y) {
+; CHECK-LABEL: @vsel_undef_true_op(
+; CHECK-NEXT:    [[S:%.*]] = select <3 x i1> <i1 true, i1 undef, i1 true>, <3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]
+; CHECK-NEXT:    ret <3 x i8> [[S]]
+;
+  %s = select <3 x i1><i1 1, i1 undef, i1 1>, <3 x i8> %x, <3 x i8> %y
+  ret <3 x i8> %s
+}
+
+define <3 x i4> @vsel_undef_false_op(<3 x i4> %x, <3 x i4> %y) {
+; CHECK-LABEL: @vsel_undef_false_op(
+; CHECK-NEXT:    [[S:%.*]] = select <3 x i1> <i1 false, i1 undef, i1 undef>, <3 x i4> [[X:%.*]], <3 x i4> [[Y:%.*]]
+; CHECK-NEXT:    ret <3 x i4> [[S]]
+;
+  %s = select <3 x i1><i1 0, i1 undef, i1 undef>, <3 x i4> %x, <3 x i4> %y
+  ret <3 x i4> %s
+}
+
+define i32 @test1(i32 %x) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    ret i32 %x
+;
+  %and = and i32 %x, 1
+  %cmp = icmp eq i32 %and, 0
+  %and1 = and i32 %x, -2
+  %and1.x = select i1 %cmp, i32 %and1, i32 %x
+  ret i32 %and1.x
+}
+
+define i32 @test2(i32 %x) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:    ret i32 %x
+;
+  %and = and i32 %x, 1
+  %cmp = icmp ne i32 %and, 0
+  %and1 = and i32 %x, -2
+  %and1.x = select i1 %cmp, i32 %x, i32 %and1
+  ret i32 %and1.x
+}
+
+define i32 @test3(i32 %x) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    [[AND1:%.*]] = and i32 %x, -2
+; CHECK-NEXT:    ret i32 [[AND1]]
+;
+  %and = and i32 %x, 1
+  %cmp = icmp ne i32 %and, 0
+  %and1 = and i32 %x, -2
+  %and1.x = select i1 %cmp, i32 %and1, i32 %x
+  ret i32 %and1.x
+}
+
+define i32 @test4(i32 %X) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %X, -2147483648
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %cmp = icmp slt i32 %X, 0
+  %or = or i32 %X, -2147483648
+  %cond = select i1 %cmp, i32 %X, i32 %or
+  ret i32 %cond
+}
+
+; Same as above, but the compare isn't canonical
+define i32 @test4noncanon(i32 %X) {
+; CHECK-LABEL: @test4noncanon(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %cmp = icmp sle i32 %X, -1
+  %or = or i32 %X, -2147483648
+  %cond = select i1 %cmp, i32 %X, i32 %or
+  ret i32 %cond
+}
+
+define i32 @test5(i32 %X) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:    ret i32 %X
+;
+  %cmp = icmp slt i32 %X, 0
+  %or = or i32 %X, -2147483648
+  %cond = select i1 %cmp, i32 %or, i32 %X
+  ret i32 %cond
+}
+
+define i32 @test6(i32 %X) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %X, 2147483647
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %cmp = icmp slt i32 %X, 0
+  %and = and i32 %X, 2147483647
+  %cond = select i1 %cmp, i32 %and, i32 %X
+  ret i32 %cond
+}
+
+define i32 @test7(i32 %X) {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT:    ret i32 %X
+;
+  %cmp = icmp slt i32 %X, 0
+  %and = and i32 %X, 2147483647
+  %cond = select i1 %cmp, i32 %X, i32 %and
+  ret i32 %cond
+}
+
+define i32 @test8(i32 %X) {
+; CHECK-LABEL: @test8(
+; CHECK-NEXT:    ret i32 %X
+;
+  %cmp = icmp sgt i32 %X, -1
+  %or = or i32 %X, -2147483648
+  %cond = select i1 %cmp, i32 %X, i32 %or
+  ret i32 %cond
+}
+
+define i32 @test9(i32 %X) {
+; CHECK-LABEL: @test9(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %X, -2147483648
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %cmp = icmp sgt i32 %X, -1
+  %or = or i32 %X, -2147483648
+  %cond = select i1 %cmp, i32 %or, i32 %X
+  ret i32 %cond
+}
+
+; Same as above, but the compare isn't canonical
+define i32 @test9noncanon(i32 %X) {
+; CHECK-LABEL: @test9noncanon(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %cmp = icmp sge i32 %X, 0
+  %or = or i32 %X, -2147483648
+  %cond = select i1 %cmp, i32 %or, i32 %X
+  ret i32 %cond
+}
+
+define i32 @test10(i32 %X) {
+; CHECK-LABEL: @test10(
+; CHECK-NEXT:    ret i32 %X
+;
+  %cmp = icmp sgt i32 %X, -1
+  %and = and i32 %X, 2147483647
+  %cond = select i1 %cmp, i32 %and, i32 %X
+  ret i32 %cond
+}
+
+define i32 @test11(i32 %X) {
+; CHECK-LABEL: @test11(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %X, 2147483647
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %cmp = icmp sgt i32 %X, -1
+  %and = and i32 %X, 2147483647
+  %cond = select i1 %cmp, i32 %X, i32 %and
+  ret i32 %cond
+}
+
+define <2 x i8> @test11vec(<2 x i8> %X) {
+; CHECK-LABEL: @test11vec(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> %X, <i8 127, i8 127>
+; CHECK-NEXT:    ret <2 x i8> [[AND]]
+;
+  %cmp = icmp sgt <2 x i8> %X, <i8 -1, i8 -1>
+  %and = and <2 x i8> %X, <i8 127, i8 127>
+  %sel = select <2 x i1> %cmp, <2 x i8> %X, <2 x i8> %and
+  ret <2 x i8> %sel
+}
+
+define i32 @test12(i32 %X) {
+; CHECK-LABEL: @test12(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %cmp = icmp ult i32 %X, 4
+  %and = and i32 %X, 3
+  %cond = select i1 %cmp, i32 %X, i32 %and
+  ret i32 %cond
+}
+
+; Same as above, but the compare isn't canonical
+define i32 @test12noncanon(i32 %X) {
+; CHECK-LABEL: @test12noncanon(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %cmp = icmp ule i32 %X, 3
+  %and = and i32 %X, 3
+  %cond = select i1 %cmp, i32 %X, i32 %and
+  ret i32 %cond
+}
+
+define i32 @test13(i32 %X) {
+; CHECK-LABEL: @test13(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %cmp = icmp ugt i32 %X, 3
+  %and = and i32 %X, 3
+  %cond = select i1 %cmp, i32 %and, i32 %X
+  ret i32 %cond
+}
+
+; Same as above, but the compare isn't canonical
+define i32 @test13noncanon(i32 %X) {
+; CHECK-LABEL: @test13noncanon(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %cmp = icmp uge i32 %X, 4
+  %and = and i32 %X, 3
+  %cond = select i1 %cmp, i32 %and, i32 %X
+  ret i32 %cond
+}
+
+define i32 @select_icmp_and_8_eq_0_or_8(i32 %x) {
+; CHECK-LABEL: @select_icmp_and_8_eq_0_or_8(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, 8
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %and = and i32 %x, 8
+  %cmp = icmp eq i32 %and, 0
+  %or = or i32 %x, 8
+  %sel = select i1 %cmp, i32 %or, i32 %x
+  ret i32 %sel
+}
+
+define i32 @select_icmp_and_8_eq_0_or_8_alt(i32 %x) {
+; CHECK-LABEL: @select_icmp_and_8_eq_0_or_8_alt(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, 8
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %and = and i32 %x, 8
+  %cmp = icmp ne i32 %and, 0
+  %or = or i32 %x, 8
+  %sel = select i1 %cmp, i32 %x, i32 %or
+  ret i32 %sel
+}
+
+define i32 @select_icmp_and_8_ne_0_or_8(i32 %x) {
+; CHECK-LABEL: @select_icmp_and_8_ne_0_or_8(
+; CHECK-NEXT:    ret i32 %x
+;
+  %and = and i32 %x, 8
+  %cmp = icmp ne i32 %and, 0
+  %or = or i32 %x, 8
+  %sel = select i1 %cmp, i32 %or, i32 %x
+  ret i32 %sel
+}
+
+define i32 @select_icmp_and_8_ne_0_or_8_alt(i32 %x) {
+; CHECK-LABEL: @select_icmp_and_8_ne_0_or_8_alt(
+; CHECK-NEXT:    ret i32 %x
+;
+  %and = and i32 %x, 8
+  %cmp = icmp eq i32 %and, 0
+  %or = or i32 %x, 8
+  %sel = select i1 %cmp, i32 %x, i32 %or
+  ret i32 %sel
+}
+
+define i32 @select_icmp_and_8_eq_0_and_not_8(i32 %x) {
+; CHECK-LABEL: @select_icmp_and_8_eq_0_and_not_8(
+; CHECK-NEXT:    [[AND1:%.*]] = and i32 %x, -9
+; CHECK-NEXT:    ret i32 [[AND1]]
+;
+  %and = and i32 %x, 8
+  %cmp = icmp eq i32 %and, 0
+  %and1 = and i32 %x, -9
+  %sel = select i1 %cmp, i32 %x, i32 %and1
+  ret i32 %sel
+}
+
+define i32 @select_icmp_and_8_eq_0_and_not_8_alt(i32 %x) {
+; CHECK-LABEL: @select_icmp_and_8_eq_0_and_not_8_alt(
+; CHECK-NEXT:    [[AND1:%.*]] = and i32 %x, -9
+; CHECK-NEXT:    ret i32 [[AND1]]
+;
+  %and = and i32 %x, 8
+  %cmp = icmp ne i32 %and, 0
+  %and1 = and i32 %x, -9
+  %sel = select i1 %cmp, i32 %and1, i32 %x
+  ret i32 %sel
+}
+
+define i32 @select_icmp_and_8_ne_0_and_not_8(i32 %x) {
+; CHECK-LABEL: @select_icmp_and_8_ne_0_and_not_8(
+; CHECK-NEXT:    ret i32 %x
+;
+  %and = and i32 %x, 8
+  %cmp = icmp ne i32 %and, 0
+  %and1 = and i32 %x, -9
+  %sel = select i1 %cmp, i32 %x, i32 %and1
+  ret i32 %sel
+}
+
+define i32 @select_icmp_and_8_ne_0_and_not_8_alt(i32 %x) {
+; CHECK-LABEL: @select_icmp_and_8_ne_0_and_not_8_alt(
+; CHECK-NEXT:    ret i32 %x
+;
+  %and = and i32 %x, 8
+  %cmp = icmp eq i32 %and, 0
+  %and1 = and i32 %x, -9
+  %sel = select i1 %cmp, i32 %and1, i32 %x
+  ret i32 %sel
+}
+
+; PR28466: https://llvm.org/bugs/show_bug.cgi?id=28466
+; Each of the previous 8 patterns has a variant that replaces the
+; 'and' with a 'trunc' and the icmp eq/ne with icmp slt/sgt.
+
+define i32 @select_icmp_trunc_8_ne_0_or_128(i32 %x) {
+; CHECK-LABEL: @select_icmp_trunc_8_ne_0_or_128(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, 128
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %trunc = trunc i32 %x to i8
+  %cmp = icmp sgt i8 %trunc, -1
+  %or = or i32 %x, 128
+  %sel = select i1 %cmp, i32 %or, i32 %x
+  ret i32 %sel
+}
+
+define i32 @select_icmp_trunc_8_ne_0_or_128_alt(i32 %x) {
+; CHECK-LABEL: @select_icmp_trunc_8_ne_0_or_128_alt(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, 128
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %trunc = trunc i32 %x to i8
+  %cmp = icmp slt i8 %trunc, 0
+  %or = or i32 %x, 128
+  %sel = select i1 %cmp, i32 %x, i32 %or
+  ret i32 %sel
+}
+
+define i32 @select_icmp_trunc_8_eq_0_or_128(i32 %x) {
+; CHECK-LABEL: @select_icmp_trunc_8_eq_0_or_128(
+; CHECK-NEXT:    ret i32 %x
+;
+  %trunc = trunc i32 %x to i8
+  %cmp = icmp slt i8 %trunc, 0
+  %or = or i32 %x, 128
+  %sel = select i1 %cmp, i32 %or, i32 %x
+  ret i32 %sel
+}
+
+define i32 @select_icmp_trunc_8_eq_0_or_128_alt(i32 %x) {
+; CHECK-LABEL: @select_icmp_trunc_8_eq_0_or_128_alt(
+; CHECK-NEXT:    ret i32 %x
+;
+  %trunc = trunc i32 %x to i8
+  %cmp = icmp sgt i8 %trunc, -1
+  %or = or i32 %x, 128
+  %sel = select i1 %cmp, i32 %x, i32 %or
+  ret i32 %sel
+}
+
+define i32 @select_icmp_trunc_8_eq_0_and_not_8(i32 %x) {
+; CHECK-LABEL: @select_icmp_trunc_8_eq_0_and_not_8(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, -9
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %trunc = trunc i32 %x to i4
+  %cmp = icmp sgt i4 %trunc, -1
+  %and = and i32 %x, -9
+  %sel = select i1 %cmp, i32 %x, i32 %and
+  ret i32 %sel
+}
+
+define i32 @select_icmp_trunc_8_eq_0_and_not_8_alt(i32 %x) {
+; CHECK-LABEL: @select_icmp_trunc_8_eq_0_and_not_8_alt(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, -9
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %trunc = trunc i32 %x to i4
+  %cmp = icmp slt i4 %trunc, 0
+  %and = and i32 %x, -9
+  %sel = select i1 %cmp, i32 %and, i32 %x
+  ret i32 %sel
+}
+
+define i32 @select_icmp_trunc_8_ne_0_and_not_8(i32 %x) {
+; CHECK-LABEL: @select_icmp_trunc_8_ne_0_and_not_8(
+; CHECK-NEXT:    ret i32 %x
+;
+  %trunc = trunc i32 %x to i4
+  %cmp = icmp slt i4 %trunc, 0
+  %and = and i32 %x, -9
+  %sel = select i1 %cmp, i32 %x, i32 %and
+  ret i32 %sel
+}
+
+define i32 @select_icmp_trunc_8_ne_0_and_not_8_alt(i32 %x) {
+; CHECK-LABEL: @select_icmp_trunc_8_ne_0_and_not_8_alt(
+; CHECK-NEXT:    ret i32 %x
+;
+  %trunc = trunc i32 %x to i4
+  %cmp = icmp sgt i4 %trunc, -1
+  %and = and i32 %x, -9
+  %sel = select i1 %cmp, i32 %and, i32 %x
+  ret i32 %sel
+}
+
+; Make sure that at least a few of the same patterns are repeated with vector types.
+
+define <2 x i32> @select_icmp_and_8_ne_0_and_not_8_vec(<2 x i32> %x) {
+; CHECK-LABEL: @select_icmp_and_8_ne_0_and_not_8_vec(
+; CHECK-NEXT:    ret <2 x i32> %x
+;
+  %and = and <2 x i32> %x, <i32 8, i32 8>
+  %cmp = icmp ne <2 x i32> %and, zeroinitializer
+  %and1 = and <2 x i32> %x, <i32 -9, i32 -9>
+  %sel = select <2 x i1> %cmp, <2 x i32> %x, <2 x i32> %and1
+  ret <2 x i32> %sel
+}
+
+define <2 x i32> @select_icmp_trunc_8_ne_0_and_not_8_alt_vec(<2 x i32> %x) {
+; CHECK-LABEL: @select_icmp_trunc_8_ne_0_and_not_8_alt_vec(
+; CHECK-NEXT:    ret <2 x i32> %x
+;
+  %trunc = trunc <2 x i32> %x to <2 x i4>
+  %cmp = icmp sgt <2 x i4> %trunc, <i4 -1, i4 -1>
+  %and = and <2 x i32> %x, <i32 -9, i32 -9>
+  %sel = select <2 x i1> %cmp, <2 x i32> %and, <2 x i32> %x
+  ret <2 x i32> %sel
+}
+
+; Insert a bit from x into y? This should be possible in InstCombine, but not InstSimplify?
+
+define i32 @select_icmp_x_and_8_eq_0_y_and_not_8(i32 %x, i32 %y) {
+; CHECK-LABEL: @select_icmp_x_and_8_eq_0_y_and_not_8(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 8
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[AND1:%.*]] = and i32 %y, -9
+; CHECK-NEXT:    [[Y_AND1:%.*]] = select i1 [[CMP]], i32 %y, i32 [[AND1]]
+; CHECK-NEXT:    ret i32 [[Y_AND1]]
+;
+  %and = and i32 %x, 8
+  %cmp = icmp eq i32 %and, 0
+  %and1 = and i32 %y, -9
+  %y.and1 = select i1 %cmp, i32 %y, i32 %and1
+  ret i32 %y.and1
+}
+
+define i64 @select_icmp_x_and_8_eq_0_y64_and_not_8(i32 %x, i64 %y) {
+; CHECK-LABEL: @select_icmp_x_and_8_eq_0_y64_and_not_8(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 8
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[AND1:%.*]] = and i64 %y, -9
+; CHECK-NEXT:    [[Y_AND1:%.*]] = select i1 [[CMP]], i64 %y, i64 [[AND1]]
+; CHECK-NEXT:    ret i64 [[Y_AND1]]
+;
+  %and = and i32 %x, 8
+  %cmp = icmp eq i32 %and, 0
+  %and1 = and i64 %y, -9
+  %y.and1 = select i1 %cmp, i64 %y, i64 %and1
+  ret i64 %y.and1
+}
+
+define i64 @select_icmp_x_and_8_ne_0_y64_and_not_8(i32 %x, i64 %y) {
+; CHECK-LABEL: @select_icmp_x_and_8_ne_0_y64_and_not_8(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 8
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[AND1:%.*]] = and i64 %y, -9
+; CHECK-NEXT:    [[AND1_Y:%.*]] = select i1 [[CMP]], i64 [[AND1]], i64 %y
+; CHECK-NEXT:    ret i64 [[AND1_Y]]
+;
+  %and = and i32 %x, 8
+  %cmp = icmp eq i32 %and, 0
+  %and1 = and i64 %y, -9
+  %and1.y = select i1 %cmp, i64 %and1, i64 %y
+  ret i64 %and1.y
+}
+
+; Don't crash on a pointer or aggregate type.
+
+define i32* @select_icmp_pointers(i32* %x, i32* %y) {
+; CHECK-LABEL: @select_icmp_pointers(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32* %x, null
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32* %x, i32* %y
+; CHECK-NEXT:    ret i32* [[SEL]]
+;
+  %cmp = icmp slt i32* %x, null
+  %sel = select i1 %cmp, i32* %x, i32* %y
+  ret i32* %sel
+}
+
+; If the condition is known, we don't need to select, but we're not
+; doing this fold here to avoid compile-time cost.
+
+declare void @llvm.assume(i1)
+
+define i8 @assume_sel_cond(i1 %cond, i8 %x, i8 %y) {
+; CHECK-LABEL: @assume_sel_cond(
+; CHECK-NEXT:    call void @llvm.assume(i1 %cond)
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 %cond, i8 %x, i8 %y
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  call void @llvm.assume(i1 %cond)
+  %sel = select i1 %cond, i8 %x, i8 %y
+  ret i8 %sel
+}
+
+define i8 @do_not_assume_sel_cond(i1 %cond, i8 %x, i8 %y) {
+; CHECK-LABEL: @do_not_assume_sel_cond(
+; CHECK-NEXT:    [[NOTCOND:%.*]] = icmp eq i1 %cond, false
+; CHECK-NEXT:    call void @llvm.assume(i1 [[NOTCOND]])
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 %cond, i8 %x, i8 %y
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %notcond = icmp eq i1 %cond, false
+  call void @llvm.assume(i1 %notcond)
+  %sel = select i1 %cond, i8 %x, i8 %y
+  ret i8 %sel
+}
+
+define i32* @select_icmp_eq_0_gep_operand(i32* %base, i64 %n) {
+; CHECK-LABEL: @select_icmp_eq_0_gep_operand(
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr
+; CHECK-NEXT: ret i32* [[GEP]]
+  %cond = icmp eq i64 %n, 0
+  %gep = getelementptr i32, i32* %base, i64 %n
+  %r = select i1 %cond, i32* %base, i32* %gep
+  ret i32* %r
+}
+
+define i32* @select_icmp_ne_0_gep_operand(i32* %base, i64 %n) {
+; CHECK-LABEL: @select_icmp_ne_0_gep_operand(
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr
+; CHECK-NEXT: ret i32* [[GEP]]
+  %cond = icmp ne i64 %n, 0
+  %gep = getelementptr i32, i32* %base, i64 %n
+  %r = select i1 %cond, i32* %gep, i32* %base
+  ret i32* %r
+}

Added: llvm/trunk/test/Transforms/InstSimplify/shift-128-kb.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/shift-128-kb.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/shift-128-kb.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/shift-128-kb.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; NOTE: Assertions have been autogenerated by update_test_checks.py
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+define zeroext i1 @_Z10isNegativemj(i64 %Val, i32 zeroext %IntegerBitWidth) {
+; CHECK-LABEL: @_Z10isNegativemj(
+; CHECK:         [[CONV:%.*]] = zext i32 %IntegerBitWidth to i64
+; CHECK-NEXT:    [[SUB:%.*]] = sub i64 128, [[CONV]]
+; CHECK-NEXT:    [[CONV1:%.*]] = trunc i64 [[SUB]] to i32
+; CHECK-NEXT:    [[CONV2:%.*]] = zext i64 %Val to i128
+; CHECK-NEXT:    [[SH_PROM:%.*]] = zext i32 [[CONV1]] to i128
+; CHECK-NEXT:    [[SHL:%.*]] = shl i128 [[CONV2]], [[SH_PROM]]
+; CHECK-NEXT:    [[SHR:%.*]] = ashr i128 [[SHL]], [[SH_PROM]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[SHR]], 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %conv = zext i32 %IntegerBitWidth to i64
+  %sub = sub i64 128, %conv
+  %conv1 = trunc i64 %sub to i32
+  %conv2 = zext i64 %Val to i128
+  %sh_prom = zext i32 %conv1 to i128
+  %shl = shl i128 %conv2, %sh_prom
+  %shr = ashr i128 %shl, %sh_prom
+  %cmp = icmp slt i128 %shr, 0
+  ret i1 %cmp
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/shift-knownbits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/shift-knownbits.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/shift-knownbits.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/shift-knownbits.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,190 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; If any bits of the shift amount are known to make it exceed or equal
+; the number of bits in the type, the shift causes undefined behavior.
+
+define i32 @shl_amount_is_known_bogus(i32 %a, i32 %b) {
+; CHECK-LABEL: @shl_amount_is_known_bogus(
+; CHECK-NEXT:    ret i32 undef
+;
+  %or = or i32 %b, 32
+  %shl = shl i32 %a, %or
+  ret i32 %shl
+}
+
+; Check some weird types and the other shift ops.
+
+define i31 @lshr_amount_is_known_bogus(i31 %a, i31 %b) {
+; CHECK-LABEL: @lshr_amount_is_known_bogus(
+; CHECK-NEXT:    ret i31 undef
+;
+  %or = or i31 %b, 31
+  %shr = lshr i31 %a, %or
+  ret i31 %shr
+}
+
+define i33 @ashr_amount_is_known_bogus(i33 %a, i33 %b) {
+; CHECK-LABEL: @ashr_amount_is_known_bogus(
+; CHECK-NEXT:    ret i33 undef
+;
+  %or = or i33 %b, 33
+  %shr = ashr i33 %a, %or
+  ret i33 %shr
+}
+
+
+; If all valid bits of the shift amount are known 0, there's no shift.
+; It doesn't matter if high bits are set because that would be undefined.
+; Therefore, the only possible valid result of these shifts is %a.
+
+define i16 @ashr_amount_is_zero(i16 %a, i16 %b) {
+; CHECK-LABEL: @ashr_amount_is_zero(
+; CHECK-NEXT:    ret i16 %a
+;
+  %and = and i16 %b, 65520 ; 0xfff0
+  %shr = ashr i16 %a, %and
+  ret i16 %shr
+}
+
+define i300 @lshr_amount_is_zero(i300 %a, i300 %b) {
+; CHECK-LABEL: @lshr_amount_is_zero(
+; CHECK-NEXT:    ret i300 %a
+;
+  %and = and i300 %b, 2048
+  %shr = lshr i300 %a, %and
+  ret i300 %shr
+}
+
+define i9 @shl_amount_is_zero(i9 %a, i9 %b) {
+; CHECK-LABEL: @shl_amount_is_zero(
+; CHECK-NEXT:    ret i9 %a
+;
+  %and = and i9 %b, 496 ; 0x1f0
+  %shl = shl i9 %a, %and
+  ret i9 %shl
+}
+
+
+; Verify that we've calculated the log2 boundary of valid bits correctly for a weird type.
+
+define i9 @shl_amount_is_not_known_zero(i9 %a, i9 %b) {
+; CHECK-LABEL: @shl_amount_is_not_known_zero(
+; CHECK-NEXT:    [[AND:%.*]] = and i9 %b, -8
+; CHECK-NEXT:    [[SHL:%.*]] = shl i9 %a, [[AND]]
+; CHECK-NEXT:    ret i9 [[SHL]]
+;
+  %and = and i9 %b, 504 ; 0x1f8
+  %shl = shl i9 %a, %and
+  ret i9 %shl
+}
+
+
+; For vectors, we need all scalar elements to meet the requirements to optimize.
+
+define <2 x i32> @ashr_vector_bogus(<2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: @ashr_vector_bogus(
+; CHECK-NEXT:    ret <2 x i32> undef
+;
+  %or = or <2 x i32> %b, <i32 32, i32 32>
+  %shr = ashr <2 x i32> %a, %or
+  ret <2 x i32> %shr
+}
+
+; FIXME: This is undef, but computeKnownBits doesn't handle the union.
+define <2 x i32> @shl_vector_bogus(<2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: @shl_vector_bogus(
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i32> %b, <i32 32, i32 64>
+; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i32> %a, [[OR]]
+; CHECK-NEXT:    ret <2 x i32> [[SHL]]
+;
+  %or = or <2 x i32> %b, <i32 32, i32 64>
+  %shl = shl <2 x i32> %a, %or
+  ret <2 x i32> %shl
+}
+
+define <2 x i32> @lshr_vector_zero(<2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: @lshr_vector_zero(
+; CHECK-NEXT:    ret <2 x i32> %a
+;
+  %and = and <2 x i32> %b, <i32 64, i32 256>
+  %shr = lshr <2 x i32> %a, %and
+  ret <2 x i32> %shr
+}
+
+; Make sure that weird vector types work too.
+define <2 x i15> @shl_vector_zero(<2 x i15> %a, <2 x i15> %b) {
+; CHECK-LABEL: @shl_vector_zero(
+; CHECK-NEXT:    ret <2 x i15> %a
+;
+  %and = and <2 x i15> %b, <i15 1024, i15 1024>
+  %shl = shl <2 x i15> %a, %and
+  ret <2 x i15> %shl
+}
+
+define <2 x i32> @shl_vector_for_real(<2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: @shl_vector_for_real(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i32> %b, <i32 3, i32 3>
+; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i32> %a, [[AND]]
+; CHECK-NEXT:    ret <2 x i32> [[SHL]]
+;
+  %and = and <2 x i32> %b, <i32 3, i32 3> ; a necessary mask op
+  %shl = shl <2 x i32> %a, %and
+  ret <2 x i32> %shl
+}
+
+
+; We calculate the valid bits of the shift using log2, and log2 of 1 (the type width) is 0.
+; That should be ok. Either the shift amount is 0 or invalid (1), so we can always return %a.
+
+define i1 @shl_i1(i1 %a, i1 %b) {
+; CHECK-LABEL: @shl_i1(
+; CHECK-NEXT:    ret i1 %a
+;
+  %shl = shl i1 %a, %b
+  ret i1 %shl
+}
+
+; Simplify count leading/trailing zeros to zero if all valid bits are shifted out.
+
+declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone
+declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
+declare <2 x i8> @llvm.cttz.v2i8(<2 x i8>, i1) nounwind readnone
+declare <2 x i8> @llvm.ctlz.v2i8(<2 x i8>, i1) nounwind readnone
+
+define i32 @lshr_ctlz_zero_is_undef(i32 %x) {
+; CHECK-LABEL: @lshr_ctlz_zero_is_undef(
+; CHECK-NEXT:    ret i32 0
+;
+  %ct = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
+  %sh = lshr i32 %ct, 5
+  ret i32 %sh
+}
+
+define i32 @lshr_cttz_zero_is_undef(i32 %x) {
+; CHECK-LABEL: @lshr_cttz_zero_is_undef(
+; CHECK-NEXT:    ret i32 0
+;
+  %ct = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %sh = lshr i32 %ct, 5
+  ret i32 %sh
+}
+
+define <2 x i8> @lshr_ctlz_zero_is_undef_splat_vec(<2 x i8> %x) {
+; CHECK-LABEL: @lshr_ctlz_zero_is_undef_splat_vec(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %ct = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %x, i1 true)
+  %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
+  ret <2 x i8> %sh
+}
+
+define <2 x i8> @lshr_cttz_zero_is_undef_splat_vec(<2 x i8> %x) {
+; CHECK-LABEL: @lshr_cttz_zero_is_undef_splat_vec(
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %ct = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %x, i1 true)
+  %sh = lshr <2 x i8> %ct, <i8 3, i8 3>
+  ret <2 x i8> %sh
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/shift.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/shift.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/shift.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/shift.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,239 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i47 @shl_by_0(i47 %A) {
+; CHECK-LABEL: @shl_by_0(
+; CHECK-NEXT:    ret i47 [[A:%.*]]
+;
+  %B = shl i47 %A, 0
+  ret i47 %B
+}
+
+define i41 @shl_0(i41 %X) {
+; CHECK-LABEL: @shl_0(
+; CHECK-NEXT:    ret i41 0
+;
+  %B = shl i41 0, %X
+  ret i41 %B
+}
+
+define <2 x i41> @shl_0_vec_undef_elt(<2 x i41> %X) {
+; CHECK-LABEL: @shl_0_vec_undef_elt(
+; CHECK-NEXT:    ret <2 x i41> zeroinitializer
+;
+  %B = shl <2 x i41> <i41 0, i41 undef>, %X
+  ret <2 x i41> %B
+}
+
+define i41 @ashr_by_0(i41 %A) {
+; CHECK-LABEL: @ashr_by_0(
+; CHECK-NEXT:    ret i41 [[A:%.*]]
+;
+  %B = ashr i41 %A, 0
+  ret i41 %B
+}
+
+define i39 @ashr_0(i39 %X) {
+; CHECK-LABEL: @ashr_0(
+; CHECK-NEXT:    ret i39 0
+;
+  %B = ashr i39 0, %X
+  ret i39 %B
+}
+
+define <2 x i141> @ashr_0_vec_undef_elt(<2 x i141> %X) {
+; CHECK-LABEL: @ashr_0_vec_undef_elt(
+; CHECK-NEXT:    ret <2 x i141> zeroinitializer
+;
+  %B = shl <2 x i141> <i141 undef, i141 0>, %X
+  ret <2 x i141> %B
+}
+
+define i55 @lshr_by_bitwidth(i55 %A) {
+; CHECK-LABEL: @lshr_by_bitwidth(
+; CHECK-NEXT:    ret i55 undef
+;
+  %B = lshr i55 %A, 55
+  ret i55 %B
+}
+
+define i32 @shl_by_bitwidth(i32 %A) {
+; CHECK-LABEL: @shl_by_bitwidth(
+; CHECK-NEXT:    ret i32 undef
+;
+  %B = shl i32 %A, 32
+  ret i32 %B
+}
+
+define <4 x i32> @lshr_by_bitwidth_splat(<4 x i32> %A) {
+; CHECK-LABEL: @lshr_by_bitwidth_splat(
+; CHECK-NEXT:    ret <4 x i32> undef
+;
+  %B = lshr <4 x i32> %A, <i32 32, i32 32, i32 32, i32 32>     ;; shift all bits out
+  ret <4 x i32> %B
+}
+
+define <4 x i32> @lshr_by_0_splat(<4 x i32> %A) {
+; CHECK-LABEL: @lshr_by_0_splat(
+; CHECK-NEXT:    ret <4 x i32> [[A:%.*]]
+;
+  %B = lshr <4 x i32> %A, zeroinitializer
+  ret <4 x i32> %B
+}
+
+define <4 x i32> @shl_by_bitwidth_splat(<4 x i32> %A) {
+; CHECK-LABEL: @shl_by_bitwidth_splat(
+; CHECK-NEXT:    ret <4 x i32> undef
+;
+  %B = shl <4 x i32> %A, <i32 32, i32 32, i32 32, i32 32>     ;; shift all bits out
+  ret <4 x i32> %B
+}
+
+define i32 @ashr_undef() {
+; CHECK-LABEL: @ashr_undef(
+; CHECK-NEXT:    ret i32 0
+;
+  %B = ashr i32 undef, 2  ;; top two bits must be equal, so not undef
+  ret i32 %B
+}
+
+define i32 @ashr_undef_variable_shift_amount(i32 %A) {
+; CHECK-LABEL: @ashr_undef_variable_shift_amount(
+; CHECK-NEXT:    ret i32 0
+;
+  %B = ashr i32 undef, %A  ;; top %A bits must be equal, so not undef
+  ret i32 %B
+}
+
+define i32 @ashr_all_ones(i32 %A) {
+; CHECK-LABEL: @ashr_all_ones(
+; CHECK-NEXT:    ret i32 -1
+;
+  %B = ashr i32 -1, %A
+  ret i32 %B
+}
+
+define <3 x i8> @ashr_all_ones_vec_with_undef_elts(<3 x i8> %x, <3 x i8> %y) {
+; CHECK-LABEL: @ashr_all_ones_vec_with_undef_elts(
+; CHECK-NEXT:    ret <3 x i8> <i8 -1, i8 -1, i8 -1>
+;
+  %sh = ashr <3 x i8> <i8 undef, i8 -1, i8 undef>, %y
+  ret <3 x i8> %sh
+}
+
+define i8 @lshr_by_sext_bool(i1 %x, i8 %y) {
+; CHECK-LABEL: @lshr_by_sext_bool(
+; CHECK-NEXT:    ret i8 [[Y:%.*]]
+;
+  %s = sext i1 %x to i8
+  %r = lshr i8 %y, %s
+  ret i8 %r
+}
+
+define <2 x i8> @lshr_by_sext_bool_vec(<2 x i1> %x, <2 x i8> %y) {
+; CHECK-LABEL: @lshr_by_sext_bool_vec(
+; CHECK-NEXT:    ret <2 x i8> [[Y:%.*]]
+;
+  %s = sext <2 x i1> %x to <2 x i8>
+  %r = lshr <2 x i8> %y, %s
+  ret <2 x i8> %r
+}
+
+define i8 @ashr_by_sext_bool(i1 %x, i8 %y) {
+; CHECK-LABEL: @ashr_by_sext_bool(
+; CHECK-NEXT:    ret i8 [[Y:%.*]]
+;
+  %s = sext i1 %x to i8
+  %r = ashr i8 %y, %s
+  ret i8 %r
+}
+
+define <2 x i8> @ashr_by_sext_bool_vec(<2 x i1> %x, <2 x i8> %y) {
+; CHECK-LABEL: @ashr_by_sext_bool_vec(
+; CHECK-NEXT:    ret <2 x i8> [[Y:%.*]]
+;
+  %s = sext <2 x i1> %x to <2 x i8>
+  %r = ashr <2 x i8> %y, %s
+  ret <2 x i8> %r
+}
+
+define i8 @shl_by_sext_bool(i1 %x, i8 %y) {
+; CHECK-LABEL: @shl_by_sext_bool(
+; CHECK-NEXT:    ret i8 [[Y:%.*]]
+;
+  %s = sext i1 %x to i8
+  %r = shl i8 %y, %s
+  ret i8 %r
+}
+
+define <2 x i8> @shl_by_sext_bool_vec(<2 x i1> %x, <2 x i8> %y) {
+; CHECK-LABEL: @shl_by_sext_bool_vec(
+; CHECK-NEXT:    ret <2 x i8> [[Y:%.*]]
+;
+  %s = sext <2 x i1> %x to <2 x i8>
+  %r = shl <2 x i8> %y, %s
+  ret <2 x i8> %r
+}
+
+define i64 @shl_or_shr(i32 %a, i32 %b) {
+; CHECK-LABEL: @shl_or_shr(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[A:%.*]] to i64
+; CHECK-NEXT:    ret i64 [[TMP1]]
+;
+  %tmp1 = zext i32 %a to i64
+  %tmp2 = zext i32 %b to i64
+  %tmp3 = shl nuw i64 %tmp1, 32
+  %tmp4 = or i64 %tmp2, %tmp3
+  %tmp5 = lshr i64 %tmp4, 32
+  ret i64 %tmp5
+}
+
+; Since shift count of shl is smaller than the size of %b, OR cannot be eliminated.
+define i64 @shl_or_shr2(i32 %a, i32 %b) {
+; CHECK-LABEL: @shl_or_shr2(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[A:%.*]] to i64
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i32 [[B:%.*]] to i64
+; CHECK-NEXT:    [[TMP3:%.*]] = shl nuw i64 [[TMP1]], 31
+; CHECK-NEXT:    [[TMP4:%.*]] = or i64 [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    [[TMP5:%.*]] = lshr i64 [[TMP4]], 31
+; CHECK-NEXT:    ret i64 [[TMP5]]
+;
+  %tmp1 = zext i32 %a to i64
+  %tmp2 = zext i32 %b to i64
+  %tmp3 = shl nuw i64 %tmp1, 31
+  %tmp4 = or i64 %tmp2, %tmp3
+  %tmp5 = lshr i64 %tmp4, 31
+  ret i64 %tmp5
+}
+
+; Unit test for vector integer
+define <2 x i64> @shl_or_shr1v(<2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: @shl_or_shr1v(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
+; CHECK-NEXT:    ret <2 x i64> [[TMP1]]
+;
+  %tmp1 = zext <2 x i32> %a to <2 x i64>
+  %tmp2 = zext <2 x i32> %b to <2 x i64>
+  %tmp3 = shl nuw <2 x i64> %tmp1, <i64 32, i64 32>
+  %tmp4 = or <2 x i64> %tmp3, %tmp2
+  %tmp5 = lshr <2 x i64> %tmp4, <i64 32, i64 32>
+  ret <2 x i64> %tmp5
+}
+
+; Negative unit test for vector integer
+define <2 x i64> @shl_or_shr2v(<2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: @shl_or_shr2v(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext <2 x i32> [[A:%.*]] to <2 x i64>
+; CHECK-NEXT:    [[TMP2:%.*]] = zext <2 x i32> [[B:%.*]] to <2 x i64>
+; CHECK-NEXT:    [[TMP3:%.*]] = shl nuw <2 x i64> [[TMP1]], <i64 31, i64 31>
+; CHECK-NEXT:    [[TMP4:%.*]] = or <2 x i64> [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    [[TMP5:%.*]] = lshr <2 x i64> [[TMP4]], <i64 31, i64 31>
+; CHECK-NEXT:    ret <2 x i64> [[TMP5]]
+;
+  %tmp1 = zext <2 x i32> %a to <2 x i64>
+  %tmp2 = zext <2 x i32> %b to <2 x i64>
+  %tmp3 = shl nuw <2 x i64> %tmp1, <i64 31, i64 31>
+  %tmp4 = or <2 x i64> %tmp2, %tmp3
+  %tmp5 = lshr <2 x i64> %tmp4, <i64 31, i64 31>
+  ret <2 x i64> %tmp5
+}

Added: llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,431 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @foo(i32 %x) {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:    [[O:%.*]] = and i32 %x, 1
+; CHECK-NEXT:    [[N:%.*]] = add i32 [[O]], -1
+; CHECK-NEXT:    ret i32 [[N]]
+;
+  %o = and i32 %x, 1
+  %n = add i32 %o, -1
+  %t = ashr i32 %n, 17
+  ret i32 %t
+}
+
+define i1 @exact_lshr_eq_both_zero(i8 %a) {
+; CHECK-LABEL: @exact_lshr_eq_both_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = lshr exact i8 0, %a
+  %cmp = icmp eq i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_eq_both_zero(i8 %a) {
+; CHECK-LABEL: @exact_ashr_eq_both_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr exact i8 0, %a
+  %cmp = icmp eq i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @nonexact_ashr_eq_both_zero(i8 %a) {
+; CHECK-LABEL: @nonexact_ashr_eq_both_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr i8 0, %a
+  %cmp = icmp eq i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @exact_lshr_ne_both_zero(i8 %a) {
+; CHECK-LABEL: @exact_lshr_ne_both_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr exact i8 0, %a
+  %cmp = icmp ne i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_ne_both_zero(i8 %a) {
+; CHECK-LABEL: @exact_ashr_ne_both_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr exact i8 0, %a
+  %cmp = icmp ne i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @nonexact_lshr_ne_both_zero(i8 %a) {
+; CHECK-LABEL: @nonexact_lshr_ne_both_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr i8 0, %a
+  %cmp = icmp ne i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @nonexact_ashr_ne_both_zero(i8 %a) {
+; CHECK-LABEL: @nonexact_ashr_ne_both_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr i8 0, %a
+  %cmp = icmp ne i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @exact_lshr_eq_last_zero(i8 %a) {
+; CHECK-LABEL: @exact_lshr_eq_last_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr exact i8 128, %a
+  %cmp = icmp eq i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_eq_last_zero(i8 %a) {
+; CHECK-LABEL: @exact_ashr_eq_last_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr exact i8 -128, %a
+  %cmp = icmp eq i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @nonexact_lshr_eq_both_zero(i8 %a) {
+; CHECK-LABEL: @nonexact_lshr_eq_both_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = lshr i8 0, %a
+  %cmp = icmp eq i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @exact_lshr_ne_last_zero(i8 %a) {
+; CHECK-LABEL: @exact_lshr_ne_last_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = lshr exact i8 128, %a
+  %cmp = icmp ne i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_ne_last_zero(i8 %a) {
+; CHECK-LABEL: @exact_ashr_ne_last_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr exact i8 -128, %a
+  %cmp = icmp ne i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @nonexact_lshr_eq_last_zero(i8 %a) {
+; CHECK-LABEL: @nonexact_lshr_eq_last_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr i8 128, %a
+  %cmp = icmp eq i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @nonexact_ashr_eq_last_zero(i8 %a) {
+; CHECK-LABEL: @nonexact_ashr_eq_last_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr i8 -128, %a
+  %cmp = icmp eq i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @nonexact_lshr_ne_last_zero(i8 %a) {
+; CHECK-LABEL: @nonexact_lshr_ne_last_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = lshr i8 128, %a
+  %cmp = icmp ne i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @nonexact_ashr_ne_last_zero(i8 %a) {
+; CHECK-LABEL: @nonexact_ashr_ne_last_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr i8 -128, %a
+  %cmp = icmp ne i8 %shr, 0
+  ret i1 %cmp
+}
+
+define i1 @lshr_eq_first_zero(i8 %a) {
+; CHECK-LABEL: @lshr_eq_first_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr i8 0, %a
+  %cmp = icmp eq i8 %shr, 2
+  ret i1 %cmp
+}
+
+define i1 @ashr_eq_first_zero(i8 %a) {
+; CHECK-LABEL: @ashr_eq_first_zero(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr i8 0, %a
+  %cmp = icmp eq i8 %shr, 2
+  ret i1 %cmp
+}
+
+define i1 @lshr_ne_first_zero(i8 %a) {
+; CHECK-LABEL: @lshr_ne_first_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = lshr i8 0, %a
+  %cmp = icmp ne i8 %shr, 2
+  ret i1 %cmp
+}
+
+define i1 @ashr_ne_first_zero(i8 %a) {
+; CHECK-LABEL: @ashr_ne_first_zero(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr i8 0, %a
+  %cmp = icmp ne i8 %shr, 2
+  ret i1 %cmp
+}
+
+define i1 @ashr_eq_both_minus1(i8 %a) {
+; CHECK-LABEL: @ashr_eq_both_minus1(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr i8 -1, %a
+  %cmp = icmp eq i8 %shr, -1
+  ret i1 %cmp
+}
+
+define i1 @ashr_ne_both_minus1(i8 %a) {
+; CHECK-LABEL: @ashr_ne_both_minus1(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr i8 -1, %a
+  %cmp = icmp ne i8 %shr, -1
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_eq_both_minus1(i8 %a) {
+; CHECK-LABEL: @exact_ashr_eq_both_minus1(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr exact i8 -1, %a
+  %cmp = icmp eq i8 %shr, -1
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_ne_both_minus1(i8 %a) {
+; CHECK-LABEL: @exact_ashr_ne_both_minus1(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr exact i8 -1, %a
+  %cmp = icmp ne i8 %shr, -1
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_eq_opposite_msb(i8 %a) {
+; CHECK-LABEL: @exact_ashr_eq_opposite_msb(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr exact i8 -128, %a
+  %cmp = icmp eq i8 %shr, 1
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_eq_noexactlog(i8 %a) {
+; CHECK-LABEL: @exact_ashr_eq_noexactlog(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr exact i8 -90, %a
+  %cmp = icmp eq i8 %shr, -30
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_ne_opposite_msb(i8 %a) {
+; CHECK-LABEL: @exact_ashr_ne_opposite_msb(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr exact i8 -128, %a
+  %cmp = icmp ne i8 %shr, 1
+  ret i1 %cmp
+}
+
+define i1 @ashr_eq_opposite_msb(i8 %a) {
+; CHECK-LABEL: @ashr_eq_opposite_msb(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr i8 -128, %a
+  %cmp = icmp eq i8 %shr, 1
+  ret i1 %cmp
+}
+
+define i1 @ashr_ne_opposite_msb(i8 %a) {
+; CHECK-LABEL: @ashr_ne_opposite_msb(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr i8 -128, %a
+  %cmp = icmp ne i8 %shr, 1
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_eq_shift_gt(i8 %a) {
+; CHECK-LABEL: @exact_ashr_eq_shift_gt(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr exact i8 -2, %a
+  %cmp = icmp eq i8 %shr, -8
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_ne_shift_gt(i8 %a) {
+; CHECK-LABEL: @exact_ashr_ne_shift_gt(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr exact i8 -2, %a
+  %cmp = icmp ne i8 %shr, -8
+  ret i1 %cmp
+}
+
+define i1 @nonexact_ashr_eq_shift_gt(i8 %a) {
+; CHECK-LABEL: @nonexact_ashr_eq_shift_gt(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = ashr i8 -2, %a
+  %cmp = icmp eq i8 %shr, -8
+  ret i1 %cmp
+}
+
+define i1 @nonexact_ashr_ne_shift_gt(i8 %a) {
+; CHECK-LABEL: @nonexact_ashr_ne_shift_gt(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr i8 -2, %a
+  %cmp = icmp ne i8 %shr, -8
+  ret i1 %cmp
+}
+
+define i1 @exact_lshr_eq_shift_gt(i8 %a) {
+; CHECK-LABEL: @exact_lshr_eq_shift_gt(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr exact i8 2, %a
+  %cmp = icmp eq i8 %shr, 8
+  ret i1 %cmp
+}
+
+define i1 @exact_lshr_ne_shift_gt(i8 %a) {
+; CHECK-LABEL: @exact_lshr_ne_shift_gt(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = lshr exact i8 2, %a
+  %cmp = icmp ne i8 %shr, 8
+  ret i1 %cmp
+}
+
+define i1 @nonexact_lshr_eq_shift_gt(i8 %a) {
+; CHECK-LABEL: @nonexact_lshr_eq_shift_gt(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr i8 2, %a
+  %cmp = icmp eq i8 %shr, 8
+  ret i1 %cmp
+}
+
+define i1 @nonexact_lshr_ne_shift_gt(i8 %a) {
+; CHECK-LABEL: @nonexact_lshr_ne_shift_gt(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr i8 2, %a
+  %cmp = icmp ne i8 %shr, 8
+  ret i1 %cmp
+}
+
+define i1 @exact_ashr_ne_noexactlog(i8 %a) {
+; CHECK-LABEL: @exact_ashr_ne_noexactlog(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = ashr exact i8 -90, %a
+  %cmp = icmp ne i8 %shr, -30
+  ret i1 %cmp
+}
+
+define i1 @exact_lshr_eq_noexactlog(i8 %a) {
+; CHECK-LABEL: @exact_lshr_eq_noexactlog(
+; CHECK-NEXT:    ret i1 false
+;
+  %shr = lshr exact i8 90, %a
+  %cmp = icmp eq i8 %shr, 30
+  ret i1 %cmp
+}
+
+define i1 @exact_lshr_ne_noexactlog(i8 %a) {
+; CHECK-LABEL: @exact_lshr_ne_noexactlog(
+; CHECK-NEXT:    ret i1 true
+;
+  %shr = lshr exact i8 90, %a
+  %cmp = icmp ne i8 %shr, 30
+  ret i1 %cmp
+}
+
+define i32 @exact_lshr_lowbit(i32 %shiftval) {
+; CHECK-LABEL: @exact_lshr_lowbit(
+; CHECK-NEXT:    ret i32 7
+;
+  %shr = lshr exact i32 7, %shiftval
+  ret i32 %shr
+}
+
+define i32 @exact_ashr_lowbit(i32 %shiftval) {
+; CHECK-LABEL: @exact_ashr_lowbit(
+; CHECK-NEXT:    ret i32 7
+;
+  %shr = ashr exact i32 7, %shiftval
+  ret i32 %shr
+}
+
+define i32 @ashr_zero(i32 %shiftval) {
+; CHECK-LABEL: @ashr_zero(
+; CHECK-NEXT:    ret i32 0
+;
+  %shr = ashr i32 0, %shiftval
+  ret i32 %shr
+}
+
+define i257 @ashr_minus1(i257 %shiftval) {
+; CHECK-LABEL: @ashr_minus1(
+; CHECK-NEXT:    ret i257 -1
+;
+  %shr = ashr i257 -1, %shiftval
+  ret i257 %shr
+}
+
+define <2 x i4097> @ashr_zero_vec(<2 x i4097> %shiftval) {
+; CHECK-LABEL: @ashr_zero_vec(
+; CHECK-NEXT:    ret <2 x i4097> zeroinitializer
+;
+  %shr = ashr <2 x i4097> zeroinitializer, %shiftval
+  ret <2 x i4097> %shr
+}
+
+define <2 x i64> @ashr_minus1_vec(<2 x i64> %shiftval) {
+; CHECK-LABEL: @ashr_minus1_vec(
+; CHECK-NEXT:    ret <2 x i64> <i64 -1, i64 -1>
+;
+  %shr = ashr <2 x i64> <i64 -1, i64 -1>, %shiftval
+  ret <2 x i64> %shr
+}
+
+define <2 x i4> @ashr_zero_minus1_vec(<2 x i4> %shiftval) {
+; CHECK-LABEL: @ashr_zero_minus1_vec(
+; CHECK-NEXT:    ret <2 x i4> <i4 0, i4 -1>
+;
+  %shr = ashr <2 x i4> <i4 0, i4 -1>, %shiftval
+  ret <2 x i4> %shr
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/shr-scalar-vector-consistency.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/shr-scalar-vector-consistency.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/shr-scalar-vector-consistency.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/shr-scalar-vector-consistency.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; This tests checks optimization consistency for scalar and vector code.
+; If m_Zero() is able to match a vector undef, but not a scalar undef,
+; the two cases will simplify differently.
+
+define i32 @test_scalar(i32 %a, i1 %b) {
+; CHECK-LABEL: @test_scalar(
+; CHECK-NEXT:    ret i32 undef
+;
+  %c = sext i1 %b to i32
+  %d = ashr i32 undef, %c
+  ret i32 %d
+}
+
+define <2 x i32> @test_vector(<2 x i32> %a, <2 x i1> %b) {
+; CHECK-LABEL: @test_vector(
+; CHECK-NEXT:    ret <2 x i32> undef
+;
+  %c = sext <2 x i1> %b to <2 x i32>
+  %d = ashr <2 x i32> undef, %c
+  ret <2 x i32> %d
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/shufflevector.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/shufflevector.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/shufflevector.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/shufflevector.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,249 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define <4 x i32> @const_folding(<4 x i32> %x) {
+; CHECK-LABEL: @const_folding(
+; CHECK-NEXT:    ret <4 x i32> zeroinitializer
+;
+  %shuf = shufflevector <4 x i32> %x, <4 x i32> zeroinitializer, <4 x i32> <i32 5, i32 4, i32 5, i32 4>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @const_folding1(<4 x i32> %x) {
+; CHECK-LABEL: @const_folding1(
+; CHECK-NEXT:    ret <4 x i32> <i32 5, i32 5, i32 5, i32 5>
+;
+  %shuf = shufflevector <4 x i32> <i32 5, i32 4, i32 5, i32 4>, <4 x i32> %x, <4 x i32> zeroinitializer
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @const_folding_negative(<3 x i32> %x) {
+; CHECK-LABEL: @const_folding_negative(
+; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <3 x i32> [[X:%.*]], <3 x i32> zeroinitializer, <4 x i32> <i32 2, i32 4, i32 5, i32 4>
+; CHECK-NEXT:    ret <4 x i32> [[SHUF]]
+;
+  %shuf = shufflevector <3 x i32> %x, <3 x i32> zeroinitializer, <4 x i32> <i32 2, i32 4, i32 5, i32 4>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @splat_operand(<4 x i32> %x) {
+; CHECK-LABEL: @splat_operand(
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
+; CHECK-NEXT:    ret <4 x i32> [[SPLAT]]
+;
+  %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
+  %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <4 x i32> <i32 0, i32 3, i32 2, i32 1>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @splat_operand1(<4 x i32> %x, <4 x i32> %y) {
+; CHECK-LABEL: @splat_operand1(
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> zeroinitializer
+; CHECK-NEXT:    ret <4 x i32> [[SPLAT]]
+;
+  %splat = shufflevector <4 x i32> %x, <4 x i32> %y, <4 x i32> zeroinitializer
+  %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <4 x i32> <i32 0, i32 3, i32 2, i32 1>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @splat_operand2(<4 x i32> %x, <4 x i32> %y) {
+; CHECK-LABEL: @splat_operand2(
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
+; CHECK-NEXT:    ret <4 x i32> [[SPLAT]]
+;
+  %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
+  %shuf = shufflevector <4 x i32> %splat, <4 x i32> %y, <4 x i32> <i32 0, i32 3, i32 2, i32 1>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @splat_operand3(<4 x i32> %x) {
+; CHECK-LABEL: @splat_operand3(
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
+; CHECK-NEXT:    ret <4 x i32> [[SPLAT]]
+;
+  %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
+  %shuf = shufflevector <4 x i32> zeroinitializer, <4 x i32> %splat, <4 x i32> <i32 7, i32 6, i32 5, i32 5>
+  ret <4 x i32> %shuf
+}
+
+define <8 x i32> @splat_operand_negative(<4 x i32> %x) {
+; CHECK-LABEL: @splat_operand_negative(
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
+; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i32> [[SPLAT]], <4 x i32> undef, <8 x i32> <i32 0, i32 3, i32 2, i32 1, i32 undef, i32 undef, i32 undef, i32 undef>
+; CHECK-NEXT:    ret <8 x i32> [[SHUF]]
+;
+  %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
+  %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <8 x i32> <i32 0, i32 3, i32 2, i32 1, i32 undef, i32 undef, i32 undef, i32 undef>
+  ret <8 x i32> %shuf
+}
+
+define <4 x i32> @splat_operand_negative2(<4 x i32> %x, <4 x i32> %y) {
+; CHECK-LABEL: @splat_operand_negative2(
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
+; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i32> [[SPLAT]], <4 x i32> [[Y:%.*]], <4 x i32> <i32 0, i32 3, i32 4, i32 1>
+; CHECK-NEXT:    ret <4 x i32> [[SHUF]]
+;
+  %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
+  %shuf = shufflevector <4 x i32> %splat, <4 x i32> %y, <4 x i32> <i32 0, i32 3, i32 4, i32 1>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @splat_operand_negative3(<4 x i32> %x, <4 x i32> %y) {
+; CHECK-LABEL: @splat_operand_negative3(
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer
+; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i32> [[Y:%.*]], <4 x i32> [[SPLAT]], <4 x i32> <i32 0, i32 3, i32 4, i32 1>
+; CHECK-NEXT:    ret <4 x i32> [[SHUF]]
+;
+  %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer
+  %shuf = shufflevector <4 x i32> %y, <4 x i32> %splat, <4 x i32> <i32 0, i32 3, i32 4, i32 1>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @splat_operand_negative4(<4 x i32> %x) {
+; CHECK-LABEL: @splat_operand_negative4(
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> <i32 2, i32 undef, i32 2, i32 undef>
+; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i32> [[SPLAT]], <4 x i32> undef, <4 x i32> <i32 0, i32 2, i32 undef, i32 undef>
+; CHECK-NEXT:    ret <4 x i32> [[SHUF]]
+;
+  %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 2, i32 undef, i32 2, i32 undef>
+  %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <4 x i32> <i32 0, i32 2, i32 undef, i32 undef>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @undef_mask(<4 x i32> %x) {
+; CHECK-LABEL: @undef_mask(
+; CHECK-NEXT:    ret <4 x i32> undef
+;
+  %shuf = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> undef
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @undef_mask_1(<4 x i32> %x, <4 x i32> %y) {
+; CHECK-LABEL: @undef_mask_1(
+; CHECK-NEXT:    ret <4 x i32> undef
+;
+  %shuf = shufflevector <4 x i32> %x, <4 x i32> %y, <4 x i32> undef
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @identity_mask_0(<4 x i32> %x) {
+; CHECK-LABEL: @identity_mask_0(
+; CHECK-NEXT:    ret <4 x i32> [[X:%.*]]
+;
+  %shuf = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @identity_mask_1(<4 x i32> %x) {
+; CHECK-LABEL: @identity_mask_1(
+; CHECK-NEXT:    ret <4 x i32> [[X:%.*]]
+;
+  %shuf = shufflevector <4 x i32> undef, <4 x i32> %x, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @pseudo_identity_mask(<4 x i32> %x) {
+; CHECK-LABEL: @pseudo_identity_mask(
+; CHECK-NEXT:    ret <4 x i32> [[X:%.*]]
+;
+  %shuf = shufflevector <4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @not_identity_mask(<4 x i32> %x) {
+; CHECK-LABEL: @not_identity_mask(
+; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[X]], <4 x i32> <i32 0, i32 1, i32 2, i32 6>
+; CHECK-NEXT:    ret <4 x i32> [[SHUF]]
+;
+  %shuf = shufflevector <4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 0, i32 1, i32 2, i32 6>
+  ret <4 x i32> %shuf
+}
+
+; TODO: Should we simplify if the mask has an undef element?
+
+define <4 x i32> @possible_identity_mask(<4 x i32> %x) {
+; CHECK-LABEL: @possible_identity_mask(
+; CHECK-NEXT:    [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
+; CHECK-NEXT:    ret <4 x i32> [[SHUF]]
+;
+  %shuf = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @const_operand(<4 x i32> %x) {
+; CHECK-LABEL: @const_operand(
+; CHECK-NEXT:    ret <4 x i32> <i32 42, i32 45, i32 44, i32 43>
+;
+  %shuf = shufflevector <4 x i32> <i32 42, i32 43, i32 44, i32 45>, <4 x i32> %x, <4 x i32> <i32 0, i32 3, i32 2, i32 1>
+  ret <4 x i32> %shuf
+}
+
+define <4 x i32> @merge(<4 x i32> %x) {
+; CHECK-LABEL: @merge(
+; CHECK-NEXT:    ret <4 x i32> [[X:%.*]]
+;
+  %lower = shufflevector <4 x i32> %x, <4 x i32> undef, <2 x i32> <i32 1, i32 0>
+  %upper = shufflevector <4 x i32> %x, <4 x i32> undef, <2 x i32> <i32 2, i32 3>
+  %merged = shufflevector <2 x i32> %upper, <2 x i32> %lower, <4 x i32> <i32 3, i32 2, i32 0, i32 1>
+  ret <4 x i32> %merged
+}
+
+; This crosses lanes from the source op.
+
+define <4 x i32> @not_merge(<4 x i32> %x) {
+; CHECK-LABEL: @not_merge(
+; CHECK-NEXT:    [[L:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <2 x i32> <i32 0, i32 1>
+; CHECK-NEXT:    [[U:%.*]] = shufflevector <4 x i32> [[X]], <4 x i32> undef, <2 x i32> <i32 2, i32 3>
+; CHECK-NEXT:    [[MERGED:%.*]] = shufflevector <2 x i32> [[U]], <2 x i32> [[L]], <4 x i32> <i32 3, i32 2, i32 0, i32 1>
+; CHECK-NEXT:    ret <4 x i32> [[MERGED]]
+;
+  %l = shufflevector <4 x i32> %x, <4 x i32> undef, <2 x i32> <i32 0, i32 1>
+  %u = shufflevector <4 x i32> %x, <4 x i32> undef, <2 x i32> <i32 2, i32 3>
+  %merged = shufflevector <2 x i32> %u, <2 x i32> %l, <4 x i32> <i32 3, i32 2, i32 0, i32 1>
+  ret <4 x i32> %merged
+}
+
+define <8 x double> @extract_and_concat(<8 x double> %x) {
+; CHECK-LABEL: @extract_and_concat(
+; CHECK-NEXT:    ret <8 x double> [[X:%.*]]
+;
+  %s1 = shufflevector <8 x double> %x, <8 x double> undef, <2 x i32> <i32 0, i32 1>
+  %s2 = shufflevector <8 x double> %x, <8 x double> undef, <2 x i32> <i32 2, i32 3>
+  %s3 = shufflevector <8 x double> %x, <8 x double> undef, <2 x i32> <i32 4, i32 5>
+  %s4 = shufflevector <8 x double> %x, <8 x double> undef, <2 x i32> <i32 6, i32 7>
+  %s5 = shufflevector <2 x double> %s1, <2 x double> %s2, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %s6 = shufflevector <2 x double> %s3, <2 x double> %s4, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %s7 = shufflevector <4 x double> %s5, <4 x double> %s6, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  ret <8 x double> %s7
+}
+
+; This case has intermediate lane crossings.
+
+define <8 x i64> @PR30630(<8 x i64> %x) {
+; CHECK-LABEL: @PR30630(
+; CHECK-NEXT:    ret <8 x i64> [[X:%.*]]
+;
+  %s1 = shufflevector <8 x i64> %x, <8 x i64> undef, <2 x i32> <i32 0, i32 4>
+  %s2 = shufflevector <8 x i64> %x, <8 x i64> undef, <2 x i32> <i32 1, i32 5>
+  %s3 = shufflevector <8 x i64> %x, <8 x i64> undef, <2 x i32> <i32 2, i32 6>
+  %s4 = shufflevector <8 x i64> %x, <8 x i64> undef, <2 x i32> <i32 3, i32 7>
+  %s5 = shufflevector <2 x i64> %s1, <2 x i64> %s2, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %s6 = shufflevector <2 x i64> %s3, <2 x i64> %s4, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %s7 = shufflevector <4 x i64> %s5, <4 x i64> %s6, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
+  ret <8 x i64> %s7
+}
+
+; This case covers internal canonicalization of shuffles with one constant input vector.
+
+;FIXME: Another issue exposed here, this whole function could be simplified to:
+;         ret <2 x float> zeroinitializer
+define <2 x float> @PR32872(<2 x float> %x) {
+; CHECK-LABEL: @PR32872(
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> zeroinitializer, <4 x i32> <i32 2, i32 2, i32 0, i32 1>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <4 x float> zeroinitializer, <4 x float> [[TMP1]], <2 x i32> <i32 4, i32 5>
+; CHECK-NEXT:    ret <2 x float> [[TMP4]]
+;
+  %tmp1 = shufflevector <2 x float> %x, <2 x float> zeroinitializer, <4 x i32> <i32 2, i32 2, i32 0, i32 1>
+  %tmp4 = shufflevector <4 x float> zeroinitializer, <4 x float> %tmp1, <2 x i32> <i32 4, i32 5>
+  ret <2 x float> %tmp4
+}

Added: llvm/trunk/test/Transforms/InstSimplify/signed-div-rem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/signed-div-rem.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/signed-div-rem.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/signed-div-rem.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,354 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @sdiv_sext_big_divisor(i8 %x) {
+; CHECK-LABEL: @sdiv_sext_big_divisor(
+; CHECK-NEXT:    ret i32 0
+;
+  %conv = sext i8 %x to i32
+  %div = sdiv i32 %conv, 129
+  ret i32 %div
+}
+
+define i32 @not_sdiv_sext_big_divisor(i8 %x) {
+; CHECK-LABEL: @not_sdiv_sext_big_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = sext i8 %x to i32
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[CONV]], 128
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %conv = sext i8 %x to i32
+  %div = sdiv i32 %conv, 128
+  ret i32 %div
+}
+
+define i32 @sdiv_sext_small_divisor(i8 %x) {
+; CHECK-LABEL: @sdiv_sext_small_divisor(
+; CHECK-NEXT:    ret i32 0
+;
+  %conv = sext i8 %x to i32
+  %div = sdiv i32 %conv, -129
+  ret i32 %div
+}
+
+define i32 @not_sdiv_sext_small_divisor(i8 %x) {
+; CHECK-LABEL: @not_sdiv_sext_small_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = sext i8 %x to i32
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[CONV]], -128
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %conv = sext i8 %x to i32
+  %div = sdiv i32 %conv, -128
+  ret i32 %div
+}
+
+define i32 @sdiv_zext_big_divisor(i8 %x) {
+; CHECK-LABEL: @sdiv_zext_big_divisor(
+; CHECK-NEXT:    ret i32 0
+;
+  %conv = zext i8 %x to i32
+  %div = sdiv i32 %conv, 256
+  ret i32 %div
+}
+
+define i32 @not_sdiv_zext_big_divisor(i8 %x) {
+; CHECK-LABEL: @not_sdiv_zext_big_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 %x to i32
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[CONV]], 255
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %conv = zext i8 %x to i32
+  %div = sdiv i32 %conv, 255
+  ret i32 %div
+}
+
+define i32 @sdiv_zext_small_divisor(i8 %x) {
+; CHECK-LABEL: @sdiv_zext_small_divisor(
+; CHECK-NEXT:    ret i32 0
+;
+  %conv = zext i8 %x to i32
+  %div = sdiv i32 %conv, -256
+  ret i32 %div
+}
+
+define i32 @not_sdiv_zext_small_divisor(i8 %x) {
+; CHECK-LABEL: @not_sdiv_zext_small_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 %x to i32
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[CONV]], -255
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %conv = zext i8 %x to i32
+  %div = sdiv i32 %conv, -255
+  ret i32 %div
+}
+
+define i32 @sdiv_dividend_known_smaller_than_pos_divisor_clear_bits(i32 %x) {
+; CHECK-LABEL: @sdiv_dividend_known_smaller_than_pos_divisor_clear_bits(
+; CHECK-NEXT:    ret i32 0
+;
+  %and = and i32 %x, 253
+  %div = sdiv i32 %and, 254
+  ret i32 %div
+}
+
+define i32 @not_sdiv_dividend_known_smaller_than_pos_divisor_clear_bits(i32 %x) {
+; CHECK-LABEL: @not_sdiv_dividend_known_smaller_than_pos_divisor_clear_bits(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 253
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[AND]], 253
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %and = and i32 %x, 253
+  %div = sdiv i32 %and, 253
+  ret i32 %div
+}
+
+define i32 @sdiv_dividend_known_smaller_than_neg_divisor_clear_bits(i32 %x) {
+; CHECK-LABEL: @sdiv_dividend_known_smaller_than_neg_divisor_clear_bits(
+; CHECK-NEXT:    ret i32 0
+;
+  %and = and i32 %x, 253
+  %div = sdiv i32 %and, -254
+  ret i32 %div
+}
+
+define i32 @not_sdiv_dividend_known_smaller_than_neg_divisor_clear_bits(i32 %x) {
+; CHECK-LABEL: @not_sdiv_dividend_known_smaller_than_neg_divisor_clear_bits(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 253
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[AND]], -253
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %and = and i32 %x, 253
+  %div = sdiv i32 %and, -253
+  ret i32 %div
+}
+
+define i32 @sdiv_dividend_known_smaller_than_pos_divisor_set_bits(i32 %x) {
+; CHECK-LABEL: @sdiv_dividend_known_smaller_than_pos_divisor_set_bits(
+; CHECK-NEXT:    ret i32 0
+;
+  %or = or i32 %x, -253
+  %div = sdiv i32 %or, 254
+  ret i32 %div
+}
+
+define i32 @not_sdiv_dividend_known_smaller_than_pos_divisor_set_bits(i32 %x) {
+; CHECK-LABEL: @not_sdiv_dividend_known_smaller_than_pos_divisor_set_bits(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, -253
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[OR]], 253
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %or = or i32 %x, -253
+  %div = sdiv i32 %or, 253
+  ret i32 %div
+}
+
+define i32 @sdiv_dividend_known_smaller_than_neg_divisor_set_bits(i32 %x) {
+; CHECK-LABEL: @sdiv_dividend_known_smaller_than_neg_divisor_set_bits(
+; CHECK-NEXT:    ret i32 0
+;
+  %or = or i32 %x, -253
+  %div = sdiv i32 %or, -254
+  ret i32 %div
+}
+
+define i32 @not_sdiv_dividend_known_smaller_than_neg_divisor_set_bits(i32 %x) {
+; CHECK-LABEL: @not_sdiv_dividend_known_smaller_than_neg_divisor_set_bits(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, -253
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[OR]], -253
+; CHECK-NEXT:    ret i32 [[DIV]]
+;
+  %or = or i32 %x, -253
+  %div = sdiv i32 %or, -253
+  ret i32 %div
+}
+
+define i32 @srem_sext_big_divisor(i8 %x) {
+; CHECK-LABEL: @srem_sext_big_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = sext i8 %x to i32
+; CHECK-NEXT:    ret i32 [[CONV]]
+;
+  %conv = sext i8 %x to i32
+  %rem = srem i32 %conv, 129
+  ret i32 %rem
+}
+
+define i32 @not_srem_sext_big_divisor(i8 %x) {
+; CHECK-LABEL: @not_srem_sext_big_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = sext i8 %x to i32
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[CONV]], 128
+; CHECK-NEXT:    ret i32 [[REM]]
+;
+  %conv = sext i8 %x to i32
+  %rem = srem i32 %conv, 128
+  ret i32 %rem
+}
+
+define i32 @srem_sext_small_divisor(i8 %x) {
+; CHECK-LABEL: @srem_sext_small_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = sext i8 %x to i32
+; CHECK-NEXT:    ret i32 [[CONV]]
+;
+  %conv = sext i8 %x to i32
+  %rem = srem i32 %conv, -129
+  ret i32 %rem
+}
+
+define i32 @not_srem_sext_small_divisor(i8 %x) {
+; CHECK-LABEL: @not_srem_sext_small_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = sext i8 %x to i32
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[CONV]], -128
+; CHECK-NEXT:    ret i32 [[REM]]
+;
+  %conv = sext i8 %x to i32
+  %rem = srem i32 %conv, -128
+  ret i32 %rem
+}
+
+define i32 @srem_zext_big_divisor(i8 %x) {
+; CHECK-LABEL: @srem_zext_big_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 %x to i32
+; CHECK-NEXT:    ret i32 [[CONV]]
+;
+  %conv = zext i8 %x to i32
+  %rem = srem i32 %conv, 256
+  ret i32 %rem
+}
+
+define i32 @not_srem_zext_big_divisor(i8 %x) {
+; CHECK-LABEL: @not_srem_zext_big_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 %x to i32
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[CONV]], 255
+; CHECK-NEXT:    ret i32 [[REM]]
+;
+  %conv = zext i8 %x to i32
+  %rem = srem i32 %conv, 255
+  ret i32 %rem
+}
+
+define i32 @srem_zext_small_divisor(i8 %x) {
+; CHECK-LABEL: @srem_zext_small_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 %x to i32
+; CHECK-NEXT:    ret i32 [[CONV]]
+;
+  %conv = zext i8 %x to i32
+  %rem = srem i32 %conv, -256
+  ret i32 %rem
+}
+
+define i32 @not_srem_zext_small_divisor(i8 %x) {
+; CHECK-LABEL: @not_srem_zext_small_divisor(
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 %x to i32
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[CONV]], -255
+; CHECK-NEXT:    ret i32 [[REM]]
+;
+  %conv = zext i8 %x to i32
+  %rem = srem i32 %conv, -255
+  ret i32 %rem
+}
+
+define i32 @srem_dividend_known_smaller_than_pos_divisor_clear_bits(i32 %x) {
+; CHECK-LABEL: @srem_dividend_known_smaller_than_pos_divisor_clear_bits(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 253
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %and = and i32 %x, 253
+  %rem = srem i32 %and, 254
+  ret i32 %rem
+}
+
+define i32 @not_srem_dividend_known_smaller_than_pos_divisor_clear_bits(i32 %x) {
+; CHECK-LABEL: @not_srem_dividend_known_smaller_than_pos_divisor_clear_bits(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 253
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[AND]], 253
+; CHECK-NEXT:    ret i32 [[REM]]
+;
+  %and = and i32 %x, 253
+  %rem = srem i32 %and, 253
+  ret i32 %rem
+}
+
+define i32 @srem_dividend_known_smaller_than_neg_divisor_clear_bits(i32 %x) {
+; CHECK-LABEL: @srem_dividend_known_smaller_than_neg_divisor_clear_bits(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 253
+; CHECK-NEXT:    ret i32 [[AND]]
+;
+  %and = and i32 %x, 253
+  %rem = srem i32 %and, -254
+  ret i32 %rem
+}
+
+define i32 @not_srem_dividend_known_smaller_than_neg_divisor_clear_bits(i32 %x) {
+; CHECK-LABEL: @not_srem_dividend_known_smaller_than_neg_divisor_clear_bits(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 253
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[AND]], -253
+; CHECK-NEXT:    ret i32 [[REM]]
+;
+  %and = and i32 %x, 253
+  %rem = srem i32 %and, -253
+  ret i32 %rem
+}
+
+define i32 @srem_dividend_known_smaller_than_pos_divisor_set_bits(i32 %x) {
+; CHECK-LABEL: @srem_dividend_known_smaller_than_pos_divisor_set_bits(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, -253
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %or = or i32 %x, -253
+  %rem = srem i32 %or, 254
+  ret i32 %rem
+}
+
+define i32 @not_srem_dividend_known_smaller_than_pos_divisor_set_bits(i32 %x) {
+; CHECK-LABEL: @not_srem_dividend_known_smaller_than_pos_divisor_set_bits(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, -253
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[OR]], 253
+; CHECK-NEXT:    ret i32 [[REM]]
+;
+  %or = or i32 %x, -253
+  %rem = srem i32 %or, 253
+  ret i32 %rem
+}
+
+define i32 @srem_dividend_known_smaller_than_neg_divisor_set_bits(i32 %x) {
+; CHECK-LABEL: @srem_dividend_known_smaller_than_neg_divisor_set_bits(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, -253
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %or = or i32 %x, -253
+  %rem = srem i32 %or, -254
+  ret i32 %rem
+}
+
+define i32 @not_srem_dividend_known_smaller_than_neg_divisor_set_bits(i32 %x) {
+; CHECK-LABEL: @not_srem_dividend_known_smaller_than_neg_divisor_set_bits(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 %x, -253
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[OR]], -253
+; CHECK-NEXT:    ret i32 [[REM]]
+;
+  %or = or i32 %x, -253
+  %rem = srem i32 %or, -253
+  ret i32 %rem
+}
+
+; Make sure that we're handling the minimum signed constant correctly - can't fold this.
+
+define i16 @sdiv_min_dividend(i8 %x) {
+; CHECK-LABEL: @sdiv_min_dividend(
+; CHECK-NEXT:    [[Z:%.*]] = zext i8 %x to i16
+; CHECK-NEXT:    [[D:%.*]] = sdiv i16 -32768, [[Z]]
+; CHECK-NEXT:    ret i16 [[D]]
+;
+  %z = zext i8 %x to i16
+  %d = sdiv i16 -32768, %z
+  ret i16 %d
+}
+
+; If the quotient is known to not be -32768, then this can fold.
+
+define i16 @sdiv_min_divisor(i8 %x) {
+; CHECK-LABEL: @sdiv_min_divisor(
+; CHECK-NEXT:    ret i16 0
+;
+  %z = zext i8 %x to i16
+  %d = sdiv i16 %z, -32768
+  ret i16 %d
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/simplify-nested-bitcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/simplify-nested-bitcast.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/simplify-nested-bitcast.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/simplify-nested-bitcast.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt -always-inline -S %s | FileCheck %s
+%0 = type { i64, i64, i8 addrspace(1)*, i8 addrspace(1)* }
+%__aaa_struct = type { { i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(1)* }, %0, [17 x i8], { i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(1)* }, %0, [18 x i8] }
+%struct.__block_descriptor = type { i64, i64 }
+%struct.__block_literal_generic = type { i8*, i32, i32, i8*, %struct.__block_descriptor addrspace(1)* }
+
+ at __aaa_struct_ptr = external addrspace(1) global %__aaa_struct
+ at __aaa_const_init = constant %__aaa_struct { { i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(1)* } { i8** null, i32 1342177280, i32 0, i8* bitcast (i32 (i8 addrspace(4)*, i32 addrspace(1)*)* @bl0_block_invoke to i8*), %struct.__block_descriptor addrspace(1)* bitcast (%0 addrspace(1)* getelementptr inbounds (%__aaa_struct, %__aaa_struct addrspace(1)* @__aaa_struct_ptr, i32 0, i32 1) to %struct.__block_descriptor addrspace(1)*) }, %0 { i64 0, i64 32, i8 addrspace(1)* getelementptr inbounds (%__aaa_struct, %__aaa_struct addrspace(1)* @__aaa_struct_ptr, i32 0, i32 2, i32 0), i8 addrspace(1)* null }, [17 x i8] c"bl0_block_invoke\00", { i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(1)* } { i8** null, i32 1342177280, i32 0, i8* bitcast (i32 (i8 addrspace(4)*, i32 addrspace(1)*)* @__f1_block_invoke to i8*), %struct.__block_descriptor addrspace(1)* bitcast (%0 addrspace(1)* getelementptr inbounds (%__aaa_struct, %__aaa_struct addrspace(1)* @__aaa_struct_ptr, i32 0, i32 4) to %struct.__block_descriptor addrspace(1)*) }, %0 { i64 0, i64 32, i8 addrspace(1)* getelementptr inbounds (%__aaa_struct, %__aaa_struct addrspace(1)* @__aaa_struct_ptr, i32 0, i32 5, i32 0), i8 addrspace(1)* null }, [18 x i8] c"__f1_block_invoke\00" }
+
+; Function Attrs: alwaysinline norecurse nounwind readonly
+define i32 @bl0_block_invoke(i8 addrspace(4)* nocapture readnone, i32 addrspace(1)* nocapture readonly) #0 {
+entry:
+  %2 = load i32, i32 addrspace(1)* %1, align 4
+  %mul = shl nsw i32 %2, 1
+  ret i32 %mul
+}
+
+; Function Attrs: alwaysinline nounwind
+define i32 @f0(i32 addrspace(1)*, i32 (i32 addrspace(1)*) addrspace(4)*) #1 {
+entry:
+  %block.literal = bitcast i32 (i32 addrspace(1)*) addrspace(4)* %1 to %struct.__block_literal_generic addrspace(4)*
+  %2 = getelementptr inbounds %struct.__block_literal_generic, %struct.__block_literal_generic addrspace(4)* %block.literal, i64 0, i32 3
+  %3 = bitcast i32 (i32 addrspace(1)*) addrspace(4)* %1 to i8 addrspace(4)*
+  %4 = bitcast i8* addrspace(4)* %2 to i32 (i8 addrspace(4)*, i32 addrspace(1)*)* addrspace(4)*
+  %5 = load i32 (i8 addrspace(4)*, i32 addrspace(1)*)*, i32 (i8 addrspace(4)*, i32 addrspace(1)*)* addrspace(4)* %4, align 8
+  %call = tail call i32 %5(i8 addrspace(4)* %3, i32 addrspace(1)* %0) #2
+  ret i32 %call
+}
+
+; CHECK-LABEL: define void @f1
+; CHECK: %1 = load i32 (i8 addrspace(4)*, i32 addrspace(1)*)*, i32 (i8 addrspace(4)*, i32 addrspace(1)*)* addrspace(4)* bitcast (i8* addrspace(4)* getelementptr (%__aaa_struct, %__aaa_struct addrspace(4)* addrspacecast (%__aaa_struct addrspace(1)* @__aaa_struct_ptr to %__aaa_struct addrspace(4)*), i64 0, i32 0, i32 3) to i32 (i8 addrspace(4)*, i32 addrspace(1)*)* addrspace(4)*), align 8
+
+; Function Attrs: alwaysinline nounwind
+define void @f1(i32 addrspace(1)*) #1 {
+entry:
+  %call = tail call i32 @f0(i32 addrspace(1)* %0, i32 (i32 addrspace(1)*) addrspace(4)* addrspacecast (i32 (i32 addrspace(1)*) addrspace(1)* bitcast (%__aaa_struct addrspace(1)* @__aaa_struct_ptr to i32 (i32 addrspace(1)*) addrspace(1)*) to i32 (i32 addrspace(1)*) addrspace(4)*)) #3
+  store i32 %call, i32 addrspace(1)* %0, align 4
+  %call1 = tail call i32 @f0(i32 addrspace(1)* %0, i32 (i32 addrspace(1)*) addrspace(4)* addrspacecast (i32 (i32 addrspace(1)*) addrspace(1)* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(1)* } addrspace(1)* getelementptr inbounds (%__aaa_struct, %__aaa_struct addrspace(1)* @__aaa_struct_ptr, i32 0, i32 3) to i32 (i32 addrspace(1)*) addrspace(1)*) to i32 (i32 addrspace(1)*) addrspace(4)*)) #3
+  store i32 %call1, i32 addrspace(1)* %0, align 4
+  ret void
+}
+
+; Function Attrs: alwaysinline norecurse nounwind readonly
+define i32 @__f1_block_invoke(i8 addrspace(4)* nocapture readnone, i32 addrspace(1)* nocapture readonly) #0 {
+entry:
+  %2 = load i32, i32 addrspace(1)* %1, align 4
+  %add = add nsw i32 %2, 1
+  ret i32 %add
+}
+
+attributes #0 = { alwaysinline norecurse nounwind readonly }
+attributes #1 = { alwaysinline nounwind }
+attributes #2 = { nobuiltin nounwind }
+attributes #3 = { nobuiltin }

Added: llvm/trunk/test/Transforms/InstSimplify/srem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/srem.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/srem.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/srem.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,69 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @negated_operand(i32 %x) {
+; CHECK-LABEL: @negated_operand(
+; CHECK-NEXT:    ret i32 0
+;
+  %negx = sub i32 0, %x
+  %rem = srem i32 %negx, %x
+  ret i32 %rem
+}
+
+define <2 x i32> @negated_operand_commute_vec(<2 x i32> %x) {
+; CHECK-LABEL: @negated_operand_commute_vec(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %negx = sub <2 x i32> zeroinitializer, %x
+  %rem = srem <2 x i32> %negx, %x
+  ret <2 x i32> %rem
+}
+
+define i32 @knownnegation(i32 %x, i32 %y) {
+; CHECK-LABEL: @knownnegation(
+; CHECK-NEXT:    ret i32 0
+;
+  %xy = sub i32 %x, %y
+  %yx = sub i32 %y, %x
+  %rem = srem i32 %xy, %yx
+  ret i32 %rem
+}
+
+define <2 x i32> @knownnegation_commute_vec(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @knownnegation_commute_vec(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %xy = sub <2 x i32> %x, %y
+  %yx = sub <2 x i32> %y, %x
+  %rem = srem <2 x i32> %xy, %yx
+  ret <2 x i32> %rem
+}
+
+define <3 x i32> @negated_operand_vec_undef(<3 x i32> %x) {
+; CHECK-LABEL: @negated_operand_vec_undef(
+; CHECK-NEXT:    ret <3 x i32> zeroinitializer
+;
+  %negx = sub <3 x i32> <i32 0, i32 undef, i32 0>, %x
+  %rem = srem <3 x i32> %negx, %x
+  ret <3 x i32> %rem
+}
+
+define <2 x i32> @negated_operand_vec_nonsplat(<2 x i32> %x) {
+; CHECK-LABEL: @negated_operand_vec_nonsplat(
+; CHECK-NEXT:    [[NEGX:%.*]] = sub <2 x i32> <i32 0, i32 1>, [[X:%.*]]
+; CHECK-NEXT:    [[REM:%.*]] = srem <2 x i32> [[NEGX]], [[X]]
+; CHECK-NEXT:    ret <2 x i32> [[REM]]
+;
+  %negx = sub <2 x i32> <i32 0, i32 1>, %x ; not 0, don't fold
+  %rem = srem <2 x i32> %negx, %x
+  ret <2 x i32> %rem
+}
+
+define i32 @negated_operand_commute(i32 %x) {
+; CHECK-LABEL: @negated_operand_commute(
+; CHECK-NEXT:    ret i32 0
+;
+  %negx = sub i32 0, %x
+  %rem = srem i32 %x, %negx
+  ret i32 %rem
+}

Added: llvm/trunk/test/Transforms/InstSimplify/sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/sub.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/sub.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/sub.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @sub_self(i32 %A) {
+; CHECK-LABEL: @sub_self(
+; CHECK-NEXT:    ret i32 0
+;
+  %B = sub i32 %A, %A
+  ret i32 %B
+}
+
+define <2 x i32> @sub_self_vec(<2 x i32> %A) {
+; CHECK-LABEL: @sub_self_vec(
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %B = sub <2 x i32> %A, %A
+  ret <2 x i32> %B
+}
+
+define i32 @sub_zero(i32 %A) {
+; CHECK-LABEL: @sub_zero(
+; CHECK-NEXT:    ret i32 [[A:%.*]]
+;
+  %B = sub i32 %A, 0
+  ret i32 %B
+}
+
+define <2 x i32> @sub_zero_vec(<2 x i32> %A) {
+; CHECK-LABEL: @sub_zero_vec(
+; CHECK-NEXT:    ret <2 x i32> [[A:%.*]]
+;
+  %B = sub <2 x i32> %A, <i32 0, i32 undef>
+  ret <2 x i32> %B
+}
+
+define i32 @neg_neg(i32 %A) {
+; CHECK-LABEL: @neg_neg(
+; CHECK-NEXT:    ret i32 [[A:%.*]]
+;
+  %B = sub i32 0, %A
+  %C = sub i32 0, %B
+  ret i32 %C
+}
+
+define <2 x i32> @neg_neg_vec(<2 x i32> %A) {
+; CHECK-LABEL: @neg_neg_vec(
+; CHECK-NEXT:    ret <2 x i32> [[A:%.*]]
+;
+  %B = sub <2 x i32> <i32 0, i32 undef>, %A
+  %C = sub <2 x i32> <i32 0, i32 undef>, %B
+  ret <2 x i32> %C
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/undef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/undef.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/undef.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/undef.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,362 @@
+; RUN: opt -instsimplify -S < %s | FileCheck %s
+
+define i64 @test0() {
+; CHECK-LABEL: @test0(
+; CHECK:         ret i64 undef
+;
+  %r = mul i64 undef, undef
+  ret i64 %r
+}
+
+define i64 @test1() {
+; CHECK-LABEL: @test1(
+; CHECK:         ret i64 undef
+;
+  %r = mul i64 3, undef
+  ret i64 %r
+}
+
+define i64 @test2() {
+; CHECK-LABEL: @test2(
+; CHECK:         ret i64 undef
+;
+  %r = mul i64 undef, 3
+  ret i64 %r
+}
+
+define i64 @test3() {
+; CHECK-LABEL: @test3(
+; CHECK:         ret i64 0
+;
+  %r = mul i64 undef, 6
+  ret i64 %r
+}
+
+define i64 @test4() {
+; CHECK-LABEL: @test4(
+; CHECK:         ret i64 0
+;
+  %r = mul i64 6, undef
+  ret i64 %r
+}
+
+define i64 @test5() {
+; CHECK-LABEL: @test5(
+; CHECK:         ret i64 undef
+;
+  %r = and i64 undef, undef
+  ret i64 %r
+}
+
+define i64 @test6() {
+; CHECK-LABEL: @test6(
+; CHECK:         ret i64 undef
+;
+  %r = or i64 undef, undef
+  ret i64 %r
+}
+
+define i64 @test7() {
+; CHECK-LABEL: @test7(
+; CHECK:         ret i64 undef
+;
+  %r = udiv i64 undef, 1
+  ret i64 %r
+}
+
+define i64 @test8() {
+; CHECK-LABEL: @test8(
+; CHECK:         ret i64 undef
+;
+  %r = sdiv i64 undef, 1
+  ret i64 %r
+}
+
+define i64 @test9() {
+; CHECK-LABEL: @test9(
+; CHECK:         ret i64 0
+;
+  %r = urem i64 undef, 1
+  ret i64 %r
+}
+
+define i64 @test10() {
+; CHECK-LABEL: @test10(
+; CHECK:         ret i64 0
+;
+  %r = srem i64 undef, 1
+  ret i64 %r
+}
+
+define i64 @test11() {
+; CHECK-LABEL: @test11(
+; CHECK:         ret i64 undef
+;
+  %r = shl i64 undef, undef
+  ret i64 %r
+}
+
+define i64 @test11b(i64 %a) {
+; CHECK-LABEL: @test11b(
+; CHECK:         ret i64 undef
+;
+  %r = shl i64 %a, undef
+  ret i64 %r
+}
+
+define i64 @test12() {
+; CHECK-LABEL: @test12(
+; CHECK:         ret i64 undef
+;
+  %r = ashr i64 undef, undef
+  ret i64 %r
+}
+
+define i64 @test12b(i64 %a) {
+; CHECK-LABEL: @test12b(
+; CHECK:         ret i64 undef
+;
+  %r = ashr i64 %a, undef
+  ret i64 %r
+}
+
+define i64 @test13() {
+; CHECK-LABEL: @test13(
+; CHECK:         ret i64 undef
+;
+  %r = lshr i64 undef, undef
+  ret i64 %r
+}
+
+define i64 @test13b(i64 %a) {
+; CHECK-LABEL: @test13b(
+; CHECK:         ret i64 undef
+;
+  %r = lshr i64 %a, undef
+  ret i64 %r
+}
+
+define i1 @test14() {
+; CHECK-LABEL: @test14(
+; CHECK:         ret i1 undef
+;
+  %r = icmp slt i64 undef, undef
+  ret i1 %r
+}
+
+define i1 @test15() {
+; CHECK-LABEL: @test15(
+; CHECK:         ret i1 undef
+;
+  %r = icmp ult i64 undef, undef
+  ret i1 %r
+}
+
+define i64 @test16(i64 %a) {
+; CHECK-LABEL: @test16(
+; CHECK:         ret i64 undef
+;
+  %r = select i1 undef, i64 %a, i64 undef
+  ret i64 %r
+}
+
+define i64 @test17(i64 %a) {
+; CHECK-LABEL: @test17(
+; CHECK:         ret i64 undef
+;
+  %r = select i1 undef, i64 undef, i64 %a
+  ret i64 %r
+}
+
+define i64 @test18(i64 %a) {
+; CHECK-LABEL: @test18(
+; CHECK:         [[R:%.*]] = call i64 undef(i64 %a)
+; CHECK-NEXT:    ret i64 undef
+;
+  %r = call i64 (i64) undef(i64 %a)
+  ret i64 %r
+}
+
+define <4 x i8> @test19(<4 x i8> %a) {
+; CHECK-LABEL: @test19(
+; CHECK:         ret <4 x i8> undef
+;
+  %b = shl <4 x i8> %a, <i8 8, i8 9, i8 undef, i8 -1>
+  ret <4 x i8> %b
+}
+
+define i32 @test20(i32 %a) {
+; CHECK-LABEL: @test20(
+; CHECK:         ret i32 undef
+;
+  %b = udiv i32 %a, 0
+  ret i32 %b
+}
+
+define <2 x i32> @test20vec(<2 x i32> %a) {
+; CHECK-LABEL: @test20vec(
+; CHECK-NEXT:    ret <2 x i32> undef
+;
+  %b = udiv <2 x i32> %a, zeroinitializer
+  ret <2 x i32> %b
+}
+
+define i32 @test21(i32 %a) {
+; CHECK-LABEL: @test21(
+; CHECK:         ret i32 undef
+;
+  %b = sdiv i32 %a, 0
+  ret i32 %b
+}
+
+define <2 x i32> @test21vec(<2 x i32> %a) {
+; CHECK-LABEL: @test21vec(
+; CHECK-NEXT:    ret <2 x i32> undef
+;
+  %b = sdiv <2 x i32> %a, zeroinitializer
+  ret <2 x i32> %b
+}
+
+define i32 @test22(i32 %a) {
+; CHECK-LABEL: @test22(
+; CHECK:         ret i32 undef
+;
+  %b = ashr exact i32 undef, %a
+  ret i32 %b
+}
+
+define i32 @test23(i32 %a) {
+; CHECK-LABEL: @test23(
+; CHECK:         ret i32 undef
+;
+  %b = lshr exact i32 undef, %a
+  ret i32 %b
+}
+
+define i32 @test24() {
+; CHECK-LABEL: @test24(
+; CHECK:         ret i32 undef
+;
+  %b = udiv i32 undef, 0
+  ret i32 %b
+}
+
+define i32 @test25() {
+; CHECK-LABEL: @test25(
+; CHECK:         ret i32 undef
+;
+  %b = lshr i32 0, undef
+  ret i32 %b
+}
+
+define i32 @test26() {
+; CHECK-LABEL: @test26(
+; CHECK:         ret i32 undef
+;
+  %b = ashr i32 0, undef
+  ret i32 %b
+}
+
+define i32 @test27() {
+; CHECK-LABEL: @test27(
+; CHECK:         ret i32 undef
+;
+  %b = shl i32 0, undef
+  ret i32 %b
+}
+
+define i32 @test28(i32 %a) {
+; CHECK-LABEL: @test28(
+; CHECK:         ret i32 undef
+;
+  %b = shl nsw i32 undef, %a
+  ret i32 %b
+}
+
+define i32 @test29(i32 %a) {
+; CHECK-LABEL: @test29(
+; CHECK:         ret i32 undef
+;
+  %b = shl nuw i32 undef, %a
+  ret i32 %b
+}
+
+define i32 @test30(i32 %a) {
+; CHECK-LABEL: @test30(
+; CHECK:         ret i32 undef
+;
+  %b = shl nsw nuw i32 undef, %a
+  ret i32 %b
+}
+
+define i32 @test31(i32 %a) {
+; CHECK-LABEL: @test31(
+; CHECK:         ret i32 0
+;
+  %b = shl i32 undef, %a
+  ret i32 %b
+}
+
+define i32 @test32(i32 %a) {
+; CHECK-LABEL: @test32(
+; CHECK:         ret i32 undef
+;
+  %b = shl i32 undef, 0
+  ret i32 %b
+}
+
+define i32 @test33(i32 %a) {
+; CHECK-LABEL: @test33(
+; CHECK:         ret i32 undef
+;
+  %b = ashr i32 undef, 0
+  ret i32 %b
+}
+
+define i32 @test34(i32 %a) {
+; CHECK-LABEL: @test34(
+; CHECK:         ret i32 undef
+;
+  %b = lshr i32 undef, 0
+  ret i32 %b
+}
+
+define i32 @test35(<4 x i32> %V) {
+; CHECK-LABEL: @test35(
+; CHECK:         ret i32 undef
+;
+  %b = extractelement <4 x i32> %V, i32 4
+  ret i32 %b
+}
+
+define i32 @test36(i32 %V) {
+; CHECK-LABEL: @test36(
+; CHECK:         ret i32 undef
+;
+  %b = extractelement <4 x i32> undef, i32 %V
+  ret i32 %b
+}
+
+define i32 @test37() {
+; CHECK-LABEL: @test37(
+; CHECK:         ret i32 undef
+;
+  %b = udiv i32 undef, undef
+  ret i32 %b
+}
+
+define i32 @test38(i32 %a) {
+; CHECK-LABEL: @test38(
+; CHECK:         ret i32 undef
+;
+  %b = udiv i32 %a, undef
+  ret i32 %b
+}
+
+define i32 @test39() {
+; CHECK-LABEL: @test39(
+; CHECK:         ret i32 undef
+;
+  %b = udiv i32 0, undef
+  ret i32 %b
+}

Added: llvm/trunk/test/Transforms/InstSimplify/vec-cmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/vec-cmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/vec-cmp.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/vec-cmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,65 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define <2 x i1> @nonzero_vec_splat(<2 x i32> %x) {
+; CHECK-LABEL: @nonzero_vec_splat(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %y = or <2 x i32> %x, <i32 1, i32 1>
+  %c = icmp eq <2 x i32> %y, zeroinitializer
+  ret <2 x i1> %c
+}
+
+define <2 x i1> @nonzero_vec_nonsplat(<2 x i32> %x) {
+; CHECK-LABEL: @nonzero_vec_nonsplat(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %y = or <2 x i32> %x, <i32 2, i32 1>
+  %c = icmp ne <2 x i32> %y, zeroinitializer
+  ret <2 x i1> %c
+}
+
+define <2 x i1> @nonzero_vec_undef_elt(<2 x i32> %x) {
+; CHECK-LABEL: @nonzero_vec_undef_elt(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %y = or <2 x i32> %x, <i32 undef, i32 1>
+  %c = icmp eq <2 x i32> %y, zeroinitializer
+  ret <2 x i1> %c
+}
+
+define <2 x i1> @may_be_zero_vec(<2 x i32> %x) {
+; CHECK-LABEL: @may_be_zero_vec(
+; CHECK-NEXT:    [[Y:%.*]] = or <2 x i32> %x, <i32 0, i32 1>
+; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[Y]], zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[C]]
+;
+  %y = or <2 x i32> %x, <i32 0, i32 1>
+  %c = icmp ne <2 x i32> %y, zeroinitializer
+  ret <2 x i1> %c
+}
+
+; Multiplies of non-zero numbers are non-zero if there is no unsigned overflow.
+define <2 x i1> @nonzero_vec_mul_nuw(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @nonzero_vec_mul_nuw(
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
+;
+  %xnz = or <2 x i32> %x, <i32 1, i32 2>
+  %ynz = or <2 x i32> %y, <i32 3, i32 undef>
+  %m = mul nuw <2 x i32> %xnz, %ynz
+  %c = icmp eq <2 x i32> %m, zeroinitializer
+  ret <2 x i1> %c
+}
+
+; Multiplies of non-zero numbers are non-zero if there is no signed overflow.
+define <2 x i1> @nonzero_vec_mul_nsw(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @nonzero_vec_mul_nsw(
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
+;
+  %xnz = or <2 x i32> %x, <i32 undef, i32 2>
+  %ynz = or <2 x i32> %y, <i32 3, i32 4>
+  %m = mul nsw <2 x i32> %xnz, %ynz
+  %c = icmp ne <2 x i32> %m, zeroinitializer
+  ret <2 x i1> %c
+}
+

Added: llvm/trunk/test/Transforms/InstSimplify/vector_gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/vector_gep.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/vector_gep.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/vector_gep.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,106 @@
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+declare void @helper(<2 x i8*>)
+define void @test(<2 x i8*> %a) {
+  %A = getelementptr i8, <2 x i8*> %a, <2 x i32> <i32 0, i32 0>
+  call void @helper(<2 x i8*> %A)
+  ret void
+}
+
+define <4 x i8*> @test1(<4 x i8*> %a) {
+  %gep = getelementptr i8, <4 x i8*> %a, <4 x i32> zeroinitializer
+  ret <4 x i8*> %gep
+
+; CHECK-LABEL: @test1
+; CHECK-NEXT: ret <4 x i8*> %a
+}
+
+define <4 x i8*> @test2(<4 x i8*> %a) {
+  %gep = getelementptr i8, <4 x i8*> %a
+  ret <4 x i8*> %gep
+
+; CHECK-LABEL: @test2
+; CHECK-NEXT: ret <4 x i8*> %a
+}
+
+%struct = type { double, float }
+
+define <4 x float*> @test3() {
+  %gep = getelementptr %struct, <4 x %struct*> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+  ret <4 x float*> %gep
+
+; CHECK-LABEL: @test3
+; CHECK-NEXT: ret <4 x float*> undef
+}
+
+%struct.empty = type { }
+
+define <4 x %struct.empty*> @test4(<4 x %struct.empty*> %a) {
+  %gep = getelementptr %struct.empty, <4 x %struct.empty*> %a, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+  ret <4 x %struct.empty*> %gep
+
+; CHECK-LABEL: @test4
+; CHECK-NEXT: ret <4 x %struct.empty*> %a
+}
+
+define <4 x i8*> @test5() {
+  %c = inttoptr <4 x i64> <i64 1, i64 2, i64 3, i64 4> to <4 x i8*>
+  %gep = getelementptr i8, <4 x i8*> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+  ret <4 x i8*> %gep
+
+; CHECK-LABEL: @test5
+; CHECK-NEXT: ret <4 x i8*> getelementptr (i8, <4 x i8*> <i8* inttoptr (i64 1 to i8*), i8* inttoptr (i64 2 to i8*), i8* inttoptr (i64 3 to i8*), i8* inttoptr (i64 4 to i8*)>, <4 x i64> <i64 1, i64 1, i64 1, i64 1>)
+}
+
+ at v = global [24 x [42 x [3 x i32]]] zeroinitializer, align 16
+
+define <16 x i32*> @test6() {
+; CHECK-LABEL: @test6
+; CHECK-NEXT: ret <16 x i32*> getelementptr inbounds ([24 x [42 x [3 x i32]]], [24 x [42 x [3 x i32]]]* @v, <16 x i64> zeroinitializer, <16 x i64> zeroinitializer, <16 x i64> <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15>, <16 x i64> zeroinitializer)
+  %VectorGep = getelementptr [24 x [42 x [3 x i32]]], [24 x [42 x [3 x i32]]]* @v, i64 0, i64 0, <16 x i64> <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15>, i64 0
+  ret <16 x i32*> %VectorGep
+}
+
+; PR32697
+; CHECK-LABEL: tinkywinky(
+; CHECK-NEXT: ret <4 x i8*> undef
+define <4 x i8*> @tinkywinky() {
+  %patatino = getelementptr i8, i8* undef, <4 x i64> undef
+  ret <4 x i8*> %patatino
+}
+
+; PR32697
+; CHECK-LABEL: dipsy(
+; CHECK-NEXT: ret <4 x i8*> undef
+define <4 x i8*> @dipsy() {
+  %patatino = getelementptr i8, <4 x i8 *> undef, <4 x i64> undef
+  ret <4 x i8*> %patatino
+}
+
+; PR32697
+; CHECK-LABEL: laalaa(
+; CHECK-NEXT: ret <4 x i8*> undef
+define <4 x i8*> @laalaa() {
+  %patatino = getelementptr i8, <4 x i8 *> undef, i64 undef
+  ret <4 x i8*> %patatino
+}
+
+define <2 x i8*> @zero_index(i8* %p) {
+; CHECK-LABEL: @zero_index(
+; CHECK-NEXT:    %gep = getelementptr i8, i8* %p, <2 x i64> zeroinitializer
+; CHECK-NEXT:    ret <2 x i8*> %gep
+;
+  %gep = getelementptr i8, i8* %p, <2 x i64> zeroinitializer
+  ret <2 x i8*> %gep
+}
+
+define <2 x {}*> @unsized({}* %p) {
+; CHECK-LABEL: @unsized(
+; CHECK-NEXT:    %gep = getelementptr {}, {}* %p, <2 x i64> undef
+; CHECK-NEXT:    ret <2 x {}*> %gep
+;
+  %gep = getelementptr {}, {}* %p, <2 x i64> undef
+  ret <2 x {}*> %gep
+}

Added: llvm/trunk/test/Transforms/InstSimplify/vector_ptr_bitcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/vector_ptr_bitcast.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/vector_ptr_bitcast.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/vector_ptr_bitcast.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
+
+%mst = type { i8*, i8* }
+%mst2 = type { i32*, i32*, i32*, i32* }
+
+ at a = private unnamed_addr constant %mst { i8* inttoptr (i64 -1 to i8*),
+                                          i8* inttoptr (i64 -1 to i8*)},
+                                          align 8
+ at b = private unnamed_addr constant %mst2 { i32* inttoptr (i64 42 to i32*),
+                                           i32* inttoptr (i64 67 to i32*),
+                                           i32* inttoptr (i64 33 to i32*),
+                                           i32* inttoptr (i64 58 to i32*)},
+                                          align 8
+
+define i64 @fn() {
+  %x = load <2 x i8*>, <2 x i8*>* bitcast (%mst* @a to <2 x i8*>*), align 8
+  %b = extractelement <2 x i8*> %x, i32 0
+  %c = ptrtoint i8* %b to i64
+  ; CHECK-LABEL: @fn
+  ; CHECK-NEXT: ret i64 -1
+  ret i64 %c
+}
+
+define i64 @fn2() {
+  %x = load <4 x i32*>, <4 x i32*>* bitcast (%mst2* @b to <4 x i32*>*), align 8
+  %b = extractelement <4 x i32*> %x, i32 0
+  %c = extractelement <4 x i32*> %x, i32 3
+  %d = ptrtoint i32* %b to i64
+  %e = ptrtoint i32* %c to i64
+  %r = add i64 %d, %e
+  ; CHECK-LABEL: @fn2
+  ; CHECK-NEXT: ret i64 100
+  ret i64 %r
+}

Added: llvm/trunk/test/Transforms/InterleavedAccess/AArch64/interleaved-accesses-extract-user.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/AArch64/interleaved-accesses-extract-user.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/AArch64/interleaved-accesses-extract-user.ll (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/AArch64/interleaved-accesses-extract-user.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,113 @@
+; RUN: opt < %s -interleaved-access -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+define void @extract_user_basic(<8 x i32>* %ptr, i1 %c) {
+; CHECK-LABEL: @extract_user_basic(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <8 x i32>* %ptr to <4 x i32>*
+; CHECK-NEXT:    [[LDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32(<4 x i32>* [[TMP0]])
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN]], 0
+; CHECK-NEXT:    br i1 %c, label %if.then, label %if.merge
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x i32> [[TMP1]], i64 1
+; CHECK-NEXT:    br label %if.merge
+; CHECK:       if.merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  br i1 %c, label %if.then, label %if.merge
+
+if.then:
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 2
+  br label %if.merge
+
+if.merge:
+  ret void
+}
+
+define void @extract_user_multi(<8 x i32>* %ptr, i1 %c) {
+; CHECK-LABEL: @extract_user_multi(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <8 x i32>* %ptr to <4 x i32>*
+; CHECK-NEXT:    [[LDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32(<4 x i32>* [[TMP0]])
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN]], 0
+; CHECK-NEXT:    br i1 %c, label %if.then, label %if.merge
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x i32> [[TMP1]], i64 0
+; CHECK-NEXT:    br label %if.merge
+; CHECK:       if.merge:
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x i32> [[TMP1]], i64 1
+; CHECK-NEXT:    ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  br i1 %c, label %if.then, label %if.merge
+
+if.then:
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 0
+  br label %if.merge
+
+if.merge:
+  %e1 = extractelement <8 x i32> %interleaved.vec, i32 2
+  ret void
+}
+
+define void @extract_user_multi_no_dom(<8 x i32>* %ptr, i1 %c) {
+; CHECK-LABEL: @extract_user_multi_no_dom(
+; CHECK-NOT:     @llvm.aarch64.neon
+; CHECK:         ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 0
+  br i1 %c, label %if.then, label %if.merge
+
+if.then:
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  %e1 = extractelement <8 x i32> %interleaved.vec, i32 2
+  br label %if.merge
+
+if.merge:
+  ret void
+}
+
+define void @extract_user_wrong_const_index(<8 x i32>* %ptr) {
+; CHECK-LABEL: @extract_user_wrong_const_index(
+; CHECK-NOT:     @llvm.aarch64.neon
+; CHECK:         ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 1
+  ret void
+}
+
+define void @extract_user_undef_index(<8 x i32>* %ptr) {
+; CHECK-LABEL: @extract_user_undef_index(
+; CHECK-NOT:     @llvm.aarch64.neon
+; CHECK:         ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 undef
+  ret void
+}
+
+define void @extract_user_var_index(<8 x i32>* %ptr, i32 %i) {
+; CHECK-LABEL: @extract_user_var_index(
+; CHECK-NOT:     @llvm.aarch64.neon
+; CHECK:         ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 %i
+  ret void
+}

Added: llvm/trunk/test/Transforms/InterleavedAccess/AArch64/interleaved-accesses.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/AArch64/interleaved-accesses.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/AArch64/interleaved-accesses.ll (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/AArch64/interleaved-accesses.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,801 @@
+; RUN: opt < %s -interleaved-access -S | FileCheck %s -check-prefix=NEON
+; RUN: opt < %s -mattr=-neon -interleaved-access -S | FileCheck %s -check-prefix=NO_NEON
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+define void @load_factor2(<16 x i8>* %ptr) {
+; NEON-LABEL:    @load_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i8>* %ptr to <8 x i8>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2.v8i8.p0v8i8(<8 x i8>* [[TMP1]])
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[LDN]], 1
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[LDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor2(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <16 x i8>, <16 x i8>* %ptr, align 4
+  %v0 = shufflevector <16 x i8> %interleaved.vec, <16 x i8> undef, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+  %v1 = shufflevector <16 x i8> %interleaved.vec, <16 x i8> undef, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+  ret void
+}
+
+define void @load_factor3(<12 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor3(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0v4i32(<4 x i32>* [[TMP1]])
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 2
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor3(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <12 x i32>, <12 x i32>* %ptr, align 4
+  %v0 = shufflevector <12 x i32> %interleaved.vec, <12 x i32> undef, <4 x i32> <i32 0, i32 3, i32 6, i32 9>
+  %v1 = shufflevector <12 x i32> %interleaved.vec, <12 x i32> undef, <4 x i32> <i32 1, i32 4, i32 7, i32 10>
+  %v2 = shufflevector <12 x i32> %interleaved.vec, <12 x i32> undef, <4 x i32> <i32 2, i32 5, i32 8, i32 11>
+  ret void
+}
+
+define void @load_factor4(<16 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor4(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4.v4i32.p0v4i32(<4 x i32>* [[TMP1]])
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 3
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 2
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 1
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor4(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <16 x i32>, <16 x i32>* %ptr, align 4
+  %v0 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
+  %v1 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 1, i32 5, i32 9, i32 13>
+  %v2 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 2, i32 6, i32 10, i32 14>
+  %v3 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 3, i32 7, i32 11, i32 15>
+  ret void
+}
+
+define void @store_factor2(<16 x i8>* %ptr, <8 x i8> %v0, <8 x i8> %v1) {
+; NEON-LABEL:    @store_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <8 x i8> %v0, <8 x i8> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i8> %v0, <8 x i8> %v1, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       [[TMP3:%.*]] = bitcast <16 x i8>* %ptr to <8 x i8>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st2.v8i8.p0v8i8(<8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <8 x i8>* [[TMP3]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor2(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <8 x i8> %v0, <8 x i8> %v1, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+  store <16 x i8> %interleaved.vec, <16 x i8>* %ptr, align 4
+  ret void
+}
+
+define void @store_factor3(<12 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2) {
+; NEON-LABEL:    @store_factor3(
+; NEON:            [[TMP1:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP4:%.*]] = bitcast <12 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st3.v4i32.p0v4i32(<4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32>* [[TMP4]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor3(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x i32> %v2, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+  %interleaved.vec = shufflevector <8 x i32> %s0, <8 x i32> %s1, <12 x i32> <i32 0, i32 4, i32 8, i32 1, i32 5, i32 9, i32 2, i32 6, i32 10, i32 3, i32 7, i32 11>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_factor4(<16 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) {
+; NEON-LABEL:    @store_factor4(
+; NEON:            [[TMP1:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       [[TMP5:%.*]] = bitcast <16 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v4i32.p0v4i32(<4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32>* [[TMP5]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor4(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x i32> %v2, <4 x i32> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %interleaved.vec = shufflevector <8 x i32> %s0, <8 x i32> %s1, <16 x i32> <i32 0, i32 4, i32 8, i32 12, i32 1, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
+  store <16 x i32> %interleaved.vec, <16 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @load_ptrvec_factor2(<4 x i32*>* %ptr) {
+; NEON-LABEL:    @load_ptrvec_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <4 x i32*>* %ptr to <2 x i64>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld2.v2i64.p0v2i64(<2 x i64>* [[TMP1]])
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <2 x i64>, <2 x i64> } [[LDN]], 1
+; NEON-NEXT:       [[TMP3:%.*]] = inttoptr <2 x i64> [[TMP2]] to <2 x i32*>
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <2 x i64>, <2 x i64> } [[LDN]], 0
+; NEON-NEXT:       [[TMP5:%.*]] = inttoptr <2 x i64> [[TMP4]] to <2 x i32*>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_ptrvec_factor2(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <4 x i32*>, <4 x i32*>* %ptr, align 4
+  %v0 = shufflevector <4 x i32*> %interleaved.vec, <4 x i32*> undef, <2 x i32> <i32 0, i32 2>
+  %v1 = shufflevector <4 x i32*> %interleaved.vec, <4 x i32*> undef, <2 x i32> <i32 1, i32 3>
+  ret void
+}
+
+define void @load_ptrvec_factor3(<6 x i32*>* %ptr) {
+; NEON-LABEL:    @load_ptrvec_factor3(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <6 x i32*>* %ptr to <2 x i64>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld3.v2i64.p0v2i64(<2 x i64>* [[TMP1]])
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64> } [[LDN]], 2
+; NEON-NEXT:       [[TMP3:%.*]] = inttoptr <2 x i64> [[TMP2]] to <2 x i32*>
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64> } [[LDN]], 1
+; NEON-NEXT:       [[TMP5:%.*]] = inttoptr <2 x i64> [[TMP4]] to <2 x i32*>
+; NEON-NEXT:       [[TMP6:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64> } [[LDN]], 0
+; NEON-NEXT:       [[TMP7:%.*]] = inttoptr <2 x i64> [[TMP6]] to <2 x i32*>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_ptrvec_factor3(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <6 x i32*>, <6 x i32*>* %ptr, align 4
+  %v0 = shufflevector <6 x i32*> %interleaved.vec, <6 x i32*> undef, <2 x i32> <i32 0, i32 3>
+  %v1 = shufflevector <6 x i32*> %interleaved.vec, <6 x i32*> undef, <2 x i32> <i32 1, i32 4>
+  %v2 = shufflevector <6 x i32*> %interleaved.vec, <6 x i32*> undef, <2 x i32> <i32 2, i32 5>
+  ret void
+}
+
+define void @load_ptrvec_factor4(<8 x i32*>* %ptr) {
+; NEON-LABEL:    @load_ptrvec_factor4(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32*>* %ptr to <2 x i64>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld4.v2i64.p0v2i64(<2 x i64>* [[TMP1]])
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[LDN]], 3
+; NEON-NEXT:       [[TMP3:%.*]] = inttoptr <2 x i64> [[TMP2]] to <2 x i32*>
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[LDN]], 2
+; NEON-NEXT:       [[TMP5:%.*]] = inttoptr <2 x i64> [[TMP4]] to <2 x i32*>
+; NEON-NEXT:       [[TMP6:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[LDN]], 1
+; NEON-NEXT:       [[TMP7:%.*]] = inttoptr <2 x i64> [[TMP6]] to <2 x i32*>
+; NEON-NEXT:       [[TMP8:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[LDN]], 0
+; NEON-NEXT:       [[TMP9:%.*]] = inttoptr <2 x i64> [[TMP8]] to <2 x i32*>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_ptrvec_factor4(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <8 x i32*>, <8 x i32*>* %ptr, align 4
+  %v0 = shufflevector <8 x i32*> %interleaved.vec, <8 x i32*> undef, <2 x i32> <i32 0, i32 4>
+  %v1 = shufflevector <8 x i32*> %interleaved.vec, <8 x i32*> undef, <2 x i32> <i32 1, i32 5>
+  %v2 = shufflevector <8 x i32*> %interleaved.vec, <8 x i32*> undef, <2 x i32> <i32 2, i32 6>
+  %v3 = shufflevector <8 x i32*> %interleaved.vec, <8 x i32*> undef, <2 x i32> <i32 3, i32 7>
+  ret void
+}
+
+define void @store_ptrvec_factor2(<4 x i32*>* %ptr, <2 x i32*> %v0, <2 x i32*> %v1) {
+; NEON-LABEL:    @store_ptrvec_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = ptrtoint <2 x i32*> %v0 to <2 x i64>
+; NEON-NEXT:       [[TMP2:%.*]] = ptrtoint <2 x i32*> %v1 to <2 x i64>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> [[TMP2]], <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> [[TMP2]], <2 x i32> <i32 2, i32 3>
+; NEON-NEXT:       [[TMP5:%.*]] = bitcast <4 x i32*>* %ptr to <2 x i64>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st2.v2i64.p0v2i64(<2 x i64> [[TMP3]], <2 x i64> [[TMP4]], <2 x i64>* [[TMP5]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_ptrvec_factor2(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
+  store <4 x i32*> %interleaved.vec, <4 x i32*>* %ptr, align 4
+  ret void
+}
+
+define void @store_ptrvec_factor3(<6 x i32*>* %ptr, <2 x i32*> %v0, <2 x i32*> %v1, <2 x i32*> %v2) {
+; NEON-LABEL:    @store_ptrvec_factor3(
+; NEON:            [[TMP1:%.*]] = ptrtoint <4 x i32*> %s0 to <4 x i64>
+; NEON-NEXT:       [[TMP2:%.*]] = ptrtoint <4 x i32*> %s1 to <4 x i64>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <4 x i64> [[TMP1]], <4 x i64> [[TMP2]], <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <4 x i64> [[TMP1]], <4 x i64> [[TMP2]], <2 x i32> <i32 2, i32 3>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <4 x i64> [[TMP1]], <4 x i64> [[TMP2]], <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP6:%.*]] = bitcast <6 x i32*>* %ptr to <2 x i64>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st3.v2i64.p0v2i64(<2 x i64> [[TMP3]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]], <2 x i64>* [[TMP6]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_ptrvec_factor3(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %s1 = shufflevector <2 x i32*> %v2, <2 x i32*> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+  %interleaved.vec = shufflevector <4 x i32*> %s0, <4 x i32*> %s1, <6 x i32> <i32 0, i32 2, i32 4, i32 1, i32 3, i32 5>
+  store <6 x i32*> %interleaved.vec, <6 x i32*>* %ptr, align 4
+  ret void
+}
+
+define void @store_ptrvec_factor4(<8 x i32*>* %ptr, <2 x i32*> %v0, <2 x i32*> %v1, <2 x i32*> %v2, <2 x i32*> %v3) {
+; NEON-LABEL:    @store_ptrvec_factor4(
+; NEON:            [[TMP1:%.*]] = ptrtoint <4 x i32*> %s0 to <4 x i64>
+; NEON-NEXT:       [[TMP2:%.*]] = ptrtoint <4 x i32*> %s1 to <4 x i64>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <4 x i64> [[TMP1]], <4 x i64> [[TMP2]], <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <4 x i64> [[TMP1]], <4 x i64> [[TMP2]], <2 x i32> <i32 2, i32 3>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <4 x i64> [[TMP1]], <4 x i64> [[TMP2]], <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP6:%.*]] = shufflevector <4 x i64> [[TMP1]], <4 x i64> [[TMP2]], <2 x i32> <i32 6, i32 7>
+; NEON-NEXT:       [[TMP7:%.*]] = bitcast <8 x i32*>* %ptr to <2 x i64>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v2i64.p0v2i64(<2 x i64> [[TMP3]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]], <2 x i64> [[TMP6]], <2 x i64>* [[TMP7]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_ptrvec_factor4(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %s1 = shufflevector <2 x i32*> %v2, <2 x i32*> %v3, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %interleaved.vec = shufflevector <4 x i32*> %s0, <4 x i32*> %s1, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
+  store <8 x i32*> %interleaved.vec, <8 x i32*>* %ptr, align 4
+  ret void
+}
+
+define void @load_undef_mask_factor2(<8 x i32>* %ptr) {
+; NEON-LABEL:    @load_undef_mask_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32(<4 x i32>* [[TMP1]])
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN]], 1
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_undef_mask_factor2(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 4
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 undef, i32 2, i32 undef, i32 6>
+  %v1 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 undef, i32 3, i32 undef, i32 7>
+  ret void
+}
+
+define void @load_undef_mask_factor3(<12 x i32>* %ptr) {
+; NEON-LABEL:    @load_undef_mask_factor3(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0v4i32(<4 x i32>* [[TMP1]])
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 2
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_undef_mask_factor3(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <12 x i32>, <12 x i32>* %ptr, align 4
+  %v0 = shufflevector <12 x i32> %interleaved.vec, <12 x i32> undef, <4 x i32> <i32 0, i32 3, i32 6, i32 9>
+  %v1 = shufflevector <12 x i32> %interleaved.vec, <12 x i32> undef, <4 x i32> <i32 1, i32 4, i32 7, i32 10>
+  %v2 = shufflevector <12 x i32> %interleaved.vec, <12 x i32> undef, <4 x i32> <i32 2, i32 undef, i32 undef, i32 undef>
+  ret void
+}
+
+define void @load_undef_mask_factor4(<16 x i32>* %ptr) {
+; NEON-LABEL:    @load_undef_mask_factor4(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4.v4i32.p0v4i32(<4 x i32>* [[TMP1]])
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 3
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 2
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 1
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_undef_mask_factor4(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <16 x i32>, <16 x i32>* %ptr, align 4
+  %v0 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 0, i32 4, i32 undef, i32 undef>
+  %v1 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 1, i32 5, i32 undef, i32 undef>
+  %v2 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 2, i32 6, i32 undef, i32 undef>
+  %v3 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 3, i32 7, i32 undef, i32 undef>
+  ret void
+}
+
+define void @store_undef_mask_factor2(<8 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1) {
+; NEON-LABEL:    @store_undef_mask_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <4 x i32> %v0, <4 x i32> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <4 x i32> %v0, <4 x i32> %v1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP3:%.*]] = bitcast <8 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st2.v4i32.p0v4i32(<4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <4 x i32>* [[TMP3]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_undef_mask_factor2(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 undef, i32 undef, i32 undef, i32 undef, i32 2, i32 6, i32 3, i32 7>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_undef_mask_factor3(<12 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2) {
+; NEON-LABEL:    @store_undef_mask_factor3(
+; NEON:            [[TMP1:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP4:%.*]] = bitcast <12 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st3.v4i32.p0v4i32(<4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32>* [[TMP4]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_undef_mask_factor3(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x i32> %v2, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+  %interleaved.vec = shufflevector <8 x i32> %s0, <8 x i32> %s1, <12 x i32> <i32 0, i32 4, i32 undef, i32 1, i32 undef, i32 9, i32 2, i32 6, i32 10, i32 3, i32 7, i32 11>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_undef_mask_factor4(<16 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) {
+; NEON-LABEL:    @store_undef_mask_factor4(
+; NEON:            [[TMP1:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       [[TMP5:%.*]] = bitcast <16 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v4i32.p0v4i32(<4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32>* [[TMP5]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_undef_mask_factor4(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x i32> %v2, <4 x i32> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %interleaved.vec = shufflevector <8 x i32> %s0, <8 x i32> %s1, <16 x i32> <i32 0, i32 4, i32 8, i32 undef, i32 undef, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
+  store <16 x i32> %interleaved.vec, <16 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @load_illegal_factor2(<3 x float>* %ptr) nounwind {
+; NEON-LABEL:    @load_illegal_factor2(
+; NEON-NOT:        @llvm.aarch64.neon
+; NEON:            ret void
+; NO_NEON-LABEL: @load_illegal_factor2(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <3 x float>, <3 x float>* %ptr, align 16
+  %v0 = shufflevector <3 x float> %interleaved.vec, <3 x float> undef, <3 x i32> <i32 0, i32 2, i32 undef>
+  ret void
+}
+
+define void @store_illegal_factor2(<3 x float>* %ptr, <3 x float> %v0) nounwind {
+; NEON-LABEL:    @store_illegal_factor2(
+; NEON-NOT:        @llvm.aarch64.neon
+; NEON:            ret void
+; NO_NEON-LABEL: @store_illegal_factor2(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <3 x float> %v0, <3 x float> undef, <3 x i32> <i32 0, i32 2, i32 undef>
+  store <3 x float> %interleaved.vec, <3 x float>* %ptr, align 16
+  ret void
+}
+
+define void @store_general_mask_factor4(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 16, i32 17>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 32, i32 33>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       [[TMP5:%.*]] = bitcast <8 x i32>* %ptr to <2 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v2i32.p0v2i32(<2 x i32> [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32>* [[TMP5]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 9>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor4_undefbeg(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4_undefbeg(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 16, i32 17>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 32, i32 33>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       [[TMP5:%.*]] = bitcast <8 x i32>* %ptr to <2 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v2i32.p0v2i32(<2 x i32> [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32>* [[TMP5]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4_undefbeg(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 undef, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 9>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor4_undefend(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4_undefend(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 16, i32 17>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 32, i32 33>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       [[TMP5:%.*]] = bitcast <8 x i32>* %ptr to <2 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v2i32.p0v2i32(<2 x i32> [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32>* [[TMP5]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4_undefend(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 undef>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor4_undefmid(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4_undefmid(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 16, i32 17>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 32, i32 33>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       [[TMP5:%.*]] = bitcast <8 x i32>* %ptr to <2 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v2i32.p0v2i32(<2 x i32> [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32>* [[TMP5]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4_undefmid(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 undef, i32 32, i32 8, i32 5, i32 17, i32 undef, i32 9>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor4_undefmulti(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4_undefmulti(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       [[TMP5:%.*]] = bitcast <8 x i32>* %ptr to <2 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v2i32.p0v2i32(<2 x i32> [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32>* [[TMP5]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4_undefmulti(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 undef, i32 undef, i32 8, i32 undef, i32 undef, i32 undef, i32 9>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 32, i32 33, i32 34, i32 35>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       [[TMP4:%.*]] = bitcast <12 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st3.v4i32.p0v4i32(<4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32>* [[TMP4]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor3(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 5, i32 33, i32 17, i32 6, i32 34, i32 18, i32 7, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_undefmultimid(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3_undefmultimid(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 32, i32 33, i32 34, i32 35>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       [[TMP4:%.*]] = bitcast <12 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st3.v4i32.p0v4i32(<4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32>* [[TMP4]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor3_undefmultimid(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 7, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_undef_fail(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3_undef_fail(
+; NEON-NOT:        @llvm.aarch64.neon
+; NEON:            ret void
+; NO_NEON-LABEL: @store_general_mask_factor3_undef_fail(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 8, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_undeflane(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3_undeflane(
+; NEON-NEXT:       [[TMP1:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 32, i32 33, i32 34, i32 35>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       [[TMP4:%.*]] = bitcast <12 x i32>* %ptr to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st3.v4i32.p0v4i32(<4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32>* [[TMP4]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor3_undeflane(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 undef, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_negativestart(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3_negativestart(
+; NEON-NOT:        @llvm.aarch64.neon
+; NEON:            ret void
+; NO_NEON-LABEL: @store_general_mask_factor3_negativestart(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 2, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+ at g = external global <4 x float>
+
+; The following does not give a valid interleaved store
+; NEON-LABEL: define void @no_interleave
+; NEON-NOT: call void @llvm.aarch64.neon.st2
+; NEON: shufflevector
+; NEON: store
+; NEON: ret void
+; NO_NEON-LABEL: define void @no_interleave
+; NO_NEON: shufflevector
+; NO_NEON: store
+; NO_NEON: ret void
+define void @no_interleave(<4 x float> %a0) {
+  %v0 = shufflevector <4 x float> %a0, <4 x float> %a0, <4 x i32> <i32 0, i32 3, i32 7, i32 undef>
+  store <4 x float> %v0, <4 x float>* @g, align 16
+  ret void
+}
+
+define void @load_factor2_wide2(<16 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor2_wide2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to <4 x i32>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32(<4 x i32>* [[TMP2]])
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN]], 0
+; NEON-NEXT:       [[TMP5:%.*]] = getelementptr i32, i32* [[TMP1]], i32 8
+; NEON-NEXT:       [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>*
+; NEON-NEXT:       [[LDN1:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32(<4 x i32>* [[TMP6]])
+; NEON-NEXT:       [[TMP7:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN1]], 1
+; NEON-NEXT:       [[TMP8:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN1]], 0
+; NEON-NEXT:       [[TMP9:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP7]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP10:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP8]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor2_wide2(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <16 x i32>, <16 x i32>* %ptr, align 4
+  %v0 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+  %v1 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+  ret void
+}
+
+define void @load_factor2_wide3(<24 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor2_wide3(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <24 x i32>* [[PTR:%.*]] to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to <4 x i32>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32(<4 x i32>* [[TMP2]])
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN]], 0
+; NEON-NEXT:       [[TMP5:%.*]] = getelementptr i32, i32* [[TMP1]], i32 8
+; NEON-NEXT:       [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>*
+; NEON-NEXT:       [[LDN1:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32(<4 x i32>* [[TMP6]])
+; NEON-NEXT:       [[TMP7:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN1]], 1
+; NEON-NEXT:       [[TMP8:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN1]], 0
+; NEON-NEXT:       [[TMP9:%.*]] = getelementptr i32, i32* [[TMP5]], i32 8
+; NEON-NEXT:       [[TMP10:%.*]] = bitcast i32* [[TMP9]] to <4 x i32>*
+; NEON-NEXT:       [[LDN2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0v4i32(<4 x i32>* [[TMP10]])
+; NEON-NEXT:       [[TMP11:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN2]], 1
+; NEON-NEXT:       [[TMP12:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[LDN2]], 0
+; NEON-NEXT:       [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP7]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP14:%.*]] = shufflevector <4 x i32> [[TMP11]], <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+; NEON-NEXT:       [[TMP15:%.*]] = shufflevector <8 x i32> [[TMP13]], <8 x i32> [[TMP14]], <12 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP16:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP8]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP17:%.*]] = shufflevector <4 x i32> [[TMP12]], <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+; NEON-NEXT:       [[TMP18:%.*]] = shufflevector <8 x i32> [[TMP16]], <8 x i32> [[TMP17]], <12 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor2_wide3(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <24 x i32>, <24 x i32>* %ptr, align 4
+  %v0 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <12 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22>
+  %v1 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <12 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23>
+  ret void
+}
+
+define void @load_factor3_wide(<24 x i32>* %ptr) {
+; NEON-LABEL: @load_factor3_wide(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <24 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to <4 x i32>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0v4i32(<4 x i32>* [[TMP2]])
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 2
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 1
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 0
+; NEON-NEXT:       [[TMP6:%.*]] = getelementptr i32, i32* [[TMP1]], i32 12
+; NEON-NEXT:       [[TMP7:%.*]] = bitcast i32* [[TMP6]] to <4 x i32>*
+; NEON-NEXT:       [[LDN1:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0v4i32(<4 x i32>* [[TMP7]])
+; NEON-NEXT:       [[TMP8:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN1]], 2
+; NEON-NEXT:       [[TMP9:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN1]], 1
+; NEON-NEXT:       [[TMP10:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[LDN1]], 0
+; NEON-NEXT:       [[TMP11:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP8]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP12:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP9]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP5]], <4 x i32> [[TMP10]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor3_wide(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <24 x i32>, <24 x i32>* %ptr, align 4
+  %v0 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <8 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 18, i32 21>
+  %v1 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <8 x i32> <i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22>
+  %v2 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <8 x i32> <i32 2, i32 5, i32 8, i32 11, i32 14, i32 17, i32 20, i32 23>
+  ret void
+}
+
+define void @load_factor4_wide(<32 x i32>* %ptr) {
+; NEON-LABEL: @load_factor4_wide(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <32 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to <4 x i32>*
+; NEON-NEXT:       [[LDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4.v4i32.p0v4i32(<4 x i32>* [[TMP2]])
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 3
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 2
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 1
+; NEON-NEXT:       [[TMP6:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN]], 0
+; NEON-NEXT:       [[TMP7:%.*]] = getelementptr i32, i32* [[TMP1]], i32 16
+; NEON-NEXT:       [[TMP8:%.*]] = bitcast i32* [[TMP7]] to <4 x i32>*
+; NEON-NEXT:       [[LDN1:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld4.v4i32.p0v4i32(<4 x i32>* [[TMP8]])
+; NEON-NEXT:       [[TMP9:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN1]], 3
+; NEON-NEXT:       [[TMP10:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN1]], 2
+; NEON-NEXT:       [[TMP11:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN1]], 1
+; NEON-NEXT:       [[TMP12:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[LDN1]], 0
+; NEON-NEXT:       [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP9]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP14:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP10]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP15:%.*]] = shufflevector <4 x i32> [[TMP5]], <4 x i32> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP16:%.*]] = shufflevector <4 x i32> [[TMP6]], <4 x i32> [[TMP12]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor4_wide(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <32 x i32>, <32 x i32>* %ptr, align 4
+  %v0 = shufflevector <32 x i32> %interleaved.vec, <32 x i32> undef, <8 x i32> <i32 0, i32 4, i32 8, i32 12, i32 16, i32 20, i32 24, i32 28>
+  %v1 = shufflevector <32 x i32> %interleaved.vec, <32 x i32> undef, <8 x i32> <i32 1, i32 5, i32 9, i32 13, i32 17, i32 21, i32 25, i32 29>
+  %v2 = shufflevector <32 x i32> %interleaved.vec, <32 x i32> undef, <8 x i32> <i32 2, i32 6, i32 10, i32 14, i32 18, i32 22, i32 26, i32 30>
+  %v3 = shufflevector <32 x i32> %interleaved.vec, <32 x i32> undef, <8 x i32> <i32 3, i32 7, i32 11, i32 15, i32 19, i32 23, i32 27, i32 31>
+  ret void
+}
+
+define void @store_factor2_wide(<16 x i32>* %ptr, <8 x i32> %v0, <8 x i32> %v1) {
+; NEON-LABEL:    @store_factor2_wide(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i32> %v0, <8 x i32> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %v0, <8 x i32> %v1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP4:%.*]] = bitcast i32* [[TMP1]] to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st2.v4i32.p0v4i32(<4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32>* [[TMP4]])
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <8 x i32> %v0, <8 x i32> %v1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP6:%.*]] = shufflevector <8 x i32> %v0, <8 x i32> %v1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       [[TMP7:%.*]] = getelementptr i32, i32* [[TMP1]], i32 8
+; NEON-NEXT:       [[TMP8:%.*]] = bitcast i32* [[TMP7]] to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st2.v4i32.p0v4i32(<4 x i32> [[TMP5]], <4 x i32> [[TMP6]], <4 x i32>* [[TMP8]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor2_wide(
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <8 x i32> %v0, <8 x i32> %v1, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+  store <16 x i32> %interleaved.vec, <16 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_factor3_wide(<24 x i32>* %ptr, <8 x i32> %v0, <8 x i32> %v1, <8 x i32> %v2) {
+; NEON-LABEL:    @store_factor3_wide(
+; NEON:            [[TMP1:%.*]] = bitcast <24 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       [[TMP5:%.*]] = bitcast i32* [[TMP1]] to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st3.v4i32.p0v4i32(<4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32>* [[TMP5]])
+; NEON-NEXT:       [[TMP6:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP7:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       [[TMP8:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 20, i32 21, i32 22, i32 23>
+; NEON-NEXT:       [[TMP9:%.*]] = getelementptr i32, i32* [[TMP1]], i32 12
+; NEON-NEXT:       [[TMP10:%.*]] = bitcast i32* [[TMP9]] to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st3.v4i32.p0v4i32(<4 x i32> [[TMP6]], <4 x i32> [[TMP7]], <4 x i32> [[TMP8]], <4 x i32>* [[TMP10]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor3_wide(
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <8 x i32> %v0, <8 x i32> %v1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %s1 = shufflevector <8 x i32> %v2, <8 x i32> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+  %interleaved.vec = shufflevector <16 x i32> %s0, <16 x i32> %s1, <24 x i32> <i32 0, i32 8, i32 16, i32 1, i32 9, i32 17, i32 2, i32 10, i32 18, i32 3, i32 11, i32 19, i32 4, i32 12, i32 20, i32 5, i32 13, i32 21, i32 6, i32 14, i32 22, i32 7, i32 15, i32 23>
+  store <24 x i32> %interleaved.vec, <24 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_factor4_wide(<32 x i32>* %ptr, <8 x i32> %v0, <8 x i32> %v1, <8 x i32> %v2, <8 x i32> %v3) {
+; NEON-LABEL:    @store_factor4_wide(
+; NEON:            [[TMP1:%.*]] = bitcast <32 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 24, i32 25, i32 26, i32 27>
+; NEON-NEXT:       [[TMP6:%.*]] = bitcast i32* [[TMP1]] to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v4i32.p0v4i32(<4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32>* [[TMP6]])
+; NEON-NEXT:       [[TMP7:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP8:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       [[TMP9:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 20, i32 21, i32 22, i32 23>
+; NEON-NEXT:       [[TMP10:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 28, i32 29, i32 30, i32 31>
+; NEON-NEXT:       [[TMP11:%.*]] = getelementptr i32, i32* [[TMP1]], i32 16
+; NEON-NEXT:       [[TMP12:%.*]] = bitcast i32* [[TMP11]] to <4 x i32>*
+; NEON-NEXT:       call void @llvm.aarch64.neon.st4.v4i32.p0v4i32(<4 x i32> [[TMP7]], <4 x i32> [[TMP8]], <4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32>* [[TMP12]])
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor4_wide(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <8 x i32> %v0, <8 x i32> %v1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %s1 = shufflevector <8 x i32> %v2, <8 x i32> %v3, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %interleaved.vec = shufflevector <16 x i32> %s0, <16 x i32> %s1, <32 x i32> <i32 0, i32 8, i32 16, i32 24, i32 1, i32 9, i32 17, i32 25, i32 2, i32 10, i32 18, i32 26, i32 3, i32 11, i32 19, i32 27, i32 4, i32 12, i32 20, i32 28, i32 5, i32 13, i32 21, i32 29, i32 6, i32 14, i32 22, i32 30, i32 7, i32 15, i32 23, i32 31>
+  store <32 x i32> %interleaved.vec, <32 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @load_factor2_fp128(<4 x fp128>* %ptr) {
+; NEON-LABEL:    @load_factor2_fp128(
+; NEON-NOT:        @llvm.aarch64.neon
+; NEON:            ret void
+; NO_NEON-LABEL: @load_factor2_fp128(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <4 x fp128>, <4 x fp128>* %ptr, align 16
+  %v0 = shufflevector <4 x fp128> %interleaved.vec, <4 x fp128> undef, <2 x i32> <i32 0, i32 2>
+  %v1 = shufflevector <4 x fp128> %interleaved.vec, <4 x fp128> undef, <2 x i32> <i32 1, i32 3>
+  ret void
+}
+
+define <4 x i1> @load_large_vector(<12 x i64 *>* %p) {
+; NEON-LABEL:    @load_large_vector(
+; NEON:            [[LDN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld3.v2i64.p0v2i64(<2 x i64>*
+; NEON-NEXT:       [[TMP1:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64> } [[LDN]], 1
+; NEON-NEXT:       [[TMP2:%.*]] = inttoptr <2 x i64> [[TMP1]] to <2 x i64*>
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64> } [[LDN]], 0
+; NEON-NEXT:       [[TMP4:%.*]] = inttoptr <2 x i64> [[TMP3]] to <2 x i64*>
+; NEON:            [[LDN1:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64> } @llvm.aarch64.neon.ld3.v2i64.p0v2i64(<2 x i64>*
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64> } [[LDN1]], 1
+; NEON-NEXT:       [[TMP6:%.*]] = inttoptr <2 x i64> [[TMP5]] to <2 x i64*>
+; NEON-NEXT:       [[TMP7:%.*]] = extractvalue { <2 x i64>, <2 x i64>, <2 x i64> } [[LDN1]], 0
+; NEON-NEXT:       [[TMP8:%.*]] = inttoptr <2 x i64> [[TMP7]] to <2 x i64*>
+; NEON-NEXT:       shufflevector <2 x i64*> [[TMP2]], <2 x i64*> [[TMP6]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       shufflevector <2 x i64*> [[TMP4]], <2 x i64*> [[TMP8]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NO_NEON-LABEL: @load_large_vector(
+; NO_NEON-NOT:     @llvm.aarch64.neon
+; NO_NEON:         ret
+;
+  %l = load <12 x i64 *>, <12 x i64 *>* %p
+  %s1 = shufflevector <12 x i64 *> %l, <12 x i64 *> undef, <4 x i32> <i32 0, i32 3, i32 6, i32 9>
+  %s2 = shufflevector <12 x i64 *> %l, <12 x i64 *> undef, <4 x i32> <i32 1, i32 4, i32 7, i32 10>
+  %ret = icmp ne <4 x i64 *> %s1, %s2
+  ret <4 x i1> %ret
+}

Added: llvm/trunk/test/Transforms/InterleavedAccess/AArch64/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/AArch64/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/AArch64/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/AArch64/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,2 @@
+if not 'AArch64' in config.root.targets:
+  config.unsupported = True

Added: llvm/trunk/test/Transforms/InterleavedAccess/ARM/interleaved-accesses-extract-user.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/ARM/interleaved-accesses-extract-user.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/ARM/interleaved-accesses-extract-user.ll (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/ARM/interleaved-accesses-extract-user.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,113 @@
+; RUN: opt < %s -mattr=+neon -interleaved-access -S | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "arm---eabi"
+
+define void @extract_user_basic(<8 x i32>* %ptr, i1 %c) {
+; CHECK-LABEL: @extract_user_basic(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <8 x i32>* %ptr to i8*
+; CHECK-NEXT:    [[VLDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP0]], i32 8)
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 0
+; CHECK-NEXT:    br i1 %c, label %if.then, label %if.merge
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x i32> [[TMP1]], i64 1
+; CHECK-NEXT:    br label %if.merge
+; CHECK:       if.merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  br i1 %c, label %if.then, label %if.merge
+
+if.then:
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 2
+  br label %if.merge
+
+if.merge:
+  ret void
+}
+
+define void @extract_user_multi(<8 x i32>* %ptr, i1 %c) {
+; CHECK-LABEL: @extract_user_multi(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <8 x i32>* %ptr to i8*
+; CHECK-NEXT:    [[VLDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP0]], i32 8)
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 0
+; CHECK-NEXT:    br i1 %c, label %if.then, label %if.merge
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x i32> [[TMP1]], i64 0
+; CHECK-NEXT:    br label %if.merge
+; CHECK:       if.merge:
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x i32> [[TMP1]], i64 1
+; CHECK-NEXT:    ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  br i1 %c, label %if.then, label %if.merge
+
+if.then:
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 0
+  br label %if.merge
+
+if.merge:
+  %e1 = extractelement <8 x i32> %interleaved.vec, i32 2
+  ret void
+}
+
+define void @extract_user_multi_no_dom(<8 x i32>* %ptr, i1 %c) {
+; CHECK-LABEL: @extract_user_multi_no_dom(
+; CHECK-NOT:     @llvm.arm.neon
+; CHECK:         ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 0
+  br i1 %c, label %if.then, label %if.merge
+
+if.then:
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  %e1 = extractelement <8 x i32> %interleaved.vec, i32 2
+  br label %if.merge
+
+if.merge:
+  ret void
+}
+
+define void @extract_user_wrong_const_index(<8 x i32>* %ptr) {
+; CHECK-LABEL: @extract_user_wrong_const_index(
+; CHECK-NOT:     @llvm.arm.neon
+; CHECK:         ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 1
+  ret void
+}
+
+define void @extract_user_undef_index(<8 x i32>* %ptr) {
+; CHECK-LABEL: @extract_user_undef_index(
+; CHECK-NOT:     @llvm.arm.neon
+; CHECK:         ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 undef
+  ret void
+}
+
+define void @extract_user_var_index(<8 x i32>* %ptr, i32 %i) {
+; CHECK-LABEL: @extract_user_var_index(
+; CHECK-NOT:     @llvm.arm.neon
+; CHECK:         ret void
+;
+entry:
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 8
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  %e0 = extractelement <8 x i32> %interleaved.vec, i32 %i
+  ret void
+}

Added: llvm/trunk/test/Transforms/InterleavedAccess/ARM/interleaved-accesses.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/ARM/interleaved-accesses.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/ARM/interleaved-accesses.ll (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/ARM/interleaved-accesses.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,898 @@
+; RUN: opt < %s -mattr=+neon -interleaved-access -S | FileCheck %s -check-prefixes=NEON,ALL
+; RUN: opt < %s -interleaved-access -S | FileCheck %s -check-prefixes=NO_NEON,ALL
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "arm---eabi"
+
+define void @load_factor2(<16 x i8>* %ptr) {
+; NEON-LABEL:    @load_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i8>* %ptr to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2.v8i8.p0i8(i8* [[TMP1]], i32 4)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[VLDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor2(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <16 x i8>, <16 x i8>* %ptr, align 4
+  %v0 = shufflevector <16 x i8> %interleaved.vec, <16 x i8> undef, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+  %v1 = shufflevector <16 x i8> %interleaved.vec, <16 x i8> undef, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+  ret void
+}
+
+define void @load_factor3(<6 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor3(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <6 x i32>* %ptr to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3.v2i32.p0i8(i8* [[TMP1]], i32 4)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 2
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor3(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <6 x i32>, <6 x i32>* %ptr, align 4
+  %v0 = shufflevector <6 x i32> %interleaved.vec, <6 x i32> undef, <2 x i32> <i32 0, i32 3>
+  %v1 = shufflevector <6 x i32> %interleaved.vec, <6 x i32> undef, <2 x i32> <i32 1, i32 4>
+  %v2 = shufflevector <6 x i32> %interleaved.vec, <6 x i32> undef, <2 x i32> <i32 2, i32 5>
+  ret void
+}
+
+define void @load_factor4(<16 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor4(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4.v4i32.p0i8(i8* [[TMP1]], i32 4)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 3
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 2
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor4(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <16 x i32>, <16 x i32>* %ptr, align 4
+  %v0 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
+  %v1 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 1, i32 5, i32 9, i32 13>
+  %v2 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 2, i32 6, i32 10, i32 14>
+  %v3 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 3, i32 7, i32 11, i32 15>
+  ret void
+}
+
+define void @store_factor2(<16 x i8>* %ptr, <8 x i8> %v0, <8 x i8> %v1) {
+; NEON-LABEL:    @store_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i8>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i8> %v0, <8 x i8> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i8> %v0, <8 x i8> %v1, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       call void @llvm.arm.neon.vst2.p0i8.v8i8(i8* [[TMP1]], <8 x i8> [[TMP2]], <8 x i8> [[TMP3]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor2(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <8 x i8> %v0, <8 x i8> %v1, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+  store <16 x i8> %interleaved.vec, <16 x i8>* %ptr, align 4
+  ret void
+}
+
+define void @store_factor3(<12 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2) {
+; NEON-LABEL:    @store_factor3(
+; NEON:            [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor3(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x i32> %v2, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+  %interleaved.vec = shufflevector <8 x i32> %s0, <8 x i32> %s1, <12 x i32> <i32 0, i32 4, i32 8, i32 1, i32 5, i32 9, i32 2, i32 6, i32 10, i32 3, i32 7, i32 11>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_factor4(<16 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) {
+; NEON-LABEL:    @store_factor4(
+; NEON:            [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor4(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x i32> %v2, <4 x i32> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %interleaved.vec = shufflevector <8 x i32> %s0, <8 x i32> %s1, <16 x i32> <i32 0, i32 4, i32 8, i32 12, i32 1, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
+  store <16 x i32> %interleaved.vec, <16 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @load_ptrvec_factor2(<4 x i32*>* %ptr) {
+; NEON-LABEL:    @load_ptrvec_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <4 x i32*>* %ptr to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2.v2i32.p0i8(i8* [[TMP1]], i32 4)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32> } [[VLDN]], 0
+; NEON-NEXT:       [[TMP3:%.*]] = inttoptr <2 x i32> [[TMP2]] to <2 x i32*>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_ptrvec_factor2(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <4 x i32*>, <4 x i32*>* %ptr, align 4
+  %v0 = shufflevector <4 x i32*> %interleaved.vec, <4 x i32*> undef, <2 x i32> <i32 0, i32 2>
+  ret void
+}
+
+define void @load_ptrvec_factor3(<6 x i32*>* %ptr) {
+; NEON-LABEL:    @load_ptrvec_factor3(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <6 x i32*>* %ptr to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3.v2i32.p0i8(i8* [[TMP1]], i32 4)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 2
+; NEON-NEXT:       [[TMP3:%.*]] = inttoptr <2 x i32> [[TMP2]] to <2 x i32*>
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP5:%.*]] = inttoptr <2 x i32> [[TMP4]] to <2 x i32*>
+; NEON-NEXT:       [[TMP6:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 0
+; NEON-NEXT:       [[TMP7:%.*]] = inttoptr <2 x i32> [[TMP6]] to <2 x i32*>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_ptrvec_factor3(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <6 x i32*>, <6 x i32*>* %ptr, align 4
+  %v0 = shufflevector <6 x i32*> %interleaved.vec, <6 x i32*> undef, <2 x i32> <i32 0, i32 3>
+  %v1 = shufflevector <6 x i32*> %interleaved.vec, <6 x i32*> undef, <2 x i32> <i32 1, i32 4>
+  %v2 = shufflevector <6 x i32*> %interleaved.vec, <6 x i32*> undef, <2 x i32> <i32 2, i32 5>
+  ret void
+}
+
+define void @load_ptrvec_factor4(<8 x i32*>* %ptr) {
+; NEON-LABEL:    @load_ptrvec_factor4(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32*>* %ptr to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4.v2i32.p0i8(i8* [[TMP1]], i32 4)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 3
+; NEON-NEXT:       [[TMP3:%.*]] = inttoptr <2 x i32> [[TMP2]] to <2 x i32*>
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 2
+; NEON-NEXT:       [[TMP5:%.*]] = inttoptr <2 x i32> [[TMP4]] to <2 x i32*>
+; NEON-NEXT:       [[TMP6:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP7:%.*]] = inttoptr <2 x i32> [[TMP6]] to <2 x i32*>
+; NEON-NEXT:       [[TMP8:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 0
+; NEON-NEXT:       [[TMP9:%.*]] = inttoptr <2 x i32> [[TMP8]] to <2 x i32*>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_ptrvec_factor4(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <8 x i32*>, <8 x i32*>* %ptr, align 4
+  %v0 = shufflevector <8 x i32*> %interleaved.vec, <8 x i32*> undef, <2 x i32> <i32 0, i32 4>
+  %v1 = shufflevector <8 x i32*> %interleaved.vec, <8 x i32*> undef, <2 x i32> <i32 1, i32 5>
+  %v2 = shufflevector <8 x i32*> %interleaved.vec, <8 x i32*> undef, <2 x i32> <i32 2, i32 6>
+  %v3 = shufflevector <8 x i32*> %interleaved.vec, <8 x i32*> undef, <2 x i32> <i32 3, i32 7>
+  ret void
+}
+
+define void @store_ptrvec_factor2(<4 x i32*>* %ptr, <2 x i32*> %v0, <2 x i32*> %v1) {
+; NEON-LABEL:    @store_ptrvec_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = ptrtoint <2 x i32*> %v0 to <2 x i32>
+; NEON-NEXT:       [[TMP2:%.*]] = ptrtoint <2 x i32*> %v1 to <2 x i32>
+; NEON-NEXT:       [[TMP3:%.*]] = bitcast <4 x i32*>* %ptr to i8*
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> <i32 2, i32 3>
+; NEON-NEXT:       call void @llvm.arm.neon.vst2.p0i8.v2i32(i8* [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_ptrvec_factor2(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
+  store <4 x i32*> %interleaved.vec, <4 x i32*>* %ptr, align 4
+  ret void
+}
+
+define void @store_ptrvec_factor3(<6 x i32*>* %ptr, <2 x i32*> %v0, <2 x i32*> %v1, <2 x i32*> %v2) {
+; NEON-LABEL:    @store_ptrvec_factor3(
+; NEON:            [[TMP1:%.*]] = ptrtoint <4 x i32*> %s0 to <4 x i32>
+; NEON-NEXT:       [[TMP2:%.*]] = ptrtoint <4 x i32*> %s1 to <4 x i32>
+; NEON-NEXT:       [[TMP3:%.*]] = bitcast <6 x i32*>* %ptr to i8*
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <2 x i32> <i32 2, i32 3>
+; NEON-NEXT:       [[TMP6:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v2i32(i8* [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> [[TMP6]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_ptrvec_factor3(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %s1 = shufflevector <2 x i32*> %v2, <2 x i32*> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+  %interleaved.vec = shufflevector <4 x i32*> %s0, <4 x i32*> %s1, <6 x i32> <i32 0, i32 2, i32 4, i32 1, i32 3, i32 5>
+  store <6 x i32*> %interleaved.vec, <6 x i32*>* %ptr, align 4
+  ret void
+}
+
+define void @store_ptrvec_factor4(<8 x i32*>* %ptr, <2 x i32*> %v0, <2 x i32*> %v1, <2 x i32*> %v2, <2 x i32*> %v3) {
+; NEON-LABEL:    @store_ptrvec_factor4(
+; NEON:            [[TMP1:%.*]] = ptrtoint <4 x i32*> %s0 to <4 x i32>
+; NEON-NEXT:       [[TMP2:%.*]] = ptrtoint <4 x i32*> %s1 to <4 x i32>
+; NEON-NEXT:       [[TMP3:%.*]] = bitcast <8 x i32*>* %ptr to i8*
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <2 x i32> <i32 2, i32 3>
+; NEON-NEXT:       [[TMP6:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP7:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> [[TMP2]], <2 x i32> <i32 6, i32 7>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v2i32(i8* [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> [[TMP6]], <2 x i32> [[TMP7]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_ptrvec_factor4(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <2 x i32*> %v0, <2 x i32*> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %s1 = shufflevector <2 x i32*> %v2, <2 x i32*> %v3, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+  %interleaved.vec = shufflevector <4 x i32*> %s0, <4 x i32*> %s1, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
+  store <8 x i32*> %interleaved.vec, <8 x i32*>* %ptr, align 4
+  ret void
+}
+
+define void @load_undef_mask_factor2(<8 x i32>* %ptr) {
+; NEON-LABEL:    @load_undef_mask_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32>* %ptr to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP1]], i32 4)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_undef_mask_factor2(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <8 x i32>, <8 x i32>* %ptr, align 4
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 undef, i32 2, i32 undef, i32 6>
+  %v1 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <4 x i32> <i32 undef, i32 3, i32 undef, i32 7>
+  ret void
+}
+
+define void @load_undef_mask_factor3(<12 x i32>* %ptr) {
+; NEON-LABEL:    @load_undef_mask_factor3(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3.v4i32.p0i8(i8* [[TMP1]], i32 4)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 2
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_undef_mask_factor3(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <12 x i32>, <12 x i32>* %ptr, align 4
+  %v0 = shufflevector <12 x i32> %interleaved.vec, <12 x i32> undef, <4 x i32> <i32 0, i32 3, i32 6, i32 9>
+  %v1 = shufflevector <12 x i32> %interleaved.vec, <12 x i32> undef, <4 x i32> <i32 1, i32 4, i32 7, i32 10>
+  %v2 = shufflevector <12 x i32> %interleaved.vec, <12 x i32> undef, <4 x i32> <i32 2, i32 undef, i32 undef, i32 undef>
+  ret void
+}
+
+define void @load_undef_mask_factor4(<16 x i32>* %ptr) {
+; NEON-LABEL:    @load_undef_mask_factor4(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4.v4i32.p0i8(i8* [[TMP1]], i32 4)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 3
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 2
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_undef_mask_factor4(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <16 x i32>, <16 x i32>* %ptr, align 4
+  %v0 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 0, i32 4, i32 undef, i32 undef>
+  %v1 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 1, i32 5, i32 undef, i32 undef>
+  %v2 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 2, i32 6, i32 undef, i32 undef>
+  %v3 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <4 x i32> <i32 3, i32 7, i32 undef, i32 undef>
+  ret void
+}
+
+define void @store_undef_mask_factor2(<8 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1) {
+; NEON-LABEL:    @store_undef_mask_factor2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <4 x i32> %v0, <4 x i32> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <4 x i32> %v0, <4 x i32> %v1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       call void @llvm.arm.neon.vst2.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_undef_mask_factor2(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 undef, i32 undef, i32 undef, i32 undef, i32 2, i32 6, i32 3, i32 7>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_undef_mask_factor3(<12 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2) {
+; NEON-LABEL:    @store_undef_mask_factor3(
+; NEON:            [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_undef_mask_factor3(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x i32> %v2, <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+  %interleaved.vec = shufflevector <8 x i32> %s0, <8 x i32> %s1, <12 x i32> <i32 0, i32 4, i32 undef, i32 1, i32 undef, i32 9, i32 2, i32 6, i32 10, i32 3, i32 7, i32 11>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_undef_mask_factor4(<16 x i32>* %ptr, <4 x i32> %v0, <4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) {
+; NEON-LABEL:    @store_undef_mask_factor4(
+; NEON:            [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <8 x i32> %s0, <8 x i32> %s1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_undef_mask_factor4(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <4 x i32> %v0, <4 x i32> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x i32> %v2, <4 x i32> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %interleaved.vec = shufflevector <8 x i32> %s0, <8 x i32> %s1, <16 x i32> <i32 0, i32 4, i32 8, i32 undef, i32 undef, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
+  store <16 x i32> %interleaved.vec, <16 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @load_address_space(<8 x i32> addrspace(1)* %ptr) {
+; NEON-LABEL:    @load_address_space(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32> addrspace(1)* %ptr to i8 addrspace(1)*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3.v2i32.p1i8(i8 addrspace(1)* [[TMP1]], i32 0)
+; NEON-NEXT:       [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 2
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLDN]], 0
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_address_space(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <8 x i32>, <8 x i32> addrspace(1)* %ptr
+  %v0 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <2 x i32> <i32 0, i32 3>
+  %v1 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <2 x i32> <i32 1, i32 4>
+  %v2 = shufflevector <8 x i32> %interleaved.vec, <8 x i32> undef, <2 x i32> <i32 2, i32 5>
+  ret void
+}
+
+define void @store_address_space(<4 x i32> addrspace(1)* %ptr, <2 x i32> %v0, <2 x i32> %v1) {
+; NEON-LABEL:    @store_address_space(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <4 x i32> addrspace(1)* %ptr to i8 addrspace(1)*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <2 x i32> %v0, <2 x i32> %v1, <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <2 x i32> %v0, <2 x i32> %v1, <2 x i32> <i32 2, i32 3>
+; NEON-NEXT:       call void @llvm.arm.neon.vst2.p1i8.v2i32(i8 addrspace(1)* [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], i32 0)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_address_space(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <2 x i32> %v0, <2 x i32> %v1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
+  store <4 x i32> %interleaved.vec, <4 x i32> addrspace(1)* %ptr
+  ret void
+}
+
+define void @load_f16_factor2(<8 x half>* %ptr) {
+; ALL-LABEL: @load_f16_factor2(
+; ALL-NOT:     @llvm.arm.neon
+; ALL:         ret void
+;
+  %interleaved.vec = load <8 x half>, <8 x half>* %ptr, align 4
+  %v0 = shufflevector <8 x half> %interleaved.vec, <8 x half> undef, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+  %v1 = shufflevector <8 x half> %interleaved.vec, <8 x half> undef, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+  ret void
+}
+
+define void @store_f16_factor2(<8 x half>* %ptr, <4 x half> %v0, <4 x half> %v1) {
+; ALL-LABEL: @store_f16_factor2(
+; ALL-NOT:     @llvm.arm.neon
+; ALL:         ret void
+;
+  %interleaved.vec = shufflevector <4 x half> %v0, <4 x half> %v1, <8 x i32> <i32 0, i32 4, i32 1, i32 5, i32 2, i32 6, i32 3, i32 7>
+  store <8 x half> %interleaved.vec, <8 x half>* %ptr, align 4
+  ret void
+}
+
+define void @load_illegal_factor2(<3 x float>* %ptr) nounwind {
+; ALL-LABEL:    @load_illegal_factor2(
+; ALL-NOT:        @llvm.arm.neon
+; ALL:            ret void
+;
+  %interleaved.vec = load <3 x float>, <3 x float>* %ptr, align 16
+  %v0 = shufflevector <3 x float> %interleaved.vec, <3 x float> undef, <3 x i32> <i32 0, i32 2, i32 undef>
+  ret void
+}
+
+define void @store_illegal_factor2(<3 x float>* %ptr, <3 x float> %v0) nounwind {
+; ALL-LABEL: @store_illegal_factor2(
+; ALL-NOT:     @llvm.arm.neon
+; ALL:         ret void
+;
+  %interleaved.vec = shufflevector <3 x float> %v0, <3 x float> undef, <3 x i32> <i32 0, i32 2, i32 undef>
+  store <3 x float> %interleaved.vec, <3 x float>* %ptr, align 16
+  ret void
+}
+
+define void @store_general_mask_factor4(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 16, i32 17>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 32, i32 33>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v2i32(i8* [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 9>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor4_undefbeg(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4_undefbeg(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 16, i32 17>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 32, i32 33>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v2i32(i8* [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4_undefbeg(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 undef, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 9>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor4_undefend(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4_undefend(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 16, i32 17>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 32, i32 33>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v2i32(i8* [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4_undefend(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 16, i32 32, i32 8, i32 5, i32 17, i32 33, i32 undef>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor4_undefmid(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4_undefmid(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 16, i32 17>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 32, i32 33>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v2i32(i8* [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4_undefmid(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 undef, i32 32, i32 8, i32 5, i32 17, i32 undef, i32 9>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor4_undefmulti(<8 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor4_undefmulti(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <8 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 4, i32 5>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 0, i32 1>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <2 x i32> <i32 8, i32 9>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v2i32(i8* [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor4_undefmulti(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <8 x i32> <i32 4, i32 undef, i32 undef, i32 8, i32 undef, i32 undef, i32 undef, i32 9>
+  store <8 x i32> %interleaved.vec, <8 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 32, i32 33, i32 34, i32 35>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor3(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 5, i32 33, i32 17, i32 6, i32 34, i32 18, i32 7, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_undefmultimid(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3_undefmultimid(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 32, i32 33, i32 34, i32 35>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor3_undefmultimid(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 7, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_undef_fail(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; ALL-LABEL: @store_general_mask_factor3_undef_fail(
+; ALL-NOT:     @llvm.arm.neon
+; ALL:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 4, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 8, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_undeflane(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3_undeflane(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 32, i32 33, i32 34, i32 35>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor3_undeflane(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 undef, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_endstart_fail(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; ALL-LABEL:    @store_general_mask_factor3_endstart_fail(
+; ALL-NOT:        @llvm.arm.neon
+; ALL:            ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 2, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_endstart_pass(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3_endstart_pass(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 32, i32 33, i32 34, i32 35>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor3_endstart_pass(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 undef, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 7, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_midstart_fail(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; ALL-LABEL:    @store_general_mask_factor3_midstart_fail(
+; ALL-NOT:        @llvm.arm.neon
+; ALL:            ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 0, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 undef, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_general_mask_factor3_midstart_pass(<12 x i32>* %ptr, <32 x i32> %v0, <32 x i32> %v1) {
+; NEON-LABEL:    @store_general_mask_factor3_midstart_pass(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <12 x i32>* %ptr to i8*
+; NEON-NEXT:       [[TMP2:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 32, i32 33, i32 34, i32 35>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <32 x i32> %v0, <32 x i32> %v1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v4i32(i8* [[TMP1]], <4 x i32> [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_general_mask_factor3_midstart_pass(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <32 x i32> %v0, <32 x i32> %v1, <12 x i32> <i32 undef, i32 32, i32 16, i32 1, i32 33, i32 17, i32 undef, i32 34, i32 18, i32 undef, i32 35, i32 19>
+  store <12 x i32> %interleaved.vec, <12 x i32>* %ptr, align 4
+  ret void
+}
+
+ at g = external global <4 x float>
+
+; The following does not give a valid interleaved store
+; ALL-LABEL: define void @no_interleave
+; ALL-NOT: call void @llvm.arm.neon.vst2
+; ALL: shufflevector
+; ALL: store
+; ALL: ret void
+define void @no_interleave(<4 x float> %a0) {
+  %v0 = shufflevector <4 x float> %a0, <4 x float> %a0, <4 x i32> <i32 0, i32 7, i32 1, i32 undef>
+  store <4 x float> %v0, <4 x float>* @g, align 16
+  ret void
+}
+
+define void @load_factor2_wide2(<16 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor2_wide2(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP2]], i32 4)
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 0
+; NEON-NEXT:       [[TMP5:%.*]] = getelementptr i32, i32* [[TMP1]], i32 8
+; NEON-NEXT:       [[TMP6:%.*]] = bitcast i32* [[TMP5]] to i8*
+; NEON-NEXT:       [[VLDN1:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP6]], i32 4)
+; NEON-NEXT:       [[TMP7:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN1]], 1
+; NEON-NEXT:       [[TMP8:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN1]], 0
+; NEON-NEXT:       [[TMP9:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP7]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP10:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP8]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor2_wide2(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <16 x i32>, <16 x i32>* %ptr, align 4
+  %v0 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+  %v1 = shufflevector <16 x i32> %interleaved.vec, <16 x i32> undef, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+  ret void
+}
+
+define void @load_factor2_wide3(<24 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor2_wide3(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <24 x i32>* [[PTR:%.*]] to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP2]], i32 4)
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 0
+; NEON-NEXT:       [[TMP5:%.*]] = getelementptr i32, i32* [[TMP1]], i32 8
+; NEON-NEXT:       [[TMP6:%.*]] = bitcast i32* [[TMP5]] to i8*
+; NEON-NEXT:       [[VLDN1:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP6]], i32 4)
+; NEON-NEXT:       [[TMP7:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN1]], 1
+; NEON-NEXT:       [[TMP8:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN1]], 0
+; NEON-NEXT:       [[TMP9:%.*]] = getelementptr i32, i32* [[TMP5]], i32 8
+; NEON-NEXT:       [[TMP10:%.*]] = bitcast i32* [[TMP9]] to i8*
+; NEON-NEXT:       [[VLDN2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP10]], i32 4)
+; NEON-NEXT:       [[TMP11:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN2]], 1
+; NEON-NEXT:       [[TMP12:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN2]], 0
+; NEON-NEXT:       [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP7]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP14:%.*]] = shufflevector <4 x i32> [[TMP11]], <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+; NEON-NEXT:       [[TMP15:%.*]] = shufflevector <8 x i32> [[TMP13]], <8 x i32> [[TMP14]], <12 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP16:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP8]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP17:%.*]] = shufflevector <4 x i32> [[TMP12]], <4 x i32> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef>
+; NEON-NEXT:       [[TMP18:%.*]] = shufflevector <8 x i32> [[TMP16]], <8 x i32> [[TMP17]], <12 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor2_wide3(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <24 x i32>, <24 x i32>* %ptr, align 4
+  %v0 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <12 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14, i32 16, i32 18, i32 20, i32 22>
+  %v1 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <12 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15, i32 17, i32 19, i32 21, i32 23>
+  ret void
+}
+
+define void @load_factor3_wide(<24 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor3_wide(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <24 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3.v4i32.p0i8(i8* [[TMP2]], i32 4)
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 2
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 0
+; NEON-NEXT:       [[TMP6:%.*]] = getelementptr i32, i32* [[TMP1]], i32 12
+; NEON-NEXT:       [[TMP7:%.*]] = bitcast i32* [[TMP6]] to i8*
+; NEON-NEXT:       [[VLDN1:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3.v4i32.p0i8(i8* [[TMP7]], i32 4)
+; NEON-NEXT:       [[TMP8:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN1]], 2
+; NEON-NEXT:       [[TMP9:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN1]], 1
+; NEON-NEXT:       [[TMP10:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN1]], 0
+; NEON-NEXT:       [[TMP11:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP8]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP12:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP9]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP5]], <4 x i32> [[TMP10]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor3_wide(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <24 x i32>, <24 x i32>* %ptr, align 4
+  %v0 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <8 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 18, i32 21>
+  %v1 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <8 x i32> <i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22>
+  %v2 = shufflevector <24 x i32> %interleaved.vec, <24 x i32> undef, <8 x i32> <i32 2, i32 5, i32 8, i32 11, i32 14, i32 17, i32 20, i32 23>
+  ret void
+}
+
+define void @load_factor4_wide(<32 x i32>* %ptr) {
+; NEON-LABEL:    @load_factor4_wide(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <32 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4.v4i32.p0i8(i8* [[TMP2]], i32 4)
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 3
+; NEON-NEXT:       [[TMP4:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 2
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP6:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN]], 0
+; NEON-NEXT:       [[TMP7:%.*]] = getelementptr i32, i32* [[TMP1]], i32 16
+; NEON-NEXT:       [[TMP8:%.*]] = bitcast i32* [[TMP7]] to i8*
+; NEON-NEXT:       [[VLDN1:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4.v4i32.p0i8(i8* [[TMP8]], i32 4)
+; NEON-NEXT:       [[TMP9:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN1]], 3
+; NEON-NEXT:       [[TMP10:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN1]], 2
+; NEON-NEXT:       [[TMP11:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN1]], 1
+; NEON-NEXT:       [[TMP12:%.*]] = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLDN1]], 0
+; NEON-NEXT:       [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP9]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP14:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP10]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP15:%.*]] = shufflevector <4 x i32> [[TMP5]], <4 x i32> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP16:%.*]] = shufflevector <4 x i32> [[TMP6]], <4 x i32> [[TMP12]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor4_wide(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <32 x i32>, <32 x i32>* %ptr, align 4
+  %v0 = shufflevector <32 x i32> %interleaved.vec, <32 x i32> undef, <8 x i32> <i32 0, i32 4, i32 8, i32 12, i32 16, i32 20, i32 24, i32 28>
+  %v1 = shufflevector <32 x i32> %interleaved.vec, <32 x i32> undef, <8 x i32> <i32 1, i32 5, i32 9, i32 13, i32 17, i32 21, i32 25, i32 29>
+  %v2 = shufflevector <32 x i32> %interleaved.vec, <32 x i32> undef, <8 x i32> <i32 2, i32 6, i32 10, i32 14, i32 18, i32 22, i32 26, i32 30>
+  %v3 = shufflevector <32 x i32> %interleaved.vec, <32 x i32> undef, <8 x i32> <i32 3, i32 7, i32 11, i32 15, i32 19, i32 23, i32 27, i32 31>
+  ret void
+}
+
+define void @store_factor2_wide(<16 x i32>* %ptr, <8 x i32> %v0, <8 x i32> %v1) {
+; NEON-LABEL:    @store_factor2_wide(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8*
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <8 x i32> %v0, <8 x i32> %v1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <8 x i32> %v0, <8 x i32> %v1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       call void @llvm.arm.neon.vst2.p0i8.v4i32(i8* [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], i32 4)
+; NEON-NEXT:       [[TMP5:%.*]] = getelementptr i32, i32* [[TMP1]], i32 8
+; NEON-NEXT:       [[TMP6:%.*]] = bitcast i32* [[TMP5]] to i8*
+; NEON-NEXT:       [[TMP7:%.*]] = shufflevector <8 x i32> %v0, <8 x i32> %v1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP8:%.*]] = shufflevector <8 x i32> %v0, <8 x i32> %v1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       call void @llvm.arm.neon.vst2.p0i8.v4i32(i8* [[TMP6]], <4 x i32> [[TMP7]], <4 x i32> [[TMP8]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor2_wide(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = shufflevector <8 x i32> %v0, <8 x i32> %v1, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+  store <16 x i32> %interleaved.vec, <16 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_factor3_wide(<24 x i32>* %ptr, <8 x i32> %v0, <8 x i32> %v1, <8 x i32> %v2) {
+; NEON-LABEL:    @store_factor3_wide(
+; NEON:            [[TMP1:%.*]] = bitcast <24 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8*
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v4i32(i8* [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], i32 4)
+; NEON-NEXT:       [[TMP6:%.*]] = getelementptr i32, i32* [[TMP1]], i32 12
+; NEON-NEXT:       [[TMP7:%.*]] = bitcast i32* [[TMP6]] to i8*
+; NEON-NEXT:       [[TMP8:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP9:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       [[TMP10:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 20, i32 21, i32 22, i32 23>
+; NEON-NEXT:       call void @llvm.arm.neon.vst3.p0i8.v4i32(i8* [[TMP7]], <4 x i32> [[TMP8]], <4 x i32> [[TMP9]], <4 x i32> [[TMP10]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor3_wide(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <8 x i32> %v0, <8 x i32> %v1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %s1 = shufflevector <8 x i32> %v2, <8 x i32> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+  %interleaved.vec = shufflevector <16 x i32> %s0, <16 x i32> %s1, <24 x i32> <i32 0, i32 8, i32 16, i32 1, i32 9, i32 17, i32 2, i32 10, i32 18, i32 3, i32 11, i32 19, i32 4, i32 12, i32 20, i32 5, i32 13, i32 21, i32 6, i32 14, i32 22, i32 7, i32 15, i32 23>
+  store <24 x i32> %interleaved.vec, <24 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @store_factor4_wide(<32 x i32>* %ptr, <8 x i32> %v0, <8 x i32> %v1, <8 x i32> %v2, <8 x i32> %v3) {
+; NEON-LABEL:    @store_factor4_wide(
+; NEON:            [[TMP1:%.*]] = bitcast <32 x i32>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8*
+; NEON-NEXT:       [[TMP3:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; NEON-NEXT:       [[TMP4:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; NEON-NEXT:       [[TMP5:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; NEON-NEXT:       [[TMP6:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 24, i32 25, i32 26, i32 27>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v4i32(i8* [[TMP2]], <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> [[TMP6]], i32 4)
+; NEON-NEXT:       [[TMP7:%.*]] = getelementptr i32, i32* [[TMP1]], i32 16
+; NEON-NEXT:       [[TMP8:%.*]] = bitcast i32* [[TMP7]] to i8*
+; NEON-NEXT:       [[TMP9:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP10:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; NEON-NEXT:       [[TMP11:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 20, i32 21, i32 22, i32 23>
+; NEON-NEXT:       [[TMP12:%.*]] = shufflevector <16 x i32> %s0, <16 x i32> %s1, <4 x i32> <i32 28, i32 29, i32 30, i32 31>
+; NEON-NEXT:       call void @llvm.arm.neon.vst4.p0i8.v4i32(i8* [[TMP8]], <4 x i32> [[TMP9]], <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], i32 4)
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @store_factor4_wide(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %s0 = shufflevector <8 x i32> %v0, <8 x i32> %v1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %s1 = shufflevector <8 x i32> %v2, <8 x i32> %v3, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %interleaved.vec = shufflevector <16 x i32> %s0, <16 x i32> %s1, <32 x i32> <i32 0, i32 8, i32 16, i32 24, i32 1, i32 9, i32 17, i32 25, i32 2, i32 10, i32 18, i32 26, i32 3, i32 11, i32 19, i32 27, i32 4, i32 12, i32 20, i32 28, i32 5, i32 13, i32 21, i32 29, i32 6, i32 14, i32 22, i32 30, i32 7, i32 15, i32 23, i32 31>
+  store <32 x i32> %interleaved.vec, <32 x i32>* %ptr, align 4
+  ret void
+}
+
+define void @load_factor2_fp128(<4 x fp128>* %ptr) {
+; ALL-LABEL: @load_factor2_fp128(
+; ALL-NOT:     @llvm.arm.neon
+; ALL:         ret void
+;
+  %interleaved.vec = load <4 x fp128>, <4 x fp128>* %ptr, align 16
+  %v0 = shufflevector <4 x fp128> %interleaved.vec, <4 x fp128> undef, <2 x i32> <i32 0, i32 2>
+  %v1 = shufflevector <4 x fp128> %interleaved.vec, <4 x fp128> undef, <2 x i32> <i32 1, i32 3>
+  ret void
+}
+
+define void @load_factor2_wide_pointer(<16 x i32*>* %ptr) {
+; NEON-LABEL:    @load_factor2_wide_pointer(
+; NEON-NEXT:       [[TMP1:%.*]] = bitcast <16 x i32*>* %ptr to i32*
+; NEON-NEXT:       [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8*
+; NEON-NEXT:       [[VLDN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP2]], i32 4)
+; NEON-NEXT:       [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 1
+; NEON-NEXT:       [[TMP4:%.*]] = inttoptr <4 x i32> [[TMP3]] to <4 x i32*>
+; NEON-NEXT:       [[TMP5:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN]], 0
+; NEON-NEXT:       [[TMP6:%.*]] = inttoptr <4 x i32> [[TMP5]] to <4 x i32*>
+; NEON-NEXT:       [[TMP7:%.*]] = getelementptr i32, i32* [[TMP1]], i32 8
+; NEON-NEXT:       [[TMP8:%.*]] = bitcast i32* [[TMP7]] to i8*
+; NEON-NEXT:       [[VLDN1:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP8]], i32 4)
+; NEON-NEXT:       [[TMP9:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN1]], 1
+; NEON-NEXT:       [[TMP10:%.*]] = inttoptr <4 x i32> [[TMP9]] to <4 x i32*>
+; NEON-NEXT:       [[TMP11:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[VLDN1]], 0
+; NEON-NEXT:       [[TMP12:%.*]] = inttoptr <4 x i32> [[TMP11]] to <4 x i32*>
+; NEON-NEXT:       [[TMP13:%.*]] = shufflevector <4 x i32*> [[TMP4]], <4 x i32*> [[TMP10]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       [[TMP14:%.*]] = shufflevector <4 x i32*> [[TMP6]], <4 x i32*> [[TMP12]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; NEON-NEXT:       ret void
+; NO_NEON-LABEL: @load_factor2_wide_pointer(
+; NO_NEON-NOT:     @llvm.arm.neon
+; NO_NEON:         ret void
+;
+  %interleaved.vec = load <16 x i32*>, <16 x i32*>* %ptr, align 4
+  %v0 = shufflevector <16 x i32*> %interleaved.vec, <16 x i32*> undef, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+  %v1 = shufflevector <16 x i32*> %interleaved.vec, <16 x i32*> undef, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+  ret void
+}
+
+; This would be a candidate for interleaving, except that load doesn't
+; actually load enough elements to satisfy the shuffle masks. (It would be
+; possible to produce a vld2.v2i32, but that currently isn't implemented.)
+define void @load_out_of_range(<4 x i32>* %ptr) {
+; ALL-LABEL: @load_out_of_range(
+; ALL-NOT:     @llvm.arm.neon
+; ALL:         ret void
+  %interleaved.vec = load <4 x i32>, <4 x i32>* %ptr, align 4
+  %v0 = shufflevector <4 x i32> %interleaved.vec, <4 x i32> undef, <4 x i32> <i32 0, i32 2, i32 undef, i32 undef>
+  %v1 = shufflevector <4 x i32> %interleaved.vec, <4 x i32> undef, <4 x i32> <i32 1, i32 3, i32 undef, i32 undef>
+  ret void
+}

Added: llvm/trunk/test/Transforms/InterleavedAccess/ARM/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/ARM/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/ARM/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/ARM/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,2 @@
+if not 'ARM' in config.root.targets:
+  config.unsupported = True

Added: llvm/trunk/test/Transforms/InterleavedAccess/X86/interleaved-accesses-64bits-avx.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/X86/interleaved-accesses-64bits-avx.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/X86/interleaved-accesses-64bits-avx.ll (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/X86/interleaved-accesses-64bits-avx.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,236 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -mtriple=x86_64-pc-linux  -mattr=+avx -interleaved-access -S | FileCheck %s
+
+; This file tests the function `llvm::lowerInterleavedLoad/Store`.
+
+define <4 x double> @load_factorf64_4(<16 x double>* %ptr) {
+; CHECK-LABEL: @load_factorf64_4(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <16 x double>* %ptr to <4 x double>*
+; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr <4 x double>, <4 x double>* [[TMP1]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[TMP2]], align 16
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr <4 x double>, <4 x double>* [[TMP1]], i32 1
+; CHECK-NEXT:    [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[TMP4]], align 16
+; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr <4 x double>, <4 x double>* [[TMP1]], i32 2
+; CHECK-NEXT:    [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[TMP6]], align 16
+; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr <4 x double>, <4 x double>* [[TMP1]], i32 3
+; CHECK-NEXT:    [[TMP9:%.*]] = load <4 x double>, <4 x double>* [[TMP8]], align 16
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <4 x double> [[TMP3]], <4 x double> [[TMP7]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP9]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <4 x double> [[TMP3]], <4 x double> [[TMP7]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP9]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> [[TMP11]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <4 x double> [[TMP12]], <4 x double> [[TMP13]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP16:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> [[TMP11]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP17:%.*]] = shufflevector <4 x double> [[TMP12]], <4 x double> [[TMP13]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[ADD1:%.*]] = fadd <4 x double> [[TMP14]], [[TMP16]]
+; CHECK-NEXT:    [[ADD2:%.*]] = fadd <4 x double> [[ADD1]], [[TMP15]]
+; CHECK-NEXT:    [[ADD3:%.*]] = fadd <4 x double> [[ADD2]], [[TMP17]]
+; CHECK-NEXT:    ret <4 x double> [[ADD3]]
+;
+  %wide.vec = load <16 x double>, <16 x double>* %ptr, align 16
+  %strided.v0 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
+  %strided.v1 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> <i32 1, i32 5, i32 9, i32 13>
+  %strided.v2 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> <i32 2, i32 6, i32 10, i32 14>
+  %strided.v3 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> <i32 3, i32 7, i32 11, i32 15>
+  %add1 = fadd <4 x double> %strided.v0, %strided.v1
+  %add2 = fadd <4 x double> %add1, %strided.v2
+  %add3 = fadd <4 x double> %add2, %strided.v3
+  ret <4 x double> %add3
+}
+
+define <4 x i64> @load_factori64_4(<16 x i64>* %ptr) {
+; CHECK-LABEL: @load_factori64_4(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <16 x i64>* %ptr to <4 x i64>*
+; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr <4 x i64>, <4 x i64>* [[TMP1]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 16
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr <4 x i64>, <4 x i64>* [[TMP1]], i32 1
+; CHECK-NEXT:    [[TMP5:%.*]] = load <4 x i64>, <4 x i64>* [[TMP4]], align 16
+; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr <4 x i64>, <4 x i64>* [[TMP1]], i32 2
+; CHECK-NEXT:    [[TMP7:%.*]] = load <4 x i64>, <4 x i64>* [[TMP6]], align 16
+; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr <4 x i64>, <4 x i64>* [[TMP1]], i32 3
+; CHECK-NEXT:    [[TMP9:%.*]] = load <4 x i64>, <4 x i64>* [[TMP8]], align 16
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <4 x i64> [[TMP3]], <4 x i64> [[TMP7]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <4 x i64> [[TMP5]], <4 x i64> [[TMP9]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <4 x i64> [[TMP3]], <4 x i64> [[TMP7]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <4 x i64> [[TMP5]], <4 x i64> [[TMP9]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <4 x i64> [[TMP10]], <4 x i64> [[TMP11]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> [[TMP13]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP16:%.*]] = shufflevector <4 x i64> [[TMP10]], <4 x i64> [[TMP11]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP17:%.*]] = shufflevector <4 x i64> [[TMP12]], <4 x i64> [[TMP13]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[ADD1:%.*]] = add <4 x i64> [[TMP14]], [[TMP16]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add <4 x i64> [[ADD1]], [[TMP15]]
+; CHECK-NEXT:    [[ADD3:%.*]] = add <4 x i64> [[ADD2]], [[TMP17]]
+; CHECK-NEXT:    ret <4 x i64> [[ADD3]]
+;
+  %wide.vec = load <16 x i64>, <16 x i64>* %ptr, align 16
+  %strided.v0 = shufflevector <16 x i64> %wide.vec, <16 x i64> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
+  %strided.v1 = shufflevector <16 x i64> %wide.vec, <16 x i64> undef, <4 x i32> <i32 1, i32 5, i32 9, i32 13>
+  %strided.v2 = shufflevector <16 x i64> %wide.vec, <16 x i64> undef, <4 x i32> <i32 2, i32 6, i32 10, i32 14>
+  %strided.v3 = shufflevector <16 x i64> %wide.vec, <16 x i64> undef, <4 x i32> <i32 3, i32 7, i32 11, i32 15>
+  %add1 = add <4 x i64> %strided.v0, %strided.v1
+  %add2 = add <4 x i64> %add1, %strided.v2
+  %add3 = add <4 x i64> %add2, %strided.v3
+  ret <4 x i64> %add3
+}
+
+define <4 x double> @load_factorf64_1(<16 x double>* %ptr) {
+; CHECK-LABEL: @load_factorf64_1(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <16 x double>* %ptr to <4 x double>*
+; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr <4 x double>, <4 x double>* [[TMP1]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = load <4 x double>, <4 x double>* [[TMP2]], align 16
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr <4 x double>, <4 x double>* [[TMP1]], i32 1
+; CHECK-NEXT:    [[TMP5:%.*]] = load <4 x double>, <4 x double>* [[TMP4]], align 16
+; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr <4 x double>, <4 x double>* [[TMP1]], i32 2
+; CHECK-NEXT:    [[TMP7:%.*]] = load <4 x double>, <4 x double>* [[TMP6]], align 16
+; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr <4 x double>, <4 x double>* [[TMP1]], i32 3
+; CHECK-NEXT:    [[TMP9:%.*]] = load <4 x double>, <4 x double>* [[TMP8]], align 16
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <4 x double> [[TMP3]], <4 x double> [[TMP7]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP9]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <4 x double> [[TMP3]], <4 x double> [[TMP7]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP9]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> [[TMP11]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <4 x double> [[TMP12]], <4 x double> [[TMP13]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP16:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> [[TMP11]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP17:%.*]] = shufflevector <4 x double> [[TMP12]], <4 x double> [[TMP13]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[MUL:%.*]] = fmul <4 x double> [[TMP14]], [[TMP14]]
+; CHECK-NEXT:    ret <4 x double> [[MUL]]
+;
+  %wide.vec = load <16 x double>, <16 x double>* %ptr, align 16
+  %strided.v0 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
+  %strided.v3 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
+  %mul = fmul <4 x double> %strided.v0, %strided.v3
+  ret <4 x double> %mul
+}
+
+define void @store_factorf64_4(<16 x double>* %ptr, <4 x double> %v0, <4 x double> %v1, <4 x double> %v2, <4 x double> %v3) {
+; CHECK-LABEL: @store_factorf64_4(
+; CHECK-NEXT:    [[S0:%.*]] = shufflevector <4 x double> [[V0:%.*]], <4 x double> [[V1:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[S1:%.*]] = shufflevector <4 x double> [[V2:%.*]], <4 x double> [[V3:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x double> [[S0]], <8 x double> [[S1]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x double> [[S0]], <8 x double> [[S1]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <8 x double> [[S0]], <8 x double> [[S1]], <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <8 x double> [[S0]], <8 x double> [[S1]], <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <4 x double> [[TMP1]], <4 x double> [[TMP3]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <4 x double> [[TMP2]], <4 x double> [[TMP4]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <4 x double> [[TMP1]], <4 x double> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <4 x double> [[TMP2]], <4 x double> [[TMP4]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP6]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <4 x double> [[TMP7]], <4 x double> [[TMP8]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP6]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <4 x double> [[TMP7]], <4 x double> [[TMP8]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <4 x double> [[TMP9]], <4 x double> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> [[TMP12]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <8 x double> [[TMP13]], <8 x double> [[TMP14]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    store <16 x double> [[TMP15]], <16 x double>* [[PTR:%.*]], align 16
+; CHECK-NEXT:    ret void
+;
+  %s0 = shufflevector <4 x double> %v0, <4 x double> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x double> %v2, <4 x double> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %interleaved.vec = shufflevector <8 x double> %s0, <8 x double> %s1, <16 x i32> <i32 0, i32 4, i32 8, i32 12, i32 1, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
+  store <16 x double> %interleaved.vec, <16 x double>* %ptr, align 16
+  ret void
+}
+
+define void @store_factori64_4(<16 x i64>* %ptr, <4 x i64> %v0, <4 x i64> %v1, <4 x i64> %v2, <4 x i64> %v3) {
+; CHECK-LABEL: @store_factori64_4(
+; CHECK-NEXT:    [[S0:%.*]] = shufflevector <4 x i64> [[V0:%.*]], <4 x i64> [[V1:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[S1:%.*]] = shufflevector <4 x i64> [[V2:%.*]], <4 x i64> [[V3:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i64> [[S0]], <8 x i64> [[S1]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i64> [[S0]], <8 x i64> [[S1]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <8 x i64> [[S0]], <8 x i64> [[S1]], <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <8 x i64> [[S0]], <8 x i64> [[S1]], <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <4 x i64> [[TMP1]], <4 x i64> [[TMP3]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <4 x i64> [[TMP2]], <4 x i64> [[TMP4]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <4 x i64> [[TMP1]], <4 x i64> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <4 x i64> [[TMP2]], <4 x i64> [[TMP4]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <4 x i64> [[TMP5]], <4 x i64> [[TMP6]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <4 x i64> [[TMP7]], <4 x i64> [[TMP8]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <4 x i64> [[TMP5]], <4 x i64> [[TMP6]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <4 x i64> [[TMP7]], <4 x i64> [[TMP8]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <4 x i64> [[TMP9]], <4 x i64> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <4 x i64> [[TMP10]], <4 x i64> [[TMP12]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <8 x i64> [[TMP13]], <8 x i64> [[TMP14]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    store <16 x i64> [[TMP15]], <16 x i64>* [[PTR:%.*]], align 16
+; CHECK-NEXT:    ret void
+;
+  %s0 = shufflevector <4 x i64> %v0, <4 x i64> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x i64> %v2, <4 x i64> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %interleaved.vec = shufflevector <8 x i64> %s0, <8 x i64> %s1, <16 x i32> <i32 0, i32 4, i32 8, i32 12, i32 1, i32 5, i32 9, i32 13, i32 2, i32 6, i32 10, i32 14, i32 3, i32 7, i32 11, i32 15>
+  store <16 x i64> %interleaved.vec, <16 x i64>* %ptr, align 16
+  ret void
+}
+
+define void @store_factorf64_4_revMask(<16 x double>* %ptr, <4 x double> %v0, <4 x double> %v1, <4 x double> %v2, <4 x double> %v3) {
+; CHECK-LABEL: @store_factorf64_4_revMask(
+; CHECK-NEXT:    [[S0:%.*]] = shufflevector <4 x double> [[V0:%.*]], <4 x double> [[V1:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[S1:%.*]] = shufflevector <4 x double> [[V2:%.*]], <4 x double> [[V3:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x double> [[S0]], <8 x double> [[S1]], <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x double> [[S0]], <8 x double> [[S1]], <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <8 x double> [[S0]], <8 x double> [[S1]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <8 x double> [[S0]], <8 x double> [[S1]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <4 x double> [[TMP1]], <4 x double> [[TMP3]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <4 x double> [[TMP2]], <4 x double> [[TMP4]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <4 x double> [[TMP1]], <4 x double> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <4 x double> [[TMP2]], <4 x double> [[TMP4]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP6]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <4 x double> [[TMP7]], <4 x double> [[TMP8]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP6]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <4 x double> [[TMP7]], <4 x double> [[TMP8]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <4 x double> [[TMP9]], <4 x double> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> [[TMP12]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <8 x double> [[TMP13]], <8 x double> [[TMP14]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    store <16 x double> [[TMP15]], <16 x double>* [[PTR:%.*]], align 16
+; CHECK-NEXT:    ret void
+;
+  %s0 = shufflevector <4 x double> %v0, <4 x double> %v1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %s1 = shufflevector <4 x double> %v2, <4 x double> %v3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+  %interleaved.vec = shufflevector <8 x double> %s0, <8 x double> %s1, <16 x i32> <i32 12, i32 8, i32 4, i32 0, i32 13, i32 9, i32 5, i32 1, i32 14, i32 10, i32 6, i32 2, i32 15, i32 11, i32 7, i32 3>
+  store <16 x double> %interleaved.vec, <16 x double>* %ptr, align 16
+  ret void
+}
+
+define void @store_factorf64_4_arbitraryMask(<16 x double>* %ptr, <16 x double> %v0, <16 x double> %v1, <16 x double> %v2, <16 x double> %v3) {
+; CHECK-LABEL: @store_factorf64_4_arbitraryMask(
+; CHECK-NEXT:    [[S0:%.*]] = shufflevector <16 x double> [[V0:%.*]], <16 x double> [[V1:%.*]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[S1:%.*]] = shufflevector <16 x double> [[V2:%.*]], <16 x double> [[V3:%.*]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <32 x double> [[S0]], <32 x double> [[S1]], <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <32 x double> [[S0]], <32 x double> [[S1]], <4 x i32> <i32 32, i32 33, i32 34, i32 35>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <32 x double> [[S0]], <32 x double> [[S1]], <4 x i32> <i32 16, i32 17, i32 18, i32 19>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <32 x double> [[S0]], <32 x double> [[S1]], <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <4 x double> [[TMP1]], <4 x double> [[TMP3]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <4 x double> [[TMP2]], <4 x double> [[TMP4]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <4 x double> [[TMP1]], <4 x double> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <4 x double> [[TMP2]], <4 x double> [[TMP4]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP6]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <4 x double> [[TMP7]], <4 x double> [[TMP8]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <4 x double> [[TMP5]], <4 x double> [[TMP6]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <4 x double> [[TMP7]], <4 x double> [[TMP8]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <4 x double> [[TMP9]], <4 x double> [[TMP11]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <4 x double> [[TMP10]], <4 x double> [[TMP12]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <8 x double> [[TMP13]], <8 x double> [[TMP14]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    store <16 x double> [[TMP15]], <16 x double>* [[PTR:%.*]], align 16
+; CHECK-NEXT:    ret void
+;
+  %s0 = shufflevector <16 x double> %v0, <16 x double> %v1, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+  %s1 = shufflevector <16 x double> %v2, <16 x double> %v3, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+  %interleaved.vec = shufflevector <32 x double> %s0, <32 x double> %s1, <16 x i32> <i32 4, i32 32, i32 16, i32 8, i32 5, i32 33, i32 17, i32 9, i32 6, i32 34, i32 18, i32 10, i32 7, i32 35, i32 19, i32 11>
+  store <16 x double> %interleaved.vec, <16 x double>* %ptr, align 16
+  ret void
+}
+
+; This verifies whether the test passes and does not hit any assertions.
+; Today, X86InterleavedAccess could have handled this case and
+; generate transposed sequence by extending the current implementation
+; which would be creating dummy vectors of undef. But it decided not to
+; optimize these cases where the load-size is less than Factor * NumberOfElements.
+; Because a better sequence can easily be generated by CG.
+
+ at a = local_unnamed_addr global <4 x double> zeroinitializer, align 32
+; Function Attrs: norecurse nounwind readonly uwtable
+define <4 x double> @test_unhandled(<4 x double> %b) {
+entry:
+  %0 = load <4 x double>, <4 x double>* @a, align 32
+  %1 = shufflevector <4 x double> %0, <4 x double> undef, <4 x i32> <i32 3, i32 undef, i32 undef, i32 undef>
+  %shuffle = shufflevector <4 x double> %1, <4 x double> %b, <4 x i32> <i32 0, i32 4, i32 0, i32 0>
+  ret <4 x double> %shuffle
+}

Added: llvm/trunk/test/Transforms/InterleavedAccess/X86/interleavedLoad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/X86/interleavedLoad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/X86/interleavedLoad.ll (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/X86/interleavedLoad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,158 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -mtriple=x86_64-pc-linux -mattr=+avx2 -interleaved-access -S | FileCheck %s --check-prefix=AVX2
+; RUN: opt < %s -mtriple=x86_64-pc-linux -mattr=+avx512f -mattr=+avx512bw -mattr=+avx512vl -interleaved-access -S | FileCheck %s --check-prefix=AVX2 --check-prefix=AVX512
+
+define <32 x i8> @interleaved_load_vf32_i8_stride3(<96 x i8>* %ptr){
+; AVX2-LABEL: @interleaved_load_vf32_i8_stride3(
+; AVX2-NEXT:    [[TMP1:%.*]] = bitcast <96 x i8>* [[PTR:%.*]] to <16 x i8>*
+; AVX2-NEXT:    [[TMP2:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 0
+; AVX2-NEXT:    [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[TMP2]]
+; AVX2-NEXT:    [[TMP4:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 1
+; AVX2-NEXT:    [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[TMP4]]
+; AVX2-NEXT:    [[TMP6:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 2
+; AVX2-NEXT:    [[TMP7:%.*]] = load <16 x i8>, <16 x i8>* [[TMP6]]
+; AVX2-NEXT:    [[TMP8:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 3
+; AVX2-NEXT:    [[TMP9:%.*]] = load <16 x i8>, <16 x i8>* [[TMP8]]
+; AVX2-NEXT:    [[TMP10:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 4
+; AVX2-NEXT:    [[TMP11:%.*]] = load <16 x i8>, <16 x i8>* [[TMP10]]
+; AVX2-NEXT:    [[TMP12:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 5
+; AVX2-NEXT:    [[TMP13:%.*]] = load <16 x i8>, <16 x i8>* [[TMP12]]
+; AVX2-NEXT:    [[TMP14:%.*]] = shufflevector <16 x i8> [[TMP3]], <16 x i8> [[TMP9]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; AVX2-NEXT:    [[TMP15:%.*]] = shufflevector <16 x i8> [[TMP5]], <16 x i8> [[TMP11]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; AVX2-NEXT:    [[TMP16:%.*]] = shufflevector <16 x i8> [[TMP7]], <16 x i8> [[TMP13]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; AVX2-NEXT:    [[TMP17:%.*]] = shufflevector <32 x i8> [[TMP14]], <32 x i8> undef, <32 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 2, i32 5, i32 8, i32 11, i32 14, i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22, i32 25, i32 28, i32 31, i32 18, i32 21, i32 24, i32 27, i32 30, i32 17, i32 20, i32 23, i32 26, i32 29>
+; AVX2-NEXT:    [[TMP18:%.*]] = shufflevector <32 x i8> [[TMP15]], <32 x i8> undef, <32 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 2, i32 5, i32 8, i32 11, i32 14, i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22, i32 25, i32 28, i32 31, i32 18, i32 21, i32 24, i32 27, i32 30, i32 17, i32 20, i32 23, i32 26, i32 29>
+; AVX2-NEXT:    [[TMP19:%.*]] = shufflevector <32 x i8> [[TMP16]], <32 x i8> undef, <32 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 2, i32 5, i32 8, i32 11, i32 14, i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22, i32 25, i32 28, i32 31, i32 18, i32 21, i32 24, i32 27, i32 30, i32 17, i32 20, i32 23, i32 26, i32 29>
+; AVX2-NEXT:    [[TMP20:%.*]] = shufflevector <32 x i8> [[TMP19]], <32 x i8> [[TMP17]], <32 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58>
+; AVX2-NEXT:    [[TMP21:%.*]] = shufflevector <32 x i8> [[TMP17]], <32 x i8> [[TMP18]], <32 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58>
+; AVX2-NEXT:    [[TMP22:%.*]] = shufflevector <32 x i8> [[TMP18]], <32 x i8> [[TMP19]], <32 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58>
+; AVX2-NEXT:    [[TMP23:%.*]] = shufflevector <32 x i8> [[TMP21]], <32 x i8> [[TMP20]], <32 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58>
+; AVX2-NEXT:    [[TMP24:%.*]] = shufflevector <32 x i8> [[TMP22]], <32 x i8> [[TMP21]], <32 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58>
+; AVX2-NEXT:    [[TMP25:%.*]] = shufflevector <32 x i8> [[TMP20]], <32 x i8> [[TMP22]], <32 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58>
+; AVX2-NEXT:    [[TMP26:%.*]] = shufflevector <32 x i8> [[TMP24]], <32 x i8> undef, <32 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 16, i32 17, i32 18, i32 19, i32 20>
+; AVX2-NEXT:    [[TMP27:%.*]] = shufflevector <32 x i8> [[TMP23]], <32 x i8> undef, <32 x i32> <i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25>
+; AVX2-NEXT:    [[ADD1:%.*]] = add <32 x i8> [[TMP27]], [[TMP26]]
+; AVX2-NEXT:    [[ADD2:%.*]] = add <32 x i8> [[TMP25]], [[ADD1]]
+; AVX2-NEXT:    ret <32 x i8> [[ADD2]]
+;
+  %wide.vec = load <96 x i8>, <96 x i8>* %ptr
+  %v1 = shufflevector <96 x i8> %wide.vec, <96 x i8> undef,<32 x i32> <i32 0,i32 3,i32 6,i32 9,i32 12,i32 15,i32 18,i32 21,i32 24,i32 27,i32 30,i32 33,i32 36,i32 39,i32 42,i32 45,i32 48,i32 51,i32 54,i32 57,i32 60,i32 63,i32 66,i32 69,i32 72,i32 75,i32 78,i32 81,i32 84,i32 87,i32 90,i32 93>
+  %v2 = shufflevector <96 x i8> %wide.vec, <96 x i8> undef,<32 x i32> <i32 1,i32 4,i32 7,i32 10,i32 13,i32 16,i32 19,i32 22,i32 25,i32 28,i32 31,i32 34,i32 37,i32 40,i32 43,i32 46,i32 49,i32 52,i32 55,i32 58,i32 61,i32 64,i32 67,i32 70,i32 73,i32 76,i32 79,i32 82,i32 85,i32 88,i32 91,i32 94>
+  %v3 = shufflevector <96 x i8> %wide.vec, <96 x i8> undef,<32 x i32> <i32 2,i32 5,i32 8,i32 11,i32 14,i32 17,i32 20,i32 23,i32 26,i32 29,i32 32,i32 35,i32 38,i32 41,i32 44,i32 47,i32 50,i32 53,i32 56,i32 59,i32 62,i32 65,i32 68,i32 71,i32 74,i32 77,i32 80,i32 83,i32 86,i32 89,i32 92,i32 95>
+  %add1 = add <32 x i8> %v1, %v2
+  %add2 = add <32 x i8> %v3, %add1
+  ret <32 x i8> %add2
+}
+
+define <16 x i8> @interleaved_load_vf16_i8_stride3(<48 x i8>* %ptr){
+; AVX2-LABEL: @interleaved_load_vf16_i8_stride3(
+; AVX2-NEXT:    [[TMP1:%.*]] = bitcast <48 x i8>* [[PTR:%.*]] to <16 x i8>*
+; AVX2-NEXT:    [[TMP2:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 0
+; AVX2-NEXT:    [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[TMP2]]
+; AVX2-NEXT:    [[TMP4:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 1
+; AVX2-NEXT:    [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[TMP4]]
+; AVX2-NEXT:    [[TMP6:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 2
+; AVX2-NEXT:    [[TMP7:%.*]] = load <16 x i8>, <16 x i8>* [[TMP6]]
+; AVX2-NEXT:    [[TMP8:%.*]] = shufflevector <16 x i8> [[TMP3]], <16 x i8> undef, <16 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 2, i32 5, i32 8, i32 11, i32 14, i32 1, i32 4, i32 7, i32 10, i32 13>
+; AVX2-NEXT:    [[TMP9:%.*]] = shufflevector <16 x i8> [[TMP5]], <16 x i8> undef, <16 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 2, i32 5, i32 8, i32 11, i32 14, i32 1, i32 4, i32 7, i32 10, i32 13>
+; AVX2-NEXT:    [[TMP10:%.*]] = shufflevector <16 x i8> [[TMP7]], <16 x i8> undef, <16 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 2, i32 5, i32 8, i32 11, i32 14, i32 1, i32 4, i32 7, i32 10, i32 13>
+; AVX2-NEXT:    [[TMP11:%.*]] = shufflevector <16 x i8> [[TMP10]], <16 x i8> [[TMP8]], <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
+; AVX2-NEXT:    [[TMP12:%.*]] = shufflevector <16 x i8> [[TMP8]], <16 x i8> [[TMP9]], <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
+; AVX2-NEXT:    [[TMP13:%.*]] = shufflevector <16 x i8> [[TMP9]], <16 x i8> [[TMP10]], <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
+; AVX2-NEXT:    [[TMP14:%.*]] = shufflevector <16 x i8> [[TMP12]], <16 x i8> [[TMP11]], <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
+; AVX2-NEXT:    [[TMP15:%.*]] = shufflevector <16 x i8> [[TMP13]], <16 x i8> [[TMP12]], <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
+; AVX2-NEXT:    [[TMP16:%.*]] = shufflevector <16 x i8> [[TMP11]], <16 x i8> [[TMP13]], <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
+; AVX2-NEXT:    [[TMP17:%.*]] = shufflevector <16 x i8> [[TMP15]], <16 x i8> undef, <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4>
+; AVX2-NEXT:    [[TMP18:%.*]] = shufflevector <16 x i8> [[TMP14]], <16 x i8> undef, <16 x i32> <i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9>
+; AVX2-NEXT:    [[ADD1:%.*]] = add <16 x i8> [[TMP18]], [[TMP17]]
+; AVX2-NEXT:    [[ADD2:%.*]] = add <16 x i8> [[TMP16]], [[ADD1]]
+; AVX2-NEXT:    ret <16 x i8> [[ADD2]]
+;
+  %wide.vec = load <48 x i8>, <48 x i8>* %ptr
+  %v1 = shufflevector <48 x i8> %wide.vec, <48 x i8> undef,<16 x i32> <i32 0,i32 3,i32 6,i32 9,i32 12,i32 15,i32 18,i32 21,i32 24,i32 27,i32 30,i32 33,i32 36,i32 39,i32 42 ,i32 45>
+  %v2 = shufflevector <48 x i8> %wide.vec, <48 x i8> undef,<16 x i32> <i32 1,i32 4,i32 7,i32 10,i32 13,i32 16,i32 19,i32 22,i32 25,i32 28,i32 31,i32 34,i32 37,i32 40,i32 43,i32 46>
+  %v3 = shufflevector <48 x i8> %wide.vec, <48 x i8> undef,<16 x i32> <i32 2,i32 5,i32 8,i32 11,i32 14,i32 17,i32 20,i32 23,i32 26,i32 29,i32 32,i32 35,i32 38,i32 41,i32 44,i32 47>
+  %add1 = add <16 x i8> %v1, %v2
+  %add2 = add <16 x i8> %v3, %add1
+  ret <16 x i8> %add2
+}
+
+define <8 x i8> @interleaved_load_vf8_i8_stride3(<24 x i8>* %ptr){
+; AVX2-LABEL: @interleaved_load_vf8_i8_stride3(
+; AVX2-NEXT:    [[WIDE_VEC:%.*]] = load <24 x i8>, <24 x i8>* [[PTR:%.*]]
+; AVX2-NEXT:    [[V1:%.*]] = shufflevector <24 x i8> [[WIDE_VEC]], <24 x i8> undef, <8 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 18, i32 21>
+; AVX2-NEXT:    [[V2:%.*]] = shufflevector <24 x i8> [[WIDE_VEC]], <24 x i8> undef, <8 x i32> <i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22>
+; AVX2-NEXT:    [[V3:%.*]] = shufflevector <24 x i8> [[WIDE_VEC]], <24 x i8> undef, <8 x i32> <i32 2, i32 5, i32 8, i32 11, i32 14, i32 17, i32 20, i32 23>
+; AVX2-NEXT:    [[ADD1:%.*]] = add <8 x i8> [[V1]], [[V2]]
+; AVX2-NEXT:    [[ADD2:%.*]] = add <8 x i8> [[V3]], [[ADD1]]
+; AVX2-NEXT:    ret <8 x i8> [[ADD2]]
+;
+  %wide.vec = load <24 x i8>, <24 x i8>* %ptr
+  %v1 = shufflevector <24 x i8> %wide.vec, <24 x i8> undef,<8 x i32> <i32 0,i32 3,i32 6,i32  9,i32 12,i32 15,i32 18,i32 21>
+  %v2 = shufflevector <24 x i8> %wide.vec, <24 x i8> undef,<8 x i32> <i32 1,i32 4,i32 7,i32 10,i32 13,i32 16,i32 19,i32 22>
+  %v3 = shufflevector <24 x i8> %wide.vec, <24 x i8> undef,<8 x i32> <i32 2,i32 5,i32 8,i32 11,i32 14,i32 17,i32 20,i32 23>
+  %add1 = add <8 x i8> %v1, %v2
+  %add2 = add <8 x i8> %v3, %add1
+  ret <8 x i8> %add2
+}
+
+
+define <64 x i8> @interleaved_load_vf64_i8_stride3(<192 x i8>* %ptr){
+; AVX2-LABEL: @interleaved_load_vf64_i8_stride3(
+; AVX2-NEXT:    [[TMP1:%.*]] = bitcast <192 x i8>* [[PTR:%.*]] to <16 x i8>*
+; AVX2-NEXT:    [[TMP2:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 0
+; AVX2-NEXT:    [[TMP3:%.*]] = load <16 x i8>, <16 x i8>* [[TMP2]], align 1
+; AVX2-NEXT:    [[TMP4:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 1
+; AVX2-NEXT:    [[TMP5:%.*]] = load <16 x i8>, <16 x i8>* [[TMP4]], align 1
+; AVX2-NEXT:    [[TMP6:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 2
+; AVX2-NEXT:    [[TMP7:%.*]] = load <16 x i8>, <16 x i8>* [[TMP6]], align 1
+; AVX2-NEXT:    [[TMP8:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 3
+; AVX2-NEXT:    [[TMP9:%.*]] = load <16 x i8>, <16 x i8>* [[TMP8]], align 1
+; AVX2-NEXT:    [[TMP10:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 4
+; AVX2-NEXT:    [[TMP11:%.*]] = load <16 x i8>, <16 x i8>* [[TMP10]], align 1
+; AVX2-NEXT:    [[TMP12:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 5
+; AVX2-NEXT:    [[TMP13:%.*]] = load <16 x i8>, <16 x i8>* [[TMP12]], align 1
+; AVX2-NEXT:    [[TMP14:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 6
+; AVX2-NEXT:    [[TMP15:%.*]] = load <16 x i8>, <16 x i8>* [[TMP14]], align 1
+; AVX2-NEXT:    [[TMP16:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 7
+; AVX2-NEXT:    [[TMP17:%.*]] = load <16 x i8>, <16 x i8>* [[TMP16]], align 1
+; AVX2-NEXT:    [[TMP18:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 8
+; AVX2-NEXT:    [[TMP19:%.*]] = load <16 x i8>, <16 x i8>* [[TMP18]], align 1
+; AVX2-NEXT:    [[TMP20:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 9
+; AVX2-NEXT:    [[TMP21:%.*]] = load <16 x i8>, <16 x i8>* [[TMP20]], align 1
+; AVX2-NEXT:    [[TMP22:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 10
+; AVX2-NEXT:    [[TMP23:%.*]] = load <16 x i8>, <16 x i8>* [[TMP22]], align 1
+; AVX2-NEXT:    [[TMP24:%.*]] = getelementptr <16 x i8>, <16 x i8>* [[TMP1]], i32 11
+; AVX2-NEXT:    [[TMP25:%.*]] = load <16 x i8>, <16 x i8>* [[TMP24]], align 1
+; AVX2-NEXT:    [[TMP26:%.*]] = shufflevector <16 x i8> [[TMP3]], <16 x i8> [[TMP9]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; AVX2-NEXT:    [[TMP27:%.*]] = shufflevector <16 x i8> [[TMP5]], <16 x i8> [[TMP11]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; AVX2-NEXT:    [[TMP28:%.*]] = shufflevector <16 x i8> [[TMP7]], <16 x i8> [[TMP13]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; AVX2-NEXT:    [[TMP29:%.*]] = shufflevector <16 x i8> [[TMP15]], <16 x i8> [[TMP21]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; AVX2-NEXT:    [[TMP30:%.*]] = shufflevector <16 x i8> [[TMP17]], <16 x i8> [[TMP23]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; AVX2-NEXT:    [[TMP31:%.*]] = shufflevector <16 x i8> [[TMP19]], <16 x i8> [[TMP25]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; AVX2-NEXT:    [[TMP32:%.*]] = shufflevector <32 x i8> [[TMP26]], <32 x i8> [[TMP29]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; AVX2-NEXT:    [[TMP33:%.*]] = shufflevector <32 x i8> [[TMP27]], <32 x i8> [[TMP30]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; AVX2-NEXT:    [[TMP34:%.*]] = shufflevector <32 x i8> [[TMP28]], <32 x i8> [[TMP31]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; AVX2-NEXT:    [[TMP35:%.*]] = shufflevector <64 x i8> [[TMP32]], <64 x i8> undef, <64 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 2, i32 5, i32 8, i32 11, i32 14, i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22, i32 25, i32 28, i32 31, i32 18, i32 21, i32 24, i32 27, i32 30, i32 17, i32 20, i32 23, i32 26, i32 29, i32 32, i32 35, i32 38, i32 41, i32 44, i32 47, i32 34, i32 37, i32 40, i32 43, i32 46, i32 33, i32 36, i32 39, i32 42, i32 45, i32 48, i32 51, i32 54, i32 57, i32 60, i32 63, i32 50, i32 53, i32 56, i32 59, i32 62, i32 49, i32 52, i32 55, i32 58, i32 61>
+; AVX2-NEXT:    [[TMP36:%.*]] = shufflevector <64 x i8> [[TMP33]], <64 x i8> undef, <64 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 2, i32 5, i32 8, i32 11, i32 14, i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22, i32 25, i32 28, i32 31, i32 18, i32 21, i32 24, i32 27, i32 30, i32 17, i32 20, i32 23, i32 26, i32 29, i32 32, i32 35, i32 38, i32 41, i32 44, i32 47, i32 34, i32 37, i32 40, i32 43, i32 46, i32 33, i32 36, i32 39, i32 42, i32 45, i32 48, i32 51, i32 54, i32 57, i32 60, i32 63, i32 50, i32 53, i32 56, i32 59, i32 62, i32 49, i32 52, i32 55, i32 58, i32 61>
+; AVX2-NEXT:    [[TMP37:%.*]] = shufflevector <64 x i8> [[TMP34]], <64 x i8> undef, <64 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 2, i32 5, i32 8, i32 11, i32 14, i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22, i32 25, i32 28, i32 31, i32 18, i32 21, i32 24, i32 27, i32 30, i32 17, i32 20, i32 23, i32 26, i32 29, i32 32, i32 35, i32 38, i32 41, i32 44, i32 47, i32 34, i32 37, i32 40, i32 43, i32 46, i32 33, i32 36, i32 39, i32 42, i32 45, i32 48, i32 51, i32 54, i32 57, i32 60, i32 63, i32 50, i32 53, i32 56, i32 59, i32 62, i32 49, i32 52, i32 55, i32 58, i32 61>
+; AVX2-NEXT:    [[TMP38:%.*]] = shufflevector <64 x i8> [[TMP37]], <64 x i8> [[TMP35]], <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122>
+; AVX2-NEXT:    [[TMP39:%.*]] = shufflevector <64 x i8> [[TMP35]], <64 x i8> [[TMP36]], <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122>
+; AVX2-NEXT:    [[TMP40:%.*]] = shufflevector <64 x i8> [[TMP36]], <64 x i8> [[TMP37]], <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122>
+; AVX2-NEXT:    [[TMP41:%.*]] = shufflevector <64 x i8> [[TMP39]], <64 x i8> [[TMP38]], <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122>
+; AVX2-NEXT:    [[TMP42:%.*]] = shufflevector <64 x i8> [[TMP40]], <64 x i8> [[TMP39]], <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122>
+; AVX2-NEXT:    [[TMP43:%.*]] = shufflevector <64 x i8> [[TMP38]], <64 x i8> [[TMP40]], <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122>
+; AVX2-NEXT:    [[TMP44:%.*]] = shufflevector <64 x i8> [[TMP42]], <64 x i8> undef, <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 16, i32 17, i32 18, i32 19, i32 20, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 32, i32 33, i32 34, i32 35, i32 36, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 48, i32 49, i32 50, i32 51, i32 52>
+; AVX2-NEXT:    [[TMP45:%.*]] = shufflevector <64 x i8> [[TMP41]], <64 x i8> undef, <64 x i32> <i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57>
+; AVX2-NEXT:    [[ADD1:%.*]] = add <64 x i8> [[TMP45]], [[TMP44]]
+; AVX2-NEXT:    [[ADD2:%.*]] = add <64 x i8> [[TMP43]], [[ADD1]]
+; AVX2-NEXT:    ret <64 x i8> [[ADD2]]
+;
+%wide.vec = load <192 x i8>, <192 x i8>* %ptr, align 1
+%v1 = shufflevector <192 x i8> %wide.vec, <192 x i8> undef, <64 x i32> <i32 0, i32 3, i32 6, i32 9, i32 12, i32 15, i32 18, i32 21, i32 24, i32 27, i32 30, i32 33, i32 36, i32 39, i32 42, i32 45, i32 48, i32 51, i32 54, i32 57, i32 60, i32 63, i32 66, i32 69, i32 72, i32 75, i32 78, i32 81, i32 84, i32 87, i32 90, i32 93, i32 96, i32 99, i32 102, i32 105, i32 108, i32 111, i32 114, i32 117, i32 120, i32 123, i32 126, i32 129, i32 132, i32 135, i32 138, i32 141, i32 144, i32 147, i32 150, i32 153, i32 156, i32 159, i32 162, i32 165, i32 168, i32 171, i32 174, i32 177, i32 180, i32 183, i32 186, i32 189>
+%v2 = shufflevector <192 x i8> %wide.vec, <192 x i8> undef, <64 x i32> <i32 1, i32 4, i32 7, i32 10, i32 13, i32 16, i32 19, i32 22, i32 25, i32 28, i32 31, i32 34, i32 37, i32 40, i32 43, i32 46, i32 49, i32 52, i32 55, i32 58, i32 61, i32 64, i32 67, i32 70, i32 73, i32 76, i32 79, i32 82, i32 85, i32 88, i32 91, i32 94, i32 97, i32 100, i32 103, i32 106, i32 109, i32 112, i32 115, i32 118, i32 121, i32 124, i32 127, i32 130, i32 133, i32 136, i32 139, i32 142, i32 145, i32 148, i32 151, i32 154, i32 157, i32 160, i32 163, i32 166, i32 169, i32 172, i32 175, i32 178, i32 181, i32 184, i32 187, i32 190>
+%v3 = shufflevector <192 x i8> %wide.vec, <192 x i8> undef, <64 x i32> <i32 2, i32 5, i32 8, i32 11, i32 14, i32 17, i32 20, i32 23, i32 26, i32 29, i32 32, i32 35, i32 38, i32 41, i32 44, i32 47, i32 50, i32 53, i32 56, i32 59, i32 62, i32 65, i32 68, i32 71, i32 74, i32 77, i32 80, i32 83, i32 86, i32 89, i32 92, i32 95, i32 98, i32 101, i32 104, i32 107, i32 110, i32 113, i32 116, i32 119, i32 122, i32 125, i32 128, i32 131, i32 134, i32 137, i32 140, i32 143, i32 146, i32 149, i32 152, i32 155, i32 158, i32 161, i32 164, i32 167, i32 170, i32 173, i32 176, i32 179, i32 182, i32 185, i32 188, i32 191>
+%add1 = add <64 x i8> %v1, %v2
+%add2 = add <64 x i8> %v3, %add1
+ret <64 x i8> %add2
+}

Added: llvm/trunk/test/Transforms/InterleavedAccess/X86/interleavedStore.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/X86/interleavedStore.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/X86/interleavedStore.ll (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/X86/interleavedStore.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,243 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+
+; RUN: opt < %s -mtriple=x86_64-pc-linux -mattr=+avx2 -interleaved-access -S | FileCheck %s
+
+define void @interleaved_store_vf32_i8_stride4(<32 x i8> %x1, <32 x i8> %x2, <32 x i8> %x3, <32 x i8> %x4, <128 x i8>* %p) {
+; CHECK-LABEL: @interleaved_store_vf32_i8_stride4(
+; CHECK-NEXT:    [[V1:%.*]] = shufflevector <32 x i8> [[X1:%.*]], <32 x i8> [[X2:%.*]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[V2:%.*]] = shufflevector <32 x i8> [[X3:%.*]], <32 x i8> [[X4:%.*]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <64 x i8> [[V1]], <64 x i8> [[V2]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <64 x i8> [[V1]], <64 x i8> [[V2]], <32 x i32> <i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <64 x i8> [[V1]], <64 x i8> [[V2]], <32 x i32> <i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <64 x i8> [[V1]], <64 x i8> [[V2]], <32 x i32> <i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <32 x i8> [[TMP1]], <32 x i8> [[TMP2]], <32 x i32> <i32 0, i32 32, i32 1, i32 33, i32 2, i32 34, i32 3, i32 35, i32 4, i32 36, i32 5, i32 37, i32 6, i32 38, i32 7, i32 39, i32 16, i32 48, i32 17, i32 49, i32 18, i32 50, i32 19, i32 51, i32 20, i32 52, i32 21, i32 53, i32 22, i32 54, i32 23, i32 55>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <32 x i8> [[TMP1]], <32 x i8> [[TMP2]], <32 x i32> <i32 8, i32 40, i32 9, i32 41, i32 10, i32 42, i32 11, i32 43, i32 12, i32 44, i32 13, i32 45, i32 14, i32 46, i32 15, i32 47, i32 24, i32 56, i32 25, i32 57, i32 26, i32 58, i32 27, i32 59, i32 28, i32 60, i32 29, i32 61, i32 30, i32 62, i32 31, i32 63>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <32 x i8> [[TMP3]], <32 x i8> [[TMP4]], <32 x i32> <i32 0, i32 32, i32 1, i32 33, i32 2, i32 34, i32 3, i32 35, i32 4, i32 36, i32 5, i32 37, i32 6, i32 38, i32 7, i32 39, i32 16, i32 48, i32 17, i32 49, i32 18, i32 50, i32 19, i32 51, i32 20, i32 52, i32 21, i32 53, i32 22, i32 54, i32 23, i32 55>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <32 x i8> [[TMP3]], <32 x i8> [[TMP4]], <32 x i32> <i32 8, i32 40, i32 9, i32 41, i32 10, i32 42, i32 11, i32 43, i32 12, i32 44, i32 13, i32 45, i32 14, i32 46, i32 15, i32 47, i32 24, i32 56, i32 25, i32 57, i32 26, i32 58, i32 27, i32 59, i32 28, i32 60, i32 29, i32 61, i32 30, i32 62, i32 31, i32 63>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <32 x i8> [[TMP5]], <32 x i8> [[TMP7]], <32 x i32> <i32 0, i32 1, i32 32, i32 33, i32 2, i32 3, i32 34, i32 35, i32 4, i32 5, i32 36, i32 37, i32 6, i32 7, i32 38, i32 39, i32 16, i32 17, i32 48, i32 49, i32 18, i32 19, i32 50, i32 51, i32 20, i32 21, i32 52, i32 53, i32 22, i32 23, i32 54, i32 55>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <32 x i8> [[TMP5]], <32 x i8> [[TMP7]], <32 x i32> <i32 8, i32 9, i32 40, i32 41, i32 10, i32 11, i32 42, i32 43, i32 12, i32 13, i32 44, i32 45, i32 14, i32 15, i32 46, i32 47, i32 24, i32 25, i32 56, i32 57, i32 26, i32 27, i32 58, i32 59, i32 28, i32 29, i32 60, i32 61, i32 30, i32 31, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <32 x i8> [[TMP6]], <32 x i8> [[TMP8]], <32 x i32> <i32 0, i32 1, i32 32, i32 33, i32 2, i32 3, i32 34, i32 35, i32 4, i32 5, i32 36, i32 37, i32 6, i32 7, i32 38, i32 39, i32 16, i32 17, i32 48, i32 49, i32 18, i32 19, i32 50, i32 51, i32 20, i32 21, i32 52, i32 53, i32 22, i32 23, i32 54, i32 55>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <32 x i8> [[TMP6]], <32 x i8> [[TMP8]], <32 x i32> <i32 8, i32 9, i32 40, i32 41, i32 10, i32 11, i32 42, i32 43, i32 12, i32 13, i32 44, i32 45, i32 14, i32 15, i32 46, i32 47, i32 24, i32 25, i32 56, i32 57, i32 26, i32 27, i32 58, i32 59, i32 28, i32 29, i32 60, i32 61, i32 30, i32 31, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <32 x i8> [[TMP9]], <32 x i8> [[TMP10]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <32 x i8> [[TMP11]], <32 x i8> [[TMP12]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <32 x i8> [[TMP9]], <32 x i8> [[TMP10]], <32 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP16:%.*]] = shufflevector <32 x i8> [[TMP11]], <32 x i8> [[TMP12]], <32 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP17:%.*]] = shufflevector <32 x i8> [[TMP13]], <32 x i8> [[TMP14]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP18:%.*]] = shufflevector <32 x i8> [[TMP15]], <32 x i8> [[TMP16]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP19:%.*]] = shufflevector <64 x i8> [[TMP17]], <64 x i8> [[TMP18]], <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    store <128 x i8> [[TMP19]], <128 x i8>* [[P:%.*]]
+; CHECK-NEXT:    ret void
+;
+  %v1 = shufflevector <32 x i8> %x1, <32 x i8> %x2, <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+  %v2 = shufflevector <32 x i8> %x3, <32 x i8> %x4, <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+  %interleaved.vec = shufflevector <64 x i8> %v1, <64 x i8> %v2, <128 x i32> <i32 0, i32 32, i32 64, i32 96, i32 1, i32 33, i32 65, i32 97, i32 2, i32 34, i32 66, i32 98, i32 3, i32 35, i32 67, i32 99, i32 4, i32 36, i32 68, i32 100, i32 5, i32 37, i32 69, i32 101, i32 6, i32 38, i32 70, i32 102, i32 7, i32 39, i32 71, i32 103, i32 8, i32 40, i32 72, i32 104, i32 9, i32 41, i32 73, i32 105, i32 10, i32 42, i32 74, i32 106, i32 11, i32 43, i32 75, i32 107, i32 12, i32 44, i32 76, i32 108, i32 13, i32 45, i32 77, i32 109, i32 14, i32 46, i32 78, i32 110, i32 15, i32 47, i32 79, i32 111, i32 16, i32 48, i32 80, i32 112, i32 17, i32 49, i32 81, i32 113, i32 18, i32 50, i32 82, i32 114, i32 19, i32 51, i32 83, i32 115, i32 20, i32 52, i32 84, i32 116, i32 21, i32 53, i32 85, i32 117, i32 22, i32 54, i32 86, i32 118, i32 23, i32 55, i32 87, i32 119, i32 24, i32 56, i32 88, i32 120, i32 25, i32 57, i32 89, i32 121, i32 26, i32 58, i32 90, i32 122, i32 27, i32 59, i32 91, i32 123, i32 28, i32 60, i32 92, i32 124, i32 29, i32 61, i32 93, i32 125, i32 30, i32 62, i32 94, i32 126, i32 31, i32 63, i32 95, i32 127>
+  store <128 x i8> %interleaved.vec, <128 x i8>* %p
+  ret void
+}
+
+define void @interleaved_store_vf16_i8_stride4(<16 x i8> %x1, <16 x i8> %x2, <16 x i8> %x3, <16 x i8> %x4, <64 x i8>* %p) {
+; CHECK-LABEL: @interleaved_store_vf16_i8_stride4(
+; CHECK-NEXT:    [[V1:%.*]] = shufflevector <16 x i8> [[X1:%.*]], <16 x i8> [[X2:%.*]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[V2:%.*]] = shufflevector <16 x i8> [[X3:%.*]], <16 x i8> [[X4:%.*]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <32 x i8> [[V1]], <32 x i8> [[V2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <32 x i8> [[V1]], <32 x i8> [[V2]], <16 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <32 x i8> [[V1]], <32 x i8> [[V2]], <16 x i32> <i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <32 x i8> [[V1]], <32 x i8> [[V2]], <16 x i32> <i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i32> <i32 0, i32 16, i32 1, i32 17, i32 2, i32 18, i32 3, i32 19, i32 4, i32 20, i32 5, i32 21, i32 6, i32 22, i32 7, i32 23>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <16 x i8> [[TMP3]], <16 x i8> [[TMP4]], <16 x i32> <i32 8, i32 24, i32 9, i32 25, i32 10, i32 26, i32 11, i32 27, i32 12, i32 28, i32 13, i32 29, i32 14, i32 30, i32 15, i32 31>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <16 x i8> [[TMP5]], <16 x i8> [[TMP7]], <16 x i32> <i32 0, i32 1, i32 16, i32 17, i32 2, i32 3, i32 18, i32 19, i32 4, i32 5, i32 20, i32 21, i32 6, i32 7, i32 22, i32 23>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <16 x i8> [[TMP5]], <16 x i8> [[TMP7]], <16 x i32> <i32 8, i32 9, i32 24, i32 25, i32 10, i32 11, i32 26, i32 27, i32 12, i32 13, i32 28, i32 29, i32 14, i32 15, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <16 x i8> [[TMP6]], <16 x i8> [[TMP8]], <16 x i32> <i32 0, i32 1, i32 16, i32 17, i32 2, i32 3, i32 18, i32 19, i32 4, i32 5, i32 20, i32 21, i32 6, i32 7, i32 22, i32 23>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <16 x i8> [[TMP6]], <16 x i8> [[TMP8]], <16 x i32> <i32 8, i32 9, i32 24, i32 25, i32 10, i32 11, i32 26, i32 27, i32 12, i32 13, i32 28, i32 29, i32 14, i32 15, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <16 x i8> [[TMP9]], <16 x i8> [[TMP10]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <16 x i8> [[TMP11]], <16 x i8> [[TMP12]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <32 x i8> [[TMP13]], <32 x i8> [[TMP14]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    store <64 x i8> [[TMP15]], <64 x i8>* [[P:%.*]]
+; CHECK-NEXT:    ret void
+;
+%v1 = shufflevector <16 x i8> %x1, <16 x i8> %x2, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+%v2 = shufflevector <16 x i8> %x3, <16 x i8> %x4, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+%interleaved.vec = shufflevector <32 x i8> %v1, <32 x i8> %v2, <64 x i32> <i32 0,i32 16,i32 32,i32 48,i32 1,i32 17,i32 33,i32 49,i32 2,i32 18,i32 34,i32 50,i32 3,i32 19,i32 35,i32 51,i32 4,i32 20,i32 36,i32 52,i32 5,i32 21,i32 37,i32 53,i32 6,i32 22,i32 38,i32 54,i32 7,i32 23,i32 39,i32 55,i32 8,i32 24,i32 40,i32 56,i32 9,i32 25,i32 41,i32 57,i32 10,i32 26,i32 42,i32 58,i32 11,i32 27,i32 43,i32 59,i32 12,i32 28,i32 44,i32 60,i32 13,i32 29,i32 45,i32 61,i32 14,i32 30,i32 46,i32 62,i32 15,i32 31,i32 47,i32 63>
+store <64 x i8> %interleaved.vec, <64 x i8>* %p
+ret void
+}
+
+define void @interleaved_store_vf8_i8_stride4(<8 x i8> %x1, <8 x i8> %x2, <8 x i8> %x3, <8 x i8> %x4, <32 x i8>* %p) {
+; CHECK-LABEL: @interleaved_store_vf8_i8_stride4(
+; CHECK-NEXT:    [[V1:%.*]] = shufflevector <8 x i8> [[X1:%.*]], <8 x i8> [[X2:%.*]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[V2:%.*]] = shufflevector <8 x i8> [[X3:%.*]], <8 x i8> [[X4:%.*]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <16 x i8> [[V1]], <16 x i8> [[V2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <16 x i8> [[V1]], <16 x i8> [[V2]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <16 x i8> [[V1]], <16 x i8> [[V2]], <8 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <16 x i8> [[V1]], <16 x i8> [[V2]], <8 x i32> <i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP2]], <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP4]], <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <16 x i8> [[TMP5]], <16 x i8> [[TMP6]], <16 x i32> <i32 0, i32 1, i32 16, i32 17, i32 2, i32 3, i32 18, i32 19, i32 4, i32 5, i32 20, i32 21, i32 6, i32 7, i32 22, i32 23>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <16 x i8> [[TMP5]], <16 x i8> [[TMP6]], <16 x i32> <i32 8, i32 9, i32 24, i32 25, i32 10, i32 11, i32 26, i32 27, i32 12, i32 13, i32 28, i32 29, i32 14, i32 15, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <16 x i8> [[TMP7]], <16 x i8> [[TMP8]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    store <32 x i8> [[TMP9]], <32 x i8>* [[P:%.*]]
+; CHECK-NEXT:    ret void
+;
+  %v1 = shufflevector <8 x i8> %x1, <8 x i8> %x2, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %v2 = shufflevector <8 x i8> %x3, <8 x i8> %x4, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  %interleaved.vec = shufflevector <16 x i8> %v1, <16 x i8> %v2, <32 x i32> <i32 0,i32 8,i32 16,i32 24,i32 1,i32 9,i32 17,i32 25,i32 2,i32 10,i32 18,i32 26,i32 3,i32 11,i32 19,i32 27,i32 4,i32 12,i32 20,i32 28,i32 5,i32 13,i32 21,i32 29,i32 6,i32 14,i32 22,i32 30,i32 7,i32 15,i32 23,i32 31>
+  store <32 x i8> %interleaved.vec, <32 x i8>* %p
+ret void
+}
+
+define void @interleaved_store_vf8_i8_stride3(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <24 x i8>* %p) {
+; CHECK-LABEL: @interleaved_store_vf8_i8_stride3(
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i8> [[A:%.*]], <8 x i8> [[B:%.*]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <8 x i8> [[C:%.*]], <8 x i8> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+; CHECK-NEXT:    [[INTERLEAVED_VEC:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> [[TMP2]], <24 x i32> <i32 0, i32 8, i32 16, i32 1, i32 9, i32 17, i32 2, i32 10, i32 18, i32 3, i32 11, i32 19, i32 4, i32 12, i32 20, i32 5, i32 13, i32 21, i32 6, i32 14, i32 22, i32 7, i32 15, i32 23>
+; CHECK-NEXT:    store <24 x i8> [[INTERLEAVED_VEC]], <24 x i8>* [[P:%.*]], align 1
+; CHECK-NEXT:    ret void
+;
+%1 = shufflevector <8 x i8> %a, <8 x i8> %b, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+%2 = shufflevector <8 x i8> %c, <8 x i8> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+%interleaved.vec = shufflevector <16 x i8> %1, <16 x i8> %2, <24 x i32> <i32 0, i32 8, i32 16, i32 1, i32 9, i32 17, i32 2, i32 10, i32 18, i32 3, i32 11, i32 19, i32 4, i32 12, i32 20, i32 5, i32 13, i32 21, i32 6, i32 14, i32 22, i32 7, i32 15, i32 23>
+store <24 x i8> %interleaved.vec, <24 x i8>* %p, align 1
+ret void
+}
+
+define void @interleaved_store_vf16_i8_stride3(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c, <48 x i8>* %p) {
+; CHECK-LABEL: @interleaved_store_vf16_i8_stride3(
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <16 x i8> [[C:%.*]], <16 x i8> undef, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <32 x i8> [[TMP1]], <32 x i8> [[TMP2]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <32 x i8> [[TMP1]], <32 x i8> [[TMP2]], <16 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <32 x i8> [[TMP1]], <32 x i8> [[TMP2]], <16 x i32> <i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <16 x i8> [[TMP3]], <16 x i8> undef, <16 x i32> <i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <16 x i8> [[TMP4]], <16 x i8> undef, <16 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <16 x i8> [[TMP6]], <16 x i8> [[TMP5]], <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <16 x i8> [[TMP7]], <16 x i8> [[TMP6]], <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <16 x i8> [[TMP5]], <16 x i8> [[TMP7]], <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <16 x i8> [[TMP8]], <16 x i8> [[TMP9]], <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <16 x i8> [[TMP9]], <16 x i8> [[TMP10]], <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <16 x i8> [[TMP10]], <16 x i8> [[TMP8]], <16 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <16 x i8> [[TMP11]], <16 x i8> undef, <16 x i32> <i32 0, i32 11, i32 6, i32 1, i32 12, i32 7, i32 2, i32 13, i32 8, i32 3, i32 14, i32 9, i32 4, i32 15, i32 10, i32 5>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <16 x i8> [[TMP12]], <16 x i8> undef, <16 x i32> <i32 0, i32 11, i32 6, i32 1, i32 12, i32 7, i32 2, i32 13, i32 8, i32 3, i32 14, i32 9, i32 4, i32 15, i32 10, i32 5>
+; CHECK-NEXT:    [[TMP16:%.*]] = shufflevector <16 x i8> [[TMP13]], <16 x i8> undef, <16 x i32> <i32 0, i32 11, i32 6, i32 1, i32 12, i32 7, i32 2, i32 13, i32 8, i32 3, i32 14, i32 9, i32 4, i32 15, i32 10, i32 5>
+; CHECK-NEXT:    [[TMP17:%.*]] = shufflevector <16 x i8> [[TMP14]], <16 x i8> [[TMP15]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP18:%.*]] = shufflevector <16 x i8> [[TMP16]], <16 x i8> undef, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+; CHECK-NEXT:    [[TMP19:%.*]] = shufflevector <32 x i8> [[TMP17]], <32 x i8> [[TMP18]], <48 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47>
+; CHECK-NEXT:    store <48 x i8> [[TMP19]], <48 x i8>* [[P:%.*]], align 1
+; CHECK-NEXT:    ret void
+;
+%1 = shufflevector <16 x i8> %a, <16 x i8> %b, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+%2 = shufflevector <16 x i8> %c, <16 x i8> undef, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+%interleaved.vec = shufflevector <32 x i8> %1, <32 x i8> %2, <48 x i32> <i32 0, i32 16, i32 32, i32 1, i32 17, i32 33, i32 2, i32 18, i32 34, i32 3, i32 19, i32 35, i32 4, i32 20, i32 36, i32 5, i32 21, i32 37, i32 6, i32 22, i32 38, i32 7, i32 23, i32 39, i32 8, i32 24, i32 40, i32 9, i32 25, i32 41, i32 10, i32 26, i32 42, i32 11, i32 27, i32 43, i32 12, i32 28, i32 44, i32 13, i32 29, i32 45, i32 14, i32 30, i32 46, i32 15, i32 31, i32 47>
+store <48 x i8> %interleaved.vec, <48 x i8>* %p, align 1
+ret void
+}
+
+define void @interleaved_store_vf32_i8_stride3(<32 x i8> %a, <32 x i8> %b, <32 x i8> %c, <96 x i8>* %p) {
+; CHECK-LABEL: @interleaved_store_vf32_i8_stride3(
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <32 x i8> [[A:%.*]], <32 x i8> [[B:%.*]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <32 x i8> [[C:%.*]], <32 x i8> undef, <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <64 x i8> [[TMP1]], <64 x i8> [[TMP2]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <64 x i8> [[TMP1]], <64 x i8> [[TMP2]], <32 x i32> <i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <64 x i8> [[TMP1]], <64 x i8> [[TMP2]], <32 x i32> <i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <32 x i8> [[TMP3]], <32 x i8> undef, <32 x i32> <i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <32 x i8> [[TMP4]], <32 x i8> undef, <32 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 27, i32 28, i32 29, i32 30, i32 31, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <32 x i8> [[TMP6]], <32 x i8> [[TMP5]], <32 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <32 x i8> [[TMP7]], <32 x i8> [[TMP6]], <32 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <32 x i8> [[TMP5]], <32 x i8> [[TMP7]], <32 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <32 x i8> [[TMP8]], <32 x i8> [[TMP9]], <32 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <32 x i8> [[TMP9]], <32 x i8> [[TMP10]], <32 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <32 x i8> [[TMP10]], <32 x i8> [[TMP8]], <32 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 32, i32 33, i32 34, i32 35, i32 36, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 48, i32 49, i32 50, i32 51, i32 52>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <32 x i8> [[TMP11]], <32 x i8> [[TMP12]], <32 x i32> <i32 0, i32 11, i32 6, i32 1, i32 12, i32 7, i32 2, i32 13, i32 8, i32 3, i32 14, i32 9, i32 4, i32 15, i32 10, i32 5, i32 32, i32 43, i32 38, i32 33, i32 44, i32 39, i32 34, i32 45, i32 40, i32 35, i32 46, i32 41, i32 36, i32 47, i32 42, i32 37>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <32 x i8> [[TMP13]], <32 x i8> [[TMP11]], <32 x i32> <i32 0, i32 11, i32 6, i32 1, i32 12, i32 7, i32 2, i32 13, i32 8, i32 3, i32 14, i32 9, i32 4, i32 15, i32 10, i32 5, i32 48, i32 59, i32 54, i32 49, i32 60, i32 55, i32 50, i32 61, i32 56, i32 51, i32 62, i32 57, i32 52, i32 63, i32 58, i32 53>
+; CHECK-NEXT:    [[TMP16:%.*]] = shufflevector <32 x i8> [[TMP12]], <32 x i8> [[TMP13]], <32 x i32> <i32 16, i32 27, i32 22, i32 17, i32 28, i32 23, i32 18, i32 29, i32 24, i32 19, i32 30, i32 25, i32 20, i32 31, i32 26, i32 21, i32 48, i32 59, i32 54, i32 49, i32 60, i32 55, i32 50, i32 61, i32 56, i32 51, i32 62, i32 57, i32 52, i32 63, i32 58, i32 53>
+; CHECK-NEXT:    [[TMP17:%.*]] = shufflevector <32 x i8> [[TMP14]], <32 x i8> [[TMP15]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP18:%.*]] = shufflevector <32 x i8> [[TMP16]], <32 x i8> undef, <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+; CHECK-NEXT:    [[TMP19:%.*]] = shufflevector <64 x i8> [[TMP17]], <64 x i8> [[TMP18]], <96 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95>
+; CHECK-NEXT:    store <96 x i8> [[TMP19]], <96 x i8>* [[P:%.*]], align 1
+; CHECK-NEXT:    ret void
+;
+%1 = shufflevector <32 x i8> %a, <32 x i8> %b, <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+%2 = shufflevector <32 x i8> %c, <32 x i8> undef, <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+%interleaved.vec = shufflevector <64 x i8> %1, <64 x i8> %2, <96 x i32> <i32 0, i32 32, i32 64, i32 1, i32 33, i32 65, i32 2, i32 34, i32 66, i32 3, i32 35, i32 67, i32 4, i32 36, i32 68, i32 5, i32 37, i32 69, i32 6, i32 38, i32 70, i32 7, i32 39, i32 71, i32 8, i32 40, i32 72, i32 9, i32 41, i32 73, i32 10, i32 42, i32 74, i32 11, i32 43, i32 75, i32 12, i32 44, i32 76, i32 13, i32 45, i32 77, i32 14, i32 46, i32 78, i32 15, i32 47, i32 79, i32 16, i32 48, i32 80, i32 17, i32 49, i32 81, i32 18, i32 50, i32 82, i32 19, i32 51, i32 83, i32 20, i32 52, i32 84, i32 21, i32 53, i32 85, i32 22, i32 54, i32 86, i32 23, i32 55, i32 87, i32 24, i32 56, i32 88, i32 25, i32 57, i32 89, i32 26, i32 58, i32 90, i32 27, i32 59, i32 91, i32 28, i32 60, i32 92, i32 29, i32 61, i32 93, i32 30, i32 62, i32 94, i32 31, i32 63, i32 95>
+store <96 x i8> %interleaved.vec, <96 x i8>* %p, align 1
+ret void
+}
+
+define void @interleaved_store_vf64_i8_stride3(<64 x i8> %a, <64 x i8> %b, <64 x i8> %c, <192 x i8>* %p) {
+; CHECK-LABEL: @interleaved_store_vf64_i8_stride3(
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <64 x i8> [[A:%.*]], <64 x i8> [[B:%.*]], <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <64 x i8> [[C:%.*]], <64 x i8> undef, <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <128 x i8> [[TMP1]], <128 x i8> [[TMP2]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <128 x i8> [[TMP1]], <128 x i8> [[TMP2]], <64 x i32> <i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <128 x i8> [[TMP1]], <128 x i8> [[TMP2]], <64 x i32> <i32 128, i32 129, i32 130, i32 131, i32 132, i32 133, i32 134, i32 135, i32 136, i32 137, i32 138, i32 139, i32 140, i32 141, i32 142, i32 143, i32 144, i32 145, i32 146, i32 147, i32 148, i32 149, i32 150, i32 151, i32 152, i32 153, i32 154, i32 155, i32 156, i32 157, i32 158, i32 159, i32 160, i32 161, i32 162, i32 163, i32 164, i32 165, i32 166, i32 167, i32 168, i32 169, i32 170, i32 171, i32 172, i32 173, i32 174, i32 175, i32 176, i32 177, i32 178, i32 179, i32 180, i32 181, i32 182, i32 183, i32 184, i32 185, i32 186, i32 187, i32 188, i32 189, i32 190, i32 191>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <64 x i8> [[TMP3]], <64 x i8> undef, <64 x i32> <i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <64 x i8> [[TMP4]], <64 x i8> undef, <64 x i32> <i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 27, i32 28, i32 29, i32 30, i32 31, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 43, i32 44, i32 45, i32 46, i32 47, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 59, i32 60, i32 61, i32 62, i32 63, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <64 x i8> [[TMP6]], <64 x i8> [[TMP5]], <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <64 x i8> [[TMP7]], <64 x i8> [[TMP6]], <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <64 x i8> [[TMP5]], <64 x i8> [[TMP7]], <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <64 x i8> [[TMP8]], <64 x i8> [[TMP9]], <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <64 x i8> [[TMP9]], <64 x i8> [[TMP10]], <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <64 x i8> [[TMP10]], <64 x i8> [[TMP8]], <64 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <64 x i8> [[TMP11]], <64 x i8> [[TMP12]], <32 x i32> <i32 0, i32 11, i32 6, i32 1, i32 12, i32 7, i32 2, i32 13, i32 8, i32 3, i32 14, i32 9, i32 4, i32 15, i32 10, i32 5, i32 64, i32 75, i32 70, i32 65, i32 76, i32 71, i32 66, i32 77, i32 72, i32 67, i32 78, i32 73, i32 68, i32 79, i32 74, i32 69>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <64 x i8> [[TMP13]], <64 x i8> [[TMP11]], <32 x i32> <i32 0, i32 11, i32 6, i32 1, i32 12, i32 7, i32 2, i32 13, i32 8, i32 3, i32 14, i32 9, i32 4, i32 15, i32 10, i32 5, i32 80, i32 91, i32 86, i32 81, i32 92, i32 87, i32 82, i32 93, i32 88, i32 83, i32 94, i32 89, i32 84, i32 95, i32 90, i32 85>
+; CHECK-NEXT:    [[TMP16:%.*]] = shufflevector <64 x i8> [[TMP12]], <64 x i8> [[TMP13]], <32 x i32> <i32 16, i32 27, i32 22, i32 17, i32 28, i32 23, i32 18, i32 29, i32 24, i32 19, i32 30, i32 25, i32 20, i32 31, i32 26, i32 21, i32 80, i32 91, i32 86, i32 81, i32 92, i32 87, i32 82, i32 93, i32 88, i32 83, i32 94, i32 89, i32 84, i32 95, i32 90, i32 85>
+; CHECK-NEXT:    [[TMP17:%.*]] = shufflevector <64 x i8> [[TMP11]], <64 x i8> [[TMP12]], <32 x i32> <i32 32, i32 43, i32 38, i32 33, i32 44, i32 39, i32 34, i32 45, i32 40, i32 35, i32 46, i32 41, i32 36, i32 47, i32 42, i32 37, i32 96, i32 107, i32 102, i32 97, i32 108, i32 103, i32 98, i32 109, i32 104, i32 99, i32 110, i32 105, i32 100, i32 111, i32 106, i32 101>
+; CHECK-NEXT:    [[TMP18:%.*]] = shufflevector <64 x i8> [[TMP13]], <64 x i8> [[TMP11]], <32 x i32> <i32 32, i32 43, i32 38, i32 33, i32 44, i32 39, i32 34, i32 45, i32 40, i32 35, i32 46, i32 41, i32 36, i32 47, i32 42, i32 37, i32 112, i32 123, i32 118, i32 113, i32 124, i32 119, i32 114, i32 125, i32 120, i32 115, i32 126, i32 121, i32 116, i32 127, i32 122, i32 117>
+; CHECK-NEXT:    [[TMP19:%.*]] = shufflevector <64 x i8> [[TMP12]], <64 x i8> [[TMP13]], <32 x i32> <i32 48, i32 59, i32 54, i32 49, i32 60, i32 55, i32 50, i32 61, i32 56, i32 51, i32 62, i32 57, i32 52, i32 63, i32 58, i32 53, i32 112, i32 123, i32 118, i32 113, i32 124, i32 119, i32 114, i32 125, i32 120, i32 115, i32 126, i32 121, i32 116, i32 127, i32 122, i32 117>
+; CHECK-NEXT:    [[TMP20:%.*]] = shufflevector <32 x i8> [[TMP14]], <32 x i8> [[TMP15]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP21:%.*]] = shufflevector <32 x i8> [[TMP16]], <32 x i8> [[TMP17]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP22:%.*]] = shufflevector <32 x i8> [[TMP18]], <32 x i8> [[TMP19]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP23:%.*]] = shufflevector <64 x i8> [[TMP20]], <64 x i8> [[TMP21]], <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP24:%.*]] = shufflevector <64 x i8> [[TMP22]], <64 x i8> undef, <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+; CHECK-NEXT:    [[TMP25:%.*]] = shufflevector <128 x i8> [[TMP23]], <128 x i8> [[TMP24]], <192 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127, i32 128, i32 129, i32 130, i32 131, i32 132, i32 133, i32 134, i32 135, i32 136, i32 137, i32 138, i32 139, i32 140, i32 141, i32 142, i32 143, i32 144, i32 145, i32 146, i32 147, i32 148, i32 149, i32 150, i32 151, i32 152, i32 153, i32 154, i32 155, i32 156, i32 157, i32 158, i32 159, i32 160, i32 161, i32 162, i32 163, i32 164, i32 165, i32 166, i32 167, i32 168, i32 169, i32 170, i32 171, i32 172, i32 173, i32 174, i32 175, i32 176, i32 177, i32 178, i32 179, i32 180, i32 181, i32 182, i32 183, i32 184, i32 185, i32 186, i32 187, i32 188, i32 189, i32 190, i32 191>
+; CHECK-NEXT:    store <192 x i8> [[TMP25]], <192 x i8>* [[P:%.*]], align 1
+; CHECK-NEXT:    ret void
+;
+%1 = shufflevector <64 x i8> %a, <64 x i8> %b, <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+%2 = shufflevector <64 x i8> %c, <64 x i8> undef, <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+%3 = shufflevector <128 x i8> %1, <128 x i8> %2, <192 x i32> <i32 0, i32 64, i32 128, i32 1, i32 65, i32 129, i32 2, i32 66, i32 130, i32 3, i32 67, i32 131, i32 4, i32 68, i32 132, i32 5, i32 69, i32 133, i32 6, i32 70, i32 134, i32 7, i32 71, i32 135, i32 8, i32 72, i32 136, i32 9, i32 73, i32 137, i32 10, i32 74, i32 138, i32 11, i32 75, i32 139, i32 12, i32 76, i32 140, i32 13, i32 77, i32 141, i32 14, i32 78, i32 142, i32 15, i32 79, i32 143, i32 16, i32 80, i32 144, i32 17, i32 81, i32 145, i32 18, i32 82, i32 146, i32 19, i32 83, i32 147, i32 20, i32 84, i32 148, i32 21, i32 85, i32 149, i32 22, i32 86, i32 150, i32 23, i32 87, i32 151, i32 24, i32 88, i32 152, i32 25, i32 89, i32 153, i32 26, i32 90, i32 154, i32 27, i32 91, i32 155, i32 28, i32 92, i32 156, i32 29, i32 93, i32 157, i32 30, i32 94, i32 158, i32 31, i32 95, i32 159, i32 32, i32 96, i32 160, i32 33, i32 97, i32 161, i32 34, i32 98, i32 162, i32 35, i32 99, i32 163, i32 36, i32 100, i32 164, i32 37, i32 101, i32 165, i32 38, i32 102, i32 166, i32 39, i32 103, i32 167, i32 40, i32 104, i32 168, i32 41, i32 105, i32 169, i32 42, i32 106, i32 170, i32 43, i32 107, i32 171, i32 44, i32 108, i32 172, i32 45, i32 109, i32 173, i32 46, i32 110, i32 174, i32 47, i32 111, i32 175, i32 48, i32 112, i32 176, i32 49, i32 113, i32 177, i32 50, i32 114, i32 178, i32 51, i32 115, i32 179, i32 52, i32 116, i32 180, i32 53, i32 117, i32 181, i32 54, i32 118, i32 182, i32 55, i32 119, i32 183, i32 56, i32 120, i32 184, i32 57, i32 121, i32 185, i32 58, i32 122, i32 186, i32 59, i32 123, i32 187, i32 60, i32 124, i32 188, i32 61, i32 125, i32 189, i32 62, i32 126, i32 190, i32 63, i32 127, i32 191>
+store <192 x i8> %3, <192 x i8>* %p, align 1
+ret void
+}
+
+define void @interleaved_store_vf64_i8_stride4(<64 x i8> %a, <64 x i8> %b, <64 x i8> %c,<64 x i8> %d, <256 x i8>* %p) {
+; CHECK-LABEL: @interleaved_store_vf64_i8_stride4(
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <64 x i8> [[A:%.*]], <64 x i8> [[B:%.*]], <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <64 x i8> [[C:%.*]], <64 x i8> [[D:%.*]], <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <128 x i8> [[TMP1]], <128 x i8> [[TMP2]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <128 x i8> [[TMP1]], <128 x i8> [[TMP2]], <64 x i32> <i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <128 x i8> [[TMP1]], <128 x i8> [[TMP2]], <64 x i32> <i32 128, i32 129, i32 130, i32 131, i32 132, i32 133, i32 134, i32 135, i32 136, i32 137, i32 138, i32 139, i32 140, i32 141, i32 142, i32 143, i32 144, i32 145, i32 146, i32 147, i32 148, i32 149, i32 150, i32 151, i32 152, i32 153, i32 154, i32 155, i32 156, i32 157, i32 158, i32 159, i32 160, i32 161, i32 162, i32 163, i32 164, i32 165, i32 166, i32 167, i32 168, i32 169, i32 170, i32 171, i32 172, i32 173, i32 174, i32 175, i32 176, i32 177, i32 178, i32 179, i32 180, i32 181, i32 182, i32 183, i32 184, i32 185, i32 186, i32 187, i32 188, i32 189, i32 190, i32 191>
+; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <128 x i8> [[TMP1]], <128 x i8> [[TMP2]], <64 x i32> <i32 192, i32 193, i32 194, i32 195, i32 196, i32 197, i32 198, i32 199, i32 200, i32 201, i32 202, i32 203, i32 204, i32 205, i32 206, i32 207, i32 208, i32 209, i32 210, i32 211, i32 212, i32 213, i32 214, i32 215, i32 216, i32 217, i32 218, i32 219, i32 220, i32 221, i32 222, i32 223, i32 224, i32 225, i32 226, i32 227, i32 228, i32 229, i32 230, i32 231, i32 232, i32 233, i32 234, i32 235, i32 236, i32 237, i32 238, i32 239, i32 240, i32 241, i32 242, i32 243, i32 244, i32 245, i32 246, i32 247, i32 248, i32 249, i32 250, i32 251, i32 252, i32 253, i32 254, i32 255>
+; CHECK-NEXT:    [[TMP7:%.*]] = shufflevector <64 x i8> [[TMP3]], <64 x i8> [[TMP4]], <64 x i32> <i32 0, i32 64, i32 1, i32 65, i32 2, i32 66, i32 3, i32 67, i32 4, i32 68, i32 5, i32 69, i32 6, i32 70, i32 7, i32 71, i32 16, i32 80, i32 17, i32 81, i32 18, i32 82, i32 19, i32 83, i32 20, i32 84, i32 21, i32 85, i32 22, i32 86, i32 23, i32 87, i32 32, i32 96, i32 33, i32 97, i32 34, i32 98, i32 35, i32 99, i32 36, i32 100, i32 37, i32 101, i32 38, i32 102, i32 39, i32 103, i32 48, i32 112, i32 49, i32 113, i32 50, i32 114, i32 51, i32 115, i32 52, i32 116, i32 53, i32 117, i32 54, i32 118, i32 55, i32 119>
+; CHECK-NEXT:    [[TMP8:%.*]] = shufflevector <64 x i8> [[TMP3]], <64 x i8> [[TMP4]], <64 x i32> <i32 8, i32 72, i32 9, i32 73, i32 10, i32 74, i32 11, i32 75, i32 12, i32 76, i32 13, i32 77, i32 14, i32 78, i32 15, i32 79, i32 24, i32 88, i32 25, i32 89, i32 26, i32 90, i32 27, i32 91, i32 28, i32 92, i32 29, i32 93, i32 30, i32 94, i32 31, i32 95, i32 40, i32 104, i32 41, i32 105, i32 42, i32 106, i32 43, i32 107, i32 44, i32 108, i32 45, i32 109, i32 46, i32 110, i32 47, i32 111, i32 56, i32 120, i32 57, i32 121, i32 58, i32 122, i32 59, i32 123, i32 60, i32 124, i32 61, i32 125, i32 62, i32 126, i32 63, i32 127>
+; CHECK-NEXT:    [[TMP9:%.*]] = shufflevector <64 x i8> [[TMP5]], <64 x i8> [[TMP6]], <64 x i32> <i32 0, i32 64, i32 1, i32 65, i32 2, i32 66, i32 3, i32 67, i32 4, i32 68, i32 5, i32 69, i32 6, i32 70, i32 7, i32 71, i32 16, i32 80, i32 17, i32 81, i32 18, i32 82, i32 19, i32 83, i32 20, i32 84, i32 21, i32 85, i32 22, i32 86, i32 23, i32 87, i32 32, i32 96, i32 33, i32 97, i32 34, i32 98, i32 35, i32 99, i32 36, i32 100, i32 37, i32 101, i32 38, i32 102, i32 39, i32 103, i32 48, i32 112, i32 49, i32 113, i32 50, i32 114, i32 51, i32 115, i32 52, i32 116, i32 53, i32 117, i32 54, i32 118, i32 55, i32 119>
+; CHECK-NEXT:    [[TMP10:%.*]] = shufflevector <64 x i8> [[TMP5]], <64 x i8> [[TMP6]], <64 x i32> <i32 8, i32 72, i32 9, i32 73, i32 10, i32 74, i32 11, i32 75, i32 12, i32 76, i32 13, i32 77, i32 14, i32 78, i32 15, i32 79, i32 24, i32 88, i32 25, i32 89, i32 26, i32 90, i32 27, i32 91, i32 28, i32 92, i32 29, i32 93, i32 30, i32 94, i32 31, i32 95, i32 40, i32 104, i32 41, i32 105, i32 42, i32 106, i32 43, i32 107, i32 44, i32 108, i32 45, i32 109, i32 46, i32 110, i32 47, i32 111, i32 56, i32 120, i32 57, i32 121, i32 58, i32 122, i32 59, i32 123, i32 60, i32 124, i32 61, i32 125, i32 62, i32 126, i32 63, i32 127>
+; CHECK-NEXT:    [[TMP11:%.*]] = shufflevector <64 x i8> [[TMP7]], <64 x i8> [[TMP9]], <64 x i32> <i32 0, i32 1, i32 64, i32 65, i32 2, i32 3, i32 66, i32 67, i32 4, i32 5, i32 68, i32 69, i32 6, i32 7, i32 70, i32 71, i32 16, i32 17, i32 80, i32 81, i32 18, i32 19, i32 82, i32 83, i32 20, i32 21, i32 84, i32 85, i32 22, i32 23, i32 86, i32 87, i32 32, i32 33, i32 96, i32 97, i32 34, i32 35, i32 98, i32 99, i32 36, i32 37, i32 100, i32 101, i32 38, i32 39, i32 102, i32 103, i32 48, i32 49, i32 112, i32 113, i32 50, i32 51, i32 114, i32 115, i32 52, i32 53, i32 116, i32 117, i32 54, i32 55, i32 118, i32 119>
+; CHECK-NEXT:    [[TMP12:%.*]] = shufflevector <64 x i8> [[TMP7]], <64 x i8> [[TMP9]], <64 x i32> <i32 8, i32 9, i32 72, i32 73, i32 10, i32 11, i32 74, i32 75, i32 12, i32 13, i32 76, i32 77, i32 14, i32 15, i32 78, i32 79, i32 24, i32 25, i32 88, i32 89, i32 26, i32 27, i32 90, i32 91, i32 28, i32 29, i32 92, i32 93, i32 30, i32 31, i32 94, i32 95, i32 40, i32 41, i32 104, i32 105, i32 42, i32 43, i32 106, i32 107, i32 44, i32 45, i32 108, i32 109, i32 46, i32 47, i32 110, i32 111, i32 56, i32 57, i32 120, i32 121, i32 58, i32 59, i32 122, i32 123, i32 60, i32 61, i32 124, i32 125, i32 62, i32 63, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP13:%.*]] = shufflevector <64 x i8> [[TMP8]], <64 x i8> [[TMP10]], <64 x i32> <i32 0, i32 1, i32 64, i32 65, i32 2, i32 3, i32 66, i32 67, i32 4, i32 5, i32 68, i32 69, i32 6, i32 7, i32 70, i32 71, i32 16, i32 17, i32 80, i32 81, i32 18, i32 19, i32 82, i32 83, i32 20, i32 21, i32 84, i32 85, i32 22, i32 23, i32 86, i32 87, i32 32, i32 33, i32 96, i32 97, i32 34, i32 35, i32 98, i32 99, i32 36, i32 37, i32 100, i32 101, i32 38, i32 39, i32 102, i32 103, i32 48, i32 49, i32 112, i32 113, i32 50, i32 51, i32 114, i32 115, i32 52, i32 53, i32 116, i32 117, i32 54, i32 55, i32 118, i32 119>
+; CHECK-NEXT:    [[TMP14:%.*]] = shufflevector <64 x i8> [[TMP8]], <64 x i8> [[TMP10]], <64 x i32> <i32 8, i32 9, i32 72, i32 73, i32 10, i32 11, i32 74, i32 75, i32 12, i32 13, i32 76, i32 77, i32 14, i32 15, i32 78, i32 79, i32 24, i32 25, i32 88, i32 89, i32 26, i32 27, i32 90, i32 91, i32 28, i32 29, i32 92, i32 93, i32 30, i32 31, i32 94, i32 95, i32 40, i32 41, i32 104, i32 105, i32 42, i32 43, i32 106, i32 107, i32 44, i32 45, i32 108, i32 109, i32 46, i32 47, i32 110, i32 111, i32 56, i32 57, i32 120, i32 121, i32 58, i32 59, i32 122, i32 123, i32 60, i32 61, i32 124, i32 125, i32 62, i32 63, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP15:%.*]] = shufflevector <64 x i8> [[TMP11]], <64 x i8> [[TMP12]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79>
+; CHECK-NEXT:    [[TMP16:%.*]] = shufflevector <64 x i8> [[TMP13]], <64 x i8> [[TMP14]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79>
+; CHECK-NEXT:    [[TMP17:%.*]] = shufflevector <64 x i8> [[TMP11]], <64 x i8> [[TMP12]], <32 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95>
+; CHECK-NEXT:    [[TMP18:%.*]] = shufflevector <64 x i8> [[TMP13]], <64 x i8> [[TMP14]], <32 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95>
+; CHECK-NEXT:    [[TMP19:%.*]] = shufflevector <64 x i8> [[TMP11]], <64 x i8> [[TMP12]], <32 x i32> <i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111>
+; CHECK-NEXT:    [[TMP20:%.*]] = shufflevector <64 x i8> [[TMP13]], <64 x i8> [[TMP14]], <32 x i32> <i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111>
+; CHECK-NEXT:    [[TMP21:%.*]] = shufflevector <64 x i8> [[TMP11]], <64 x i8> [[TMP12]], <32 x i32> <i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP22:%.*]] = shufflevector <64 x i8> [[TMP13]], <64 x i8> [[TMP14]], <32 x i32> <i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP23:%.*]] = shufflevector <32 x i8> [[TMP15]], <32 x i8> [[TMP16]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP24:%.*]] = shufflevector <32 x i8> [[TMP17]], <32 x i8> [[TMP18]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP25:%.*]] = shufflevector <32 x i8> [[TMP19]], <32 x i8> [[TMP20]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP26:%.*]] = shufflevector <32 x i8> [[TMP21]], <32 x i8> [[TMP22]], <64 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63>
+; CHECK-NEXT:    [[TMP27:%.*]] = shufflevector <64 x i8> [[TMP23]], <64 x i8> [[TMP24]], <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP28:%.*]] = shufflevector <64 x i8> [[TMP25]], <64 x i8> [[TMP26]], <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+; CHECK-NEXT:    [[TMP29:%.*]] = shufflevector <128 x i8> [[TMP27]], <128 x i8> [[TMP28]], <256 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127, i32 128, i32 129, i32 130, i32 131, i32 132, i32 133, i32 134, i32 135, i32 136, i32 137, i32 138, i32 139, i32 140, i32 141, i32 142, i32 143, i32 144, i32 145, i32 146, i32 147, i32 148, i32 149, i32 150, i32 151, i32 152, i32 153, i32 154, i32 155, i32 156, i32 157, i32 158, i32 159, i32 160, i32 161, i32 162, i32 163, i32 164, i32 165, i32 166, i32 167, i32 168, i32 169, i32 170, i32 171, i32 172, i32 173, i32 174, i32 175, i32 176, i32 177, i32 178, i32 179, i32 180, i32 181, i32 182, i32 183, i32 184, i32 185, i32 186, i32 187, i32 188, i32 189, i32 190, i32 191, i32 192, i32 193, i32 194, i32 195, i32 196, i32 197, i32 198, i32 199, i32 200, i32 201, i32 202, i32 203, i32 204, i32 205, i32 206, i32 207, i32 208, i32 209, i32 210, i32 211, i32 212, i32 213, i32 214, i32 215, i32 216, i32 217, i32 218, i32 219, i32 220, i32 221, i32 222, i32 223, i32 224, i32 225, i32 226, i32 227, i32 228, i32 229, i32 230, i32 231, i32 232, i32 233, i32 234, i32 235, i32 236, i32 237, i32 238, i32 239, i32 240, i32 241, i32 242, i32 243, i32 244, i32 245, i32 246, i32 247, i32 248, i32 249, i32 250, i32 251, i32 252, i32 253, i32 254, i32 255>
+; CHECK-NEXT:    store <256 x i8> [[TMP29]], <256 x i8>* [[P:%.*]]
+; CHECK-NEXT:    ret void
+;
+%1 = shufflevector <64 x i8> %a, <64 x i8> %b, <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+%2 = shufflevector <64 x i8> %c, <64 x i8> %d, <128 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 32, i32 33, i32 34, i32 35, i32 36, i32 37, i32 38, i32 39, i32 40, i32 41, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49, i32 50, i32 51, i32 52, i32 53, i32 54, i32 55, i32 56, i32 57, i32 58, i32 59, i32 60, i32 61, i32 62, i32 63, i32 64, i32 65, i32 66, i32 67, i32 68, i32 69, i32 70, i32 71, i32 72, i32 73, i32 74, i32 75, i32 76, i32 77, i32 78, i32 79, i32 80, i32 81, i32 82, i32 83, i32 84, i32 85, i32 86, i32 87, i32 88, i32 89, i32 90, i32 91, i32 92, i32 93, i32 94, i32 95, i32 96, i32 97, i32 98, i32 99, i32 100, i32 101, i32 102, i32 103, i32 104, i32 105, i32 106, i32 107, i32 108, i32 109, i32 110, i32 111, i32 112, i32 113, i32 114, i32 115, i32 116, i32 117, i32 118, i32 119, i32 120, i32 121, i32 122, i32 123, i32 124, i32 125, i32 126, i32 127>
+%interleaved = shufflevector <128 x i8> %1, <128 x i8> %2, <256 x i32> <i32 0, i32 64, i32 128, i32 192, i32 1, i32 65, i32 129, i32 193, i32 2, i32 66, i32 130, i32 194, i32 3, i32 67, i32 131, i32 195, i32 4, i32 68, i32 132, i32 196, i32 5, i32 69, i32 133, i32 197, i32 6, i32 70, i32 134, i32 198, i32 7, i32 71, i32 135, i32 199, i32 8, i32 72, i32 136, i32 200, i32 9, i32 73, i32 137, i32 201, i32 10, i32 74, i32 138, i32 202, i32 11, i32 75, i32 139, i32 203, i32 12, i32 76, i32 140, i32 204, i32 13, i32 77, i32 141, i32 205, i32 14, i32 78, i32 142, i32 206, i32 15, i32 79, i32 143, i32 207, i32 16, i32 80, i32 144, i32 208, i32 17, i32 81, i32 145, i32 209, i32 18, i32 82, i32 146, i32 210, i32 19, i32 83, i32 147, i32 211, i32 20, i32 84, i32 148, i32 212, i32 21, i32 85, i32 149, i32 213, i32 22, i32 86, i32 150, i32 214, i32 23, i32 87, i32 151, i32 215, i32 24, i32 88, i32 152, i32 216, i32 25, i32 89, i32 153, i32 217, i32 26, i32 90, i32 154, i32 218, i32 27, i32 91, i32 155, i32 219, i32 28, i32 92, i32 156, i32 220, i32 29, i32 93, i32 157, i32 221, i32 30, i32 94, i32 158, i32 222, i32 31, i32 95, i32 159, i32 223, i32 32, i32 96, i32 160, i32 224, i32 33, i32 97, i32 161, i32 225, i32 34, i32 98, i32 162, i32 226, i32 35, i32 99, i32 163, i32 227, i32 36, i32 100, i32 164, i32 228, i32 37, i32 101, i32 165, i32 229, i32 38, i32 102, i32 166, i32 230, i32 39, i32 103, i32 167, i32 231, i32 40, i32 104, i32 168, i32 232, i32 41, i32 105, i32 169, i32 233, i32 42, i32 106, i32 170, i32 234, i32 43, i32 107, i32 171, i32 235, i32 44, i32 108, i32 172, i32 236, i32 45, i32 109, i32 173, i32 237, i32 46, i32 110, i32 174, i32 238, i32 47, i32 111, i32 175, i32 239, i32 48, i32 112, i32 176, i32 240, i32 49, i32 113, i32 177, i32 241, i32 50, i32 114, i32 178, i32 242, i32 51, i32 115, i32 179, i32 243, i32 52, i32 116, i32 180, i32 244, i32 53, i32 117, i32 181, i32 245, i32 54, i32 118, i32 182, i32 246, i32 55, i32 119, i32 183, i32 247, i32 56, i32 120, i32 184, i32 248, i32 57, i32 121, i32 185, i32 249, i32 58, i32 122, i32 186, i32 250, i32 59, i32 123, i32 187, i32 251, i32 60, i32 124, i32 188, i32 252, i32 61, i32 125, i32 189, i32 253, i32 62, i32 126, i32 190, i32 254, i32 63, i32 127, i32 191, i32 255>
+store <256 x i8> %interleaved, <256 x i8>* %p
+ret void
+}

Added: llvm/trunk/test/Transforms/InterleavedAccess/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InterleavedAccess/X86/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InterleavedAccess/X86/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/InterleavedAccess/X86/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,2 @@
+if not 'X86' in config.root.targets:
+  config.unsupported = True

Added: llvm/trunk/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll (added)
+++ llvm/trunk/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -internalize -internalize-public-api-list main -S | FileCheck %s
+
+ at A = global i32 0
+; CHECK: @A = internal global i32 0
+
+ at B = alias i32, i32* @A
+; CHECK: @B = internal alias i32, i32* @A
+
+ at C = alias i32, i32* @A
+; CHECK: @C = internal alias i32, i32* @A
+
+define i32 @main() {
+	%tmp = load i32, i32* @C
+	ret i32 %tmp
+}
+
+; CHECK: define i32 @main() {

Added: llvm/trunk/test/Transforms/Internalize/apifile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Internalize/apifile?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Internalize/apifile (added)
+++ llvm/trunk/test/Transforms/Internalize/apifile Tue Apr 16 21:52:47 2019
@@ -0,0 +1,2 @@
+foo
+j

Added: llvm/trunk/test/Transforms/Internalize/comdat.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Internalize/comdat.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Internalize/comdat.ll (added)
+++ llvm/trunk/test/Transforms/Internalize/comdat.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt < %s -internalize -internalize-public-api-list c1 -internalize-public-api-list c2 -internalize-public-api-list c3 -internalize-public-api-list c4 -S | FileCheck %s
+
+$c1 = comdat any
+$c2 = comdat any
+$c3 = comdat any
+$c4 = comdat any
+
+; CHECK: @c1_c = global i32 0, comdat($c1)
+ at c1_c = global i32 0, comdat($c1)
+
+; CHECK: @c2_b = internal global i32 0{{$}}
+ at c2_b = global i32 0, comdat($c2)
+
+; CHECK: @c3 = global i32 0, comdat{{$}}
+ at c3 = global i32 0, comdat
+
+; CHECK: @c4_a = internal global i32 0, comdat($c4)
+ at c4_a = internal global i32 0, comdat($c4)
+
+; CHECK: @c1_d = alias i32, i32* @c1_c
+ at c1_d = alias i32, i32* @c1_c
+
+; CHECK: @c2_c = internal alias i32, i32* @c2_b
+ at c2_c = alias i32, i32* @c2_b
+
+; CHECK: @c4 = alias i32, i32* @c4_a
+ at c4 = alias i32, i32* @c4_a
+
+; CHECK: define void @c1() comdat {
+define void @c1() comdat {
+  ret void
+}
+
+; CHECK: define void @c1_a() comdat($c1) {
+define void @c1_a() comdat($c1) {
+  ret void
+}
+
+; CHECK: define internal void @c2() {
+define internal void @c2() comdat {
+  ret void
+}
+
+; CHECK: define internal void @c2_a() {
+define void @c2_a() comdat($c2) {
+  ret void
+}
+
+; CHECK: define void @c3_a() comdat($c3) {
+define void @c3_a() comdat($c3) {
+  ret void
+}

Added: llvm/trunk/test/Transforms/Internalize/lists.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Internalize/lists.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Internalize/lists.ll (added)
+++ llvm/trunk/test/Transforms/Internalize/lists.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; No arguments means internalize everything
+; RUN: opt < %s -internalize -S | FileCheck --check-prefix=ALL %s
+
+; Non-existent files should be treated as if they were empty (so internalize
+; everything)
+; RUN: opt < %s -internalize -internalize-public-api-file /nonexistent/file 2> /dev/null -S | FileCheck --check-prefix=ALL %s
+
+; Internalize all but foo and j
+; RUN: opt < %s -internalize -internalize-public-api-list foo -internalize-public-api-list j -S | FileCheck --check-prefix=FOO_AND_J %s
+
+; RUN: opt < %s -S -internalize -internalize-public-api-list bar -internalize-public-api-list foo -internalize-public-api-file /nonexistent/file  2> /dev/null | FileCheck --check-prefix=FOO_AND_BAR %s
+
+; -file and -list options should be merged, the apifile contains foo and j
+; RUN: opt < %s -internalize -internalize-public-api-list bar -internalize-public-api-file %S/apifile -S | FileCheck --check-prefix=FOO_J_AND_BAR %s
+
+; ALL: @i = internal global
+; FOO_AND_J: @i = internal global
+; FOO_AND_BAR: @i = internal global
+; FOO_J_AND_BAR: @i = internal global
+ at i = global i32 0
+
+; ALL: @j = internal global
+; FOO_AND_J: @j = global
+; FOO_AND_BAR: @j = internal global
+; FOO_J_AND_BAR: @j = global
+ at j = global i32 0
+
+; ALL: define internal void @main() {
+; FOO_AND_J: define internal void @main() {
+; FOO_AND_BAR: define internal void @main() {
+; FOO_J_AND_BAR: define internal void @main() {
+define void @main() {
+        ret void
+}
+
+; ALL: define internal void @foo() {
+; FOO_AND_J: define void @foo() {
+; FOO_AND_BAR: define void @foo() {
+; FOO_J_AND_BAR: define void @foo() {
+define void @foo() {
+        ret void
+}
+
+; ALL: define available_externally void @bar() {
+; FOO_AND_J: define available_externally void @bar() {
+; FOO_AND_BAR: define available_externally void @bar() {
+; FOO_J_AND_BAR: define available_externally void @bar() {
+define available_externally void @bar() {
+  ret void
+}
+
+; ALL: define dllexport void @export_foo() {
+; FOO_AND_J: define dllexport void @export_foo() {
+; FOO_AND_BAR: define dllexport void @export_foo() {
+; FOO_J_AND_BAR: define dllexport void @export_foo() {
+define dllexport void @export_foo() {
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/Internalize/local-visibility.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Internalize/local-visibility.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Internalize/local-visibility.ll (added)
+++ llvm/trunk/test/Transforms/Internalize/local-visibility.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt < %s -internalize -S | FileCheck %s
+; Internalized symbols should have default visibility.
+
+; CHECK: @global = global i32 0
+ at global = global i32 0
+ at llvm.used = appending global [1 x i32*] [i32* @global]
+
+; CHECK: @hidden.variable = internal global i32 0
+ at hidden.variable = hidden global i32 0
+; CHECK: @protected.variable = internal global i32 0
+ at protected.variable = protected global i32 0
+
+; CHECK: @hidden.alias = internal alias  i32,  i32* @global
+ at hidden.alias = hidden alias i32, i32* @global
+; CHECK: @protected.alias = internal alias i32, i32* @global
+ at protected.alias = protected alias i32, i32* @global
+
+; CHECK: define internal void @hidden.function() {
+define hidden void @hidden.function() {
+  ret void
+}
+; CHECK: define internal void @protected.function() {
+define protected void @protected.function() {
+  ret void
+}

Added: llvm/trunk/test/Transforms/Internalize/stackguard.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Internalize/stackguard.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Internalize/stackguard.ll (added)
+++ llvm/trunk/test/Transforms/Internalize/stackguard.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+; __stack_chk_guard and __stack_chk_fail should not be internalized.
+; RUN: opt < %s -internalize -S | FileCheck %s
+; RUN: opt < %s -passes=internalize -S | FileCheck %s
+
+; CHECK: @__stack_chk_guard = hidden global [8 x i64] zeroinitializer, align 16
+ at __stack_chk_guard = hidden global [8 x i64] zeroinitializer, align 16
+
+; CHECK: @__stack_chk_fail = hidden global [8 x i64] zeroinitializer, align 16
+ at __stack_chk_fail = hidden global [8 x i64] zeroinitializer, align 16

Added: llvm/trunk/test/Transforms/Internalize/used.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Internalize/used.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Internalize/used.ll (added)
+++ llvm/trunk/test/Transforms/Internalize/used.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt < %s -internalize -S | FileCheck %s
+; RUN: opt < %s -passes=internalize -S | FileCheck %s
+
+ at llvm.used = appending global [1 x void ()*] [void ()* @f], section "llvm.metadata"
+
+ at llvm.compiler.used = appending global [1 x void ()*] [void ()* @g], section "llvm.metadata"
+
+; CHECK: define void @f()
+define void @f() {
+  ret void
+}
+
+; CHECK: define internal void @g()
+define void @g() {
+  ret void
+}
+
+; CHECK: define internal void @h()
+define void @h() {
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/2008-11-27-EntryMunge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/2008-11-27-EntryMunge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/2008-11-27-EntryMunge.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/2008-11-27-EntryMunge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; RUN: opt < %s -jump-threading -S | grep "ret i32 0"
+; PR3138
+
+define i32 @jt() {
+entry:
+       br i1 true, label %bb3, label %bb
+
+bb:             ; preds = %entry
+       unreachable
+
+bb3:            ; preds = %entry
+       ret i32 0
+}

Added: llvm/trunk/test/Transforms/JumpThreading/2010-08-26-and.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/2010-08-26-and.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/2010-08-26-and.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/2010-08-26-and.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,162 @@
+; RUN: opt -jump-threading -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin10.0.0"
+
+%class.StringSwitch = type { i8*, i32, i32, i8 }
+
+ at .str = private constant [4 x i8] c"red\00"       ; <[4 x i8]*> [#uses=1]
+ at .str1 = private constant [7 x i8] c"orange\00"   ; <[7 x i8]*> [#uses=1]
+ at .str2 = private constant [7 x i8] c"yellow\00"   ; <[7 x i8]*> [#uses=1]
+ at .str3 = private constant [6 x i8] c"green\00"    ; <[6 x i8]*> [#uses=1]
+ at .str4 = private constant [5 x i8] c"blue\00"     ; <[5 x i8]*> [#uses=1]
+ at .str5 = private constant [7 x i8] c"indigo\00"   ; <[7 x i8]*> [#uses=1]
+ at .str6 = private constant [7 x i8] c"violet\00"   ; <[7 x i8]*> [#uses=1]
+ at .str7 = private constant [12 x i8] c"Color = %d\0A\00" ; <[12 x i8]*> [#uses=1]
+
+define i32 @main(i32 %argc, i8** nocapture %argv) nounwind ssp {
+entry:
+  %cmp142 = icmp sgt i32 %argc, 1                 ; <i1> [#uses=1]
+  br i1 %cmp142, label %bb.nph, label %for.end
+
+bb.nph:                                           ; preds = %entry
+  %tmp = add i32 %argc, -2                        ; <i32> [#uses=1]
+  %tmp144 = zext i32 %tmp to i64                  ; <i64> [#uses=1]
+  %tmp145 = add i64 %tmp144, 1                    ; <i64> [#uses=1]
+  br label %land.lhs.true.i
+
+land.lhs.true.i:                                  ; preds = %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit134, %bb.nph
+  %retval.0.i.pre161 = phi i32 [ undef, %bb.nph ], [ %retval.0.i.pre, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit134 ] ; <i32> [#uses=3]
+  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp146, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit134 ] ; <i64> [#uses=1]
+  %tmp146 = add i64 %indvar, 1                    ; <i64> [#uses=3]
+  %arrayidx = getelementptr i8*, i8** %argv, i64 %tmp146 ; <i8**> [#uses=1]
+  %tmp6 = load i8*, i8** %arrayidx, align 8            ; <i8*> [#uses=8]
+  %call.i.i = call i64 @strlen(i8* %tmp6) nounwind ; <i64> [#uses=1]
+  %conv.i.i = trunc i64 %call.i.i to i32          ; <i32> [#uses=6]\
+; CHECK: switch i32 %conv.i.i
+; CHECK-NOT: if.then.i40
+; CHECK: }
+  switch i32 %conv.i.i, label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit [
+    i32 3, label %land.lhs.true5.i
+    i32 6, label %land.lhs.true5.i37
+  ]
+
+land.lhs.true5.i:                                 ; preds = %land.lhs.true.i
+  %call.i = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* %tmp6, i64 4) nounwind ; <i32> [#uses=1]
+  %cmp9.i = icmp eq i32 %call.i, 0                ; <i1> [#uses=1]
+  br i1 %cmp9.i, label %_ZN12StringSwitchI5ColorE4CaseILj4EEERS1_RAT__KcRKS0_.exit, label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit
+
+_ZN12StringSwitchI5ColorE4CaseILj4EEERS1_RAT__KcRKS0_.exit: ; preds = %land.lhs.true5.i
+  br label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit
+
+land.lhs.true5.i37:                               ; preds = %land.lhs.true.i
+  %call.i35 = call i32 @memcmp(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str1, i64 0, i64 0), i8* %tmp6, i64 7) nounwind ; <i32> [#uses=1]
+  %cmp9.i36 = icmp eq i32 %call.i35, 0            ; <i1> [#uses=1]
+  br i1 %cmp9.i36, label %if.then.i40, label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit
+
+if.then.i40:                                      ; preds = %land.lhs.true5.i37
+  br label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit
+
+_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit: ; preds = %if.then.i40, %land.lhs.true5.i37, %_ZN12StringSwitchI5ColorE4CaseILj4EEERS1_RAT__KcRKS0_.exit, %land.lhs.true5.i, %land.lhs.true.i
+  %retval.0.i.pre159 = phi i32 [ 1, %_ZN12StringSwitchI5ColorE4CaseILj4EEERS1_RAT__KcRKS0_.exit ], [ %retval.0.i.pre161, %land.lhs.true5.i37 ], [ 2, %if.then.i40 ], [ %retval.0.i.pre161, %land.lhs.true5.i ], [ %retval.0.i.pre161, %land.lhs.true.i ] ; <i32> [#uses=2]
+  %tmp2.i44 = phi i8 [ 1, %_ZN12StringSwitchI5ColorE4CaseILj4EEERS1_RAT__KcRKS0_.exit ], [ 0, %land.lhs.true5.i37 ], [ 1, %if.then.i40 ], [ 0, %land.lhs.true5.i ], [ 0, %land.lhs.true.i ] ; <i8> [#uses=3]
+  %tobool.i46 = icmp eq i8 %tmp2.i44, 0           ; <i1> [#uses=1]
+  %cmp.i49 = icmp eq i32 %conv.i.i, 6             ; <i1> [#uses=1]
+  %or.cond = and i1 %tobool.i46, %cmp.i49         ; <i1> [#uses=1]
+  br i1 %or.cond, label %land.lhs.true5.i55, label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit60
+
+land.lhs.true5.i55:                               ; preds = %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit
+  %call.i53 = call i32 @memcmp(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str2, i64 0, i64 0), i8* %tmp6, i64 7) nounwind ; <i32> [#uses=1]
+  %cmp9.i54 = icmp eq i32 %call.i53, 0            ; <i1> [#uses=1]
+  br i1 %cmp9.i54, label %if.then.i58, label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit60
+
+if.then.i58:                                      ; preds = %land.lhs.true5.i55
+  br label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit60
+
+_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit60: ; preds = %if.then.i58, %land.lhs.true5.i55, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit
+  %retval.0.i.pre158 = phi i32 [ %retval.0.i.pre159, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit ], [ %retval.0.i.pre159, %land.lhs.true5.i55 ], [ 3, %if.then.i58 ] ; <i32> [#uses=2]
+  %tmp2.i63 = phi i8 [ %tmp2.i44, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit ], [ %tmp2.i44, %land.lhs.true5.i55 ], [ 1, %if.then.i58 ] ; <i8> [#uses=3]
+  %tmp14.i64 = and i8 %tmp2.i63, 1                ; <i8> [#uses=1]
+  %tobool.i65 = icmp eq i8 %tmp14.i64, 0          ; <i1> [#uses=1]
+  %cmp.i68 = icmp eq i32 %conv.i.i, 5             ; <i1> [#uses=1]
+  %or.cond168 = and i1 %tobool.i65, %cmp.i68      ; <i1> [#uses=1]
+  br i1 %or.cond168, label %land.lhs.true5.i74, label %_ZN12StringSwitchI5ColorE4CaseILj6EEERS1_RAT__KcRKS0_.exit
+
+land.lhs.true5.i74:                               ; preds = %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit60
+  %call.i72 = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str3, i64 0, i64 0), i8* %tmp6, i64 6) nounwind ; <i32> [#uses=1]
+  %cmp9.i73 = icmp eq i32 %call.i72, 0            ; <i1> [#uses=1]
+  br i1 %cmp9.i73, label %if.then.i77, label %_ZN12StringSwitchI5ColorE4CaseILj6EEERS1_RAT__KcRKS0_.exit
+
+if.then.i77:                                      ; preds = %land.lhs.true5.i74
+  br label %_ZN12StringSwitchI5ColorE4CaseILj6EEERS1_RAT__KcRKS0_.exit
+
+_ZN12StringSwitchI5ColorE4CaseILj6EEERS1_RAT__KcRKS0_.exit: ; preds = %if.then.i77, %land.lhs.true5.i74, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit60
+  %retval.0.i.pre157 = phi i32 [ %retval.0.i.pre158, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit60 ], [ %retval.0.i.pre158, %land.lhs.true5.i74 ], [ 4, %if.then.i77 ] ; <i32> [#uses=2]
+  %tmp2.i81 = phi i8 [ %tmp2.i63, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit60 ], [ %tmp2.i63, %land.lhs.true5.i74 ], [ 1, %if.then.i77 ] ; <i8> [#uses=3]
+  %tmp14.i82 = and i8 %tmp2.i81, 1                ; <i8> [#uses=1]
+  %tobool.i83 = icmp eq i8 %tmp14.i82, 0          ; <i1> [#uses=1]
+  %cmp.i86 = icmp eq i32 %conv.i.i, 4             ; <i1> [#uses=1]
+  %or.cond169 = and i1 %tobool.i83, %cmp.i86      ; <i1> [#uses=1]
+  br i1 %or.cond169, label %land.lhs.true5.i92, label %_ZN12StringSwitchI5ColorE4CaseILj5EEERS1_RAT__KcRKS0_.exit
+
+land.lhs.true5.i92:                               ; preds = %_ZN12StringSwitchI5ColorE4CaseILj6EEERS1_RAT__KcRKS0_.exit
+  %call.i90 = call i32 @memcmp(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str4, i64 0, i64 0), i8* %tmp6, i64 5) nounwind ; <i32> [#uses=1]
+  %cmp9.i91 = icmp eq i32 %call.i90, 0            ; <i1> [#uses=1]
+  br i1 %cmp9.i91, label %if.then.i95, label %_ZN12StringSwitchI5ColorE4CaseILj5EEERS1_RAT__KcRKS0_.exit
+
+if.then.i95:                                      ; preds = %land.lhs.true5.i92
+  br label %_ZN12StringSwitchI5ColorE4CaseILj5EEERS1_RAT__KcRKS0_.exit
+
+_ZN12StringSwitchI5ColorE4CaseILj5EEERS1_RAT__KcRKS0_.exit: ; preds = %if.then.i95, %land.lhs.true5.i92, %_ZN12StringSwitchI5ColorE4CaseILj6EEERS1_RAT__KcRKS0_.exit
+  %retval.0.i.pre156 = phi i32 [ %retval.0.i.pre157, %_ZN12StringSwitchI5ColorE4CaseILj6EEERS1_RAT__KcRKS0_.exit ], [ %retval.0.i.pre157, %land.lhs.true5.i92 ], [ 5, %if.then.i95 ] ; <i32> [#uses=2]
+  %tmp2.i99 = phi i8 [ %tmp2.i81, %_ZN12StringSwitchI5ColorE4CaseILj6EEERS1_RAT__KcRKS0_.exit ], [ %tmp2.i81, %land.lhs.true5.i92 ], [ 1, %if.then.i95 ] ; <i8> [#uses=3]
+  %tmp14.i100 = and i8 %tmp2.i99, 1               ; <i8> [#uses=1]
+  %tobool.i101 = icmp eq i8 %tmp14.i100, 0        ; <i1> [#uses=1]
+  %cmp.i104 = icmp eq i32 %conv.i.i, 6            ; <i1> [#uses=1]
+  %or.cond170 = and i1 %tobool.i101, %cmp.i104    ; <i1> [#uses=1]
+  br i1 %or.cond170, label %land.lhs.true5.i110, label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit115
+
+land.lhs.true5.i110:                              ; preds = %_ZN12StringSwitchI5ColorE4CaseILj5EEERS1_RAT__KcRKS0_.exit
+  %call.i108 = call i32 @memcmp(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str5, i64 0, i64 0), i8* %tmp6, i64 7) nounwind ; <i32> [#uses=1]
+  %cmp9.i109 = icmp eq i32 %call.i108, 0          ; <i1> [#uses=1]
+  br i1 %cmp9.i109, label %if.then.i113, label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit115
+
+if.then.i113:                                     ; preds = %land.lhs.true5.i110
+  br label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit115
+
+_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit115: ; preds = %if.then.i113, %land.lhs.true5.i110, %_ZN12StringSwitchI5ColorE4CaseILj5EEERS1_RAT__KcRKS0_.exit
+  %retval.0.i.pre155 = phi i32 [ %retval.0.i.pre156, %_ZN12StringSwitchI5ColorE4CaseILj5EEERS1_RAT__KcRKS0_.exit ], [ %retval.0.i.pre156, %land.lhs.true5.i110 ], [ 6, %if.then.i113 ] ; <i32> [#uses=2]
+  %tmp2.i118 = phi i8 [ %tmp2.i99, %_ZN12StringSwitchI5ColorE4CaseILj5EEERS1_RAT__KcRKS0_.exit ], [ %tmp2.i99, %land.lhs.true5.i110 ], [ 1, %if.then.i113 ] ; <i8> [#uses=3]
+  %tmp14.i119 = and i8 %tmp2.i118, 1              ; <i8> [#uses=1]
+  %tobool.i120 = icmp eq i8 %tmp14.i119, 0        ; <i1> [#uses=1]
+  %cmp.i123 = icmp eq i32 %conv.i.i, 6            ; <i1> [#uses=1]
+  %or.cond171 = and i1 %tobool.i120, %cmp.i123    ; <i1> [#uses=1]
+  br i1 %or.cond171, label %land.lhs.true5.i129, label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit134
+
+land.lhs.true5.i129:                              ; preds = %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit115
+  %call.i127 = call i32 @memcmp(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str6, i64 0, i64 0), i8* %tmp6, i64 7) nounwind ; <i32> [#uses=1]
+  %cmp9.i128 = icmp eq i32 %call.i127, 0          ; <i1> [#uses=1]
+  br i1 %cmp9.i128, label %if.then.i132, label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit134
+
+if.then.i132:                                     ; preds = %land.lhs.true5.i129
+  br label %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit134
+
+_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit134: ; preds = %if.then.i132, %land.lhs.true5.i129, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit115
+  %retval.0.i.pre = phi i32 [ %retval.0.i.pre155, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit115 ], [ %retval.0.i.pre155, %land.lhs.true5.i129 ], [ 7, %if.then.i132 ] ; <i32> [#uses=2]
+  %tmp2.i137 = phi i8 [ %tmp2.i118, %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit115 ], [ %tmp2.i118, %land.lhs.true5.i129 ], [ 1, %if.then.i132 ] ; <i8> [#uses=1]
+  %tmp7.i138 = and i8 %tmp2.i137, 1               ; <i8> [#uses=1]
+  %tobool.i139 = icmp eq i8 %tmp7.i138, 0         ; <i1> [#uses=1]
+  %retval.0.i = select i1 %tobool.i139, i32 0, i32 %retval.0.i.pre ; <i32> [#uses=1]
+  %call22 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str7, i64 0, i64 0), i32 %retval.0.i) ; <i32> [#uses=0]
+  %exitcond = icmp eq i64 %tmp146, %tmp145        ; <i1> [#uses=1]
+  br i1 %exitcond, label %for.end, label %land.lhs.true.i
+
+for.end:                                          ; preds = %_ZN12StringSwitchI5ColorE4CaseILj7EEERS1_RAT__KcRKS0_.exit134, %entry
+  ret i32 0
+}
+
+declare i32 @printf(i8* nocapture, ...) nounwind
+
+declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) nounwind readonly
+
+declare i64 @strlen(i8* nocapture) nounwind readonly

Added: llvm/trunk/test/Transforms/JumpThreading/2011-04-02-SimplifyDeadBlock.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/2011-04-02-SimplifyDeadBlock.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/2011-04-02-SimplifyDeadBlock.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/2011-04-02-SimplifyDeadBlock.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -jump-threading
+; PR9446
+; Just check that it doesn't crash
+
+define void @int327() nounwind {
+entry:
+  unreachable
+
+for.cond:                                         ; preds = %for.cond4
+  %tobool3 = icmp eq i8 undef, 0
+  br i1 %tobool3, label %for.cond23, label %for.cond4
+
+for.cond4:                                        ; preds = %for.cond
+  br label %for.cond
+
+for.cond23:                                       ; preds = %for.body28, %for.cond23, %for.cond
+  %conv321 = phi i32 [ %conv32, %for.body28 ], [ 0, %for.cond ], [ %conv321, %for.cond23 ]
+  %l_266.0 = phi i32 [ %phitmp, %for.body28 ], [ 0, %for.cond ], [ 0, %for.cond23 ]
+  %cmp26 = icmp eq i32 %l_266.0, 0
+  br i1 %cmp26, label %for.body28, label %for.cond23
+
+for.body28:                                       ; preds = %for.cond23
+  %and = and i32 %conv321, 1
+  %conv32 = zext i8 undef to i32
+  %add = add nsw i32 %l_266.0, 1
+  %phitmp = and i32 %add, 255
+  br label %for.cond23
+
+if.end43:                                         ; No predecessors!
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/JumpThreading/2011-04-14-InfLoop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/2011-04-14-InfLoop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/2011-04-14-InfLoop.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/2011-04-14-InfLoop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -jump-threading < %s
+; <rdar://problem/9284786>
+
+%0 = type <{ i64, i16, i64, i8, i8 }>
+
+ at g_338 = external global %0, align 8
+
+define void @func_1() nounwind ssp {
+entry:
+  ret void
+
+for.cond1177:
+  %inc1187 = add nsw i32 0, 1
+  %cmp1179 = icmp slt i32 %inc1187, 5
+  br i1 %cmp1179, label %for.cond1177, label %land.rhs1320
+
+land.rhs1320:
+  %tmp1324 = load volatile i64, i64* getelementptr inbounds (%0, %0* @g_338, i64 0, i32 2), align 1
+  br label %if.end.i
+
+if.end.i:
+  %tobool.pr.i = phi i1 [ false, %if.end.i ], [ false, %land.rhs1320 ]
+  br i1 %tobool.pr.i, label %return, label %if.end.i
+
+return:
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/2012-07-19-NoSuccessorIndirectBr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/2012-07-19-NoSuccessorIndirectBr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/2012-07-19-NoSuccessorIndirectBr.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/2012-07-19-NoSuccessorIndirectBr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+; RUN: opt < %s -jump-threading
+; PR 13405
+; Just check that it doesn't crash / assert
+
+define i32 @f() nounwind {
+entry:
+  indirectbr i8* undef, []
+}

Added: llvm/trunk/test/Transforms/JumpThreading/PR33357-lvi-recursion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/PR33357-lvi-recursion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/PR33357-lvi-recursion.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/PR33357-lvi-recursion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -S -jump-threading -verify -o - %s | FileCheck %s
+ at a = external global i16, align 1
+
+; CHECK-LABEL: f
+; CHECK: bb6:
+; CHECK: bb2:
+; CHECK: bb3:
+; CHECK-NOT: bb0:
+; CHECK-NOT: bb1:
+; CHECK-NOT: bb4:
+; CHECK-NOT: bb5:
+define void @f(i32 %p1) {
+bb0:
+  %0 = icmp eq i32 %p1, 0
+  br i1 undef, label %bb6, label %bb1
+
+bb1:
+  br label %bb2
+
+bb2:
+  %1 = phi i1 [ %0, %bb1 ], [ %2, %bb4 ]
+  %2 = and i1 %1, undef
+  br i1 %2, label %bb3, label %bb4
+
+bb3:
+  store i16 undef, i16* @a, align 1
+  br label %bb4
+
+bb4:
+  br i1 %0, label %bb2, label %bb5
+
+bb5:
+  unreachable
+
+bb6:
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/PR37745.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/PR37745.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/PR37745.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/PR37745.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt -jump-threading -verify-each -S -mtriple=x86_64-- -o - %s
+
+define void @foo() {
+entry:
+  br i1 false, label %A, label %B
+
+A:
+  %x = phi i32 [ undef, %entry ], [ %z, %B ]
+  br label %B
+
+B:
+  %y = phi i32 [ undef, %entry ], [ %x, %A ]
+  %z = add i32 %y, 1
+  %cmp = icmp ne i32 %z, 0
+  br i1 %cmp, label %exit, label %A
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/and-and-cond.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/and-and-cond.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/and-and-cond.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/and-and-cond.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt < %s -jump-threading -mem2reg -instcombine -simplifycfg  -S | FileCheck %s
+
+declare i32 @f1()
+declare i32 @f2()
+declare void @f3()
+
+define i32 @test(i1 %cond, i1 %cond2, i1 %cond3) {
+; CHECK: test
+	br i1 %cond, label %T1, label %F1
+
+; CHECK-NOT: T1:
+T1:
+	%v1 = call i32 @f1()
+	br label %Merge
+
+F1:
+	%v2 = call i32 @f2()
+	br label %Merge
+
+Merge:
+; CHECK: Merge:
+; CHECK: %v1 = call i32 @f1()
+; CHECK-NEXT: %D = and i1 %cond2, %cond3
+; CHECK-NEXT: br i1 %D
+	%A = phi i1 [true, %T1], [false, %F1]
+	%B = phi i32 [%v1, %T1], [%v2, %F1]
+	%C = and i1 %A, %cond2
+	%D = and i1 %C, %cond3
+	br i1 %D, label %T2, label %F2
+
+T2:
+	call void @f3()
+	ret i32 %B
+
+F2:
+	ret i32 %B
+}

Added: llvm/trunk/test/Transforms/JumpThreading/and-cond.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/and-cond.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/and-cond.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/and-cond.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt < %s -jump-threading -mem2reg -instcombine -simplifycfg  -S | FileCheck %s
+
+declare i32 @f1()
+declare i32 @f2()
+declare void @f3()
+
+define i32 @test(i1 %cond, i1 %cond2) {
+; CHECK: test
+	br i1 %cond, label %T1, label %F1
+
+; CHECK-NOT: T1
+T1:
+	%v1 = call i32 @f1()
+	br label %Merge
+
+F1:
+	%v2 = call i32 @f2()
+	br label %Merge
+
+Merge:
+; CHECK: Merge:
+; CHECK: %v1 = call i32 @f1()
+; CHECK-NEXT: br i1 %cond2
+	%A = phi i1 [true, %T1], [false, %F1]
+	%B = phi i32 [%v1, %T1], [%v2, %F1]
+	%C = and i1 %A, %cond2
+	br i1 %C, label %T2, label %F2
+
+T2:
+	call void @f3()
+	ret i32 %B
+
+F2:
+	ret i32 %B
+}

Added: llvm/trunk/test/Transforms/JumpThreading/assume-edge-dom.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/assume-edge-dom.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/assume-edge-dom.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/assume-edge-dom.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt -S -jump-threading < %s | FileCheck %s
+
+declare i8* @escape()
+declare void @llvm.assume(i1)
+
+define i1 @test1(i1 %cond) {
+entry:
+    br i1 %cond, label %taken, label %not_taken
+
+; CHECK-LABEL: @test1
+; CHECK: br i1 %cond, label %no, label %yes
+; CHECK: ret i1 true
+
+taken:
+    %res1 = call i8* @escape()
+    %a = icmp eq i8* %res1, null
+    tail call void @llvm.assume(i1 %a)
+    br label %done
+not_taken:
+    %res2 = call i8* @escape()
+    %b = icmp ne i8* %res2, null
+    tail call void @llvm.assume(i1 %b)
+    br label %done
+
+; An assume that can be used to simplify this comparison dominates each
+; predecessor branch (although no assume dominates the cmp itself). Make sure
+; this still can be simplified.
+
+done:
+    %res = phi i8* [ %res1, %taken ], [ %res2, %not_taken ]
+    %cnd = icmp ne i8* %res, null
+    br i1 %cnd, label %yes, label %no
+
+yes:
+    ret i1 true
+no:
+    ret i1 false
+}
+

Added: llvm/trunk/test/Transforms/JumpThreading/assume.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/assume.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/assume.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/assume.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,241 @@
+; RUN: opt -S -jump-threading -dce < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define i32 @test1(i32 %a, i32 %b) #0 {
+entry:
+  %cmp = icmp sgt i32 %a, 5
+  tail call void @llvm.assume(i1 %cmp)
+  %cmp1 = icmp sgt i32 %b, 1234
+  br i1 %cmp1, label %if.then, label %if.else
+
+; CHECK-LABEL: @test1
+; CHECK: icmp sgt i32 %a, 5
+; CHECK: call void @llvm.assume
+; CHECK-NOT: icmp sgt i32 %a, 3
+; CHECK: ret i32
+
+if.then:                                          ; preds = %entry
+  %cmp2 = icmp sgt i32 %a, 3
+  br i1 %cmp2, label %if.then3, label %return
+
+if.then3:                                         ; preds = %if.then
+  tail call void (...) @bar() #1
+  br label %return
+
+if.else:                                          ; preds = %entry
+  tail call void (...) @car() #1
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then, %if.then3
+  %retval.0 = phi i32 [ 1, %if.then3 ], [ 0, %if.then ], [ 0, %if.else ]
+  ret i32 %retval.0
+}
+
+define i32 @test2(i32 %a) #0 {
+entry:
+  %cmp = icmp sgt i32 %a, 5
+  tail call void @llvm.assume(i1 %cmp)
+  %cmp1 = icmp sgt i32 %a, 3
+  br i1 %cmp1, label %if.then, label %return
+
+; CHECK-LABEL: @test2
+; CHECK: icmp sgt i32 %a, 5
+; CHECK: tail call void @llvm.assume
+; CHECK: tail call void (...) @bar()
+; CHECK: ret i32 1
+
+
+if.then:                                          ; preds = %entry
+  tail call void (...) @bar() #1
+  br label %return
+
+return:                                           ; preds = %entry, %if.then
+  %retval.0 = phi i32 [ 1, %if.then ], [ 0, %entry ]
+  ret i32 %retval.0
+}
+
+ at g = external global i32
+
+; Check that we do prove a fact using an assume within the block.
+; We can fold the assume based on the semantics of assume.
+define void @can_fold_assume(i32* %array) {
+; CHECK-LABEL: @can_fold_assume
+; CHECK-NOT: call void @llvm.assume
+; CHECK-NOT: br
+; CHECK: ret void
+  %notnull = icmp ne i32* %array, null
+  call void @llvm.assume(i1 %notnull)
+  br i1 %notnull, label %normal, label %error
+
+normal:
+  ret void
+
+error:
+  store atomic i32 0, i32* @g unordered, align 4
+  ret void
+}
+
+declare void @f(i1)
+declare void @exit()
+; We can fold the assume but not the uses before the assume.
+define void @cannot_fold_use_before_assume(i32* %array) {
+; CHECK-LABEL:@cannot_fold_use_before_assume
+; CHECK: @f(i1 %notnull)
+; CHECK-NEXT: exit()
+; CHECK-NOT: assume
+; CHECK-NEXT: ret void
+  %notnull = icmp ne i32* %array, null
+  call void @f(i1 %notnull)
+  call void @exit()
+  call void @llvm.assume(i1 %notnull)
+  br i1 %notnull, label %normal, label %error
+
+normal:
+  ret void
+
+error:
+  store atomic i32 0, i32* @g unordered, align 4
+  ret void
+}
+
+declare void @dummy(i1) nounwind argmemonly
+define void @can_fold_some_use_before_assume(i32* %array) {
+
+; CHECK-LABEL:@can_fold_some_use_before_assume
+; CHECK: @f(i1 %notnull)
+; CHECK-NEXT: @dummy(i1 true)
+; CHECK-NOT: assume
+; CHECK-NEXT: ret void
+  %notnull = icmp ne i32* %array, null
+  call void @f(i1 %notnull)
+  call void @dummy(i1 %notnull)
+  call void @llvm.assume(i1 %notnull)
+  br i1 %notnull, label %normal, label %error
+
+normal:
+  ret void
+
+error:
+  store atomic i32 0, i32* @g unordered, align 4
+  ret void
+
+}
+
+; FIXME: can fold assume and all uses before/after assume.
+; because the trapping exit call is after the assume.
+define void @can_fold_assume_and_all_uses(i32* %array) {
+; CHECK-LABEL:@can_fold_assume_and_all_uses
+; CHECK: @dummy(i1 %notnull)
+; CHECK-NEXT: assume(i1 %notnull)
+; CHECK-NEXT: exit()
+; CHECK-NEXT: %notnull2 = or i1 true, false
+; CHECK-NEXT: @f(i1 %notnull2)
+; CHECK-NEXT: ret void
+  %notnull = icmp ne i32* %array, null
+  call void @dummy(i1 %notnull)
+  call void @llvm.assume(i1 %notnull)
+  call void @exit()
+  br i1 %notnull, label %normal, label %error
+
+normal:
+  %notnull2 = or i1 %notnull, false
+  call void @f(i1 %notnull2)
+  ret void
+
+error:
+  store atomic i32 0, i32* @g unordered, align 4
+  ret void
+}
+
+declare void @fz(i8)
+; FIXME: We can fold assume to true, and the use after assume, but we do not do so
+; currently, because of the function call after the assume.
+define void @can_fold_assume2(i32* %array) {
+
+; CHECK-LABEL:@can_fold_assume2
+; CHECK: @f(i1 %notnull)
+; CHECK-NEXT: assume(i1 %notnull)
+; CHECK-NEXT: znotnull = zext i1 %notnull to i8
+; CHECK-NEXT: @f(i1 %notnull)
+; CHECK-NEXT: @f(i1 true)
+; CHECK-NEXT: @fz(i8 %znotnull)
+; CHECK-NEXT: ret void
+  %notnull = icmp ne i32* %array, null
+  call void @f(i1 %notnull)
+  call void @llvm.assume(i1 %notnull)
+  %znotnull = zext i1 %notnull to i8
+  call void @f(i1 %notnull)
+  br i1 %notnull, label %normal, label %error
+
+normal:
+  call void @f(i1 %notnull)
+  call void @fz(i8 %znotnull)
+  ret void
+
+error:
+  store atomic i32 0, i32* @g unordered, align 4
+  ret void
+}
+
+declare void @llvm.experimental.guard(i1, ...)
+; FIXME: We can fold assume to true, but we do not do so
+; because of the guard following the assume.
+define void @can_fold_assume3(i32* %array){
+
+; CHECK-LABEL:@can_fold_assume3
+; CHECK: @f(i1 %notnull)
+; CHECK-NEXT: assume(i1 %notnull)
+; CHECK-NEXT: guard(i1 %notnull)
+; CHECK-NEXT: znotnull = zext i1 true to i8
+; CHECK-NEXT: @f(i1 true)
+; CHECK-NEXT: @fz(i8 %znotnull)
+; CHECK-NEXT: ret void
+  %notnull = icmp ne i32* %array, null
+  call void @f(i1 %notnull)
+  call void @llvm.assume(i1 %notnull)
+  call void(i1, ...) @llvm.experimental.guard(i1 %notnull) [ "deopt"() ]
+  %znotnull = zext i1 %notnull to i8
+  br i1 %notnull, label %normal, label %error
+
+normal:
+  call void @f(i1 %notnull)
+  call void @fz(i8 %znotnull)
+  ret void
+
+error:
+  store atomic i32 0, i32* @g unordered, align 4
+  ret void
+}
+
+
+; can fold all uses and remove the cond
+define void @can_fold_assume4(i32* %array) {
+; CHECK-LABEL: can_fold_assume4
+; CHECK-NOT: notnull
+; CHECK: dummy(i1 true)
+; CHECK-NEXT: ret void
+  %notnull = icmp ne i32* %array, null
+  call void @exit()
+  call void @dummy(i1 %notnull)
+  call void @llvm.assume(i1 %notnull)
+  br i1 %notnull, label %normal, label %error
+
+normal:
+  ret void
+
+error:
+  store atomic i32 0, i32* @g unordered, align 4
+  ret void
+}
+; Function Attrs: nounwind
+declare void @llvm.assume(i1) #1
+
+declare void @bar(...)
+
+declare void @car(...)
+
+attributes #0 = { nounwind uwtable }
+attributes #1 = { nounwind }
+

Added: llvm/trunk/test/Transforms/JumpThreading/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/basic.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,610 @@
+; RUN: opt -jump-threading -S < %s | FileCheck %s
+
+declare i32 @f1()
+declare i32 @f2()
+declare void @f3()
+
+define i32 @test1(i1 %cond) {
+; CHECK-LABEL: @test1(
+
+	br i1 %cond, label %T1, label %F1
+
+T1:
+	%v1 = call i32 @f1()
+	br label %Merge
+
+F1:
+	%v2 = call i32 @f2()
+	br label %Merge
+
+Merge:
+	%A = phi i1 [true, %T1], [false, %F1]
+	%B = phi i32 [%v1, %T1], [%v2, %F1]
+	br i1 %A, label %T2, label %F2
+
+T2:
+; CHECK: T2:
+; CHECK: ret i32 %v1
+	call void @f3()
+	ret i32 %B
+
+F2:
+; CHECK: F2:
+; CHECK: ret i32 %v2
+	ret i32 %B
+}
+
+
+;; cond is known false on Entry -> F1 edge!
+define i32 @test2(i1 %cond) {
+; CHECK-LABEL: @test2(
+Entry:
+	br i1 %cond, label %T1, label %F1
+
+T1:
+; CHECK: %v1 = call i32 @f1()
+; CHECK: ret i32 47
+	%v1 = call i32 @f1()
+	br label %Merge
+
+F1:
+	br i1 %cond, label %Merge, label %F2
+
+Merge:
+	%B = phi i32 [47, %T1], [192, %F1]
+	ret i32 %B
+
+F2:
+	call void @f3()
+	ret i32 12
+}
+
+
+; Undef handling.
+define i32 @test3(i1 %cond) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT: T1:
+; CHECK-NEXT: ret i32 42
+	br i1 undef, label %T1, label %F1
+
+T1:
+	ret i32 42
+
+F1:
+	ret i32 17
+}
+
+define i32 @test4(i1 %cond, i1 %cond2) {
+; CHECK-LABEL: @test4(
+
+	br i1 %cond, label %T1, label %F1
+
+T1:
+; CHECK:   %v1 = call i32 @f1()
+; CHECK-NEXT:   br label %T
+
+	%v1 = call i32 @f1()
+	br label %Merge
+
+F1:
+	%v2 = call i32 @f2()
+; CHECK:   %v2 = call i32 @f2()
+; CHECK-NEXT:   br i1 %cond2,
+	br label %Merge
+
+Merge:
+	%A = phi i1 [undef, %T1], [%cond2, %F1]
+	%B = phi i32 [%v1, %T1], [%v2, %F1]
+	br i1 %A, label %T2, label %F2
+
+T2:
+	call void @f3()
+	ret i32 %B
+
+F2:
+	ret i32 %B
+}
+
+
+;; This tests that the branch in 'merge' can be cloned up into T1.
+define i32 @test5(i1 %cond, i1 %cond2) {
+; CHECK-LABEL: @test5(
+
+	br i1 %cond, label %T1, label %F1
+
+T1:
+; CHECK: T1:
+; CHECK-NEXT:   %v1 = call i32 @f1()
+; CHECK-NEXT:   %cond3 = icmp eq i32 %v1, 412
+; CHECK-NEXT:   br i1 %cond3, label %T2, label %F2
+
+	%v1 = call i32 @f1()
+        %cond3 = icmp eq i32 %v1, 412
+	br label %Merge
+
+F1:
+	%v2 = call i32 @f2()
+	br label %Merge
+
+Merge:
+	%A = phi i1 [%cond3, %T1], [%cond2, %F1]
+	%B = phi i32 [%v1, %T1], [%v2, %F1]
+	br i1 %A, label %T2, label %F2
+
+T2:
+	call void @f3()
+	ret i32 %B
+
+F2:
+	ret i32 %B
+}
+
+
+;; Lexically duplicated conditionals should be threaded.
+
+
+define i32 @test6(i32 %A) {
+; CHECK-LABEL: @test6(
+	%tmp455 = icmp eq i32 %A, 42
+	br i1 %tmp455, label %BB1, label %BB2
+
+; CHECK: call i32 @f2()
+; CHECK-NEXT: ret i32 3
+
+; CHECK: call i32 @f1()
+; CHECK-NOT: br
+; CHECK: call void @f3()
+; CHECK-NOT: br
+; CHECK: ret i32 4
+
+BB2:
+	call i32 @f1()
+	br label %BB1
+
+
+BB1:
+	%tmp459 = icmp eq i32 %A, 42
+	br i1 %tmp459, label %BB3, label %BB4
+
+BB3:
+	call i32 @f2()
+        ret i32 3
+
+BB4:
+	call void @f3()
+	ret i32 4
+}
+
+
+;; This tests that the branch in 'merge' can be cloned up into T1.
+;; rdar://7367025
+define i32 @test7(i1 %cond, i1 %cond2) {
+Entry:
+; CHECK-LABEL: @test7(
+	%v1 = call i32 @f1()
+	br i1 %cond, label %Merge, label %F1
+
+F1:
+	%v2 = call i32 @f2()
+	br label %Merge
+
+Merge:
+	%B = phi i32 [%v1, %Entry], [%v2, %F1]
+        %M = icmp ne i32 %B, %v1
+        %N = icmp eq i32 %B, 47
+        %O = and i1 %M, %N
+	br i1 %O, label %T2, label %F2
+
+; CHECK: Merge:
+; CHECK-NOT: phi
+; CHECK-NEXT:   %v2 = call i32 @f2()
+
+T2:
+	call void @f3()
+	ret i32 %B
+
+F2:
+	ret i32 %B
+; CHECK: F2:
+; CHECK-NEXT: phi i32
+}
+
+
+declare i1 @test8a()
+
+define i32 @test8b(i1 %cond, i1 %cond2) {
+; CHECK-LABEL: @test8b(
+T0:
+        %A = call i1 @test8a()
+	br i1 %A, label %T1, label %F1
+
+; CHECK: T0:
+; CHECK-NEXT: call
+; CHECK-NEXT: br i1 %A, label %T1, label %Y
+
+T1:
+        %B = call i1 @test8a()
+	br i1 %B, label %T2, label %F1
+
+; CHECK: T1:
+; CHECK-NEXT: call
+; CHECK-NEXT: br i1 %B, label %T2, label %Y
+T2:
+        %C = call i1 @test8a()
+	br i1 %cond, label %T3, label %F1
+
+; CHECK: T2:
+; CHECK-NEXT: call
+; CHECK-NEXT: br i1 %cond, label %T3, label %Y
+T3:
+        ret i32 0
+
+F1:
+        %D = phi i32 [0, %T0], [0, %T1], [1, %T2]
+        %E = icmp eq i32 %D, 1
+        %F = and i1 %E, %cond
+	br i1 %F, label %X, label %Y
+X:
+        call i1 @test8a()
+        ret i32 1
+Y:
+        ret i32 2
+}
+
+
+;;; Verify that we can handle constraint propagation through "xor x, 1".
+define i32 @test9(i1 %cond, i1 %cond2) {
+Entry:
+; CHECK-LABEL: @test9(
+	%v1 = call i32 @f1()
+	br i1 %cond, label %Merge, label %F1
+
+; CHECK: Entry:
+; CHECK-NEXT:  %v1 = call i32 @f1()
+; CHECK-NEXT:  br i1 %cond, label %F2, label %Merge
+
+F1:
+	%v2 = call i32 @f2()
+	br label %Merge
+
+Merge:
+	%B = phi i32 [%v1, %Entry], [%v2, %F1]
+        %M = icmp eq i32 %B, %v1
+        %M1 = xor i1 %M, 1
+        %N = icmp eq i32 %B, 47
+        %O = and i1 %M1, %N
+	br i1 %O, label %T2, label %F2
+
+; CHECK: Merge:
+; CHECK-NOT: phi
+; CHECK-NEXT:   %v2 = call i32 @f2()
+
+T2:
+	%Q = zext i1 %M to i32
+	ret i32 %Q
+
+F2:
+	ret i32 %B
+; CHECK: F2:
+; CHECK-NEXT: phi i32
+}
+
+
+
+; CHECK: @test10
+declare i32 @test10f1()
+declare i32 @test10f2()
+declare void @test10f3()
+
+;; Non-local condition threading.
+define i32 @test10g(i1 %cond) {
+; CHECK-LABEL: @test10g(
+; CHECK-NEXT:   br i1 %cond, label %T2, label %F2
+        br i1 %cond, label %T1, label %F1
+
+T1:
+        %v1 = call i32 @test10f1()
+        br label %Merge
+
+; CHECK: %v1 = call i32 @test10f1()
+; CHECK-NEXT: call void @f3()
+; CHECK-NEXT: ret i32 %v1
+
+F1:
+        %v2 = call i32 @test10f2()
+        br label %Merge
+
+Merge:
+        %B = phi i32 [%v1, %T1], [%v2, %F1]
+        br i1 %cond, label %T2, label %F2
+
+T2:
+        call void @f3()
+        ret i32 %B
+
+F2:
+        ret i32 %B
+}
+
+
+; Impossible conditional constraints should get threaded.  BB3 is dead here.
+define i32 @test11(i32 %A) {
+; CHECK-LABEL: @test11(
+; CHECK-NEXT: icmp
+; CHECK-NEXT: br i1 %tmp455, label %BB4, label %BB2
+	%tmp455 = icmp eq i32 %A, 42
+	br i1 %tmp455, label %BB1, label %BB2
+
+BB2:
+; CHECK: call i32 @f1()
+; CHECK-NEXT: ret i32 %C
+	%C = call i32 @f1()
+	ret i32 %C
+
+
+BB1:
+	%tmp459 = icmp eq i32 %A, 43
+	br i1 %tmp459, label %BB3, label %BB4
+
+BB3:
+	call i32 @f2()
+        ret i32 3
+
+BB4:
+	call void @f3()
+	ret i32 4
+}
+
+;; Correlated value through boolean expression.  GCC PR18046.
+define void @test12(i32 %A) {
+; CHECK-LABEL: @test12(
+entry:
+  %cond = icmp eq i32 %A, 0
+  br i1 %cond, label %bb, label %bb1
+; Should branch to the return block instead of through BB1.
+; CHECK: entry:
+; CHECK-NEXT: %cond = icmp eq i32 %A, 0
+; CHECK-NEXT: br i1 %cond, label %bb1, label %return
+
+bb:
+  %B = call i32 @test10f2()
+  br label %bb1
+
+bb1:
+  %C = phi i32 [ %A, %entry ], [ %B, %bb ]
+  %cond4 = icmp eq i32 %C, 0
+  br i1 %cond4, label %bb2, label %return
+
+; CHECK: bb1:
+; CHECK-NEXT: %B = call i32 @test10f2()
+; CHECK-NEXT: %cond4 = icmp eq i32 %B, 0
+; CHECK-NEXT: br i1 %cond4, label %bb2, label %return
+
+bb2:
+  %D = call i32 @test10f2()
+  ret void
+
+return:
+  ret void
+}
+
+
+;; Duplicate condition to avoid xor of cond.
+;; rdar://7391699
+define i32 @test13(i1 %cond, i1 %cond2) {
+Entry:
+; CHECK-LABEL: @test13(
+	%v1 = call i32 @f1()
+	br i1 %cond, label %Merge, label %F1
+
+F1:
+	br label %Merge
+
+Merge:
+	%B = phi i1 [true, %Entry], [%cond2, %F1]
+        %C = phi i32 [192, %Entry], [%v1, %F1]
+        %M = icmp eq i32 %C, 192
+        %N = xor i1 %B, %M
+	br i1 %N, label %T2, label %F2
+
+T2:
+	ret i32 123
+
+F2:
+	ret i32 %v1
+
+; CHECK:   br i1 %cond, label %F2, label %Merge
+
+; CHECK:      Merge:
+; CHECK-NEXT:   %M = icmp eq i32 %v1, 192
+; CHECK-NEXT:   %N = xor i1 %cond2, %M
+; CHECK-NEXT:   br i1 %N, label %T2, label %F2
+}
+
+; CHECK-LABEL: @test14(
+define i32 @test14(i32 %in) {
+entry:
+	%A = icmp eq i32 %in, 0
+; CHECK: br i1 %A, label %right_ret, label %merge
+  br i1 %A, label %left, label %right
+
+; CHECK-NOT: left:
+left:
+	br label %merge
+
+; CHECK-NOT: right:
+right:
+  %B = call i32 @f1()
+	br label %merge
+
+merge:
+; CHECK-NOT: %C = phi i32 [%in, %left], [%B, %right]
+	%C = phi i32 [%in, %left], [%B, %right]
+	%D = add i32 %C, 1
+	%E = icmp eq i32 %D, 2
+	br i1 %E, label %left_ret, label %right_ret
+
+; CHECK: left_ret:
+left_ret:
+	ret i32 0
+
+right_ret:
+	ret i32 1
+}
+
+; PR5652
+; CHECK-LABEL: @test15(
+define i32 @test15(i32 %len) {
+entry:
+; CHECK: icmp ult i32 %len, 13
+  %tmp = icmp ult i32 %len, 13
+  br i1 %tmp, label %check, label %exit0
+
+exit0:
+  ret i32 0
+
+check:
+  %tmp9 = icmp ult i32 %len, 21
+  br i1 %tmp9, label %exit1, label %exit2
+
+exit2:
+; CHECK-NOT: ret i32 2
+  ret i32 2
+
+exit1:
+  ret i32 1
+; CHECK: }
+}
+
+;;; Verify that we can handle constraint propagation through cast.
+define i32 @test16(i1 %cond) {
+Entry:
+; CHECK-LABEL: @test16(
+	br i1 %cond, label %Merge, label %F1
+
+; CHECK: Entry:
+; CHECK-NEXT:  br i1 %cond, label %F2, label %Merge
+
+F1:
+	%v1 = call i32 @f1()
+	br label %Merge
+
+Merge:
+	%B = phi i32 [0, %Entry], [%v1, %F1]
+	%M = icmp eq i32 %B, 0
+	%M1 = zext i1 %M to i32
+	%N = icmp eq i32 %M1, 0
+	br i1 %N, label %T2, label %F2
+
+; CHECK: Merge:
+; CHECK-NOT: phi
+; CHECK-NEXT:   %v1 = call i32 @f1()
+
+T2:
+	%Q = call i32 @f2()
+	ret i32 %Q
+
+F2:
+	ret i32 %B
+; CHECK: F2:
+; CHECK-NEXT: phi i32
+}
+
+; In this test we check that block duplication is inhibited by the presence
+; of a function with the 'noduplicate' attribute.
+
+declare void @g()
+declare void @j()
+declare void @k()
+
+; CHECK-LABEL: define void @h(i32 %p) {
+define void @h(i32 %p) {
+  %x = icmp ult i32 %p, 5
+  br i1 %x, label %l1, label %l2
+
+l1:
+  call void @j()
+  br label %l3
+
+l2:
+  call void @k()
+  br label %l3
+
+l3:
+; CHECK: call void @g() [[$NOD:#[0-9]+]]
+; CHECK-NOT: call void @g() [[$NOD]]
+  call void @g() noduplicate
+  %y = icmp ult i32 %p, 5
+  br i1 %y, label %l4, label %l5
+
+l4:
+  call void @j()
+  ret void
+
+l5:
+  call void @k()
+  ret void
+; CHECK: }
+}
+
+define i1 @trunc_switch(i1 %arg) {
+; CHECK-LABEL: @trunc_switch
+top:
+; CHECK: br i1 %arg, label %exitA, label %exitB
+  br i1 %arg, label %common, label %B
+
+B:
+  br label %common
+
+common:
+  %phi = phi i8 [ 2, %B ], [ 1, %top ]
+  %trunc = trunc i8 %phi to i2
+; CHECK-NOT: switch
+  switch i2 %trunc, label %unreach [
+    i2 1, label %exitA
+    i2 -2, label %exitB
+  ]
+
+unreach:
+  unreachable
+
+exitA:
+  ret i1 true
+
+exitB:
+  ret i1 false
+}
+
+; CHECK-LABEL: define void @h_con(i32 %p) {
+define void @h_con(i32 %p) {
+  %x = icmp ult i32 %p, 5
+  br i1 %x, label %l1, label %l2
+
+l1:
+  call void @j()
+  br label %l3
+
+l2:
+  call void @k()
+  br label %l3
+
+l3:
+; CHECK: call void @g() [[$CON:#[0-9]+]]
+; CHECK-NOT: call void @g() [[$CON]]
+  call void @g() convergent
+  %y = icmp ult i32 %p, 5
+  br i1 %y, label %l4, label %l5
+
+l4:
+  call void @j()
+  ret void
+
+l5:
+  call void @k()
+  ret void
+; CHECK: }
+}
+
+
+; CHECK: attributes [[$NOD]] = { noduplicate }
+; CHECK: attributes [[$CON]] = { convergent }

Added: llvm/trunk/test/Transforms/JumpThreading/bb-unreachable-from-entry.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/bb-unreachable-from-entry.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/bb-unreachable-from-entry.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/bb-unreachable-from-entry.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt -S < %s -jump-threading | FileCheck %s
+; CHECK-LABEL: @foo
+; CHECK-NEXT: exit2:
+; CHECK-NEXT: ret void
+define void @foo() {
+entry:
+  br label %bb1
+
+entry2:
+  br label %bb1
+
+bb1:
+  %a0 = phi i32 [ undef, %entry2 ], [ 0, %entry ]
+  %b = icmp ne i32 %a0, 0
+  br i1 %b, label %bb2, label %exit2
+
+bb2:
+  br label %exit1
+
+exit1:
+  %a1 = phi i32 [ %a0, %bb2 ]
+  ret void
+
+exit2:
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/branch-debug-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/branch-debug-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/branch-debug-info.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/branch-debug-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; RUN: opt %s -debugify -jump-threading -S | FileCheck %s
+; Tests Bug 37966
+
+define void @test0(i32 %i) {
+; CHECK-LABEL: @test0(
+; CHECK: left:
+; CHECK: br label %left, !dbg ![[DBG0:[0-9]+]]
+ entry:
+  %c0 = icmp ult i32 %i, 5
+  br i1 %c0, label %left, label %right
+
+ left:
+  br i1 %c0, label %left, label %right ; "line 3" to -debugify
+
+ right:
+  ret void
+}
+
+define void @test1(i32 %i, i32 %len) {
+; CHECK-LABEL: @test1(
+; CHECK: left:
+; CHECK: br label %right, !dbg ![[DBG1:[0-9]+]]
+ entry:
+  %i.inc = add nuw i32 %i, 1
+  %c0 = icmp ult i32 %i.inc, %len
+  br i1 %c0, label %left, label %right
+
+ left:
+  %c1 = icmp ult i32 %i, %len
+  br i1 %c1, label %right, label %left0 ; "line 9" to -debugify
+
+ left0:
+  ret void
+
+ right:
+  ret void
+}
+
+; CHECK-DAG: ![[DBG0]] = !DILocation(line: 3,
+; CHECK-DAG: ![[DBG1]] = !DILocation(line: 9,
+

Added: llvm/trunk/test/Transforms/JumpThreading/branch-no-const.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/branch-no-const.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/branch-no-const.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/branch-no-const.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt < %s -jump-threading -S | not grep phi
+
+declare i8 @mcguffin()
+
+define i32 @test(i1 %foo, i8 %b) {
+entry:
+  %a = call i8 @mcguffin()
+  br i1 %foo, label %bb1, label %bb2
+bb1:
+  br label %jt
+bb2:
+  br label %jt
+jt:
+  %x = phi i8 [%a, %bb1], [%b, %bb2]
+  %A = icmp eq i8 %x, %a
+  br i1 %A, label %rt, label %rf
+rt:
+  ret i32 7
+rf:
+  ret i32 8
+}

Added: llvm/trunk/test/Transforms/JumpThreading/callbr-edge-split.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/callbr-edge-split.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/callbr-edge-split.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/callbr-edge-split.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,58 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -jump-threading | FileCheck %s
+
+; This test used to cause jump threading to try to split an edge of a callbr.
+
+ at a = global i32 0
+
+define i32 @c() {
+; CHECK-LABEL: @c(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 @b()
+; CHECK-NEXT:    [[PHITMP:%.*]] = icmp ne i32 [[CALL]], 0
+; CHECK-NEXT:    br i1 [[PHITMP]], label [[IF_THEN2:%.*]], label [[IF_END4:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    callbr void asm sideeffect "", "X"(i8* blockaddress(@c, [[IF_THEN2]]))
+; CHECK-NEXT:    to label [[IF_END_THREAD:%.*]] [label %if.then2]
+; CHECK:       if.end.thread:
+; CHECK-NEXT:    br label [[IF_THEN2]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    [[CALL3:%.*]] = call i32 @b()
+; CHECK-NEXT:    br label [[IF_END4]]
+; CHECK:       if.end4:
+; CHECK-NEXT:    ret i32 undef
+;
+entry:
+  %0 = load i32, i32* @a
+  %tobool = icmp eq i32 %0, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  %call = call i32 @b() #2
+  %phitmp = icmp ne i32 %call, 0
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  callbr void asm sideeffect "", "X"(i8* blockaddress(@c, %if.end)) #2
+  to label %normal [label %if.end]
+
+normal:                                           ; preds = %if.else
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %normal, %if.then
+  %d.0 = phi i1 [ %phitmp, %if.then ], [ undef, %normal ], [ undef, %if.else ]
+  br i1 %d.0, label %if.then2, label %if.end4
+
+if.then2:                                         ; preds = %if.end
+  %call3 = call i32 @b()
+  br label %if.end4
+
+if.end4:                                          ; preds = %if.then2, %if.end
+  ret i32 undef
+}
+
+declare i32 @b()

Added: llvm/trunk/test/Transforms/JumpThreading/combine-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/combine-metadata.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/combine-metadata.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/combine-metadata.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,122 @@
+; RUN: opt < %s -jump-threading -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+
+declare void @use(i32 *)
+
+; Check that we propagate nonnull to dominated loads, when we find an available
+; loaded value.
+; CHECK-LABEL: @test1(
+; CHECK-LABEL: ret1:
+; CHECK-NEXT: %[[p1:.*]] = load i32*, i32** %ptr
+; CHECK-NOT: !nonnull
+; CHECK-NEXT: store i32 1, i32* %[[p1]]
+; CHECK-NEXT: tail call void @use(i32* null)
+; CHECK-NEXT: ret void
+
+; CHECK-LABEL: ret2:
+; CHECK-NEXT: %[[p2:.*]] = load i32*, i32** %ptr, !nonnull !0
+; CHECK: tail call void @use(i32* %[[p2]])
+; CHECK-NEXT: ret void
+define void @test1(i32** %ptr, i1 %c) {
+  br i1 %c, label %d1, label %d2
+
+d1:
+  %p1 = load i32*, i32** %ptr, !nonnull !0
+  br label %d3
+
+d2:
+  br label %d3
+
+d3:
+  %pm = phi i32* [ null, %d2 ], [ %p1, %d1 ]
+  %p2 = load i32*, i32** %ptr
+  store i32 1, i32* %p2
+  %c2 = icmp eq i32* %pm, null
+  br i1 %c2, label %ret1, label %ret2
+
+ret1:
+  tail call void @use(i32* %pm) nounwind
+  ret void
+
+ret2:
+  tail call void @use(i32* %pm) nounwind
+  ret void
+}
+
+; Check that we propagate nonnull to dominated loads, when we find an available
+; loaded value.
+; CHECK-LABEL: @test2(
+; CHECK-LABEL: d3.thread:
+; CHECK-NEXT: %[[p1:.*]] = load i32*, i32** %ptr, !nonnull !0
+; CHECK-NEXT: store i32 1, i32* %[[p1]]
+; CHECK-NEXT: br label %ret1
+
+; CHECK-LABEL: d3:
+; CHECK-NEXT: %[[p_cmp:.*]] = load i32*, i32** %ptr
+; CHECK-NEXT: %[[p2:.*]] = load i32*, i32** %ptr, !nonnull !0
+; CHECK-NEXT: store i32 1, i32* %[[p2]]
+; CHECK-NEXT: icmp eq i32* %[[p_cmp]], null
+define void @test2(i32** %ptr, i1 %c) {
+  br i1 %c, label %d1, label %d2
+
+d1:
+  %p1 = load i32*, i32** %ptr
+  br label %d3
+
+d2:
+  br label %d3
+
+d3:
+  %pm = phi i32* [ null, %d2 ], [ %p1, %d1 ]
+  %p2 = load i32*, i32** %ptr, !nonnull !0
+  store i32 1, i32* %p2
+  %c2 = icmp eq i32* %pm, null
+  br i1 %c2, label %ret1, label %ret2
+
+ret1:
+  tail call void @use(i32* %pm) nounwind
+  ret void
+
+ret2:
+  tail call void @use(i32* %pm) nounwind
+  ret void
+}
+
+; Check that we do not propagate nonnull to loads predecessors that are combined
+; to a PHI node.
+; CHECK-LABEL: @test3(
+; CHECK-LABEL: d1:
+; CHECK-NEXT: %[[p1:.*]] = load i32*, i32** %ptr
+; CHECK-NOT: !nonnull
+
+; CHECK-LABEL: d2:
+; CHECK-NEXT: %[[p2:.*]] = load i32*, i32** %ptr
+; CHECK-NOT: !nonnull
+
+; CHECK-LABEL: d3:
+; CHECK-NEXT:  phi i32* [ %[[p2]], %d2 ], [ %[[p1]], %d1 ]
+define void @test3(i32** %ptr) {
+d1:
+  %x = load i32*, i32** %ptr, !nonnull !0
+  br label %d3
+
+d2:
+  br label %d3
+
+d3:
+  %y = load i32*, i32** %ptr
+  store i32 1, i32* %y
+  %c2 = icmp eq i32* %y, null
+  br i1 %c2, label %ret1, label %ret2
+
+ret1:
+  ret void
+
+ret2:
+  ret void
+}
+
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/JumpThreading/compare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/compare.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/compare.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/compare.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; There should be no phi nodes left.
+; RUN: opt < %s -jump-threading  -S | not grep "phi i32"
+
+declare i32 @f1()
+declare i32 @f2()
+declare void @f3()
+
+define i32 @test(i1 %cond) {
+	br i1 %cond, label %T1, label %F1
+
+T1:
+	%v1 = call i32 @f1()
+	br label %Merge
+
+F1:
+	%v2 = call i32 @f2()
+	br label %Merge
+
+Merge:
+	%B = phi i32 [%v1, %T1], [12, %F1]
+	%A = icmp ne i32 %B, 42
+	br i1 %A, label %T2, label %F2
+
+T2:
+	call void @f3()
+	ret i32 1
+
+F2:
+	ret i32 0
+}

Added: llvm/trunk/test/Transforms/JumpThreading/conservative-lvi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/conservative-lvi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/conservative-lvi.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/conservative-lvi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,58 @@
+; RUN: opt -jump-threading -S %s | FileCheck %s
+
+; Check that we thread arg2neg -> checkpos -> end.
+;
+; LazyValueInfo would previously fail to analyze the value of %arg in arg2neg
+; because its predecessing blocks (checkneg) hadn't been processed yet (PR21238)
+
+; CHECK-LABEL: @test_jump_threading
+; CHECK: arg2neg:
+; CHECK-NEXT: br i1 %arg1, label %end, label %checkpos.thread
+; CHECK: checkpos.thread:
+; CHECK-NEXT: br label %end
+
+define i32 @test_jump_threading(i1 %arg1, i32 %arg2) {
+checkneg:
+  %cmp = icmp slt i32 %arg2, 0
+  br i1 %cmp, label %arg2neg, label %checkpos
+
+arg2neg:
+  br i1 %arg1, label %end, label %checkpos
+
+checkpos:
+  %cmp2 = icmp sgt i32 %arg2, 0
+  br i1 %cmp2, label %arg2pos, label %end
+
+arg2pos:
+  br label %end
+
+end:
+  %0 = phi i32 [ 1, %arg2neg ], [ 2, %checkpos ], [ 3, %arg2pos ]
+  ret i32 %0
+}
+
+
+; arg2neg has an edge back to itself. If LazyValueInfo is not careful when
+; visiting predecessors, it could get into an infinite loop.
+
+; CHECK-LABEL: test_infinite_loop
+
+define i32 @test_infinite_loop(i1 %arg1, i32 %arg2) {
+checkneg:
+  %cmp = icmp slt i32 %arg2, 0
+  br i1 %cmp, label %arg2neg, label %checkpos
+
+arg2neg:
+  br i1 %arg1, label %arg2neg, label %checkpos
+
+checkpos:
+  %cmp2 = icmp sgt i32 %arg2, 0
+  br i1 %cmp2, label %arg2pos, label %end
+
+arg2pos:
+  br label %end
+
+end:
+  %0 = phi i32 [ 2, %checkpos ], [ 3, %arg2pos ]
+  ret i32 %0
+}

Added: llvm/trunk/test/Transforms/JumpThreading/crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/crash.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,626 @@
+; RUN: opt < %s -jump-threading -S | FileCheck %s
+; PR2285
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+	%struct.system__secondary_stack__mark_id = type { i64, i64 }
+
+define void @_ada_c35507b() {
+entry:
+	br label %bb
+
+bb:		; preds = %bb13, %entry
+	%ch.0 = phi i8 [ 0, %entry ], [ 0, %bb13 ]		; <i8> [#uses=1]
+	%tmp11 = icmp ugt i8 %ch.0, 31		; <i1> [#uses=1]
+	%tmp120 = call %struct.system__secondary_stack__mark_id @system__secondary_stack__ss_mark( )		; <%struct.system__secondary_stack__mark_id> [#uses=1]
+	br i1 %tmp11, label %bb110, label %bb13
+
+bb13:		; preds = %bb
+	br label %bb
+
+bb110:		; preds = %bb
+	%mrv_gr124 = extractvalue %struct.system__secondary_stack__mark_id %tmp120, 1		; <i64> [#uses=0]
+	unreachable
+}
+
+declare %struct.system__secondary_stack__mark_id @system__secondary_stack__ss_mark()
+
+
+
+define fastcc void @findratio(double* nocapture %res1, double* nocapture %res2) nounwind ssp {
+entry:
+  br label %bb12
+
+bb6.us:                                        
+  %tmp = icmp eq i32 undef, undef              
+  %tmp1 = fsub double undef, undef             
+  %tmp2 = fcmp ult double %tmp1, 0.000000e+00  
+  br i1 %tmp, label %bb6.us, label %bb13
+
+
+bb12:                                            
+  %tmp3 = fcmp ult double undef, 0.000000e+00  
+  br label %bb13
+
+bb13:                                            
+  %.lcssa31 = phi double [ undef, %bb12 ], [ %tmp1, %bb6.us ]
+  %.lcssa30 = phi i1 [ %tmp3, %bb12 ], [ %tmp2, %bb6.us ] 
+  br i1 %.lcssa30, label %bb15, label %bb61
+
+bb15:                                            
+  %tmp4 = fsub double -0.000000e+00, %.lcssa31   
+  ret void
+
+
+bb61:                                            
+  ret void
+}
+
+
+; PR5258
+define i32 @test(i1 %cond, i1 %cond2, i32 %a) {
+A:
+  br i1 %cond, label %F, label %A1
+F:
+  br label %A1
+
+A1:  
+  %d = phi i1 [false, %A], [true, %F]
+  %e = add i32 %a, %a
+  br i1 %d, label %B, label %G
+  
+G:
+  br i1 %cond2, label %B, label %D
+  
+B:
+  %f = phi i32 [%e, %G], [%e, %A1]
+  %b = add i32 0, 0
+  switch i32 %a, label %C [
+    i32 7, label %D
+    i32 8, label %D
+    i32 9, label %D
+  ]
+
+C:
+  br label %D
+  
+D:
+  %c = phi i32 [%e, %B], [%e, %B], [%e, %B], [%f, %C], [%e, %G]
+  ret i32 %c
+E:
+  ret i32 412
+}
+
+
+define i32 @test2() nounwind {
+entry:
+        br i1 true, label %decDivideOp.exit, label %bb7.i
+
+bb7.i:          ; preds = %bb7.i, %entry
+        br label %bb7.i
+
+decDivideOp.exit:               ; preds = %entry
+        ret i32 undef
+}
+
+
+; PR3298
+
+define i32 @test3(i32 %p_79, i32 %p_80) nounwind {
+entry:
+	br label %bb7
+
+bb1:		; preds = %bb2
+	br label %bb2
+
+bb2:		; preds = %bb7, %bb1
+	%l_82.0 = phi i8 [ 0, %bb1 ], [ %l_82.1, %bb7 ]		; <i8> [#uses=3]
+	br i1 true, label %bb3, label %bb1
+
+bb3:		; preds = %bb2
+	%0 = icmp eq i32 %p_80_addr.1, 0		; <i1> [#uses=1]
+	br i1 %0, label %bb7, label %bb6
+
+bb5:		; preds = %bb6
+	%1 = icmp eq i8 %l_82.0, 0		; <i1> [#uses=1]
+	br i1 %1, label %bb1.i, label %bb.i
+
+bb.i:		; preds = %bb5
+	br label %safe_div_func_char_s_s.exit
+
+bb1.i:		; preds = %bb5
+	br label %safe_div_func_char_s_s.exit
+
+safe_div_func_char_s_s.exit:		; preds = %bb1.i, %bb.i
+	br label %bb6
+
+bb6:		; preds = %safe_div_func_char_s_s.exit, %bb3
+	%p_80_addr.0 = phi i32 [ %p_80_addr.1, %bb3 ], [ 1, %safe_div_func_char_s_s.exit ]		; <i32> [#uses=2]
+	%2 = icmp eq i32 %p_80_addr.0, 0		; <i1> [#uses=1]
+	br i1 %2, label %bb7, label %bb5
+
+bb7:		; preds = %bb6, %bb3, %entry
+	%l_82.1 = phi i8 [ 1, %entry ], [ %l_82.0, %bb3 ], [ %l_82.0, %bb6 ]		; <i8> [#uses=2]
+	%p_80_addr.1 = phi i32 [ 0, %entry ], [ %p_80_addr.1, %bb3 ], [ %p_80_addr.0, %bb6 ]		; <i32> [#uses=4]
+	%3 = icmp eq i32 %p_80_addr.1, 0		; <i1> [#uses=1]
+	br i1 %3, label %bb8, label %bb2
+
+bb8:		; preds = %bb7
+	%4 = sext i8 %l_82.1 to i32		; <i32> [#uses=0]
+	ret i32 0
+}
+
+
+; PR3353
+
+define i32 @test4(i8 %X) {
+entry:
+        %Y = add i8 %X, 1
+        %Z = add i8 %Y, 1
+        br label %bb33.i
+
+bb33.i:         ; preds = %bb33.i, %bb32.i
+        switch i8 %Y, label %bb32.i [
+                i8 39, label %bb35.split.i
+                i8 13, label %bb33.i
+        ]
+
+bb35.split.i:
+        ret i32 5
+bb32.i:
+        ret i32 1
+}
+
+
+define fastcc void @test5(i1 %tmp, i32 %tmp1) nounwind ssp {
+entry:
+  br i1 %tmp, label %bb12, label %bb13
+
+
+bb12:                                            
+  br label %bb13
+
+bb13:                                            
+  %.lcssa31 = phi i32 [ undef, %bb12 ], [ %tmp1, %entry ]
+  %A = and i1 undef, undef
+  br i1 %A, label %bb15, label %bb61
+
+bb15:                                            
+  ret void
+
+
+bb61:                                            
+  ret void
+}
+
+
+; PR5640
+define fastcc void @test6(i1 %tmp, i1 %tmp1) nounwind ssp {
+entry:
+  br i1 %tmp, label %bb12, label %bb14
+
+bb12:           
+  br label %bb14
+
+bb14:           
+  %A = phi i1 [ %A, %bb13 ],  [ true, %bb12 ], [%tmp1, %entry]
+  br label %bb13
+
+bb13:                                            
+  br i1 %A, label %bb14, label %bb61
+
+
+bb61:                                            
+  ret void
+}
+
+
+; PR5698
+define void @test7(i32 %x) {
+entry:
+  br label %tailrecurse
+
+tailrecurse:
+  switch i32 %x, label %return [
+    i32 2, label %bb2
+    i32 3, label %bb
+  ]
+
+bb:         
+  switch i32 %x, label %return [
+    i32 2, label %bb2
+    i32 3, label %tailrecurse
+  ]
+
+bb2:        
+  ret void
+
+return:     
+  ret void
+}
+
+; PR6119
+define i32 @test8(i32 %action) nounwind {
+entry:
+  switch i32 %action, label %lor.rhs [
+    i32 1, label %if.then
+    i32 0, label %lor.end
+  ]
+
+if.then:                                          ; preds = %for.cond, %lor.end, %entry
+  ret i32 undef
+
+lor.rhs:                                          ; preds = %entry
+  br label %lor.end
+
+lor.end:                                          ; preds = %lor.rhs, %entry
+  %cmp103 = xor i1 undef, undef                   ; <i1> [#uses=1]
+  br i1 %cmp103, label %for.cond, label %if.then
+
+for.cond:                                         ; preds = %for.body, %lor.end
+  br i1 undef, label %if.then, label %for.body
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond
+}
+
+; PR6119
+define i32 @test9(i32 %action) nounwind {
+entry:
+  switch i32 %action, label %lor.rhs [
+    i32 1, label %if.then
+    i32 0, label %lor.end
+  ]
+
+if.then:                                          ; preds = %for.cond, %lor.end, %entry
+  ret i32 undef
+
+lor.rhs:                                          ; preds = %entry
+  br label %lor.end
+
+lor.end:                                          ; preds = %lor.rhs, %entry
+  %0 = phi i1 [ undef, %lor.rhs ], [ true, %entry ] ; <i1> [#uses=1]
+  %cmp103 = xor i1 undef, %0                      ; <i1> [#uses=1]
+  br i1 %cmp103, label %for.cond, label %if.then
+
+for.cond:                                         ; preds = %for.body, %lor.end
+  br i1 undef, label %if.then, label %for.body
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond
+}
+
+; PR6119
+define i32 @test10(i32 %action, i32 %type) nounwind {
+entry:
+  %cmp2 = icmp eq i32 %type, 0                    ; <i1> [#uses=1]
+  switch i32 %action, label %lor.rhs [
+    i32 1, label %if.then
+    i32 0, label %lor.end
+  ]
+
+if.then:                                          ; preds = %for.cond, %lor.end, %entry
+  ret i32 undef
+
+lor.rhs:                                          ; preds = %entry
+  %cmp101 = icmp eq i32 %action, 2                ; <i1> [#uses=1]
+  br label %lor.end
+
+lor.end:                                          ; preds = %lor.rhs, %entry
+  %0 = phi i1 [ %cmp101, %lor.rhs ], [ true, %entry ] ; <i1> [#uses=1]
+  %cmp103 = xor i1 %cmp2, %0                      ; <i1> [#uses=1]
+  br i1 %cmp103, label %for.cond, label %if.then
+
+for.cond:                                         ; preds = %for.body, %lor.end
+  br i1 undef, label %if.then, label %for.body
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond
+}
+
+
+; PR6305
+define void @test11() nounwind {
+entry:
+  br label %A
+
+A:                                             ; preds = %entry
+  call void undef(i64 ptrtoint (i8* blockaddress(@test11, %A) to i64)) nounwind
+  unreachable
+}
+
+; PR6743
+define void @test12() nounwind ssp {
+entry:
+  br label %lbl_51
+
+lbl_51:                                           ; preds = %if.then, %entry
+  %tmp3 = phi i1 [ false, %if.then ], [ undef, %entry ] ; <i1> [#uses=2]
+  br i1 %tmp3, label %if.end12, label %if.then
+
+if.then:                                          ; preds = %lbl_51
+  br i1 %tmp3, label %lbl_51, label %if.end12
+
+if.end12:                                         ; preds = %if.then, %lbl_51
+  ret void
+}
+
+
+
+; PR7356
+define i32 @test13(i32* %P, i8* %Ptr) {
+entry:
+  indirectbr i8* %Ptr, [label %BrBlock, label %B2]
+  
+B2:
+  store i32 4, i32 *%P
+  br label %BrBlock
+
+BrBlock:
+  %L = load i32, i32* %P
+  %C = icmp eq i32 %L, 42
+  br i1 %C, label %T, label %F
+  
+T:
+  ret i32 123
+F:
+  ret i32 1422
+}
+
+
+; PR7498
+define void @test14() nounwind {
+entry:
+  %cmp33 = icmp slt i8 undef, 0                   ; <i1> [#uses=1]
+  %tobool = icmp eq i8 undef, 0                   ; <i1> [#uses=1]
+  br i1 %tobool, label %land.end69, label %land.rhs
+
+land.rhs:                                         ; preds = %entry
+  br label %land.end69
+
+land.end69:                                       ; preds = %land.rhs, %entry
+  %0 = phi i1 [ undef, %land.rhs ], [ true, %entry ] ; <i1> [#uses=1]
+  %cmp71 = or i1 true, %0                         ; <i1> [#uses=1]
+  %cmp73 = xor i1 %cmp33, %cmp71                  ; <i1> [#uses=1]
+  br i1 %cmp73, label %if.then, label %if.end
+
+if.then:                                          ; preds = %land.end69
+  ret void
+
+if.end:                                           ; preds = %land.end69
+  ret void
+}
+
+; PR7647
+define void @test15() nounwind {
+entry:
+  ret void
+  
+if.then237:
+  br label %lbl_664
+
+lbl_596:                                          ; preds = %lbl_664, %for.end37
+  store volatile i64 undef, i64* undef, align 4
+  br label %for.cond111
+
+for.cond111:                                      ; preds = %safe_sub_func_int64_t_s_s.exit, %lbl_596
+  %storemerge = phi i8 [ undef, %cond.true.i100 ], [ 22, %lbl_596 ] ; <i8> [#uses=1]
+  %l_678.5 = phi i64 [ %l_678.3, %cond.true.i100 ], [ undef, %lbl_596 ] ; <i64> [#uses=2]
+  %cmp114 = icmp slt i8 %storemerge, -2           ; <i1> [#uses=1]
+  br i1 %cmp114, label %lbl_664, label %if.end949
+
+lbl_664:                                          ; preds = %for.end1058, %if.then237, %for.cond111
+  %l_678.3 = phi i64 [ %l_678.5, %for.cond111 ], [ %l_678.2, %for.cond1035 ], [ 5, %if.then237 ] ; <i64> [#uses=1]
+  %tobool118 = icmp eq i32 undef, 0               ; <i1> [#uses=1]
+  br i1 %tobool118, label %cond.true.i100, label %lbl_596
+
+cond.true.i100:                                   ; preds = %for.inc120
+  br label %for.cond111
+
+lbl_709:
+  br label %if.end949
+  
+for.cond603:                                      ; preds = %for.body607, %if.end336
+  br i1 undef, label %for.cond603, label %if.end949
+
+if.end949:                                        ; preds = %for.cond603, %lbl_709, %for.cond111
+  %l_678.2 = phi i64 [ %l_678.5, %for.cond111 ], [ undef, %lbl_709 ], [ 5, %for.cond603 ] ; <i64> [#uses=1]
+  br label %for.body1016
+
+for.body1016:                                     ; preds = %for.cond1012
+  br label %for.body1016
+
+for.cond1035:                                     ; preds = %for.inc1055, %if.then1026
+  br i1 undef, label %for.cond1040, label %lbl_664
+
+for.cond1040:                                     ; preds = %for.body1044, %for.cond1035
+  ret void
+}
+
+; PR7755
+define void @test16(i1 %c, i1 %c2, i1 %c3, i1 %c4) nounwind ssp {
+entry:
+  %cmp = icmp sgt i32 undef, 1                    ; <i1> [#uses=1]
+  br i1 %c, label %land.end, label %land.rhs
+
+land.rhs:                                         ; preds = %entry
+  br i1 %c2, label %lor.lhs.false.i, label %land.end
+
+lor.lhs.false.i:                                  ; preds = %land.rhs
+  br i1 %c3, label %land.end, label %land.end
+
+land.end:                            
+  %0 = phi i1 [ true, %entry ], [ false, %land.rhs ], [false, %lor.lhs.false.i], [false, %lor.lhs.false.i] ; <i1> [#uses=1]
+  %cmp12 = and i1 %cmp, %0 
+  %xor1 = xor i1 %cmp12, %c4
+  br i1 %xor1, label %if.then, label %if.end
+
+if.then:                      
+  ret void
+
+if.end:                       
+  ret void
+}
+
+define void @test17() {
+entry:
+  br i1 undef, label %bb269.us.us, label %bb269.us.us.us
+
+bb269.us.us.us:
+  %indvar = phi i64 [ %indvar.next, %bb287.us.us.us ], [ 0, %entry ]
+  %0 = icmp eq i16 undef, 0
+  br i1 %0, label %bb287.us.us.us, label %bb286.us.us.us
+
+bb287.us.us.us:
+  %indvar.next = add i64 %indvar, 1
+  %exitcond = icmp eq i64 %indvar.next, 4
+  br i1 %exitcond, label %bb288.bb289.loopexit_crit_edge, label %bb269.us.us.us
+
+bb286.us.us.us:
+  unreachable
+
+bb269.us.us:
+	unreachable
+
+bb288.bb289.loopexit_crit_edge:
+  unreachable
+}
+
+; PR 8247
+%struct.S1 = type { i8, i8 }
+ at func_89.l_245 = internal constant %struct.S1 { i8 33, i8 6 }, align 1
+define void @func_89(i16 zeroext %p_90, %struct.S1* nocapture %p_91, i32* nocapture %p_92) nounwind ssp {
+entry:
+  store i32 0, i32* %p_92, align 4
+  br i1 false, label %lbl_260, label %if.else
+
+if.else:                                          ; preds = %entry
+  br label %for.cond
+
+for.cond:                                         ; preds = %lbl_260, %if.else
+  %l_245.0 = phi i16 [ %l_245.1, %lbl_260 ], [ 33, %if.else ]
+  %l_261.0 = phi i32 [ %and, %lbl_260 ], [ 255, %if.else ]
+  %tobool21 = icmp ult i16 %l_245.0, 256
+  br i1 %tobool21, label %if.end, label %lbl_260
+
+lbl_260:                                          ; preds = %for.cond, %entry
+  %l_245.1 = phi i16 [ 1569, %entry ], [ %l_245.0, %for.cond ]
+  %l_261.1 = phi i32 [ 255, %entry ], [ %l_261.0, %for.cond ]
+  %and = and i32 %l_261.1, 1
+  br label %for.cond
+
+if.end:                                           ; preds = %for.cond
+  ret void
+}
+
+define void @PR14233(i1 %cmp, i1 %cmp2, i1 %cmp3, i1 %cmp4) {
+entry:
+  br i1 %cmp, label %cond.true, label %cond.false
+
+cond.true:
+  br label %if.end
+
+cond.false:
+  br label %if.end
+
+if.end:
+  %A = phi i64 [ 0, %cond.true ], [ 1, %cond.false ]
+  br i1 %cmp2, label %bb, label %if.end2
+
+bb:
+  br label %if.end2
+
+if.end2:
+  %B = phi i64 [ ptrtoint (i8* ()* @PR14233.f1 to i64), %bb ], [ %A, %if.end ]
+  %cmp.ptr = icmp eq i64 %B, ptrtoint (i8* ()* @PR14233.f2 to i64)
+  br i1 %cmp.ptr, label %cond.true2, label %if.end3
+
+cond.true2:
+  br i1 %cmp3, label %bb2, label %ur
+
+bb2:
+  br i1 %cmp4, label %if.end4, label %if.end3
+
+if.end4:
+  unreachable
+
+if.end3:
+  %cmp.ptr2 = icmp eq i64 %B, ptrtoint (i8* ()* @PR14233.f2 to i64)
+  br i1 %cmp.ptr2, label %ur, label %if.then601
+
+if.then601:
+  %C = icmp eq i64 %B, 0
+  br i1 %C, label %bb3, label %bb4
+
+bb3:
+  unreachable
+
+bb4:
+  unreachable
+
+ur:
+  unreachable
+}
+
+declare i8* @PR14233.f1()
+
+declare i8* @PR14233.f2()
+
+; Make sure the following compiles in a sane amount of time, as opposed
+; to taking exponential time.
+; (CHECK to make sure the condition doesn't get simplified somehow;
+; if it does, the testcase will need to be revised.)
+; CHECK-LABEL: define void @almost_infinite_loop
+; CHECK: %x39 = or i1 %x38, %x38
+; CHECK: br i1 %x39, label %dest1, label %dest2
+define void @almost_infinite_loop(i1 %x0) {
+entry:
+  br label %if.then57.i
+
+if.then57.i:
+  %x1 = or i1 %x0, %x0
+  %x2 = or i1 %x1, %x1
+  %x3 = or i1 %x2, %x2
+  %x4 = or i1 %x3, %x3
+  %x5 = or i1 %x4, %x4
+  %x6 = or i1 %x5, %x5
+  %x7 = or i1 %x6, %x6
+  %x8 = or i1 %x7, %x7
+  %x9 = or i1 %x8, %x8
+  %x10 = or i1 %x9, %x9
+  %x11 = or i1 %x10, %x10
+  %x12 = or i1 %x11, %x11
+  %x13 = or i1 %x12, %x12
+  %x14 = or i1 %x13, %x13
+  %x15 = or i1 %x14, %x14
+  %x16 = or i1 %x15, %x15
+  %x17 = or i1 %x16, %x16
+  %x18 = or i1 %x17, %x17
+  %x19 = or i1 %x18, %x18
+  %x20 = or i1 %x19, %x19
+  %x21 = or i1 %x20, %x20
+  %x22 = or i1 %x21, %x21
+  %x23 = or i1 %x22, %x22
+  %x24 = or i1 %x23, %x23
+  %x25 = or i1 %x24, %x24
+  %x26 = or i1 %x25, %x25
+  %x27 = or i1 %x26, %x26
+  %x28 = or i1 %x27, %x27
+  %x29 = or i1 %x28, %x28
+  %x30 = or i1 %x29, %x29
+  %x31 = or i1 %x30, %x30
+  %x32 = or i1 %x31, %x31
+  %x33 = or i1 %x32, %x32
+  %x34 = or i1 %x33, %x33
+  %x35 = or i1 %x34, %x34
+  %x36 = or i1 %x35, %x35
+  %x37 = or i1 %x36, %x36
+  %x38 = or i1 %x37, %x37
+  %x39 = or i1 %x38, %x38
+  br i1 %x39, label %dest1, label %dest2
+
+dest1:
+  unreachable
+
+dest2:
+  unreachable
+}

Added: llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,265 @@
+; RUN: opt < %s -jump-threading -disable-output
+
+%struct.ham = type { i8, i8, i16, i32 }
+%struct.zot = type { i32 (...)** }
+%struct.quux.0 = type { %struct.wombat }
+%struct.wombat = type { %struct.zot }
+
+ at global = external global %struct.ham*, align 8
+ at global.1 = external constant i8*
+
+declare i32 @wombat.2()
+
+define void @blam() {
+bb:
+  %tmp = load i32, i32* undef
+  %tmp1 = icmp eq i32 %tmp, 0
+  br i1 %tmp1, label %bb11, label %bb2
+
+bb2:
+  %tmp3 = tail call i32 @wombat.2()
+  switch i32 %tmp3, label %bb4 [
+    i32 0, label %bb5
+    i32 1, label %bb7
+    i32 2, label %bb7
+    i32 3, label %bb11
+  ]
+
+bb4:
+  br label %bb7
+
+bb5:
+  %tmp6 = tail call i32 @wombat.2()
+  br label %bb7
+
+bb7:
+  %tmp8 = phi i32 [ 0, %bb5 ], [ 1, %bb4 ], [ 2, %bb2 ], [ 2, %bb2 ]
+  %tmp9 = icmp eq i32 %tmp8, 0
+  br i1 %tmp9, label %bb11, label %bb10
+
+bb10:
+  ret void
+
+bb11:
+  ret void
+}
+
+define void @spam(%struct.ham* %arg) {
+bb:
+  %tmp = load i8, i8* undef, align 8
+  switch i8 %tmp, label %bb11 [
+    i8 1, label %bb11
+    i8 2, label %bb11
+    i8 3, label %bb1
+    i8 4, label %bb1
+  ]
+
+bb1:
+  br label %bb2
+
+bb2:
+  %tmp3 = phi i32 [ 0, %bb1 ], [ %tmp3, %bb8 ]
+  br label %bb4
+
+bb4:
+  %tmp5 = load i8, i8* undef, align 8
+  switch i8 %tmp5, label %bb11 [
+    i8 0, label %bb11
+    i8 1, label %bb10
+    i8 2, label %bb10
+    i8 3, label %bb6
+    i8 4, label %bb6
+  ]
+
+bb6:
+  br label %bb7
+
+bb7:
+  br i1 undef, label %bb8, label %bb10
+
+bb8:
+  %tmp9 = icmp eq %struct.ham* undef, %arg
+  br i1 %tmp9, label %bb10, label %bb2
+
+bb10:
+  switch i32 %tmp3, label %bb4 [
+    i32 0, label %bb14
+    i32 1, label %bb11
+    i32 2, label %bb12
+  ]
+
+bb11:
+  unreachable
+
+bb12:
+  %tmp13 = load %struct.ham*, %struct.ham** undef
+  br label %bb14
+
+bb14:
+  %tmp15 = phi %struct.ham* [ %tmp13, %bb12 ], [ null, %bb10 ]
+  br label %bb16
+
+bb16:
+  %tmp17 = load i8, i8* undef, align 8
+  switch i8 %tmp17, label %bb11 [
+    i8 0, label %bb11
+    i8 11, label %bb18
+    i8 12, label %bb18
+  ]
+
+bb18:
+  br label %bb19
+
+bb19:
+  br label %bb20
+
+bb20:
+  %tmp21 = load %struct.ham*, %struct.ham** undef
+  switch i8 undef, label %bb22 [
+    i8 0, label %bb4
+    i8 11, label %bb10
+    i8 12, label %bb10
+  ]
+
+bb22:
+  br label %bb23
+
+bb23:
+  %tmp24 = icmp eq %struct.ham* %tmp21, null
+  br i1 %tmp24, label %bb35, label %bb25
+
+bb25:
+  %tmp26 = icmp eq %struct.ham* %tmp15, null
+  br i1 %tmp26, label %bb34, label %bb27
+
+bb27:
+  %tmp28 = load %struct.ham*, %struct.ham** undef
+  %tmp29 = icmp eq %struct.ham* %tmp28, %tmp21
+  br i1 %tmp29, label %bb35, label %bb30
+
+bb30:
+  br label %bb31
+
+bb31:
+  %tmp32 = load i8, i8* undef, align 8
+  %tmp33 = icmp eq i8 %tmp32, 0
+  br i1 %tmp33, label %bb31, label %bb34
+
+bb34:
+  br label %bb35
+
+bb35:
+  %tmp36 = phi i1 [ true, %bb34 ], [ false, %bb23 ], [ true, %bb27 ]
+  br label %bb37
+
+bb37:
+  %tmp38 = icmp eq %struct.ham* %tmp15, null
+  br i1 %tmp38, label %bb39, label %bb41
+
+bb39:
+  %tmp40 = load %struct.ham*, %struct.ham** @global
+  br label %bb41
+
+bb41:
+  %tmp42 = select i1 %tmp36, %struct.ham* undef, %struct.ham* undef
+  ret void
+}
+
+declare i32 @foo(...)
+
+define void @zot() align 2 personality i8* bitcast (i32 (...)* @foo to i8*) {
+bb:
+  invoke void @bar()
+          to label %bb1 unwind label %bb3
+
+bb1:
+  invoke void @bar()
+          to label %bb2 unwind label %bb4
+
+bb2:
+  invoke void @bar()
+          to label %bb6 unwind label %bb17
+
+bb3:
+  %tmp = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb4:
+  %tmp5 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb6:
+  invoke void @bar()
+          to label %bb7 unwind label %bb19
+
+bb7:
+  invoke void @bar()
+          to label %bb10 unwind label %bb8
+
+bb8:
+  %tmp9 = landingpad { i8*, i32 }
+          cleanup
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb10:
+  %tmp11 = load i32 (%struct.zot*)*, i32 (%struct.zot*)** undef, align 8
+  %tmp12 = invoke i32 %tmp11(%struct.zot* nonnull undef)
+          to label %bb13 unwind label %bb21
+
+bb13:
+  invoke void @bar()
+          to label %bb14 unwind label %bb23
+
+bb14:
+  %tmp15 = load i32 (%struct.zot*)*, i32 (%struct.zot*)** undef, align 8
+  %tmp16 = invoke i32 %tmp15(%struct.zot* nonnull undef)
+          to label %bb26 unwind label %bb23
+
+bb17:
+  %tmp18 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb19:
+  %tmp20 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb21:
+  %tmp22 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb23:
+  %tmp24 = phi %struct.quux.0* [ null, %bb26 ], [ null, %bb14 ], [ undef, %bb13 ]
+  %tmp25 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  br label %bb30
+
+bb26:
+  %tmp27 = load i32 (%struct.zot*)*, i32 (%struct.zot*)** undef, align 8
+  %tmp28 = invoke i32 %tmp27(%struct.zot* nonnull undef)
+          to label %bb29 unwind label %bb23
+
+bb29:
+  unreachable
+
+bb30:
+  %tmp31 = icmp eq %struct.quux.0* %tmp24, null
+  br i1 %tmp31, label %bb32, label %bb29
+
+bb32:
+  unreachable
+}
+
+declare void @bar()

Added: llvm/trunk/test/Transforms/JumpThreading/ddt-crash2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/ddt-crash2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/ddt-crash2.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/ddt-crash2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -jump-threading -disable-output
+
+%struct.aaa = type { i8 }
+
+define void @chrome(%struct.aaa* noalias sret %arg) local_unnamed_addr #0 align 2 personality i8* bitcast (i32 (...)* @chrome2 to i8*) {
+bb:
+  %tmp = load i32, i32* undef, align 4
+  %tmp1 = icmp eq i32 %tmp, 0
+  br i1 %tmp1, label %bb2, label %bb13
+
+bb2:
+  %tmp3 = getelementptr inbounds %struct.aaa, %struct.aaa* %arg, i64 0, i32 0
+  %tmp4 = load i8, i8* %tmp3, align 1
+  %tmp5 = icmp eq i8 %tmp4, 0
+  br i1 %tmp5, label %bb6, label %bb7
+
+bb6:
+  store i8 0, i8* %tmp3, align 1
+  br label %bb7
+
+bb7:
+  %tmp8 = load i8, i8* %tmp3, align 1
+  %tmp9 = icmp ne i8 %tmp8, 0
+  %tmp10 = select i1 %tmp9, i1 true, i1 false
+  br i1 %tmp10, label %bb12, label %bb11
+
+bb11:
+  br label %bb12
+
+bb12:
+  br i1 %tmp9, label %bb14, label %bb13
+
+bb13:
+  unreachable
+
+bb14:
+  ret void
+}
+
+declare i32 @chrome2(...)

Added: llvm/trunk/test/Transforms/JumpThreading/ddt-crash3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/ddt-crash3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/ddt-crash3.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/ddt-crash3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt < %s -jump-threading -disable-output -verify-dom-info
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at global = external local_unnamed_addr global i64, align 8
+ at global.1 = external local_unnamed_addr global i64, align 8
+ at global.2 = external local_unnamed_addr global i64, align 8
+
+; Function Attrs: norecurse noreturn nounwind uwtable
+define void @hoge() local_unnamed_addr #0 {
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb26, %bb
+  %tmp = load i64, i64* @global, align 8, !tbaa !1
+  %tmp2 = icmp eq i64 %tmp, 0
+  br i1 %tmp2, label %bb27, label %bb3
+
+bb3:                                              ; preds = %bb1
+  %tmp4 = load i64, i64* @global.1, align 8, !tbaa !1
+  %tmp5 = icmp eq i64 %tmp4, 0
+  br i1 %tmp5, label %bb23, label %bb23
+
+bb23:                                             ; preds = %bb3, %bb3
+  br label %bb26
+
+bb26:                                             ; preds = %bb27, %bb23
+  br label %bb1
+
+bb27:                                             ; preds = %bb1
+  br label %bb26
+}
+
+attributes #0 = { norecurse noreturn nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 7.0.0 "}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"long", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}

Added: llvm/trunk/test/Transforms/JumpThreading/ddt-crash4.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/ddt-crash4.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/ddt-crash4.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/ddt-crash4.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,75 @@
+; RUN: opt < %s -jump-threading -disable-output -verify-dom-info
+ at global = external global i64, align 8
+
+define void @f() {
+bb:
+  br label %bb1
+
+bb1:
+  %tmp = load i64, i64* @global, align 8
+  %tmp2 = icmp eq i64 %tmp, 0
+  br i1 %tmp2, label %bb27, label %bb3
+
+bb3:
+  %tmp4 = load i64, i64* @global, align 8
+  %tmp5 = icmp eq i64 %tmp4, 0
+  br i1 %tmp5, label %bb6, label %bb7
+
+bb6:
+  br label %bb7
+
+bb7:
+  %tmp8 = phi i1 [ true, %bb3 ], [ undef, %bb6 ]
+  %tmp9 = select i1 %tmp8, i64 %tmp4, i64 0
+  br i1 false, label %bb10, label %bb23
+
+bb10:
+  %tmp11 = load i64, i64* @global, align 8
+  %tmp12 = icmp slt i64 %tmp11, 5
+  br i1 %tmp12, label %bb13, label %bb17
+
+bb13:
+  br label %bb14
+
+bb14:
+  br i1 undef, label %bb15, label %bb16
+
+bb15:
+  unreachable
+
+bb16:
+  br label %bb10
+
+bb17:
+  br label %bb18
+
+bb18:
+  br i1 undef, label %bb22, label %bb13
+
+bb19:
+  br i1 undef, label %bb20, label %bb21
+
+bb20:
+  unreachable
+
+bb21:
+  br label %bb18
+
+bb22:
+  br label %bb23
+
+bb23:
+  br i1 undef, label %bb24, label %bb13
+
+bb24:
+  br i1 undef, label %bb26, label %bb25
+
+bb25:
+  br label %bb19
+
+bb26:
+  br label %bb1
+
+bb27:
+  br label %bb24
+}

Added: llvm/trunk/test/Transforms/JumpThreading/degenerate-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/degenerate-phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/degenerate-phi.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/degenerate-phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -jump-threading -disable-output < %s
+; PR9112
+
+; This is actually a test for value tracking. Jump threading produces
+; "%phi = phi i16" when it removes all edges leading to %unreachable.
+; The .ll parser won't let us write that directly since it's invalid code.
+
+define void @func() nounwind {
+entry:
+  br label %bb
+
+bb:
+  br label %bb
+
+unreachable:
+  %phi = phi i16 [ %add, %unreachable ], [ 0, %next ]
+  %add = add i16 0, %phi
+  %cmp = icmp slt i16 %phi, 0
+  br i1 %cmp, label %unreachable, label %next
+
+next:
+  br label %unreachable
+}
+

Added: llvm/trunk/test/Transforms/JumpThreading/fold-not-thread.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/fold-not-thread.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/fold-not-thread.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/fold-not-thread.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,246 @@
+; RUN: opt -jump-threading -S -verify < %s | FileCheck %s
+
+declare i32 @f1()
+declare i32 @f2()
+declare void @f3()
+declare void @f4(i32)
+
+
+; Make sure we update the phi node properly.
+;
+; CHECK-LABEL: define void @test_br_folding_not_threading_update_phi(
+; CHECK: br label %L1
+; Make sure we update the phi node properly here, i.e. we only have 2 predecessors, entry and L0
+; CHECK: %res.0 = phi i32 [ 0, %L0 ], [ 1, %entry ]
+define void @test_br_folding_not_threading_update_phi(i32 %val) nounwind {
+entry:
+  %cmp = icmp eq i32 %val, 32
+  br i1 %cmp, label %L0, label %L1
+L0:
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  switch i32 %val, label %L2 [
+    i32 0, label %L1
+    i32 32, label %L1
+  ]
+
+L1:
+	%res.0 = phi i32 [ 0, %L0 ], [ 0, %L0 ], [1, %entry]
+  call void @f4(i32 %res.0)
+  ret void
+L2:
+  call void @f3()
+  ret void
+}
+
+; Make sure we can fold this branch ... We will not be able to thread it as
+; L0 is too big to duplicate. L2 is the unreachable block here.
+;
+; CHECK-LABEL: @test_br_folding_not_threading(
+; CHECK: L1:
+; CHECK: call i32 @f2()
+; CHECK: call void @f3()
+; CHECK-NEXT: ret void
+; CHECK-NOT: br
+; CHECK: L3:
+define void @test_br_folding_not_threading(i1 %cond) nounwind {
+entry:
+  br i1 %cond, label %L0, label %L3 
+L0:
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  br i1 %cond, label %L1, label %L2 
+
+L1:
+  call void @f3()
+  ret void
+L2:
+  call void @f3()
+  ret void
+L3:
+  call void @f3()
+  ret void
+}
+
+
+; Make sure we can fold this branch ... We will not be able to thread it as
+; L0 is too big to duplicate. L2 is the unreachable block here.
+; With more than 1 predecessors.
+;
+; CHECK-LABEL: @test_br_folding_not_threading_multiple_preds(
+; CHECK: L1:
+; CHECK: call i32 @f2()
+; CHECK: call void @f3()
+; CHECK-NEXT: ret void
+; CHECK-NOT: br
+; CHECK: L3:
+define void @test_br_folding_not_threading_multiple_preds(i1 %condx, i1 %cond) nounwind {
+entry:
+  br i1 %condx, label %X0, label %X1
+
+X0:
+  br i1 %cond, label %L0, label %L3 
+
+X1:
+  br i1 %cond, label %L0, label %L3 
+
+L0:
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  br i1 %cond, label %L1, label %L2 
+
+L1:
+  call void @f3()
+  ret void
+L2:
+  call void @f3()
+  ret void
+L3:
+  call void @f3()
+  ret void
+}
+
+; Make sure we can do the RAUW for %add...
+;
+; CHECK-LABEL: @rauw_if_possible(
+; CHECK: call void @f4(i32 96)
+define void @rauw_if_possible(i32 %value) nounwind {
+entry:
+  %cmp = icmp eq i32 %value, 32
+  br i1 %cmp, label %L0, label %L3 
+L0:
+  call i32 @f2()
+  call i32 @f2()
+  %add = add i32 %value, 64
+  switch i32 %add, label %L3 [
+    i32 32, label %L1
+    i32 96, label %L2
+    ]
+
+L1:
+  call void @f3()
+  ret void
+L2:
+  call void @f4(i32 %add)
+  ret void
+L3:
+  call void @f3()
+  ret void
+}
+
+; Make sure we can NOT do the RAUW for %add...
+;
+; CHECK-LABEL: @rauw_if_possible2(
+; CHECK: call void @f4(i32 %add) 
+define void @rauw_if_possible2(i32 %value) nounwind {
+entry:
+  %cmp = icmp eq i32 %value, 32
+  %add = add i32 %value, 64
+  br i1 %cmp, label %L0, label %L2 
+L0:
+  call i32 @f2()
+  call i32 @f2()
+  switch i32 %add, label %L3 [
+    i32 32, label %L1
+    i32 96, label %L2
+    ]
+
+L1:
+  call void @f3()
+  ret void
+L2:
+  call void @f4(i32 %add)
+  ret void
+L3:
+  call void @f3()
+  ret void
+}
+
+; Make sure we can fold this branch ... We will not be able to thread it as
+; L0 is too big to duplicate.
+; We do not attempt to rewrite the indirectbr target here, but we still take
+; its target after L0 into account and that enables us to fold.
+;
+; L2 is the unreachable block here.
+; 
+; CHECK-LABEL: @test_br_folding_not_threading_indirect_branch(
+; CHECK: L1:
+; CHECK: call i32 @f2()
+; CHECK: call void @f3()
+; CHECK-NEXT: ret void
+; CHECK-NOT: br
+; CHECK: L3:
+define void @test_br_folding_not_threading_indirect_branch(i1 %condx, i1 %cond) nounwind {
+entry:
+  br i1 %condx, label %X0, label %X1
+
+X0:
+  br i1 %cond, label %L0, label %L3
+
+X1:
+  br i1 %cond, label %XX1, label %L3
+
+XX1:
+  indirectbr i8* blockaddress(@test_br_folding_not_threading_indirect_branch, %L0), [label %L0]
+
+L0:
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  call i32 @f2()
+  br i1 %cond, label %L1, label %L2
+
+L1:
+  call void @f3()
+  ret void
+
+L2:
+  call void @f3()
+  ret void
+
+L3:
+  call void @f3()
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/guards.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/guards.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/guards.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/guards.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,383 @@
+; RUN: opt < %s -jump-threading -dce -S | FileCheck %s
+
+declare void @llvm.experimental.guard(i1, ...)
+
+declare i32 @f1()
+declare i32 @f2()
+
+define i32 @branch_implies_guard(i32 %a) {
+; CHECK-LABEL: @branch_implies_guard(
+  %cond = icmp slt i32 %a, 10
+  br i1 %cond, label %T1, label %F1
+
+T1:
+; CHECK:       T1.split
+; CHECK:         %v1 = call i32 @f1()
+; CHECK-NEXT:    %retVal
+; CHECK-NEXT:    br label %Merge
+  %v1 = call i32 @f1()
+  br label %Merge
+
+F1:
+; CHECK:       F1.split
+; CHECK:         %v2 = call i32 @f2()
+; CHECK-NEXT:    %retVal
+; CHECK-NEXT:    %condGuard
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %condGuard
+; CHECK-NEXT:    br label %Merge
+  %v2 = call i32 @f2()
+  br label %Merge
+
+Merge:
+; CHECK:       Merge
+; CHECK-NOT:     call void(i1, ...) @llvm.experimental.guard(
+  %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ]
+  %retVal = add i32 %retPhi, 10
+  %condGuard = icmp slt i32 %a, 20
+  call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
+  ret i32 %retVal
+}
+
+define i32 @not_branch_implies_guard(i32 %a) {
+; CHECK-LABEL: @not_branch_implies_guard(
+  %cond = icmp slt i32 %a, 20
+  br i1 %cond, label %T1, label %F1
+
+T1:
+; CHECK:       T1.split:
+; CHECK-NEXT:    %v1 = call i32 @f1()
+; CHECK-NEXT:    %retVal
+; CHECK-NEXT:    %condGuard
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %condGuard
+; CHECK-NEXT:    br label %Merge
+  %v1 = call i32 @f1()
+  br label %Merge
+
+F1:
+; CHECK:       F1.split:
+; CHECK-NEXT:   %v2 = call i32 @f2()
+; CHECK-NEXT:   %retVal
+; CHECK-NEXT:   br label %Merge
+  %v2 = call i32 @f2()
+  br label %Merge
+
+Merge:
+; CHECK:       Merge
+; CHECK-NOT:     call void(i1, ...) @llvm.experimental.guard(
+  %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ]
+  %retVal = add i32 %retPhi, 10
+  %condGuard = icmp sgt i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
+  ret i32 %retVal
+}
+
+define i32 @branch_overlaps_guard(i32 %a) {
+; CHECK-LABEL: @branch_overlaps_guard(
+  %cond = icmp slt i32 %a, 20
+  br i1 %cond, label %T1, label %F1
+
+T1:
+; CHECK:        T1:
+; CHECK-NEXT:      %v1 = call i32 @f1()
+; CHECK-NEXT:      br label %Merge
+  %v1 = call i32 @f1()
+  br label %Merge
+
+F1:
+; CHECK:        F1:
+; CHECK-NEXT:     %v2 = call i32 @f2()
+; CHECK-NEXT:     br label %Merge
+  %v2 = call i32 @f2()
+  br label %Merge
+
+Merge:
+; CHECK:       Merge
+; CHECK:         %condGuard = icmp slt i32 %a, 10
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
+  %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ]
+  %retVal = add i32 %retPhi, 10
+  %condGuard = icmp slt i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
+  ret i32 %retVal
+}
+
+define i32 @branch_doesnt_overlap_guard(i32 %a) {
+; CHECK-LABEL: @branch_doesnt_overlap_guard(
+  %cond = icmp slt i32 %a, 10
+  br i1 %cond, label %T1, label %F1
+
+T1:
+; CHECK:        T1:
+; CHECK-NEXT:      %v1 = call i32 @f1()
+; CHECK-NEXT:      br label %Merge
+  %v1 = call i32 @f1()
+  br label %Merge
+
+F1:
+; CHECK:        F1:
+; CHECK-NEXT:     %v2 = call i32 @f2()
+; CHECK-NEXT:     br label %Merge
+  %v2 = call i32 @f2()
+  br label %Merge
+
+Merge:
+; CHECK:       Merge
+; CHECK:         %condGuard = icmp sgt i32 %a, 20
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
+  %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ]
+  %retVal = add i32 %retPhi, 10
+  %condGuard = icmp sgt i32 %a, 20
+  call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
+  ret i32 %retVal
+}
+
+define i32 @not_a_diamond1(i32 %a, i1 %cond1) {
+; CHECK-LABEL: @not_a_diamond1(
+  br i1 %cond1, label %Pred, label %Exit
+
+Pred:
+; CHECK:       Pred:
+; CHECK-NEXT:    switch i32 %a, label %Exit
+  switch i32 %a, label %Exit [
+    i32 10, label %Merge
+    i32 20, label %Merge
+  ]
+
+Merge:
+; CHECK:       Merge:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
+; CHECK-NEXT:    br label %Exit
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
+  br label %Exit
+
+Exit:
+; CHECK:       Exit:
+; CHECK-NEXT:    ret i32 %a
+  ret i32 %a
+}
+
+define void @not_a_diamond2(i32 %a, i1 %cond1) {
+; CHECK-LABEL: @not_a_diamond2(
+  br label %Parent
+
+Merge:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond1)[ "deopt"() ]
+  ret void
+
+Pred:
+; CHECK-NEXT:  Pred:
+; CHECK-NEXT:    switch i32 %a, label %Exit
+  switch i32 %a, label %Exit [
+    i32 10, label %Merge
+    i32 20, label %Merge
+  ]
+
+Parent:
+  br label %Pred
+
+Exit:
+; CHECK:       Merge:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
+; CHECK-NEXT:    ret void
+  ret void
+}
+
+declare void @never_called(i1)
+
+; LVI uses guard to identify value of %c2 in branch as true, we cannot replace that
+; guard with guard(true & c1).
+define void @dont_fold_guard(i8* %addr, i32 %i, i32 %length) {
+; CHECK-LABEL: dont_fold_guard
+; CHECK: %wide.chk = and i1 %c1, %c2
+; CHECK-NEXT: experimental.guard(i1 %wide.chk)
+; CHECK-NEXT: call void @never_called(i1 true)
+; CHECK-NEXT: ret void
+  %c1 = icmp ult i32 %i, %length
+  %c2 = icmp eq i32 %i, 0
+  %wide.chk = and i1 %c1, %c2
+  call void(i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+  br i1 %c2, label %BB1, label %BB2
+
+BB1:
+  call void @never_called(i1 %c2)
+  ret void
+
+BB2:
+  ret void
+}
+
+declare void @dummy(i1) nounwind argmemonly
+; same as dont_fold_guard1 but there's a use immediately after guard and before
+; branch. We can fold that use.
+define void @dont_fold_guard2(i8* %addr, i32 %i, i32 %length) {
+; CHECK-LABEL: dont_fold_guard2
+; CHECK: %wide.chk = and i1 %c1, %c2
+; CHECK-NEXT: experimental.guard(i1 %wide.chk)
+; CHECK-NEXT: dummy(i1 true)
+; CHECK-NEXT: call void @never_called(i1 true)
+; CHECK-NEXT: ret void
+  %c1 = icmp ult i32 %i, %length
+  %c2 = icmp eq i32 %i, 0
+  %wide.chk = and i1 %c1, %c2
+  call void(i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+  call void @dummy(i1 %c2)
+  br i1 %c2, label %BB1, label %BB2
+
+BB1:
+  call void @never_called(i1 %c2)
+  ret void
+
+BB2:
+  ret void
+}
+
+; same as dont_fold_guard1 but condition %cmp is not an instruction.
+; We cannot fold the guard under any circumstance.
+; FIXME: We can merge unreachableBB2 into not_zero.
+define void @dont_fold_guard3(i8* %addr, i1 %cmp, i32 %i, i32 %length) {
+; CHECK-LABEL: dont_fold_guard3
+; CHECK: guard(i1 %cmp)
+  call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  br i1 %cmp, label %BB1, label %BB2
+
+BB1:
+  call void @never_called(i1 %cmp)
+  ret void
+
+BB2:
+  ret void
+}
+
+declare void @f(i1)
+; Same as dont_fold_guard1 but use switch instead of branch.
+; triggers source code `ProcessThreadableEdges`.
+define void @dont_fold_guard4(i1 %cmp1, i32 %i) nounwind {
+; CHECK-LABEL: dont_fold_guard4 
+; CHECK-LABEL: L2:
+; CHECK-NEXT: %cmp = icmp eq i32 %i, 0 
+; CHECK-NEXT: guard(i1 %cmp)
+; CHECK-NEXT: dummy(i1 true)
+; CHECK-NEXT: @f(i1 true)
+; CHECK-NEXT: ret void
+entry:
+  br i1 %cmp1, label %L0, label %L3 
+L0:
+  %cmp = icmp eq i32 %i, 0
+  call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  call void @dummy(i1 %cmp)
+  switch i1 %cmp, label %L3 [
+    i1 false, label %L1
+    i1 true, label %L2
+    ]
+
+L1:
+  ret void
+L2:
+  call void @f(i1 %cmp)
+  ret void
+L3:
+  ret void
+}
+
+; Make sure that we don't PRE a non-speculable load across a guard.
+define void @unsafe_pre_across_guard(i8* %p, i1 %load.is.valid) {
+
+; CHECK-LABEL: @unsafe_pre_across_guard(
+; CHECK-NOT:   loaded.pr
+; CHECK:       entry:
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %load.is.valid) [ "deopt"() ]
+; CHECK-NEXT:    %loaded = load i8, i8* %p
+; CHECK-NEXT:    %continue = icmp eq i8 %loaded, 0
+; CHECK-NEXT:    br i1 %continue, label %exit, label %loop
+entry:
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  call void (i1, ...) @llvm.experimental.guard(i1 %load.is.valid) [ "deopt"() ]
+  %loaded = load i8, i8* %p
+  %continue = icmp eq i8 %loaded, 0
+  br i1 %continue, label %exit, label %loop
+
+exit:                                             ; preds = %loop
+  ret void
+}
+
+; Make sure that we can safely PRE a speculable load across a guard.
+define void @safe_pre_across_guard(i8* noalias nocapture readonly dereferenceable(8) %p, i1 %load.is.valid) {
+
+; CHECK-LABEL: @safe_pre_across_guard(
+; CHECK:       entry:
+; CHECK-NEXT:    %loaded.pr = load i8, i8* %p
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    %loaded = phi i8 [ %loaded, %loop ], [ %loaded.pr, %entry ]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %load.is.valid) [ "deopt"() ]
+; CHECK-NEXT:    %continue = icmp eq i8 %loaded, 0
+; CHECK-NEXT:    br i1 %continue, label %exit, label %loop
+
+entry:
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  call void (i1, ...) @llvm.experimental.guard(i1 %load.is.valid) [ "deopt"() ]
+  %loaded = load i8, i8* %p
+  %continue = icmp eq i8 %loaded, 0
+  br i1 %continue, label %exit, label %loop
+
+exit:                                             ; preds = %loop
+  ret void
+}
+
+; Make sure that we don't PRE a non-speculable load across a call which may
+; alias with the load.
+define void @unsafe_pre_across_call(i8* %p) {
+
+; CHECK-LABEL: @unsafe_pre_across_call(
+; CHECK-NOT:   loaded.pr
+; CHECK:       entry:
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    call i32 @f1()
+; CHECK-NEXT:    %loaded = load i8, i8* %p
+; CHECK-NEXT:    %continue = icmp eq i8 %loaded, 0
+; CHECK-NEXT:    br i1 %continue, label %exit, label %loop
+entry:
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  call i32 @f1()
+  %loaded = load i8, i8* %p
+  %continue = icmp eq i8 %loaded, 0
+  br i1 %continue, label %exit, label %loop
+
+exit:                                             ; preds = %loop
+  ret void
+}
+
+; Make sure that we can safely PRE a speculable load across a call.
+define void @safe_pre_across_call(i8* noalias nocapture readonly dereferenceable(8) %p) {
+
+; CHECK-LABEL: @safe_pre_across_call(
+; CHECK:       entry:
+; CHECK-NEXT:    %loaded.pr = load i8, i8* %p
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    %loaded = phi i8 [ %loaded, %loop ], [ %loaded.pr, %entry ]
+; CHECK-NEXT:    call i32 @f1()
+; CHECK-NEXT:    %continue = icmp eq i8 %loaded, 0
+; CHECK-NEXT:    br i1 %continue, label %exit, label %loop
+
+entry:
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  call i32 @f1()
+  %loaded = load i8, i8* %p
+  %continue = icmp eq i8 %loaded, 0
+  br i1 %continue, label %exit, label %loop
+
+exit:                                             ; preds = %loop
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/header-succ.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/header-succ.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/header-succ.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/header-succ.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,99 @@
+; RUN: opt -S -jump-threading < %s | FileCheck %s
+
+; Check that the heuristic for avoiding accidental introduction of irreducible
+; loops doesn't also prevent us from threading simple constructs where this
+; isn't a problem.
+
+declare void @opaque_body()
+
+define void @jump_threading_loopheader() {
+; CHECK-LABEL: @jump_threading_loopheader
+top:
+    br label %entry
+
+entry:
+    %ind = phi i32 [0, %top], [%nextind, %latch]
+    %nextind = add i32 %ind, 1
+    %cmp = icmp ule i32 %ind, 10
+; CHECK: br i1 %cmp, label %latch, label %exit
+    br i1 %cmp, label %body, label %latch
+
+body:
+    call void @opaque_body()
+; CHECK: br label %entry
+    br label %latch
+
+latch:
+    %cond = phi i2 [1, %entry], [2, %body]
+    switch i2 %cond, label %unreach [
+        i2 2, label %entry
+        i2 1, label %exit
+    ]
+
+unreach:
+    unreachable
+
+exit:
+    ret void
+}
+
+; We also need to check the opposite order of the branches, in the switch
+; instruction because jump-threading relies on that to decide which edge to
+; try to thread first.
+define void @jump_threading_loopheader2() {
+; CHECK-LABEL: @jump_threading_loopheader2
+top:
+    br label %entry
+
+entry:
+    %ind = phi i32 [0, %top], [%nextind, %latch]
+    %nextind = add i32 %ind, 1
+    %cmp = icmp ule i32 %ind, 10
+; CHECK: br i1 %cmp, label %exit, label %latch
+    br i1 %cmp, label %body, label %latch
+
+body:
+    call void @opaque_body()
+; CHECK: br label %entry
+    br label %latch
+
+latch:
+    %cond = phi i2 [1, %entry], [2, %body]
+    switch i2 %cond, label %unreach [
+        i2 1, label %entry
+        i2 2, label %exit
+    ]
+
+unreach:
+    unreachable
+
+exit:
+    ret void
+}
+
+; Check if we can handle undef branch condition.
+define void @jump_threading_loopheader3() {
+; CHECK-LABEL: @jump_threading_loopheader3
+top:
+    br label %entry
+
+entry:
+    %ind = phi i32 [0, %top], [%nextind, %latch]
+    %nextind = add i32 %ind, 1
+    %cmp = icmp ule i32 %ind, 10
+; CHECK: br i1 %cmp, label %latch, label %exit
+    br i1 %cmp, label %body, label %latch
+
+body:
+    call void @opaque_body()
+; CHECK: br label %entry
+    br label %latch
+
+latch:
+   %phi = phi i32 [undef, %entry], [0, %body]
+   %cmp1 = icmp eq i32 %phi, 0
+   br i1 %cmp1, label %entry, label %exit
+
+exit:
+    ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/implied-cond.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/implied-cond.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/implied-cond.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/implied-cond.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,177 @@
+; RUN: opt -jump-threading -S < %s | FileCheck %s
+
+declare void @side_effect(i32)
+
+define void @test0(i32 %i, i32 %len) {
+; CHECK-LABEL: @test0(
+ entry:
+  call void @side_effect(i32 0)
+  %i.inc = add nuw i32 %i, 1
+  %c0 = icmp ult i32 %i.inc, %len
+  br i1 %c0, label %left, label %right
+
+ left:
+; CHECK: entry:
+; CHECK: br i1 %c0, label %left0, label %right
+
+; CHECK: left0:
+; CHECK: call void @side_effect
+; CHECK-NOT: br i1 %c1
+; CHECK: call void @side_effect
+  call void @side_effect(i32 0)
+  %c1 = icmp ult i32 %i, %len
+  br i1 %c1, label %left0, label %right
+
+ left0:
+  call void @side_effect(i32 0)
+  ret void
+
+ right:
+  %t = phi i32 [ 1, %left ], [ 2, %entry ]
+  call void @side_effect(i32 %t)
+  ret void
+}
+
+define void @test1(i32 %i, i32 %len) {
+; CHECK-LABEL: @test1(
+ entry:
+  call void @side_effect(i32 0)
+  %i.inc = add nsw i32 %i, 1
+  %c0 = icmp slt i32 %i.inc, %len
+  br i1 %c0, label %left, label %right
+
+ left:
+; CHECK: entry:
+; CHECK: br i1 %c0, label %left0, label %right
+
+; CHECK: left0:
+; CHECK: call void @side_effect
+; CHECK-NOT: br i1 %c1
+; CHECK: call void @side_effect
+  call void @side_effect(i32 0)
+  %c1 = icmp slt i32 %i, %len
+  br i1 %c1, label %left0, label %right
+
+ left0:
+  call void @side_effect(i32 0)
+  ret void
+
+ right:
+  %t = phi i32 [ 1, %left ], [ 2, %entry ]
+  call void @side_effect(i32 %t)
+  ret void
+}
+
+define void @test2(i32 %i, i32 %len, i1* %c.ptr) {
+; CHECK-LABEL: @test2(
+
+; CHECK: entry:
+; CHECK: br i1 %c0, label %cont, label %right
+; CHECK: cont:
+; CHECK: br i1 %c, label %left0, label %right
+; CHECK: left0:
+; CHECK: call void @side_effect(i32 0)
+; CHECK: call void @side_effect(i32 0)
+ entry:
+  call void @side_effect(i32 0)
+  %i.inc = add nsw i32 %i, 1
+  %c0 = icmp slt i32 %i.inc, %len
+  br i1 %c0, label %cont, label %right
+
+ cont:
+  %c = load i1, i1* %c.ptr
+  br i1 %c, label %left, label %right
+
+ left:
+  call void @side_effect(i32 0)
+  %c1 = icmp slt i32 %i, %len
+  br i1 %c1, label %left0, label %right
+
+ left0:
+  call void @side_effect(i32 0)
+  ret void
+
+ right:
+  %t = phi i32 [ 1, %left ], [ 2, %entry ], [ 3, %cont ]
+  call void @side_effect(i32 %t)
+  ret void
+}
+
+; A s<= B implies A s> B is false.
+; CHECK-LABEL: @test3(
+; CHECK: entry:
+; CHECK: br i1 %cmp, label %if.end, label %if.end3
+; CHECK-NOT: br i1 %cmp1, label %if.then2, label %if.end
+; CHECK-NOT: call void @side_effect(i32 0)
+; CHECK: br label %if.end3
+; CHECK: ret void
+
+define void @test3(i32 %a, i32 %b) {
+entry:
+  %cmp = icmp sle i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end3
+
+if.then:
+  %cmp1 = icmp sgt i32 %a, %b
+  br i1 %cmp1, label %if.then2, label %if.end
+
+if.then2:
+  call void @side_effect(i32 0)
+  br label %if.end
+
+if.end:
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+declare void @is(i1)
+
+; If A >=s B is false then A <=s B is implied true.
+; CHECK-LABEL: @test_sge_sle
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_sge_sle(i32 %a, i32 %b) {
+  %cmp1 = icmp sge i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp sle i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A <=s B is false then A <=s B is implied false.
+; CHECK-LABEL: @test_sle_sle
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_sle_sle(i32 %a, i32 %b) {
+  %cmp1 = icmp sle i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp sle i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/indirectbr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/indirectbr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/indirectbr.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/indirectbr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,94 @@
+; RUN: opt -S < %s -jump-threading | FileCheck %s
+
+; Keep block addresses alive.
+ at addresses = constant [4 x i8*] [
+  i8* blockaddress(@test1, %L1), i8* blockaddress(@test1, %L2),
+  i8* blockaddress(@test2, %L1), i8* blockaddress(@test2, %L2)
+]
+
+declare void @bar()
+declare void @baz()
+
+
+
+; Check basic jump threading for indirectbr instructions.
+
+; CHECK: void @test1
+; CHECK: br i1 %tobool, label %L1, label %indirectgoto
+; CHECK-NOT: if.else:
+; CHECK: L1:
+; CHECK: indirectbr i8* %address, [label %L1, label %L2]
+define void @test1(i32 %i, i8* %address) nounwind {
+entry:
+  %rem = srem i32 %i, 2
+  %tobool = icmp ne i32 %rem, 0
+  br i1 %tobool, label %indirectgoto, label %if.else
+
+if.else:                                          ; preds = %entry
+  br label %indirectgoto
+
+L1:                                               ; preds = %indirectgoto
+  call void @bar()
+  ret void
+
+L2:                                               ; preds = %indirectgoto
+  call void @baz()
+  ret void
+
+indirectgoto:                                     ; preds = %if.else, %entry
+  %indirect.goto.dest = phi i8* [ %address, %if.else ], [ blockaddress(@test1, %L1), %entry ]
+  indirectbr i8* %indirect.goto.dest, [label %L1, label %L2]
+}
+
+
+; Check constant folding of indirectbr
+
+; CHECK: void @test2
+; CHECK: entry:
+; CHECK-NEXT: br label %L1
+; CHECK: L1:
+; CHECK-NEXT: call void @bar
+; CHECK-NEXT: ret void
+define void @test2() nounwind {
+entry:
+  indirectbr i8* blockaddress(@test2, %L1), [label %L1, label %L2]
+
+L1:                                               ; preds = %indirectgoto
+  call void @bar()
+  ret void
+
+L2:                                               ; preds = %indirectgoto
+  call void @baz()
+  ret void
+}
+
+
+; PR4151
+; Don't merge address-taken blocks.
+ at .str = private unnamed_addr constant [4 x i8] c"%p\0A\00"
+
+; CHECK-LABEL: @test3(
+; CHECK: __here:
+; CHECK: blockaddress(@test3, %__here)
+; CHECK: __here1:
+; CHECK: blockaddress(@test3, %__here1)
+; CHECK: __here3:
+; CHECK: blockaddress(@test3, %__here3)
+define void @test3() nounwind ssp noredzone {
+entry:
+  br label %__here
+
+__here:                                           ; preds = %entry
+  %call = call i32 (...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i64 ptrtoint (i8* blockaddress(@test3, %__here) to i64)) nounwind noredzone
+  br label %__here1
+
+__here1:                                          ; preds = %__here
+  %call2 = call i32 (...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i64 ptrtoint (i8* blockaddress(@test3, %__here1) to i64)) nounwind noredzone
+  br label %__here3
+
+__here3:                                          ; preds = %__here1
+  %call4 = call i32 (...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i64 ptrtoint (i8* blockaddress(@test3, %__here3) to i64)) nounwind noredzone
+  ret void
+}
+
+declare i32 @printf(...) noredzone

Added: llvm/trunk/test/Transforms/JumpThreading/induction.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/induction.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/induction.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/induction.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt -S -jump-threading < %s | FileCheck %s
+
+define i8 @test(i32 %a, i32 %length) {
+; CHECK-LABEL: @test
+entry:
+; CHECK: br label %backedge
+  br label %loop
+
+loop:
+; CHECK-LABEL: backedge:
+; CHECK: phi i32
+; CHECK: br i1 %cont, label %backedge, label %exit
+  %iv = phi i32 [0, %entry], [%iv.next, %backedge]
+  ;; We can use an inductive argument to prove %iv is always positive
+  %cnd = icmp sge i32 %iv, 0
+  br i1 %cnd, label %backedge, label %exit
+
+backedge:
+  %iv.next = add nsw i32 %iv, 1
+  %cont = icmp slt i32 %iv.next, 400
+  br i1 %cont, label %loop, label %exit
+exit:
+  ret i8 0
+}
+

Added: llvm/trunk/test/Transforms/JumpThreading/landing-pad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/landing-pad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/landing-pad.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/landing-pad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,203 @@
+; RUN: opt < %s -disable-output -jump-threading
+
+%class.E = type { i32 (...)**, %class.C }
+%class.C = type { %class.A }
+%class.A = type { i32 }
+%class.D = type { %class.F }
+%class.F = type { %class.E }
+%class.B = type { %class.D* }
+
+ at _ZTV1D = unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1D to i8*), i8* bitcast (void (%class.D*)* @_ZN1D7doApplyEv to i8*)]
+ at _ZTI1D = external unnamed_addr constant { i8*, i8*, i8* }
+
+define void @_ZN15EditCommandImpl5applyEv(%class.E* %this) uwtable align 2 {
+entry:
+  %0 = bitcast %class.E* %this to void (%class.E*)***
+  %vtable = load void (%class.E*)**, void (%class.E*)*** %0, align 8
+  %1 = load void (%class.E*)*, void (%class.E*)** %vtable, align 8
+  call void %1(%class.E* %this)
+  ret void
+}
+
+define void @_ZN1DC1Ev(%class.D* nocapture %this) unnamed_addr uwtable align 2 {
+entry:
+  call void @_ZN24CompositeEditCommandImplC2Ev()
+  %0 = getelementptr inbounds %class.D, %class.D* %this, i64 0, i32 0, i32 0, i32 0
+  store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1D, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 8
+  ret void
+}
+
+define void @_ZN1DC2Ev(%class.D* nocapture %this) unnamed_addr uwtable align 2 {
+entry:
+  call void @_ZN24CompositeEditCommandImplC2Ev()
+  %0 = getelementptr inbounds %class.D, %class.D* %this, i64 0, i32 0, i32 0, i32 0
+  store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1D, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 8
+  ret void
+}
+
+declare void @_ZN24CompositeEditCommandImplC2Ev() #1
+
+define void @_ZN1D7doApplyEv(%class.D* nocapture %this) unnamed_addr nounwind readnone uwtable align 2 {
+entry:
+  ret void
+}
+
+define void @_Z3fn1v() uwtable personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %call = call noalias i8* @_Znwm() #8
+  invoke void @_ZN24CompositeEditCommandImplC2Ev()
+          to label %_ZN1DC1Ev.exit unwind label %lpad
+
+_ZN1DC1Ev.exit:                                   ; preds = %entry
+  %0 = bitcast i8* %call to i32 (...)***
+  store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1D, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 8
+  %_ref.i.i.i = getelementptr inbounds i8, i8* %call, i64 8
+  %1 = bitcast i8* %_ref.i.i.i to i32*
+  %2 = load i32, i32* %1, align 4
+  %inc.i.i.i = add nsw i32 %2, 1
+  store i32 %inc.i.i.i, i32* %1, align 4
+  %3 = bitcast i8* %call to %class.D*
+  invoke void @_ZN1D7doApplyEv(%class.D* %3)
+          to label %_ZN15EditCommandImpl5applyEv.exit unwind label %lpad1
+
+_ZN15EditCommandImpl5applyEv.exit:                ; preds = %_ZN1DC1Ev.exit
+  invoke void @_ZN1D16deleteKeyPressedEv()
+          to label %invoke.cont7 unwind label %lpad1
+
+invoke.cont7:                                     ; preds = %_ZN15EditCommandImpl5applyEv.exit
+  ret void
+
+lpad:                                             ; preds = %entry
+  %4 = landingpad { i8*, i32 }
+          cleanup
+  call void @_ZdlPv() #9
+  unreachable
+
+lpad1:                                            ; preds = %_ZN1DC1Ev.exit, %_ZN15EditCommandImpl5applyEv.exit
+  %5 = landingpad { i8*, i32 }
+          cleanup
+  %6 = load i32, i32* %1, align 4
+  %tobool.i.i.i = icmp eq i32 %6, 0
+  br i1 %tobool.i.i.i, label %_ZN1BI1DED1Ev.exit, label %if.then.i.i.i
+
+if.then.i.i.i:                                    ; preds = %lpad1
+  br i1 undef, label %_ZN1BI1DED1Ev.exit, label %delete.notnull.i.i.i
+
+delete.notnull.i.i.i:                             ; preds = %if.then.i.i.i
+  call void @_ZdlPv() #9
+  unreachable
+
+_ZN1BI1DED1Ev.exit:                               ; preds = %lpad1, %if.then.i.i.i
+  resume { i8*, i32 } undef
+
+terminate.lpad:                                   ; No predecessors!
+  %7 = landingpad { i8*, i32 }
+          catch i8* null
+  unreachable
+}
+
+define void @_ZN1BI1DEC1EPS0_(%class.B* nocapture %this, %class.D* %p1) unnamed_addr uwtable align 2 {
+entry:
+  %m_ptr.i = getelementptr inbounds %class.B, %class.B* %this, i64 0, i32 0
+  store %class.D* %p1, %class.D** %m_ptr.i, align 8
+  %_ref.i.i = getelementptr inbounds %class.D, %class.D* %p1, i64 0, i32 0, i32 0, i32 1, i32 0, i32 0
+  %0 = load i32, i32* %_ref.i.i, align 4
+  %inc.i.i = add nsw i32 %0, 1
+  store i32 %inc.i.i, i32* %_ref.i.i, align 4
+  ret void
+}
+
+declare noalias i8* @_Znwm()
+
+declare i32 @__gxx_personality_v0(...)
+
+declare void @_ZdlPv()
+
+define %class.D* @_ZN1BI1DEptEv(%class.B* nocapture readonly %this) nounwind readonly uwtable align 2 {
+entry:
+  %m_ptr = getelementptr inbounds %class.B, %class.B* %this, i64 0, i32 0
+  %0 = load %class.D*, %class.D** %m_ptr, align 8
+  ret %class.D* %0
+}
+
+declare void @_ZN1D16deleteKeyPressedEv()
+
+define void @_ZN1BI1DED1Ev(%class.B* nocapture readonly %this) unnamed_addr uwtable align 2 {
+entry:
+  %m_ptr.i = getelementptr inbounds %class.B, %class.B* %this, i64 0, i32 0
+  %0 = load %class.D*, %class.D** %m_ptr.i, align 8
+  %_ref.i.i = getelementptr inbounds %class.D, %class.D* %0, i64 0, i32 0, i32 0, i32 1, i32 0, i32 0
+  %1 = load i32, i32* %_ref.i.i, align 4
+  %tobool.i.i = icmp eq i32 %1, 0
+  br i1 %tobool.i.i, label %_ZN1BI1DED2Ev.exit, label %if.then.i.i
+
+if.then.i.i:                                      ; preds = %entry
+  br i1 undef, label %_ZN1BI1DED2Ev.exit, label %delete.notnull.i.i
+
+delete.notnull.i.i:                               ; preds = %if.then.i.i
+  call void @_ZdlPv() #9
+  unreachable
+
+_ZN1BI1DED2Ev.exit:                               ; preds = %entry, %if.then.i.i
+  ret void
+}
+
+declare hidden void @__clang_call_terminate()
+
+define void @_ZN1BI1DED2Ev(%class.B* nocapture readonly %this) unnamed_addr uwtable align 2 {
+entry:
+  %m_ptr = getelementptr inbounds %class.B, %class.B* %this, i64 0, i32 0
+  %0 = load %class.D*, %class.D** %m_ptr, align 8
+  %_ref.i = getelementptr inbounds %class.D, %class.D* %0, i64 0, i32 0, i32 0, i32 1, i32 0, i32 0
+  %1 = load i32, i32* %_ref.i, align 4
+  %tobool.i = icmp eq i32 %1, 0
+  br i1 %tobool.i, label %_ZN1AI1CE5derefEv.exit, label %if.then.i
+
+if.then.i:                                        ; preds = %entry
+  br i1 undef, label %_ZN1AI1CE5derefEv.exit, label %delete.notnull.i
+
+delete.notnull.i:                                 ; preds = %if.then.i
+  call void @_ZdlPv() #9
+  unreachable
+
+_ZN1AI1CE5derefEv.exit:                           ; preds = %entry, %if.then.i
+  ret void
+}
+
+define void @_ZN1AI1CE5derefEv(%class.A* nocapture readonly %this) nounwind uwtable align 2 {
+entry:
+  %_ref = getelementptr inbounds %class.A, %class.A* %this, i64 0, i32 0
+  %0 = load i32, i32* %_ref, align 4
+  %tobool = icmp eq i32 %0, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  br i1 undef, label %if.end, label %delete.notnull
+
+delete.notnull:                                   ; preds = %if.then
+  call void @_ZdlPv() #9
+  unreachable
+
+if.end:                                           ; preds = %entry, %if.then
+  ret void
+}
+
+define void @_ZN1BI1DEC2EPS0_(%class.B* nocapture %this, %class.D* %p1) unnamed_addr uwtable align 2 {
+entry:
+  %m_ptr = getelementptr inbounds %class.B, %class.B* %this, i64 0, i32 0
+  store %class.D* %p1, %class.D** %m_ptr, align 8
+  %_ref.i = getelementptr inbounds %class.D, %class.D* %p1, i64 0, i32 0, i32 0, i32 1, i32 0, i32 0
+  %0 = load i32, i32* %_ref.i, align 4
+  %inc.i = add nsw i32 %0, 1
+  store i32 %inc.i, i32* %_ref.i, align 4
+  ret void
+}
+
+define void @_ZN1AI1CE3refEv(%class.A* nocapture %this) nounwind uwtable align 2 {
+entry:
+  %_ref = getelementptr inbounds %class.A, %class.A* %this, i64 0, i32 0
+  %0 = load i32, i32* %_ref, align 4
+  %inc = add nsw i32 %0, 1
+  store i32 %inc, i32* %_ref, align 4
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/lvi-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/lvi-load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/lvi-load.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/lvi-load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt -S -jump-threading -dce < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin10.4"
+
+%"struct.llvm::PATypeHolder" = type { %"struct.llvm::Type"* }
+%"struct.llvm::PointerIntPair<llvm::Use**,2u,llvm::Use::PrevPtrTag,llvm::PointerLikeTypeTraits<llvm::Use**> >" = type { i64 }
+%"struct.llvm::Type" = type opaque
+%"struct.llvm::Use" = type { %"struct.llvm::Value"*, %"struct.llvm::Use"*, %"struct.llvm::PointerIntPair<llvm::Use**,2u,llvm::Use::PrevPtrTag,llvm::PointerLikeTypeTraits<llvm::Use**> >" }
+%"struct.llvm::Value" = type { i32 (...)**, i8, i8, i16, %"struct.llvm::PATypeHolder", %"struct.llvm::Use"*, %"struct.llvm::ValueName"* }
+%"struct.llvm::ValueName" = type opaque
+
+ at _ZZN4llvm4castINS_11InstructionEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_E8__func__ = internal constant [5 x i8] c"cast\00", align 8 ; <[5 x i8]*> [#uses=1]
+ at .str = private constant [31 x i8] c"include/llvm/Support/Casting.h\00", align 8 ; <[31 x i8]*> [#uses=1]
+ at .str1 = private constant [59 x i8] c"isa<X>(Val) && \22cast<Ty>() argument of incompatible type!\22\00", align 8 ; <[59 x i8]*> [#uses=1]
+
+; CHECK: Z3fooPN4llvm5ValueE
+define zeroext i8 @_Z3fooPN4llvm5ValueE(%"struct.llvm::Value"* %V) ssp {
+entry:
+  %0 = getelementptr inbounds %"struct.llvm::Value", %"struct.llvm::Value"* %V, i64 0, i32 1 ; <i8*> [#uses=1]
+  %1 = load i8, i8* %0, align 8                       ; <i8> [#uses=2]
+  %2 = icmp ugt i8 %1, 20                         ; <i1> [#uses=1]
+  br i1 %2, label %bb.i, label %bb2
+
+bb.i:                                             ; preds = %entry
+  %toBoolnot.i.i = icmp ult i8 %1, 21             ; <i1> [#uses=1]
+  br i1 %toBoolnot.i.i, label %bb6.i.i, label %_ZN4llvm8dyn_castINS_11InstructionEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_.exit
+
+; CHECK-NOT: assert
+bb6.i.i:                                          ; preds = %bb.i
+  tail call void @__assert_rtn(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @_ZZN4llvm4castINS_11InstructionEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_E8__func__, i64 0, i64 0), i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str, i64 0, i64 0), i32 202, i8* getelementptr inbounds ([59 x i8], [59 x i8]* @.str1, i64 0, i64 0)) noreturn
+  unreachable
+
+_ZN4llvm8dyn_castINS_11InstructionEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_.exit: ; preds = %bb.i
+; CHECK-NOT: null
+  %3 = icmp eq %"struct.llvm::Value"* %V, null    ; <i1> [#uses=1]
+  br i1 %3, label %bb2, label %bb
+
+bb:                                               ; preds = %_ZN4llvm8dyn_castINS_11InstructionEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_.exit
+  tail call void @_ZNK4llvm5Value4dumpEv(%"struct.llvm::Value"* %V)
+; CHECK: ret
+  ret i8 1
+
+bb2:                                              ; preds = %entry, %_ZN4llvm8dyn_castINS_11InstructionEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_.exit
+  ret i8 0
+}
+
+declare void @__assert_rtn(i8*, i8*, i32, i8*) noreturn
+
+declare void @_ZNK4llvm5Value4dumpEv(%"struct.llvm::Value"*)

Added: llvm/trunk/test/Transforms/JumpThreading/lvi-tristate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/lvi-tristate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/lvi-tristate.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/lvi-tristate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -jump-threading -simplifycfg -S < %s | FileCheck %s
+; CHECK-NOT: bb6:
+; CHECK-NOT: bb7:
+; CHECK-NOT: bb8:
+; CHECK-NOT: bb11:
+; CHECK-NOT: bb12:
+; CHECK: bb:
+; CHECK: bb2:
+; CHECK: bb4:
+; CHECK: bb10:
+; CHECK: bb13:
+declare void @ham()
+
+define void @hoge() {
+bb:
+  %tmp = and i32 undef, 1073741823
+  %tmp1 = icmp eq i32 %tmp, 2
+  br i1 %tmp1, label %bb12, label %bb2
+
+bb2:
+  %tmp3 = icmp eq i32 %tmp, 3
+  br i1 %tmp3, label %bb13, label %bb4
+
+bb4:
+  %tmp5 = icmp eq i32 %tmp, 5
+  br i1 %tmp5, label %bb6, label %bb7
+
+bb6:
+  tail call void @ham()
+  br label %bb7
+
+bb7:
+  br i1 %tmp3, label %bb13, label %bb8
+
+bb8:
+  %tmp9 = icmp eq i32 %tmp, 4
+  br i1 %tmp9, label %bb13, label %bb10
+
+bb10:
+  br i1 %tmp9, label %bb11, label %bb13
+
+bb11:
+  br label %bb13
+
+bb12:
+  br label %bb2
+
+bb13:
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/no-irreducible-loops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/no-irreducible-loops.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/no-irreducible-loops.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/no-irreducible-loops.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt < %s -jump-threading -loop-rotate -instcombine -indvars -loop-unroll -simplifycfg -S -verify-dom-info -verify-loop-info > %t
+; RUN: grep "store volatile" %t | count 3
+; RUN: not grep "br label" %t
+
+; Jump threading should not prevent this loop from being unrolled.
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin9.6"
+ at v1 = external global i32		; <i32*> [#uses=2]
+
+define i32 @unroll() nounwind {
+entry:
+	br label %bb4
+
+bb:		; preds = %bb4
+	%0 = icmp eq i32 %i.0, 0		; <i1> [#uses=1]
+	br i1 %0, label %bb1, label %bb2
+
+bb1:		; preds = %bb
+	store volatile i32 1000, i32* @v1, align 4
+	br label %bb3
+
+bb2:		; preds = %bb
+	store volatile i32 1001, i32* @v1, align 4
+	br label %bb3
+
+bb3:		; preds = %bb2, %bb1
+	%1 = add i32 %i.0, 1		; <i32> [#uses=1]
+	br label %bb4
+
+bb4:		; preds = %bb3, %entry
+	%i.0 = phi i32 [ 0, %entry ], [ %1, %bb3 ]		; <i32> [#uses=3]
+	%2 = icmp sgt i32 %i.0, 2		; <i1> [#uses=1]
+	br i1 %2, label %bb5, label %bb
+
+bb5:		; preds = %bb4
+	ret i32 0
+}

Added: llvm/trunk/test/Transforms/JumpThreading/or-undef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/or-undef.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/or-undef.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/or-undef.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,69 @@
+; RUN: opt -jump-threading -S < %s | FileCheck %s
+; rdar://7620633
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin11.0"
+
+define void @test1(i8* %args, i32 %from_tty) nounwind optsize ssp {
+entry:
+  %tmp = call i8* @f3(void (i8*)* null, i8* null) nounwind ; <i8*> [#uses=1]
+  %tmp1 = icmp eq i8* %args, null                 ; <i1> [#uses=1]
+  br i1 %tmp1, label %bb2, label %bb
+
+; CHECK: entry:
+; CHECK-NEXT: %tmp = call i8* @f3
+; CHECK-NEXT: %tmp1 = icmp eq i8* %args, null
+; CHECK-NEXT: br i1 %tmp1, label %bb7, label %bb
+
+bb:                                               ; preds = %entry
+  %tmp2 = call noalias i8** @buildargv(i8* %args) nounwind ; <i8**> [#uses=4]
+  %tmp3 = icmp eq i8** %tmp2, null                ; <i1> [#uses=1]
+  br i1 %tmp3, label %bb2, label %bb1
+
+bb1:                                              ; preds = %bb
+  call void @f2(i8** %tmp2) nounwind
+  br label %bb2
+
+bb2:                                              ; preds = %bb1, %bb, %entry
+  %argv.0 = phi i8** [ %tmp2, %bb1 ], [ %tmp2, %bb ], [ undef, %entry ] ; <i8**> [#uses=4]
+  %tmp5 = icmp eq i8* %args, null                 ; <i1> [#uses=1]
+  %tmp6 = icmp eq i8** %argv.0, null              ; <i1> [#uses=1]
+  %tmp7 = or i1 %tmp5, %tmp6                      ; <i1> [#uses=1]
+  br i1 %tmp7, label %bb7, label %bb5
+
+bb5:                                              ; preds = %bb2
+  %tmp8 = load i8*, i8** %argv.0, align 8              ; <i8*> [#uses=1]
+  %tmp9 = icmp eq i8* %tmp8, null                 ; <i1> [#uses=1]
+  br i1 %tmp9, label %bb7, label %bb6
+
+bb6:                                              ; preds = %bb5
+  %tmp10 = load i8*, i8** %argv.0, align 8             ; <i8*> [#uses=1]
+  %tmp11 = load i8, i8* %tmp10, align 1               ; <i8> [#uses=1]
+  %tmp12 = icmp eq i8 %tmp11, 0                   ; <i1> [#uses=1]
+  br i1 %tmp12, label %bb7, label %bb8
+
+bb7:                                              ; preds = %bb6, %bb5, %bb2
+  call void @f1() nounwind optsize ssp
+  br label %bb9
+
+bb8:                                              ; preds = %bb6
+  %tmp13 = load i8*, i8** %argv.0, align 8             ; <i8*> [#uses=1]
+  %tmp14 = call i64 @f5(i8* %tmp13) nounwind      ; <i64> [#uses=0]
+  br label %bb9
+
+bb9:                                              ; preds = %bb8, %bb7
+  call void @f4(i8* %tmp) nounwind
+  ret void
+}
+
+declare noalias i8** @buildargv(i8*)
+
+declare void @f2(i8**)
+
+declare void @f4(i8*)
+
+declare i8* @f3(void (i8*)*, i8*)
+
+declare void @f1()
+
+declare i64 @f5(i8*)

Added: llvm/trunk/test/Transforms/JumpThreading/phi-eq.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/phi-eq.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/phi-eq.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/phi-eq.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,209 @@
+; RUN: opt < %s -jump-threading -S | FileCheck %s
+; Test whether two consecutive switches with identical structures assign the
+; proper value to the proper variable.  This is really testing 
+; Instruction::isIdenticalToWhenDefined, as previously that function was 
+; returning true if the value part of the operands of two phis were identical, 
+; even if the incoming blocks were not.
+; NB: this function should be pruned down more.
+
+%struct._GList = type { i8*, %struct._GList*, %struct._GList* }
+%struct.filter_def = type { i8*, i8* }
+
+ at capture_filters = external hidden global %struct._GList*, align 8
+ at display_filters = external hidden global %struct._GList*, align 8
+ at .str2 = external hidden unnamed_addr constant [10 x i8], align 1
+ at __PRETTY_FUNCTION__.copy_filter_list = external hidden unnamed_addr constant [62 x i8], align 1
+ at .str12 = external hidden unnamed_addr constant [22 x i8], align 1
+ at .str13 = external hidden unnamed_addr constant [31 x i8], align 1
+ at capture_edited_filters = external hidden global %struct._GList*, align 8
+ at display_edited_filters = external hidden global %struct._GList*, align 8
+ at __PRETTY_FUNCTION__.get_filter_list = external hidden unnamed_addr constant [44 x i8], align 1
+
+declare void @g_assertion_message(i8*, i8*, i32, i8*, i8*) noreturn
+
+declare void @g_free(i8*)
+
+declare %struct._GList* @g_list_first(%struct._GList*)
+
+declare noalias i8* @g_malloc(i64)
+
+define void @copy_filter_list(i32 %dest_type, i32 %src_type) nounwind uwtable ssp {
+entry:
+  br label %do.body
+
+do.body:                                          ; preds = %entry
+  %cmp = icmp ne i32 %dest_type, %src_type
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %do.body
+  br label %if.end
+
+if.else:                                          ; preds = %do.body
+  call void @g_assertion_message_expr(i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str2, i32 0, i32 0), i32 581, i8* getelementptr inbounds ([62 x i8], [62 x i8]* @__PRETTY_FUNCTION__.copy_filter_list, i32 0, i32 0), i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str12, i32 0, i32 0)) noreturn
+  unreachable
+
+if.end:                                           ; preds = %if.then
+  br label %do.end
+
+do.end:                                           ; preds = %if.end
+  switch i32 %dest_type, label %sw.default.i [
+    i32 0, label %sw.bb.i
+    i32 1, label %sw.bb1.i
+    i32 2, label %sw.bb2.i
+    i32 3, label %sw.bb3.i
+  ]
+
+sw.bb.i:                                          ; preds = %do.end
+  br label %get_filter_list.exit
+
+sw.bb1.i:                                         ; preds = %do.end
+  br label %get_filter_list.exit
+
+sw.bb2.i:                                         ; preds = %do.end
+  br label %get_filter_list.exit
+
+sw.bb3.i:                                         ; preds = %do.end
+  br label %get_filter_list.exit
+
+sw.default.i:                                     ; preds = %do.end
+  call void @g_assertion_message(i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str2, i32 0, i32 0), i32 408, i8* getelementptr inbounds ([44 x i8], [44 x i8]* @__PRETTY_FUNCTION__.get_filter_list, i32 0, i32 0), i8* null) noreturn nounwind
+  unreachable
+
+get_filter_list.exit:                             ; preds = %sw.bb3.i, %sw.bb2.i, %sw.bb1.i, %sw.bb.i
+  %0 = phi %struct._GList** [ @display_edited_filters, %sw.bb3.i ], [ @capture_edited_filters, %sw.bb2.i ], [ @display_filters, %sw.bb1.i ], [ @capture_filters, %sw.bb.i ]
+  switch i32 %src_type, label %sw.default.i5 [
+    i32 0, label %sw.bb.i1
+    i32 1, label %sw.bb1.i2
+    i32 2, label %sw.bb2.i3
+    i32 3, label %sw.bb3.i4
+  ]
+
+sw.bb.i1:                                         ; preds = %get_filter_list.exit
+  br label %get_filter_list.exit6
+
+sw.bb1.i2:                                        ; preds = %get_filter_list.exit
+  br label %get_filter_list.exit6
+
+sw.bb2.i3:                                        ; preds = %get_filter_list.exit
+  br label %get_filter_list.exit6
+
+sw.bb3.i4:                                        ; preds = %get_filter_list.exit
+  br label %get_filter_list.exit6
+
+sw.default.i5:                                    ; preds = %get_filter_list.exit
+  call void @g_assertion_message(i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str2, i32 0, i32 0), i32 408, i8* getelementptr inbounds ([44 x i8], [44 x i8]* @__PRETTY_FUNCTION__.get_filter_list, i32 0, i32 0), i8* null) noreturn nounwind
+  unreachable
+
+; CHECK: get_filter_list.exit
+get_filter_list.exit6:                            ; preds = %sw.bb3.i4, %sw.bb2.i3, %sw.bb1.i2, %sw.bb.i1
+  %1 = phi %struct._GList** [ @display_edited_filters, %sw.bb3.i4 ], [ @capture_edited_filters, %sw.bb2.i3 ], [ @display_filters, %sw.bb1.i2 ], [ @capture_filters, %sw.bb.i1 ]
+; CHECK: %2 = load
+  %2 = load %struct._GList*, %struct._GList** %1, align 8
+; We should have jump-threading insert an additional load here for the value
+; coming out of the first switch, which is picked up by a subsequent phi
+; CHECK: %.pr = load %struct._GList*, %struct._GList** %0
+; CHECK-NEXT:  br label %while.cond
+  br label %while.cond
+
+; CHECK: while.cond
+while.cond:                                       ; preds = %while.body, %get_filter_list.exit6
+; CHECK: {{= phi .*%.pr}}
+  %3 = load %struct._GList*, %struct._GList** %0, align 8
+; CHECK: tobool
+  %tobool = icmp ne %struct._GList* %3, null
+  br i1 %tobool, label %while.body, label %while.end
+
+while.body:                                       ; preds = %while.cond
+  %4 = load %struct._GList*, %struct._GList** %0, align 8
+  %5 = load %struct._GList*, %struct._GList** %0, align 8
+  %call2 = call %struct._GList* @g_list_first(%struct._GList* %5)
+  %data.i = getelementptr inbounds %struct._GList, %struct._GList* %call2, i32 0, i32 0
+  %6 = load i8*, i8** %data.i, align 8
+  %7 = bitcast i8* %6 to %struct.filter_def*
+  %name.i = getelementptr inbounds %struct.filter_def, %struct.filter_def* %7, i32 0, i32 0
+  %8 = load i8*, i8** %name.i, align 8
+  call void @g_free(i8* %8) nounwind
+  %strval.i = getelementptr inbounds %struct.filter_def, %struct.filter_def* %7, i32 0, i32 1
+  %9 = load i8*, i8** %strval.i, align 8
+  call void @g_free(i8* %9) nounwind
+  %10 = bitcast %struct.filter_def* %7 to i8*
+  call void @g_free(i8* %10) nounwind
+  %call.i = call %struct._GList* @g_list_remove_link(%struct._GList* %4, %struct._GList* %call2) nounwind
+  store %struct._GList* %call.i, %struct._GList** %0, align 8
+  br label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  br label %do.body4
+
+do.body4:                                         ; preds = %while.end
+  %11 = load %struct._GList*, %struct._GList** %0, align 8
+  %call5 = call i32 @g_list_length(%struct._GList* %11)
+  %cmp6 = icmp eq i32 %call5, 0
+  br i1 %cmp6, label %if.then7, label %if.else8
+
+if.then7:                                         ; preds = %do.body4
+  br label %if.end9
+
+if.else8:                                         ; preds = %do.body4
+  call void @g_assertion_message_expr(i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str2, i32 0, i32 0), i32 600, i8* getelementptr inbounds ([62 x i8], [62 x i8]* @__PRETTY_FUNCTION__.copy_filter_list, i32 0, i32 0), i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str13, i32 0, i32 0)) noreturn
+  unreachable
+
+if.end9:                                          ; preds = %if.then7
+  br label %do.end10
+
+do.end10:                                         ; preds = %if.end9
+  br label %while.cond11
+
+while.cond11:                                     ; preds = %cond.end, %do.end10
+  %cond10 = phi %struct._GList* [ %cond, %cond.end ], [ %2, %do.end10 ]
+  %tobool12 = icmp ne %struct._GList* %cond10, null
+  br i1 %tobool12, label %while.body13, label %while.end16
+
+while.body13:                                     ; preds = %while.cond11
+  %data = getelementptr inbounds %struct._GList, %struct._GList* %cond10, i32 0, i32 0
+  %12 = load i8*, i8** %data, align 8
+  %13 = bitcast i8* %12 to %struct.filter_def*
+  %14 = load %struct._GList*, %struct._GList** %0, align 8
+  %name = getelementptr inbounds %struct.filter_def, %struct.filter_def* %13, i32 0, i32 0
+  %15 = load i8*, i8** %name, align 8
+  %strval = getelementptr inbounds %struct.filter_def, %struct.filter_def* %13, i32 0, i32 1
+  %16 = load i8*, i8** %strval, align 8
+  %call.i7 = call noalias i8* @g_malloc(i64 16) nounwind
+  %17 = bitcast i8* %call.i7 to %struct.filter_def*
+  %call1.i = call noalias i8* @g_strdup(i8* %15) nounwind
+  %name.i8 = getelementptr inbounds %struct.filter_def, %struct.filter_def* %17, i32 0, i32 0
+  store i8* %call1.i, i8** %name.i8, align 8
+  %call2.i = call noalias i8* @g_strdup(i8* %16) nounwind
+  %strval.i9 = getelementptr inbounds %struct.filter_def, %struct.filter_def* %17, i32 0, i32 1
+  store i8* %call2.i, i8** %strval.i9, align 8
+  %18 = bitcast %struct.filter_def* %17 to i8*
+  %call3.i = call %struct._GList* @g_list_append(%struct._GList* %14, i8* %18) nounwind
+  store %struct._GList* %call3.i, %struct._GList** %0, align 8
+  %tobool15 = icmp ne %struct._GList* %cond10, null
+  br i1 %tobool15, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %while.body13
+  %next = getelementptr inbounds %struct._GList, %struct._GList* %cond10, i32 0, i32 1
+  %19 = load %struct._GList*, %struct._GList** %next, align 8
+  br label %cond.end
+
+cond.false:                                       ; preds = %while.body13
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi %struct._GList* [ %19, %cond.true ], [ null, %cond.false ]
+  br label %while.cond11
+
+while.end16:                                      ; preds = %while.cond11
+  ret void
+}
+
+declare void @g_assertion_message_expr(i8*, i8*, i32, i8*, i8*) noreturn
+
+declare i32 @g_list_length(%struct._GList*)
+
+declare noalias i8* @g_strdup(i8*)
+
+declare %struct._GList* @g_list_append(%struct._GList*, i8*)
+
+declare %struct._GList* @g_list_remove_link(%struct._GList*, %struct._GList*)

Added: llvm/trunk/test/Transforms/JumpThreading/phi-known.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/phi-known.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/phi-known.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/phi-known.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,104 @@
+; RUN: opt -S -jump-threading %s | FileCheck %s
+
+; Value of predicate known on all inputs (trivial case)
+; Note: InstCombine/EarlyCSE would also get this case
+define void @test(i8* %p, i8** %addr) {
+; CHECK-LABEL: @test
+entry:
+  %cmp0 = icmp eq i8* %p, null
+  br i1 %cmp0, label %exit, label %loop
+loop:
+; CHECK-LABEL: loop:
+; CHECK-NEXT: phi
+; CHECK-NEXT: br label %loop
+  %p1 = phi i8* [%p, %entry], [%p1, %loop]
+  %cmp1 = icmp eq i8* %p1, null
+  br i1 %cmp1, label %exit, label %loop
+exit:
+  ret void
+}
+
+; Value of predicate known on all inputs (non-trivial)
+define void @test2(i8* %p) {
+; CHECK-LABEL: @test2
+entry:
+  %cmp0 = icmp eq i8* %p, null
+  br i1 %cmp0, label %exit, label %loop
+loop:
+  %p1 = phi i8* [%p, %entry], [%p2, %backedge]
+  %cmp1 = icmp eq i8* %p1, null
+  br i1 %cmp1, label %exit, label %backedge
+backedge:
+; CHECK-LABEL: backedge:
+; CHECK-NEXT: phi
+; CHECK-NEXT: bitcast
+; CHECK-NEXT: load
+; CHECK-NEXT: cmp
+; CHECK-NEXT: br 
+; CHECK-DAG: label %backedge
+  %addr = bitcast i8* %p1 to i8**
+  %p2 = load i8*, i8** %addr
+  %cmp2 = icmp eq i8* %p2, null
+  br i1 %cmp2, label %exit, label %loop
+exit:
+  ret void
+}
+
+; If the inputs don't branch the same way, we can't rewrite
+; Well, we could unroll this loop exactly twice, but that's
+; a different transform.
+define void @test_mixed(i8* %p) {
+; CHECK-LABEL: @test_mixed
+entry:
+  %cmp0 = icmp eq i8* %p, null
+  br i1 %cmp0, label %exit, label %loop
+loop:
+; CHECK-LABEL: loop:
+; CHECK-NEXT: phi
+; CHECK-NEXT: %cmp1 = icmp
+; CHECK-NEXT: br i1 %cmp1
+  %p1 = phi i8* [%p, %entry], [%p1, %loop]
+  %cmp1 = icmp ne i8* %p1, null
+  br i1 %cmp1, label %exit, label %loop
+exit:
+  ret void
+}
+
+; The eq predicate is always true if we go through the path from
+; L1 to L3, no matter the phi result %t5 is on the lhs or rhs of
+; the predicate.
+declare void @goo()
+declare void @hoo()
+
+define void @test3(i32 %m, i32** %t1) {
+L1:
+  %t0 = add i32 %m, 7
+  %t2 = load i32*, i32** %t1, align 8
+; CHECK-LABEL: @test3
+; CHECK: %t3 = icmp eq i32* %t2, null
+; CHECK: br i1 %t3, label %[[LABEL2:.*]], label %[[LABEL1:.*]]
+
+  %t3 = icmp eq i32* %t2, null
+  br i1 %t3, label %L3, label %L2
+
+; CHECK: [[LABEL1]]:
+; CHECK-NEXT: %t4 = load i32, i32* %t2, align 4
+L2:
+  %t4 = load i32, i32* %t2, align 4
+  br label %L3
+
+L3:
+  %t5 = phi i32 [ %t0, %L1 ], [ %t4, %L2 ]
+  %t6 = icmp eq i32 %t0, %t5
+  br i1 %t6, label %L4, label %L5
+
+; CHECK: [[LABEL2]]:
+; CHECK-NEXT: call void @goo()
+L4:
+  call void @goo()
+  ret void
+
+L5:
+  call void @hoo()
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/pr15851_hang.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr15851_hang.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr15851_hang.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr15851_hang.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -S -jump-threading < %s | FileCheck %s
+
+; CHECK-LABEL: @f(
+; CHECK-LABEL: entry
+; CHECK-NEXT: ret void
+;
+; JumpThreading must detect the next two blocks are unreachable from entry
+; and leave them alone. A subsequent pass will remove them from @f.
+;
+; CHECK: for.cond1:
+; CHECK-NEXT: phi
+; CHECK-NEXT: icmp
+; CHECK-NEXT: br i1 %cmp, label %for.body, label %for.cond1
+; CHECK: for.body:
+; CHECK-NEXT: add
+; CHECK-NEXT: icmp
+; CHECK-NEXT: br i1 %a, label %for.cond1, label %for.cond1
+
+define void @f() {
+entry:
+  ret void
+
+for.cond1:
+  %i.025 = phi i32 [ %inc, %for.body ], [ %inc, %for.body ], [ 1, %for.cond1 ]
+  %cmp = icmp slt i32 %i.025, 2
+  br i1 %cmp, label %for.body, label %for.cond1
+
+for.body:
+  %inc = add nsw i32 %i.025, 0
+  %a = icmp ugt i32 %inc, 2
+  br i1 %a, label %for.cond1, label %for.cond1
+}

Added: llvm/trunk/test/Transforms/JumpThreading/pr22086.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr22086.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr22086.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr22086.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt -S -jump-threading < %s | FileCheck %s
+
+
+; CHECK-LABEL: @f(
+; CHECK-LABEL: entry:
+; CHECK-NEXT:  br label %[[loop:.*]]
+; CHECK:       [[loop]]:
+; CHECK-NEXT:  br label %[[loop]]
+
+define void @f() {
+entry:
+  br label %for.cond1
+
+if.end16:
+  %phi1 = phi i32 [ undef, %for.cond1 ]
+  %g.3 = phi i32 [ %g.1, %for.cond1 ]
+  %sext = shl i32 %g.3, 16
+  %conv20 = ashr exact i32 %sext, 16
+  %tobool21 = icmp eq i32 %phi1, 0
+  br i1 %tobool21, label %lor.rhs, label %for.cond1
+
+for.cond1:
+  %g.1 = phi i32 [ 0, %entry ], [ 0, %lor.rhs ], [ %g.3, %if.end16 ]
+  br i1 undef, label %lor.rhs, label %if.end16
+
+lor.rhs:
+  br label %for.cond1
+}

Added: llvm/trunk/test/Transforms/JumpThreading/pr26096.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr26096.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr26096.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr26096.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,73 @@
+; RUN: opt -prune-eh -inline -jump-threading -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at d = external global i32*, align 8
+
+define void @fn3(i1 %B) {
+entry:
+  br i1 %B, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  call void @fn2(i1 %B)
+  ret void
+
+if.end:                                           ; preds = %entry
+  call void @fn2(i1 %B)
+  ret void
+}
+
+define internal void @fn2(i1 %B) unnamed_addr {
+entry:
+  call void @fn1()
+  call void @fn1()
+  call void @fn1()
+  br i1 %B, label %if.end, label %if.then
+if.then:
+  unreachable
+
+if.end:
+  unreachable
+}
+
+; CHECK-LABEL: define internal void @fn2(
+; CHECK:   %[[LOAD:.*]] = load i32*, i32** @d, align 8
+; CHECK:   %tobool1.i = icmp eq i32* %[[LOAD]], null
+
+define internal void @fn1() unnamed_addr {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry
+  %0 = load i32*, i32** @d, align 8
+  %tobool1 = icmp eq i32* %0, null
+  br i1 %tobool1, label %cond.false, label %cond.end
+
+cond.false:                                       ; preds = %for.body
+  call void @__assert_fail(i8* null)
+  unreachable
+
+cond.end:                                         ; preds = %for.body
+  %1 = load i32*, i32** @d, align 8
+  %cmp = icmp eq i32* %1, null
+  br i1 %cmp, label %cond.end4, label %cond.false3
+
+cond.false3:                                      ; preds = %cond.end
+  call void @__assert_fail(i8* null)
+  unreachable
+
+cond.end4:                                        ; preds = %cond.end
+  call void @__assert_fail(i8* null)
+  unreachable
+
+for.end:                                          ; No predecessors!
+  ret void
+}
+
+declare void @__assert_fail(i8*)
+
+; Function Attrs: noreturn nounwind
+declare void @llvm.trap() #0
+
+attributes #0 = { noreturn nounwind }

Added: llvm/trunk/test/Transforms/JumpThreading/pr27840.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr27840.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr27840.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr27840.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt -jump-threading -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+declare void @helper()
+declare i32 @__gxx_personality_v0(...)
+
+
+define void @pr27840(i8* %call, i1 %A) personality i32(...)* @__gxx_personality_v0 {
+entry:
+  invoke void @helper()
+          to label %invoke.cont unwind label %lpad
+
+; Don't jump threading; we can't split the critical edge from entry to lpad.
+; CHECK-LABEL: @pr27840
+; CHECK: invoke
+; CHECK-NEXT: to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  invoke void @helper()
+          to label %nowhere unwind label %lpad
+
+lpad:
+  %b = phi i1 [ true, %invoke.cont ], [ false, %entry ]
+  landingpad { i8*, i32 }
+          cleanup
+  %xor = xor i1 %b, %A
+  br i1 %xor, label %nowhere, label %invoke.cont
+
+nowhere:
+  unreachable
+}

Added: llvm/trunk/test/Transforms/JumpThreading/pr33605.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr33605.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr33605.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr33605.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; RUN: opt < %s -jump-threading -S | FileCheck %s
+
+; Skip simplifying unconditional branches from empty blocks in simplifyCFG,
+; when it can destroy canonical loop structure.
+
+; void foo();
+; bool test(int a, int b, int *c) {
+;   bool changed = false;
+;   for (unsigned int i = 2; i--;) {
+;     int r = a | b;
+;     if ( r != c[i]) {
+;       c[i] = r;
+;       foo();
+;       changed = true;
+;     }
+;   }
+;   return changed;
+; }
+
+; CHECK-LABEL: @test(
+; CHECK: for.cond:
+; CHECK-NEXT: %i.0 = phi i32 [ 2, %entry ], [ %dec, %if.end ]
+; CHECK: for.body:
+; CHECK: br i1 %cmp, label %if.end, label %if.then
+; CHECK-NOT: br i1 %cmp, label %for.cond, label %if.then
+; CHECK: if.then:
+; CHECK: br label %if.end
+; CHECK-NOT: br label %for.cond
+; CHECK: if.end:
+; CHECK br label %for.cond
+define i1 @test(i32 %a, i32 %b, i32* %c) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %if.end, %entry
+  %i.0 = phi i32 [ 2, %entry ], [ %dec, %if.end ]
+  %changed.0.off0 = phi i1 [ false, %entry ], [ %changed.1.off0, %if.end ]
+  %dec = add nsw i32 %i.0, -1
+  %tobool = icmp eq i32 %i.0, 0
+  br i1 %tobool, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %changed.0.off0.lcssa = phi i1 [ %changed.0.off0, %for.cond ]
+  ret i1 %changed.0.off0.lcssa
+
+for.body:                                         ; preds = %for.cond
+  %or = or i32 %a, %b
+  %idxprom = sext i32 %dec to i64
+  %arrayidx = getelementptr inbounds i32, i32* %c, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %cmp = icmp eq i32 %or, %0
+  br i1 %cmp, label %if.end, label %if.then
+
+if.then:                                          ; preds = %for.body
+  store i32 %or, i32* %arrayidx, align 4
+  call void @foo()
+  br label %if.end
+
+if.end:                                           ; preds = %for.body, %if.then
+  %changed.1.off0 = phi i1 [ true, %if.then ], [ %changed.0.off0, %for.body ]
+  br label %for.cond
+}
+
+declare void @foo()

Added: llvm/trunk/test/Transforms/JumpThreading/pr33917.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr33917.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr33917.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr33917.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -jump-threading -correlated-propagation %s -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i8* @foo()
+
+declare i32 @rust_eh_personality() unnamed_addr
+
+; Function Attrs: nounwind
+declare void @llvm.assume(i1) #0
+
+define void @patatino() personality i32 ()* @rust_eh_personality {
+; CHECK-LABEL: @patatino(
+; CHECK-NEXT:  bb9:
+; CHECK-NEXT:    [[T9:%.*]] = invoke i8* @foo()
+; CHECK-NEXT:    to label [[GOOD:%.*]] unwind label [[BAD:%.*]]
+; CHECK:       bad:
+; CHECK-NEXT:    [[T10:%.*]] = landingpad { i8*, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    resume { i8*, i32 } [[T10]]
+; CHECK:       good:
+; CHECK-NEXT:    [[T11:%.*]] = icmp ne i8* [[T9]], null
+; CHECK-NEXT:    [[T12:%.*]] = zext i1 [[T11]] to i64
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[T12]], 1
+; CHECK-NEXT:    br i1 [[COND]], label [[IF_TRUE:%.*]], label [[DONE:%.*]]
+; CHECK:       if_true:
+; CHECK-NEXT:    call void @llvm.assume(i1 [[T11]])
+; CHECK-NEXT:    br label [[DONE]]
+; CHECK:       done:
+; CHECK-NEXT:    ret void
+;
+bb9:
+  %t9 = invoke i8* @foo()
+  to label %good unwind label %bad
+
+bad:
+  %t10 = landingpad { i8*, i32 }
+  cleanup
+  resume { i8*, i32 } %t10
+
+good:
+  %t11 = icmp ne i8* %t9, null
+  %t12 = zext i1 %t11 to i64
+  %cond = icmp eq i64 %t12, 1
+  br i1 %cond, label %if_true, label %done
+
+if_true:
+  call void @llvm.assume(i1 %t11)
+  br label %done
+
+done:
+  ret void
+}
+
+attributes #0 = { nounwind }

Added: llvm/trunk/test/Transforms/JumpThreading/pr36133.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr36133.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr36133.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr36133.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt -jump-threading -S < %s | FileCheck %s
+ at global = external global i8*, align 8
+
+define i32 @foo(i32 %arg) {
+; CHECK-LABEL: @foo
+; CHECK-LABEL: bb:
+; CHECK: icmp eq
+; CHECK-NEXT: br i1 %tmp1, label %bb7, label %bb7
+bb:
+  %tmp = load i8*, i8** @global, align 8
+  %tmp1 = icmp eq i8* %tmp, null
+  br i1 %tmp1, label %bb3, label %bb2
+
+; CHECK-NOT: bb2:
+bb2:
+  br label %bb3
+
+; CHECK-NOT: bb3:
+bb3:
+  %tmp4 = phi i8 [ 1, %bb2 ], [ 0, %bb ]
+  %tmp5 = icmp eq i8 %tmp4, 0
+  br i1 %tmp5, label %bb7, label %bb6
+
+; CHECK-NOT: bb6:
+bb6:
+  br label %bb7
+
+; CHECK-LABEL: bb7:
+bb7:
+  %tmp8 = icmp eq i32 %arg, -1
+  br i1 %tmp8, label %bb9, label %bb10
+
+; CHECK-LABEL: bb9:
+bb9:
+  ret i32 0
+
+; CHECK-LABEL: bb10:
+bb10:
+  %tmp11 = icmp sgt i32 %arg, -1
+  call void @llvm.assume(i1 %tmp11)
+  ret i32 1
+}
+
+declare void @llvm.assume(i1)

Added: llvm/trunk/test/Transforms/JumpThreading/pr40992-indirectbr-folding.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr40992-indirectbr-folding.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr40992-indirectbr-folding.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr40992-indirectbr-folding.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt -S < %s -jump-threading | FileCheck %s
+
+; PR40992: Do not incorrectly fold %bb5 into an unconditional br to %bb7.
+;          Also verify we correctly thread %bb1 -> %bb7 when %c is false.
+
+define i32 @jtbr(i1 %v1, i1 %v2, i1 %v3) {
+; CHECK: bb0:
+bb0:
+  br label %bb1
+
+; CHECK: bb1:
+; CHECK-NEXT: and
+; CHECK-NEXT: br i1 %c, label %bb2, label %bb7
+bb1:
+  %c = and i1 %v1, %v2
+  br i1 %c, label %bb2, label %bb5
+
+; CHECK: bb2:
+; CHECK-NEXT: select
+; CHECK-NEXT: indirectbr i8* %ba, [label %bb3, label %bb5]
+bb2:
+  %ba = select i1 %v3, i8* blockaddress(@jtbr, %bb3), i8* blockaddress(@jtbr, %bb4)
+  indirectbr i8* %ba, [label %bb3, label %bb4]
+
+; CHECK: bb3:
+bb3:
+  br label %bb1
+
+; CHECK-NOT: bb4:
+bb4:
+  br label %bb5
+
+; CHECK: bb5:
+bb5:
+  br i1 %c, label %bb6, label %bb7
+
+; CHECK: bb6:
+bb6:
+  ret i32 0
+
+; CHECK: bb7:
+bb7:
+  ret i32 1
+}

Added: llvm/trunk/test/Transforms/JumpThreading/pr9331.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr9331.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr9331.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr9331.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -jump-threading -S < %s
+
+define void @func(i8 zeroext %p_44) nounwind {
+entry:
+  br i1 false, label %for.cond2, label %if.end50
+
+for.cond2:                                        ; preds = %for.inc46, %lor.end, %entry
+  %p_44.addr.1 = phi i8 [ %p_44.addr.1, %lor.end ], [ %p_44, %entry ], [ %p_44.addr.1, %for.inc46 ]
+  br i1 undef, label %for.inc46, label %for.body5
+
+for.body5:                                        ; preds = %for.cond2
+  br i1 undef, label %lbl_465, label %if.then9
+
+if.then9:                                         ; preds = %for.body5
+  br label %return
+
+lbl_465:                                          ; preds = %lbl_465, %for.body5
+  %tobool19 = icmp eq i8 undef, 0
+  br i1 %tobool19, label %if.end21, label %lbl_465
+
+if.end21:                                         ; preds = %lbl_465
+  %conv23 = zext i8 %p_44.addr.1 to i64
+  %xor = xor i64 %conv23, 1
+  %tobool.i = icmp eq i64 %conv23, 0
+  br i1 %tobool.i, label %cond.false.i, label %safe_mod_func_uint64_t_u_u.exit
+
+cond.false.i:                                     ; preds = %if.end21
+  %div.i = udiv i64 %xor, %conv23
+  br label %safe_mod_func_uint64_t_u_u.exit
+
+safe_mod_func_uint64_t_u_u.exit:                  ; preds = %cond.false.i, %if.end21
+  %cond.i = phi i64 [ %div.i, %cond.false.i ], [ %conv23, %if.end21 ]
+  %tobool28 = icmp eq i64 %cond.i, 0
+  br i1 %tobool28, label %lor.rhs, label %lor.end
+
+lor.rhs:                                          ; preds = %safe_mod_func_uint64_t_u_u.exit
+  br label %lor.end
+
+lor.end:                                          ; preds = %lor.rhs, %safe_mod_func_uint64_t_u_u.exit
+  br label %for.cond2
+
+for.inc46:                                        ; preds = %for.cond2
+  br label %for.cond2
+
+if.end50:                                         ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %if.end50, %if.then9
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/range-compare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/range-compare.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/range-compare.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/range-compare.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,125 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+;RUN: opt < %s -jump-threading -S | FileCheck %s
+
+
+declare void @bar(...)
+declare void @baz(...)
+
+; Make sure we thread the end of the bar block to the end of the function.
+define void @test1(i32 %x) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], 9
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_END_THREAD:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.end.thread:
+; CHECK-NEXT:    call void (...) @bar()
+; CHECK-NEXT:    br label [[IF_END4:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X]], -3
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X_OFF]], 5
+; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN3:%.*]], label [[IF_END4]]
+; CHECK:       if.then3:
+; CHECK-NEXT:    call void (...) @baz()
+; CHECK-NEXT:    br label [[IF_END4]]
+; CHECK:       if.end4:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp sgt i32 %x, 9
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void (...) @bar()
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %x.off = add i32 %x, -3
+  %0 = icmp ult i32 %x.off, 5
+  br i1 %0, label %if.then3, label %if.end4
+
+if.then3:                                         ; preds = %if.end
+  call void (...) @baz()
+  br label %if.end4
+
+if.end4:                                          ; preds = %if.then3, %if.end
+  ret void
+}
+
+; Make sure we thread the false side of the first if to the end of the function.
+define void @test2(i32 %x) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 9
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_END:%.*]], label [[IF_END4:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    call void (...) @bar()
+; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X]], -3
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X_OFF]], 5
+; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN3:%.*]], label [[IF_END4]]
+; CHECK:       if.then3:
+; CHECK-NEXT:    call void (...) @baz()
+; CHECK-NEXT:    br label [[IF_END4]]
+; CHECK:       if.end4:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp slt i32 %x, 9
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void (...) @bar()
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %x.off = add i32 %x, -3
+  %0 = icmp ult i32 %x.off, 5
+  br i1 %0, label %if.then3, label %if.end4
+
+if.then3:                                         ; preds = %if.end
+  call void (...) @baz()
+  br label %if.end4
+
+if.end4:                                          ; preds = %if.then3, %if.end
+  ret void
+}
+
+; Negative test to make sure we don't thread when the ranges overlap.
+define void @test3(i32 %x) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], 6
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void (...) @bar()
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X]], -3
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X_OFF]], 5
+; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]]
+; CHECK:       if.then3:
+; CHECK-NEXT:    call void (...) @baz()
+; CHECK-NEXT:    br label [[IF_END4]]
+; CHECK:       if.end4:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp sgt i32 %x, 6
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void (...) @bar()
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %x.off = add i32 %x, -3
+  %0 = icmp ult i32 %x.off, 5
+  br i1 %0, label %if.then3, label %if.end4
+
+if.then3:                                         ; preds = %if.end
+  call void (...) @baz()
+  br label %if.end4
+
+if.end4:                                          ; preds = %if.then3, %if.end
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/JumpThreading/removed-use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/removed-use.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/removed-use.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/removed-use.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt -S < %s -jump-threading | FileCheck %s
+; CHECK-LABEL: @foo
+; CHECK: bb6:
+; CHECK-NEXT: ret void
+; CHECK: bb3:
+; CHECK: br label %bb3
+define void @foo() {
+entry:
+  br i1 true, label %bb6, label %bb3
+
+bb3:
+  %x0 = phi i32 [ undef, %entry ], [ %x1, %bb5 ]
+  %y  = and i64 undef, 1
+  %p  = icmp ne i64 %y, 0
+  br i1 %p, label %bb4, label %bb5
+
+bb4:
+  br label %bb5
+
+bb5:
+  %x1 = phi i32 [ %x0, %bb3 ], [ %x0, %bb4 ]
+  %z  = phi i32 [ 0, %bb3 ], [ 1, %bb4 ]
+  %q  = icmp eq i32 %z, 0
+  br i1 %q, label %bb3, label %bb6
+
+bb6:
+  ret void
+}
+
+; CHECK-LABEL: @bar
+; Just check that we don't crash on this test.
+define void @bar(i1 %p) {
+entry:
+  br i1 false, label %bb2, label %exit
+
+bb2:
+  %x0 = phi i32 [ undef, %entry ], [ %x1, %bb5 ]
+  br i1 %p, label %bb3, label %bb4
+
+bb3:
+  br label %bb5
+
+bb4:
+  br label %bb5
+
+bb5:
+  %x1 = phi i32 [ %x0, %bb3 ], [ 0, %bb4 ]
+  switch i32 %x1, label %exit [
+    i32 10, label %bb2
+  ]
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/JumpThreading/select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/select.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/select.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/select.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,443 @@
+; RUN: opt -S -jump-threading < %s | FileCheck %s
+
+declare void @foo()
+declare void @bar()
+declare void @baz()
+declare void @quux()
+
+
+; Jump threading of branch with select as condition.
+; Mostly theoretical since instruction combining simplifies all selects of
+; booleans where at least one operand is true/false/undef.
+
+; CHECK-LABEL: @test_br(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 %cond, label %L1,
+define void @test_br(i1 %cond, i1 %value) nounwind {
+entry:
+  br i1 %cond, label %L0, label %L3
+L0:
+  %expr = select i1 %cond, i1 true, i1 %value
+  br i1 %expr, label %L1, label %L2
+
+L1:
+  call void @foo()
+  ret void
+L2:
+  call void @bar()
+  ret void
+L3:
+  call void @baz()
+  br label %L0
+}
+
+
+; Jump threading of switch with select as condition.
+
+; CHECK-LABEL: @test_switch(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 %cond, label %L1,
+define void @test_switch(i1 %cond, i8 %value) nounwind {
+entry:
+  br i1 %cond, label %L0, label %L4
+L0:
+  %expr = select i1 %cond, i8 1, i8 %value
+  switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2]
+
+L1:
+  call void @foo()
+  ret void
+L2:
+  call void @bar()
+  ret void
+L3:
+  call void @baz()
+  ret void
+L4:
+  call void @quux()
+  br label %L0
+}
+
+; Make sure the blocks in the indirectbr test aren't trivially removable as
+; successors by taking their addresses.
+ at anchor = constant [3 x i8*] [
+  i8* blockaddress(@test_indirectbr, %L1),
+  i8* blockaddress(@test_indirectbr, %L2),
+  i8* blockaddress(@test_indirectbr, %L3)
+]
+
+
+; Jump threading of indirectbr with select as address.
+
+; CHECK-LABEL: @test_indirectbr(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 %cond, label %L1, label %L3
+define void @test_indirectbr(i1 %cond, i8* %address) nounwind {
+entry:
+  br i1 %cond, label %L0, label %L3
+L0:
+  %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr, %L1), i8* %address
+  indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3]
+
+L1:
+  call void @foo()
+  ret void
+L2:
+  call void @bar()
+  ret void
+L3:
+  call void @baz()
+  ret void
+}
+
+
+; Jump threading of indirectbr with select as address.  Test increased
+; duplication threshold for cases where indirectbr is being threaded
+; through.
+
+; CHECK-LABEL: @test_indirectbr_thresh(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 %cond, label %L1, label %L3
+; CHECK-NOT: indirectbr
+define void @test_indirectbr_thresh(i1 %cond, i8* %address) nounwind {
+entry:
+  br i1 %cond, label %L0, label %L3
+L0:
+  %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr_thresh, %L1), i8* %address
+  call void @quux()
+  call void @quux()
+  call void @quux()
+  indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3]
+
+L1:
+  call void @foo()
+  ret void
+L2:
+  call void @bar()
+  ret void
+L3:
+  call void @baz()
+  ret void
+}
+
+
+; A more complicated case: the condition is a select based on a comparison.
+
+; CHECK-LABEL: @test_switch_cmp(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 %cond, label %L0, label %[[THREADED:[A-Za-z.0-9]+]]
+; CHECK: [[THREADED]]:
+; CHECK-NEXT: call void @quux
+; CHECK-NEXT: br label %L1
+define void @test_switch_cmp(i1 %cond, i32 %val, i8 %value) nounwind {
+entry:
+  br i1 %cond, label %L0, label %L4
+L0:
+  %val.phi = phi i32 [%val, %entry], [-1, %L4]
+  %cmp = icmp slt i32 %val.phi, 0
+  %expr = select i1 %cmp, i8 1, i8 %value
+  switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2]
+
+L1:
+  call void @foo()
+  ret void
+L2:
+  call void @bar()
+  ret void
+L3:
+  call void @baz()
+  ret void
+L4:
+  call void @quux()
+  br label %L0
+}
+
+; Make sure the edge value of %0 from entry to L2 includes 0 and L3 is
+; reachable.
+; CHECK: test_switch_default
+; CHECK: entry:
+; CHECK: load
+; CHECK: switch
+; CHECK: [[THREADED:[A-Za-z.0-9]+]]:
+; CHECK: store
+; CHECK: br
+; CHECK: L2:
+; CHECK-SAME: preds = %entry, %entry
+; CHECK-NEXT: phi i32
+define void @test_switch_default(i32* nocapture %status) nounwind {
+entry:
+  %0 = load i32, i32* %status, align 4
+  switch i32 %0, label %L2 [
+    i32 5061, label %L1
+    i32 0, label %L2
+  ]
+
+L1:
+  store i32 10025, i32* %status, align 4
+  br label %L2
+
+L2:
+  %1 = load i32, i32* %status, align 4
+  %cmp57.i = icmp eq i32 %1, 0
+  br i1 %cmp57.i, label %L3, label %L4
+
+L3:
+  store i32 10000, i32* %status, align 4
+  br label %L4
+
+L4:
+  ret void
+}
+
+define void @unfold1(double %x, double %y) nounwind {
+entry:
+  %sub = fsub double %x, %y
+  %cmp = fcmp ogt double %sub, 1.000000e+01
+  br i1 %cmp, label %cond.end4, label %cond.false
+
+cond.false:                                       ; preds = %entry
+  %add = fadd double %x, %y
+  %cmp1 = fcmp ogt double %add, 1.000000e+01
+  %add. = select i1 %cmp1, double %add, double 0.000000e+00
+  br label %cond.end4
+
+cond.end4:                                        ; preds = %entry, %cond.false
+  %cond5 = phi double [ %add., %cond.false ], [ %sub, %entry ]
+  %cmp6 = fcmp oeq double %cond5, 0.000000e+00
+  br i1 %cmp6, label %if.then, label %if.end
+
+if.then:                                          ; preds = %cond.end4
+  call void @foo()
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %cond.end4
+  ret void
+
+; CHECK-LABEL: @unfold1
+; CHECK: br i1 %cmp, label %cond.end4, label %cond.false
+; CHECK: br i1 %cmp1, label %cond.end4, label %if.then
+; CHECK: br i1 %cmp6, label %if.then, label %if.end
+; CHECK: br label %if.end
+}
+
+
+define void @unfold2(i32 %x, i32 %y) nounwind {
+entry:
+  %sub = sub nsw i32 %x, %y
+  %cmp = icmp sgt i32 %sub, 10
+  br i1 %cmp, label %cond.end4, label %cond.false
+
+cond.false:                                       ; preds = %entry
+  %add = add nsw i32 %x, %y
+  %cmp1 = icmp sgt i32 %add, 10
+  %add. = select i1 %cmp1, i32 0, i32 %add
+  br label %cond.end4
+
+cond.end4:                                        ; preds = %entry, %cond.false
+  %cond5 = phi i32 [ %add., %cond.false ], [ %sub, %entry ]
+  %cmp6 = icmp eq i32 %cond5, 0
+  br i1 %cmp6, label %if.then, label %if.end
+
+if.then:                                          ; preds = %cond.end4
+  call void @foo()
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %cond.end4
+  ret void
+
+; CHECK-LABEL: @unfold2
+; CHECK: br i1 %cmp, label %if.end, label %cond.false
+; CHECK: br i1 %cmp1, label %if.then, label %cond.end4
+; CHECK: br i1 %cmp6, label %if.then, label %if.end
+; CHECK: br label %if.end
+}
+
+
+define i32 @unfold3(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind {
+entry:
+  %add3 = add nsw i32 %j, 2
+  %cmp.i = icmp slt i32 %u, %v
+  br i1 %cmp.i, label %.exit, label %cond.false.i
+
+cond.false.i:                                     ; preds = %entry
+  %cmp4.i = icmp sgt i32 %u, %v
+  br i1 %cmp4.i, label %.exit, label %cond.false.6.i
+
+cond.false.6.i:                                   ; preds = %cond.false.i
+  %cmp8.i = icmp slt i32 %w, %x
+  br i1 %cmp8.i, label %.exit, label %cond.false.10.i
+
+cond.false.10.i:                                  ; preds = %cond.false.6.i
+  %cmp13.i = icmp sgt i32 %w, %x
+  br i1 %cmp13.i, label %.exit, label %cond.false.15.i
+
+cond.false.15.i:                                  ; preds = %cond.false.10.i
+  %phitmp = icmp sge i32 %y, %z
+  br label %.exit
+
+.exit:                                  ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i
+  %cond23.i = phi i1 [ false, %entry ], [ true, %cond.false.i ], [ false, %cond.false.6.i ], [ %phitmp, %cond.false.15.i ], [ true, %cond.false.10.i ]
+  %j.add3 = select i1 %cond23.i, i32 %j, i32 %add3
+  ret i32 %j.add3
+
+; CHECK-LABEL: @unfold3
+; CHECK: br i1 %cmp.i, label %.exit.thread2, label %cond.false.i
+; CHECK: br i1 %cmp4.i, label %.exit.thread, label %cond.false.6.i
+; CHECK: br i1 %cmp8.i, label %.exit.thread2, label %cond.false.10.i
+; CHECK: br i1 %cmp13.i, label %.exit.thread, label %.exit
+; CHECK: br i1 %phitmp, label %.exit.thread, label %.exit.thread2
+; CHECK: br label %.exit.thread2
+}
+
+define i32 @unfold4(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind {
+entry:
+  %add3 = add nsw i32 %j, 2
+  %cmp.i = icmp slt i32 %u, %v
+  br i1 %cmp.i, label %.exit, label %cond.false.i
+
+cond.false.i:                                     ; preds = %entry
+  %cmp4.i = icmp sgt i32 %u, %v
+  br i1 %cmp4.i, label %.exit, label %cond.false.6.i
+
+cond.false.6.i:                                   ; preds = %cond.false.i
+  %cmp8.i = icmp slt i32 %w, %x
+  br i1 %cmp8.i, label %.exit, label %cond.false.10.i
+
+cond.false.10.i:                                  ; preds = %cond.false.6.i
+  %cmp13.i = icmp sgt i32 %w, %x
+  br i1 %cmp13.i, label %.exit, label %cond.false.15.i
+
+cond.false.15.i:                                  ; preds = %cond.false.10.i
+  %cmp19.i = icmp sge i32 %y, %z
+  %conv = zext i1 %cmp19.i to i32
+  br label %.exit
+
+.exit:                                  ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i
+  %cond23.i = phi i32 [ 1, %entry ], [ 0, %cond.false.i ], [ 1, %cond.false.6.i ], [ %conv, %cond.false.15.i ], [ 0, %cond.false.10.i ]
+  %lnot.i18 = icmp eq i32 %cond23.i, 1
+  %j.add3 = select i1 %lnot.i18, i32 %j, i32 %add3
+  ret i32 %j.add3
+
+; CHECK-LABEL: @unfold4
+; CHECK: br i1 %cmp.i, label %.exit.thread, label %cond.false.i
+; CHECK: br i1 %cmp4.i, label %.exit.thread3, label %cond.false.6.i
+; CHECK: br i1 %cmp8.i, label %.exit.thread, label %cond.false.10.i
+; CHECK: br i1 %cmp13.i, label %.exit.thread3, label %.exit
+; CHECK: br i1 %lnot.i18, label %.exit.thread, label %.exit.thread3
+; CHECK: br label %.exit.thread3
+}
+
+define i32 @unfold5(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind {
+entry:
+  %add3 = add nsw i32 %j, 2
+  %cmp.i = icmp slt i32 %u, %v
+  br i1 %cmp.i, label %.exit, label %cond.false.i
+
+cond.false.i:                                     ; preds = %entry
+  %cmp4.i = icmp sgt i32 %u, %v
+  br i1 %cmp4.i, label %.exit, label %cond.false.6.i
+
+cond.false.6.i:                                   ; preds = %cond.false.i
+  %cmp8.i = icmp slt i32 %w, %x
+  br i1 %cmp8.i, label %.exit, label %cond.false.10.i
+
+cond.false.10.i:                                  ; preds = %cond.false.6.i
+  %cmp13.i = icmp sgt i32 %w, %x
+  br i1 %cmp13.i, label %.exit, label %cond.false.15.i
+
+cond.false.15.i:                                  ; preds = %cond.false.10.i
+  %cmp19.i = icmp sge i32 %y, %z
+  %conv = zext i1 %cmp19.i to i32
+  br label %.exit
+
+.exit:                                  ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i
+  %cond23.i = phi i32 [ 2, %entry ], [ 3, %cond.false.i ], [ 1, %cond.false.6.i ], [ %conv, %cond.false.15.i ], [ 7, %cond.false.10.i ]
+  %lnot.i18 = icmp sgt i32 %cond23.i, 5
+  %j.add3 = select i1 %lnot.i18, i32 %j, i32 %cond23.i
+  ret i32 %j.add3
+
+; CHECK-LABEL: @unfold5
+; CHECK: br i1 %cmp.i, label %.exit, label %cond.false.i
+; CHECK: br i1 %cmp4.i, label %.exit, label %cond.false.6.i
+; CHECK: br i1 %cmp8.i, label %.exit, label %cond.false.10.i
+; CHECK: br i1 %cmp13.i, label %.exit, label %cond.false.15.i
+; CHECK: br label %.exit
+}
+
+; When a select has a constant operand in one branch, and it feeds a phi node
+; and the phi node feeds a switch we unfold the select
+define void @test_func(i32* nocapture readonly %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %n) local_unnamed_addr #0 {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %sw.default, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %sw.default ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  ret void
+
+for.body:                                         ; preds = %for.cond
+  %0 = zext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %0
+  %1 = load i32, i32* %arrayidx, align 4
+  %cmp1 = icmp eq i32 %1, 4
+  br i1 %cmp1, label %land.lhs.true, label %if.end
+
+land.lhs.true:                                    ; preds = %for.body
+  %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %0
+  %2 = load i32, i32* %arrayidx3, align 4
+  %arrayidx5 = getelementptr inbounds i32, i32* %c, i64 %0
+  %3 = load i32, i32* %arrayidx5, align 4
+  %cmp6 = icmp eq i32 %2, %3
+  %spec.select = select i1 %cmp6, i32 2, i32 4
+  br label %if.end
+
+if.end:                                           ; preds = %land.lhs.true, %for.body
+  %local_var.0 = phi i32 [ %1, %for.body ], [ %spec.select, %land.lhs.true ]
+  switch i32 %local_var.0, label %sw.default [
+    i32 2, label %sw.bb
+    i32 4, label %sw.bb7
+    i32 5, label %sw.bb8
+    i32 7, label %sw.bb9
+  ]
+
+sw.bb:                                            ; preds = %if.end
+  call void @foo()
+  br label %sw.bb7
+
+sw.bb7:                                           ; preds = %if.end, %sw.bb
+  call void @bar()
+  br label %sw.bb8
+
+sw.bb8:                                           ; preds = %if.end, %sw.bb7
+  call void @baz()
+  br label %sw.bb9
+
+sw.bb9:                                           ; preds = %if.end, %sw.bb8
+  call void @quux()
+  br label %sw.default
+
+sw.default:                                       ; preds = %if.end, %sw.bb9
+  call void @baz()
+  %inc = add nuw nsw i32 %i.0, 1
+  br label %for.cond
+
+; CHECK-LABEL: @test_func(
+; CHECK: [[REG:%[0-9]+]] = load
+; CHECK-NOT: select
+; CHECK: br i1
+; CHECK-NOT: select
+; CHECK: br i1 {{.*}}, label [[DEST1:%.*]], label [[DEST2:%.*]]
+
+; The following line checks existence of a phi node, and makes sure
+; it only has one incoming value. To do this, we check every '%'. Note
+; that REG and REG2 each contain one '%;. There is another one in the
+; beginning of the incoming block name. After that there should be no other '%'.
+
+; CHECK: [[REG2:%.*]] = phi i32 {{[^%]*}}[[REG]]{{[^%]*%[^%]*}}
+; CHECK: switch i32 [[REG2]]
+; CHECK: i32 2, label [[DEST1]]
+; CHECK: i32 4, label [[DEST2]]
+}

Added: llvm/trunk/test/Transforms/JumpThreading/static-profile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/static-profile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/static-profile.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/static-profile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,128 @@
+; RUN: opt -S -jump-threading < %s | FileCheck %s
+
+; Check that based solely on static profile estimation we don't update the
+; branch-weight metadata.  Even if the function has an entry frequency, a
+; completely cold part of the CFG may be statically estimated.
+
+; For example in the loop below, jump threading would update the weight of the
+; loop-exiting branch to 0, drastically inflating the frequency of the loop
+; (in the range of billions).
+;
+; This is the CFG of the loop.  There is no run-time profile info for edges
+; inside the loop, so branch and block frequencies are estimated as shown:
+;
+;                 check_1 (16)
+;             (8) /  |
+;             eq_1   | (8)
+;                 \  |
+;                 check_2 (16)
+;             (8) /  |
+;             eq_2   | (8)
+;                 \  |
+;                 check_3 (16)
+;             (1) /  |
+;        (loop exit) | (15)
+;                    |
+;                  latch
+;                    |
+;               (back edge)
+;
+; First we thread eq_1->check_2 to check_3.  Frequencies are updated to remove
+; the frequency of eq_1 from check_2 and then the false edge leaving check_2
+; (changed frequencies are highlighted with * *):
+;
+;                 check_1 (16)
+;             (8) /  |
+;            eq_1~   | (8)
+;            /       |
+;           /     check_2 (*8*)
+;          /  (8) /  |
+;          \  eq_2   | (*0*)
+;           \     \  |
+;            ` --- check_3 (16)
+;             (1) /  |
+;        (loop exit) | (15)
+;                    |
+;                  latch
+;                    |
+;               (back edge)
+;
+; Next we thread eq_1->check_3 and eq_2->check_3 to check_1 as new edges to
+; the loop latch.  Frequencies are updated to remove the frequency of eq_1
+; and eq_3 from check_3 and then the false edge leaving check_3 (changed
+; frequencies are highlighted with * *):
+;
+;                 check_1 (16)
+;             (8) /  |
+;            eq_1~   | (8)
+;            /       |
+;           /     check_2 (*8*)
+;          /  (8) /  |
+;         /-- eq_2~  | (*0*)
+;        /           |
+;       /         check_3 (*0*)
+;      /    (*0*) /  |
+;     |  (loop exit) | (*0*)
+;      \             |
+;       `--------- latch
+;                    |
+;               (back edge)
+;
+; As a result, the loop exit edge ends up with 0 frequency which in turn makes
+; the loop header to have maximum frequency.
+
+declare void @bar()
+
+define void @foo(i32 *%p, i32 %n) !prof !0 {
+entry:
+  %enter_loop = icmp eq i32 %n, 0
+  br i1 %enter_loop, label %exit, label %check_1, !prof !1
+; CHECK: br i1 %enter_loop, label %exit, label %check_1, !prof !1
+
+check_1:
+  %v = load i32, i32* %p
+  %cond1 = icmp eq i32 %v, 1
+  br i1 %cond1, label %eq_1, label %check_2
+; No metadata:
+; CHECK:   br i1 %cond1, label %check_2.thread, label %check_2{{$}}
+
+eq_1:
+  call void @bar()
+  br label %check_2
+; Verify the new edge:
+; CHECK: check_2.thread:
+; CHECK-NEXT: call void @bar()
+; CHECK-NEXT: br label %latch
+
+check_2:
+  %cond2 = icmp eq i32 %v, 2
+  br i1 %cond2, label %eq_2, label %check_3
+; No metadata:
+; CHECK: br i1 %cond2, label %eq_2, label %check_3{{$}}
+
+eq_2:
+  call void @bar()
+  br label %check_3
+; Verify the new edge:
+; CHECK: eq_2:
+; CHECK-NEXT: call void @bar()
+; CHECK-NEXT: br label %latch
+
+check_3:
+  %condE = icmp eq i32 %v, 3
+  br i1 %condE, label %exit, label %latch
+; No metadata:
+; CHECK: br i1 %condE, label %exit, label %latch{{$}}
+
+latch:
+  br label %check_1
+
+exit:
+  ret void
+}
+
+!0 = !{!"function_entry_count", i64 120}
+; CHECK-NOT: branch_weights
+!1 = !{!"branch_weights", i32 119, i32 1}
+; CHECK: !1 = !{!"branch_weights", i32 119, i32 1}
+; CHECK-NOT: branch_weights

Added: llvm/trunk/test/Transforms/JumpThreading/thread-cmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/thread-cmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/thread-cmp.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/thread-cmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,69 @@
+; RUN: opt -S -jump-threading %s | FileCheck %s
+; When simplify a branch based on LVI predicates, we should replace the 
+; comparison itself with a constant (when possible) in case it's otherwise used.
+
+define i32 @test(i32* %p) {
+; CHECK-LABEL: @test
+; CHECK: icmp eq
+; CHECK-NEXT: br i1 %cmp, label %exit2, label %exit1
+; CHECK-NOT: icmp ne
+entry:
+  %cmp = icmp eq i32* %p, null
+  br i1 %cmp, label %is_null, label %not_null
+is_null:
+  %cmp2 = icmp ne i32* %p, null
+  br i1 %cmp2, label %exit1, label %exit2
+not_null:
+  %cmp3 = icmp ne i32* %p, null
+  br i1 %cmp3, label %exit1, label %exit2
+exit1:
+  ret i32 0
+exit2:
+  ret i32 1
+}
+
+declare void @use(i1)
+
+; It would not be legal to replace %cmp2 (well, in this case it actually is, 
+; but that's a CSE problem, not a LVI/jump threading problem)
+define i32 @test_negative(i32* %p) {
+; CHECK-LABEL: @test
+; CHECK: icmp ne
+; CHECK: icmp eq
+; CHECK-NEXT: br i1 %cmp, label %exit2, label %exit1
+; CHECK-NOT: icmp ne
+entry:
+  %cmp2 = icmp ne i32* %p, null
+  call void @use(i1 %cmp2)
+  %cmp = icmp eq i32* %p, null
+  br i1 %cmp, label %is_null, label %not_null
+is_null:
+  br i1 %cmp2, label %exit1, label %exit2
+not_null:
+  br i1 %cmp2, label %exit1, label %exit2
+exit1:
+  ret i32 0
+exit2:
+  ret i32 1
+}
+
+; In this case, we can remove cmp2 because it's otherwise unused
+define i32 @test2(i32* %p) {
+; CHECK-LABEL: @test
+; CHECK-LABEL: entry:
+; CHECK-NEXT: icmp eq
+; CHECK-NEXT: br i1 %cmp, label %exit2, label %exit1
+; CHECK-NOT: icmp ne
+entry:
+  %cmp2 = icmp ne i32* %p, null
+  %cmp = icmp eq i32* %p, null
+  br i1 %cmp, label %is_null, label %not_null
+is_null:
+  br i1 %cmp2, label %exit1, label %exit2
+not_null:
+  br i1 %cmp2, label %exit1, label %exit2
+exit1:
+  ret i32 0
+exit2:
+  ret i32 1
+}

Added: llvm/trunk/test/Transforms/JumpThreading/thread-loads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/thread-loads.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/thread-loads.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/thread-loads.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,542 @@
+; RUN: opt < %s -jump-threading -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=jump-threading -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+
+; Test that we can thread through the block with the partially redundant load (%2).
+; rdar://6402033
+define i32 @test1(i32* %P) nounwind {
+; CHECK-LABEL: @test1(
+entry:
+	%0 = tail call i32 (...) @f1() nounwind		; <i32> [#uses=1]
+	%1 = icmp eq i32 %0, 0		; <i1> [#uses=1]
+	br i1 %1, label %bb1, label %bb
+
+bb:		; preds = %entry
+; CHECK: bb1.thread:
+; CHECK: store
+; CHECK: br label %bb3
+	store i32 42, i32* %P, align 4
+	br label %bb1
+
+bb1:		; preds = %entry, %bb
+	%res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]		; <i32> [#uses=2]
+	%2 = load i32, i32* %P, align 4		; <i32> [#uses=1]
+	%3 = icmp sgt i32 %2, 36		; <i1> [#uses=1]
+	br i1 %3, label %bb3, label %bb2
+
+bb2:		; preds = %bb1
+	%4 = tail call i32 (...) @f2() nounwind		; <i32> [#uses=0]
+	ret i32 %res.0
+
+bb3:		; preds = %bb1
+; CHECK: bb3:
+; CHECK: %res.01 = phi i32 [ 1, %bb1.thread ], [ 0, %bb1 ]
+; CHECK: ret i32 %res.01
+	ret i32 %res.0
+}
+
+declare i32 @f1(...)
+
+declare i32 @f2(...)
+
+
+;; Check that we preserve TBAA information.
+; rdar://11039258
+
+define i32 @test2(i32* %P) nounwind {
+; CHECK-LABEL: @test2(
+entry:
+	%0 = tail call i32 (...) @f1() nounwind		; <i32> [#uses=1]
+	%1 = icmp eq i32 %0, 0		; <i1> [#uses=1]
+	br i1 %1, label %bb1, label %bb
+
+bb:		; preds = %entry
+; CHECK: bb1.thread:
+; CHECK: store{{.*}}, !tbaa !0
+; CHECK: br label %bb3
+	store i32 42, i32* %P, align 4, !tbaa !0
+	br label %bb1
+
+bb1:		; preds = %entry, %bb
+	%res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]
+	%2 = load i32, i32* %P, align 4, !tbaa !0
+	%3 = icmp sgt i32 %2, 36
+	br i1 %3, label %bb3, label %bb2
+
+bb2:		; preds = %bb1
+	%4 = tail call i32 (...) @f2() nounwind
+	ret i32 %res.0
+
+bb3:		; preds = %bb1
+; CHECK: bb3:
+; CHECK: %res.01 = phi i32 [ 1, %bb1.thread ], [ 0, %bb1 ]
+; CHECK: ret i32 %res.01
+	ret i32 %res.0
+}
+
+define i32 @test3(i8** %x, i1 %f) {
+; Correctly thread loads of different (but compatible) types, placing bitcasts
+; as necessary in the predecessors. This is especially tricky because the same
+; predecessor ends up with two entries in the PHI node and they must share
+; a single cast.
+; CHECK-LABEL: @test3(
+entry:
+  %0 = bitcast i8** %x to i32**
+  %1 = load i32*, i32** %0, align 8
+  br i1 %f, label %if.end57, label %if.then56
+; CHECK: %[[LOAD:.*]] = load i32*, i32**
+; CHECK: %[[CAST:.*]] = bitcast i32* %[[LOAD]] to i8*
+
+if.then56:
+  br label %if.end57
+
+if.end57:
+  %2 = load i8*, i8** %x, align 8
+  %tobool59 = icmp eq i8* %2, null
+  br i1 %tobool59, label %return, label %if.then60
+; CHECK: %[[PHI:.*]] = phi i8* [ %[[CAST]], %[[PRED:[^ ]+]] ], [ %[[CAST]], %[[PRED]] ]
+; CHECK-NEXT: %[[CMP:.*]] = icmp eq i8* %[[PHI]], null
+; CHECK-NEXT: br i1 %[[CMP]]
+
+if.then60:
+  ret i32 42
+
+return:
+  ret i32 13
+}
+
+define i32 @test4(i32* %P) {
+; CHECK-LABEL: @test4(
+entry:
+  %v0 = tail call i32 (...) @f1()
+  %v1 = icmp eq i32 %v0, 0
+  br i1 %v1, label %bb1, label %bb
+
+bb:
+; CHECK: bb1.thread:
+; CHECK: store atomic
+; CHECK: br label %bb3
+  store atomic i32 42, i32* %P unordered, align 4
+  br label %bb1
+
+bb1:
+; CHECK: bb1:
+; CHECK-NOT: phi
+; CHECK: load atomic
+  %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]
+  %v2 = load atomic i32, i32* %P unordered, align 4
+  %v3 = icmp sgt i32 %v2, 36
+  br i1 %v3, label %bb3, label %bb2
+
+bb2:
+  %v4 = tail call i32 (...) @f2()
+  ret i32 %res.0
+
+bb3:
+  ret i32 %res.0
+}
+
+define i32 @test5(i32* %P) {
+; Negative test
+
+; CHECK-LABEL: @test5(
+entry:
+  %v0 = tail call i32 (...) @f1()
+  %v1 = icmp eq i32 %v0, 0
+  br i1 %v1, label %bb1, label %bb
+
+bb:
+; CHECK: bb:
+; CHECK-NEXT:   store atomic i32 42, i32* %P release, align 4
+; CHECK-NEXT:   br label %bb1
+  store atomic i32 42, i32* %P release, align 4
+  br label %bb1
+
+bb1:
+; CHECK: bb1:
+; CHECK-NEXT:  %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]
+; CHECK-NEXT:  %v2 = load atomic i32, i32* %P acquire, align 4
+; CHECK-NEXT:  %v3 = icmp sgt i32 %v2, 36
+; CHECK-NEXT:  br i1 %v3, label %bb3, label %bb2
+
+  %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]
+  %v2 = load atomic i32, i32* %P acquire, align 4
+  %v3 = icmp sgt i32 %v2, 36
+  br i1 %v3, label %bb3, label %bb2
+
+bb2:
+  %v4 = tail call i32 (...) @f2()
+  ret i32 %res.0
+
+bb3:
+  ret i32 %res.0
+}
+
+define i32 @test6(i32* %P) {
+; Negative test
+
+; CHECK-LABEL: @test6(
+entry:
+  %v0 = tail call i32 (...) @f1()
+  %v1 = icmp eq i32 %v0, 0
+  br i1 %v1, label %bb1, label %bb
+
+bb:
+; CHECK: bb:
+; CHECK-NEXT:   store i32 42, i32* %P
+; CHECK-NEXT:   br label %bb1
+  store i32 42, i32* %P
+  br label %bb1
+
+bb1:
+; CHECK: bb1:
+; CHECK-NEXT:  %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]
+; CHECK-NEXT:  %v2 = load atomic i32, i32* %P acquire, align 4
+; CHECK-NEXT:  %v3 = icmp sgt i32 %v2, 36
+; CHECK-NEXT:  br i1 %v3, label %bb3, label %bb2
+
+  %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]
+  %v2 = load atomic i32, i32* %P acquire, align 4
+  %v3 = icmp sgt i32 %v2, 36
+  br i1 %v3, label %bb3, label %bb2
+
+bb2:
+  %v4 = tail call i32 (...) @f2()
+  ret i32 %res.0
+
+bb3:
+  ret i32 %res.0
+}
+
+define i32 @test7(i32* %P) {
+; Negative test
+
+; CHECK-LABEL: @test7(
+entry:
+  %v0 = tail call i32 (...) @f1()
+  %v1 = icmp eq i32 %v0, 0
+  br i1 %v1, label %bb1, label %bb
+
+bb:
+; CHECK: bb:
+; CHECK-NEXT:   %val = load i32, i32* %P
+; CHECK-NEXT:   br label %bb1
+  %val = load i32, i32* %P
+  br label %bb1
+
+bb1:
+; CHECK: bb1:
+; CHECK-NEXT:  %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]
+; CHECK-NEXT:  %v2 = load atomic i32, i32* %P acquire, align 4
+; CHECK-NEXT:  %v3 = icmp sgt i32 %v2, 36
+; CHECK-NEXT:  br i1 %v3, label %bb3, label %bb2
+
+  %res.0 = phi i32 [ 1, %bb ], [ 0, %entry ]
+  %v2 = load atomic i32, i32* %P acquire, align 4
+  %v3 = icmp sgt i32 %v2, 36
+  br i1 %v3, label %bb3, label %bb2
+
+bb2:
+  %v4 = tail call i32 (...) @f2()
+  ret i32 %res.0
+
+bb3:
+  ret i32 %res.0
+}
+
+; Make sure we merge the aliasing metadata. We keep the range metadata for the
+; first load, as it dominates the second load. Hence we can eliminate the
+; branch.
+define void @test8(i32*, i32*, i32*) {
+; CHECK-LABEL: @test8(
+; CHECK: %a = load i32, i32* %0, !range ![[RANGE4:[0-9]+]]
+; CHECK-NEXT: store i32 %a
+; CHECK-NEXT: %xxx = tail call i32 (...) @f1()
+; CHECK-NEXT: ret void
+  %a = load i32, i32* %0, !tbaa !0, !range !4, !alias.scope !9, !noalias !10
+  %b = load i32, i32* %0, !range !5
+  store i32 %a, i32* %1
+  %c = icmp eq i32 %b, 8
+  br i1 %c, label %ret1, label %ret2
+
+ret1:
+  ret void
+
+ret2:
+  %xxx = tail call i32 (...) @f1() nounwind
+  ret void
+}
+
+; Make sure we merge/PRE aliasing metadata correctly.  That means that
+; we need to remove metadata from the existing load, and add appropriate
+; metadata to the newly inserted load.
+define void @test9(i32*, i32*, i32*, i1 %c) {
+; CHECK-LABEL: @test9(
+  br i1 %c, label %d1, label %d2
+
+; CHECK: d1:
+; CHECK-NEXT: %a = load i32, i32* %0{{$}}
+d1:
+  %a = load i32, i32* %0, !range !4, !alias.scope !9, !noalias !10
+  br label %d3
+
+; CHECK: d2:
+; CHECK-NEXT: %xxxx = tail call i32 (...) @f1()
+; CHECK-NEXT: %b.pr = load i32, i32* %0, !tbaa !0{{$}}
+d2:
+  %xxxx = tail call i32 (...) @f1() nounwind
+  br label %d3
+
+d3:
+  %p = phi i32 [ 1, %d2 ], [ %a, %d1 ]
+  %b = load i32, i32* %0, !tbaa !0
+  store i32 %p, i32* %1
+  %c2 = icmp eq i32 %b, 8
+  br i1 %c2, label %ret1, label %ret2
+
+ret1:
+  ret void
+
+ret2:
+  %xxx = tail call i32 (...) @f1() nounwind
+  ret void
+}
+
+define i32 @fn_noalias(i1 %c2,i64* noalias %P, i64* noalias %P2) {
+; CHECK-LABEL: @fn_noalias
+; CHECK-LABEL: cond1:
+; CHECK: %[[LD1:.*]] = load i64, i64* %P
+; CHECK: br i1 %c, label %[[THREAD:.*]], label %end
+; CHECK-LABEL: cond2:
+; CHECK: %[[LD2:.*]] = load i64, i64* %P
+; CHECK-LABEL: cond3:
+; CHECK: %[[PHI:.*]] = phi i64 [ %[[LD1]], %[[THREAD]] ], [ %[[LD2]], %cond2 ]
+; CHECK: call void @fn3(i64 %[[PHI]])
+entry:
+  br i1 %c2, label %cond2, label %cond1
+
+cond1:
+  %l1 = load i64, i64* %P
+  store i64 42, i64* %P2
+  %c = icmp eq i64 %l1, 0
+  br i1 %c, label %cond2, label %end
+
+cond2:
+  %l2 = load i64, i64* %P
+  call void @fn2(i64 %l2)
+  %c3 = icmp eq i64 %l2,  0
+  br i1 %c3, label %cond3, label %end
+
+cond3:
+  call void @fn3(i64 %l2)
+  br label %end
+
+end:
+  ret i32 0
+}
+
+; This tests if we can thread from %sw.bb.i to %do.body.preheader.i67 through
+; %sw.bb21.i. To make this happen, %l2 should be detected as a partically
+; redundant load with %l3 across the store to %phase in %sw.bb21.i.
+
+%struct.NEXT_MOVE = type { i32, i32, i32* }
+ at hash_move = unnamed_addr global [65 x i32] zeroinitializer, align 4
+ at current_move = internal global [65 x i32] zeroinitializer, align 4
+ at last = internal unnamed_addr global [65 x i32*] zeroinitializer, align 8
+ at next_status = internal unnamed_addr global [65 x %struct.NEXT_MOVE] zeroinitializer, align 8
+define fastcc i32 @Search(i64 %idxprom.i, i64 %idxprom.i89, i32 %c) {
+; CHECK-LABEL: @Search
+; CHECK-LABEL: sw.bb.i:
+; CHECK: %[[LD1:.*]] = load i32, i32* %arrayidx185, align 4
+; CHECK: %[[C1:.*]] = icmp eq i32 %[[LD1]], 0
+; CHECK: br i1 %[[C1]], label %sw.bb21.i.thread, label %if.then.i64
+; CHECK-LABEL: sw.bb21.i.thread:
+; CHECK: br label %[[THREAD_TO:.*]]
+; CHECK-LABEL: sw.bb21.i:
+; CHECK: %[[LD2:.*]] = load i32, i32* %arrayidx185, align 4
+; CHECK: %[[C2:.*]] = icmp eq i32 %[[LD2]], 0
+; CHECK:br i1 %[[C2]], label %[[THREAD_TO]], label %cleanup
+entry:
+  %arrayidx185 = getelementptr inbounds [65 x i32], [65 x i32]* @hash_move, i64 0, i64 %idxprom.i
+  %arrayidx307 = getelementptr inbounds [65 x i32], [65 x i32]* @current_move, i64 0, i64 %idxprom.i
+  %arrayidx89 = getelementptr inbounds [65 x i32*], [65 x i32*]* @last, i64 0, i64 %idxprom.i
+  %phase = getelementptr inbounds [65 x %struct.NEXT_MOVE], [65 x %struct.NEXT_MOVE]* @next_status, i64 0, i64 %idxprom.i, i32 0
+  br label %cond.true282
+
+cond.true282:
+  switch i32 %c, label %sw.default.i [
+    i32 1, label %sw.bb.i
+    i32 0, label %sw.bb21.i
+  ]
+
+sw.default.i:
+  br label %cleanup
+
+sw.bb.i:
+  %call.i62 = call fastcc i32* @GenerateCheckEvasions()
+  store i32* %call.i62, i32** %arrayidx89, align 8
+  %l2 = load i32, i32* %arrayidx185, align 4
+  %tobool.i63 = icmp eq i32 %l2, 0
+  br i1 %tobool.i63, label %sw.bb21.i, label %if.then.i64
+
+if.then.i64:                                      ; preds = %sw.bb.i
+  store i32 7, i32* %phase, align 8
+  store i32 %l2, i32* %arrayidx307, align 4
+  %call16.i = call fastcc i32 @ValidMove(i32 %l2)
+  %tobool17.i = icmp eq i32 %call16.i, 0
+  br i1 %tobool17.i, label %if.else.i65, label %cleanup
+
+if.else.i65:
+  call void @f65()
+  br label %sw.bb21.i
+
+sw.bb21.i:
+  store i32 10, i32* %phase, align 8
+  %l3= load i32, i32* %arrayidx185, align 4
+  %tobool27.i = icmp eq i32 %l3, 0
+  br i1 %tobool27.i, label %do.body.preheader.i67, label %cleanup
+
+do.body.preheader.i67:
+  call void @f67()
+  ret  i32 67
+
+cleanup:
+  call void @Cleanup()
+  ret  i32 0
+}
+
+declare fastcc i32* @GenerateCheckEvasions()
+declare fastcc i32 @ValidMove(i32 %move)
+declare void @f67()
+declare void @Cleanup()
+declare void @f65()
+
+define i32 @fn_SinglePred(i1 %c2,i64* %P) {
+; CHECK-LABEL: @fn_SinglePred
+; CHECK-LABEL: entry:
+; CHECK: %[[L1:.*]] = load i64, i64* %P
+; CHECK: br i1 %c, label %cond3, label %cond1
+; CHECK-LABEL: cond2:
+; CHECK-NOT: load
+; CHECK: %[[PHI:.*]] = phi i64 [ %[[L1]], %cond1 ]
+; CHECK: call void @fn2(i64 %[[PHI]])
+; CHECK: br label %end
+; CHECK-LABEL: cond3:
+; CHECK: call void @fn2(i64 %l1)
+; CHECK: call void @fn3(i64 %l1)
+
+entry:
+  %l1 = load i64, i64* %P
+  %c = icmp eq i64 %l1, 0
+  br i1 %c, label %cond2, label %cond1
+
+cond1:
+  br i1 %c2, label %cond2, label %end
+
+cond2:
+  %l2 = load i64, i64* %P
+  call void @fn2(i64 %l2)
+  %c3 = icmp eq i64 %l2,  0
+  br i1 %c3, label %cond3, label %end
+
+cond3:
+  call void @fn3(i64 %l2)
+  br label %end
+
+end:
+  ret i32 0
+}
+
+define i32 @fn_SinglePredMultihop(i1 %c1, i1 %c2,i64* %P) {
+; CHECK-LABEL: @fn_SinglePredMultihop
+; CHECK-LABEL: entry:
+; CHECK: %[[L1:.*]] = load i64, i64* %P
+; CHECK: br i1 %c0, label %cond3, label %cond0
+; CHECK-LABEL: cond2:
+; CHECK-NOT: load
+; CHECK: %[[PHI:.*]] = phi i64 [ %[[L1]], %cond1 ]
+; CHECK: call void @fn2(i64 %[[PHI]])
+; CHECK: br label %end
+; CHECK-LABEL: cond3:
+; CHECK: call void @fn2(i64 %l1)
+; CHECK: call void @fn3(i64 %l1)
+
+entry:
+  %l1 = load i64, i64* %P
+  %c0 = icmp eq i64 %l1, 0
+  br i1 %c0, label %cond2, label %cond0
+
+cond0:
+  br i1 %c1, label %cond1, label %end
+
+cond1:
+  br i1 %c2, label %cond2, label %end
+
+cond2:
+  %l2 = load i64, i64* %P
+  call void @fn2(i64 %l2)
+  %c3 = icmp eq i64 %l2,  0
+  br i1 %c3, label %cond3, label %end
+
+cond3:
+  call void @fn3(i64 %l2)
+  br label %end
+
+end:
+  ret i32 0
+}
+
+declare void @fn2(i64)
+declare void @fn3(i64)
+
+
+; Make sure we phi-translate and make the partially redundant load in
+; merge fully redudant and then we can jump-thread the block with the
+; store.
+;
+; CHECK-LABEL: define i32 @phi_translate_partial_redundant_loads(i32, i32*, i32*
+; CHECK: merge.thread:
+; CHECK: store
+; CHECK: br label %left_x
+;
+; CHECK: left_x:
+; CHECK-NEXT: ret i32 20
+define i32 @phi_translate_partial_redundant_loads(i32, i32*, i32*)  {
+  %cmp0 = icmp ne i32 %0, 0
+  br i1 %cmp0, label %left, label %right
+
+left:
+  store i32 1, i32* %1, align 4
+  br label %merge
+
+right:
+  br label %merge
+
+merge:
+  %phiptr = phi i32* [ %1, %left ], [ %2, %right ]
+  %newload = load i32, i32* %phiptr, align 4
+  %cmp1 = icmp slt i32 %newload, 5
+  br i1 %cmp1, label %left_x, label %right_x
+
+left_x:
+  ret i32 20
+
+right_x:
+  ret i32 10
+}
+
+; CHECK: ![[RANGE4]] = !{i32 0, i32 1}
+
+!0 = !{!3, !3, i64 0}
+!1 = !{!"omnipotent char", !2}
+!2 = !{!"Simple C/C++ TBAA"}
+!3 = !{!"int", !1}
+!4 = !{ i32 0, i32 1 }
+!5 = !{ i32 8, i32 10 }
+!6 = !{!6}
+!7 = !{!7, !6}
+!8 = !{!8, !6}
+!9 = !{!7}
+!10 = !{!8}




More information about the llvm-commits mailing list