llvm/llvm/test/Transforms/InstSimplify/select_or_and.ll

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=instsimplify < %s | FileCheck %s

; select(Y | X == 0, X, Y | X)
define i32 @select_or_1(i32 %x, i32 %y) {
; CHECK-LABEL: @select_or_1(
; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i32 [[OR]]
;
  %or = or i32 %y, %x
  %cmp = icmp eq i32 %or, 0
  %ret = select i1 %cmp, i32 %x, i32 %or
  ret i32 %ret
}

; select(Y | X == 0, Y, Y | X)
define i32 @select_or_2(i32 %x, i32 %y) {
; CHECK-LABEL: @select_or_2(
; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i32 [[OR]]
;
  %or = or i32 %y, %x
  %cmp = icmp eq i32 %or, 0
  %ret = select i1 %cmp, i32 %y, i32 %or
  ret i32 %ret
}

; select(Y | X != 0, Y | X, X)
define i32 @select_or_3(i32 %x, i32 %y) {
; CHECK-LABEL: @select_or_3(
; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i32 [[OR]]
;
  %or = or i32 %y, %x
  %cmp = icmp ne i32 %or, 0
  %ret = select i1 %cmp, i32 %or, i32 %x
  ret i32 %ret
}

; select(Y | X != 0, Y | X, Y)
define i32 @select_or_4(i32 %x, i32 %y) {
; CHECK-LABEL: @select_or_4(
; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i32 [[OR]]
;
  %or = or i32 %y, %x
  %cmp = icmp ne i32 %or, 0
  %ret = select i1 %cmp, i32 %or, i32 %y
  ret i32 %ret
}

; select(Y | X != 0, Y | X, Y)
define <4 x i32> @select_or_vec(<4 x i32> %x, <4 x i32> %y) {
; CHECK-LABEL: @select_or_vec(
; CHECK-NEXT:    [[OR:%.*]] = or <4 x i32> [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret <4 x i32> [[OR]]
;
  %or = or <4 x i32> %y, %x
  %cmp = icmp ne <4 x i32> %or, zeroinitializer
  %ret = select <4 x i1> %cmp, <4 x i32> %or, <4 x i32> %y
  ret <4 x i32> %ret
}

; select(Y | X == 0, Y | X, Y)
define i32 @select_or_not_1(i32 %x, i32 %y) {
; CHECK-LABEL: @select_or_not_1(
; CHECK-NEXT:    ret i32 [[Y:%.*]]
;
  %or = or i32 %y, %x
  %cmp = icmp eq i32 %or, 0
  %ret = select i1 %cmp, i32 %or, i32 %y
  ret i32 %ret
}
; select(Y | X != 0, Y, Y | X)
define i32 @select_or_not_2(i32 %x, i32 %y) {
; CHECK-LABEL: @select_or_not_2(
; CHECK-NEXT:    ret i32 [[Y:%.*]]
;
  %or = or i32 %y, %x
  %cmp = icmp ne i32 %or, 0
  %ret = select i1 %cmp, i32 %y, i32 %or
  ret i32 %ret
}
; select(Y | X != 1, Y, Y | X)
define i32 @select_or_not_3(i32 %x, i32 %y) {
; CHECK-LABEL: @select_or_not_3(
; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[OR]], 1
; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[OR]]
; CHECK-NEXT:    ret i32 [[RET]]
;
  %or = or i32 %y, %x
  %cmp = icmp ne i32 %or, 1
  %ret = select i1 %cmp, i32 %y, i32 %or
  ret i32 %ret
}

; select(Y & X == -1, X, Y & X)
define i32 @select_and_1(i32 %x, i32 %y) {
; CHECK-LABEL: @select_and_1(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i32 [[AND]]
;
  %and = and i32 %y, %x
  %cmp = icmp eq i32 %and, -1
  %ret = select i1 %cmp, i32 %x, i32 %and
  ret i32 %ret
}

; select(Y & X == -1, Y, Y & X)
define i32 @select_and_2(i32 %x, i32 %y) {
; CHECK-LABEL: @select_and_2(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i32 [[AND]]
;
  %and = and i32 %y, %x
  %cmp = icmp eq i32 %and, -1
  %ret = select i1 %cmp, i32 %y, i32 %and
  ret i32 %ret
}


; select(Y & X != -1, Y & X, X)
define i32 @select_and_3(i32 %x, i32 %y) {
; CHECK-LABEL: @select_and_3(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i32 [[AND]]
;
  %and = and i32 %y, %x
  %cmp = icmp ne i32 %and, -1
  %ret = select i1 %cmp, i32 %and, i32 %x
  ret i32 %ret
}

; select(Y & X != -1, Y & X, Y)
define i32 @select_and_4(i32 %x, i32 %y) {
; CHECK-LABEL: @select_and_4(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i32 [[AND]]
;
  %and = and i32 %y, %x
  %cmp = icmp ne i32 %and, -1
  %ret = select i1 %cmp, i32 %and, i32 %y
  ret i32 %ret
}

; select(Y & X != -1, Y, Y & X)
define i32 @select_and_not_1(i32 %x, i32 %y) {
; CHECK-LABEL: @select_and_not_1(
; CHECK-NEXT:    ret i32 [[Y:%.*]]
;
  %and = and i32 %y, %x
  %cmp = icmp eq i32 %and, -1
  %ret = select i1 %cmp, i32 %and, i32 %y
  ret i32 %ret
}

; select(Y & X != -1, Y, Y & X)
define i32 @select_and_not_2(i32 %x, i32 %y) {
; CHECK-LABEL: @select_and_not_2(
; CHECK-NEXT:    ret i32 [[Y:%.*]]
;
  %and = and i32 %y, %x
  %cmp = icmp ne i32 %and, -1
  %ret = select i1 %cmp, i32 %y, i32 %and
  ret i32 %ret
}

; select(Y & X != 123, Y, Y & X)
define i32 @select_and_not_3(i32 %x, i32 %y) {
; CHECK-LABEL: @select_and_not_3(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[AND]], 123
; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[AND]]
; CHECK-NEXT:    ret i32 [[RET]]
;
  %and = and i32 %y, %x
  %cmp = icmp ne i32 %and, 123
  %ret = select i1 %cmp, i32 %y, i32 %and
  ret i32 %ret
}

; https://alive2.llvm.org/ce/z/1ILbih
define i32 @select_icmp_and_eq(i32 %a, i32 %b) {
; CHECK-LABEL: @select_icmp_and_eq(
; CHECK-NEXT:    ret i32 -1
;
  %and = and i32 %a, %b
  %tobool = icmp eq i32 %and, -1
  %cond = select i1 %tobool, i32 %a, i32 -1
  ret i32 %cond
}

define i32 @select_icmp_and_eq_commuted(i32 %a, i32 %b) {
; CHECK-LABEL: @select_icmp_and_eq_commuted(
; CHECK-NEXT:    ret i32 -1
;
  %and = and i32 %a, %b
  %tobool = icmp eq i32 %and, -1
  %cond = select i1 %tobool, i32 %b, i32 -1
  ret i32 %cond
}

; https://alive2.llvm.org/ce/z/HfYXvx
define <2 x i16> @select_icmp_and_eq_vec(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: @select_icmp_and_eq_vec(
; CHECK-NEXT:    ret <2 x i16> <i16 -1, i16 -1>
;
  %and = and <2 x i16> %a, %b
  %tobool = icmp eq <2 x i16> %and, <i16 -1, i16 -1>
  %cond = select <2 x i1> %tobool, <2 x i16> %a, <2 x i16> <i16 -1, i16 -1>
  ret <2 x i16> %cond
}

; The ne should also be macthed
define i32 @select_icmp_and_ne(i32 %a, i32 %b) {
; CHECK-LABEL: @select_icmp_and_ne(
; CHECK-NEXT:    ret i32 -1
;
  %and = and i32 %a, %b
  %tobool = icmp ne i32 %and, -1
  %cond = select i1 %tobool, i32 -1, i32 %a
  ret i32 %cond
}

; Negative test: Incorrect const value for icmp
define i32 @select_icmp_and_eq_incorrect_const(i32 %a, i32 %b) {
; CHECK-LABEL: @select_icmp_and_eq_incorrect_const(
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[AND]], 0
; CHECK-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[A]], i32 -1
; CHECK-NEXT:    ret i32 [[COND]]
;
  %and = and i32 %a, %b
  %tobool = icmp eq i32 %and, 0  ; Incorrect const value
  %cond = select i1 %tobool, i32 %a, i32 -1
  ret i32 %cond
}

; https://alive2.llvm.org/ce/z/hSyCuR
define i32 @select_icmp_or_eq(i32 %a, i32 %b) {
; CHECK-LABEL: @select_icmp_or_eq(
; CHECK-NEXT:    ret i32 0
;
  %or = or i32 %a, %b
  %tobool = icmp eq i32 %or, 0
  %cond = select i1 %tobool, i32 %a, i32 0
  ret i32 %cond
}

define i32 @select_icmp_or_eq_commuted(i32 %a, i32 %b) {
; CHECK-LABEL: @select_icmp_or_eq_commuted(
; CHECK-NEXT:    ret i32 0
;
  %or = or i32 %a, %b
  %tobool = icmp eq i32 %or, 0
  %cond = select i1 %tobool, i32 %b, i32 0
  ret i32 %cond
}

; https://alive2.llvm.org/ce/z/S_pQek
define <2 x i16> @select_icmp_or_eq_vec(<2 x i16> %a, <2 x i16> %b) {
; CHECK-LABEL: @select_icmp_or_eq_vec(
; CHECK-NEXT:    ret <2 x i16> zeroinitializer
;
  %or = or <2 x i16> %a, %b
  %tobool = icmp eq <2 x i16> %or, <i16 0, i16 0>
  %cond = select <2 x i1> %tobool, <2 x i16> %a, <2 x i16> zeroinitializer
  ret <2 x i16> %cond
}

; The ne will also be matched
define i32 @select_icmp_or_ne(i32 %a, i32 %b) {
; CHECK-LABEL: @select_icmp_or_ne(
; CHECK-NEXT:    ret i32 0
;
  %or = or i32 %a, %b
  %tobool = icmp ne i32 %or, 0
  %cond = select i1 %tobool, i32 0, i32 %a
  ret i32 %cond
}

; Negative test: Incorrect const value for icmp
define i32 @select_icmp_or_eq_incorrect_const(i32 %a, i32 %b) {
; CHECK-LABEL: @select_icmp_or_eq_incorrect_const(
; CHECK-NEXT:    [[OR:%.*]] = or i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[OR]], -1
; CHECK-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[A]], i32 0
; CHECK-NEXT:    ret i32 [[COND]]
;
  %or = or i32 %a, %b
  %tobool = icmp eq i32 %or, -1
  %cond = select i1 %tobool, i32 %a, i32 0
  ret i32 %cond
}