llvm/llvm/test/Transforms/BDCE/binops-multiuse.ll

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

define void @or(i64 %a) {
; CHECK-LABEL: define void @or(
; CHECK-SAME: i64 [[A:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[A]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[A]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %or = or i64 %a, 3                              ; Mask:          0000 0011
  %ret1 = and i64 %or, 8                          ; Demanded bits: 0000 1000
  %ret2 = and i64 %or, 16                         ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @xor(i64 %a) {
; CHECK-LABEL: define void @xor(
; CHECK-SAME: i64 [[A:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[A]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[A]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %xor = xor i64 %a, 3                            ; Mask:          0000 0011
  %ret1 = and i64 %xor, 8                         ; Demanded bits: 0000 1000
  %ret2 = and i64 %xor, 16                        ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @and(i64 %a) {
; CHECK-LABEL: define void @and(
; CHECK-SAME: i64 [[A:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[A]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[A]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %and = and i64 %a, 24                           ; Mask:          0001 1000
  %ret1 = and i64 %and, 8                         ; Demanded bits: 0000 1000
  %ret2 = and i64 %and, 16                        ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @or_of_and(i64 %a, i64 %b) {
; CHECK-LABEL: define void @or_of_and(
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[OR:%.*]] = or i64 [[A]], [[B]]
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[OR]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[OR]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %and1 = and i64 %a, 24                          ; Mask:          0001 1000
  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
  %or = or i64 %and1, %and2
  %ret1 = and i64 %or, 8                          ; Demanded bits: 0000 1000
  %ret2 = and i64 %or, 16                         ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @or_disjoint_of_and(i64 %a, i64 %b) {
; CHECK-LABEL: define void @or_disjoint_of_and(
; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[OR:%.*]] = or i64 [[A]], [[B]]
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[OR]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[OR]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %and1 = and i64 %a, 56                          ; Mask:          0011 1000
  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
  %or = or disjoint i64 %and1, %and2
  %ret1 = and i64 %or, 8                          ; Demanded bits: 0000 1000
  %ret2 = and i64 %or, 16                         ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @select_of_and(i1 %c, i64 %a, i64 %b) {
; CHECK-LABEL: define void @select_of_and(
; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[B]]
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %and1 = and i64 %a, 24                          ; Mask:          0001 1000
  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
  %s = select i1 %c, i64 %and1, i64 %and2
  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @select_of_and_2(i1 %c, i64 %a, i64 %b) {
; CHECK-LABEL: define void @select_of_and_2(
; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[B]], 23
; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[AND2]]
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %and1 = and i64 %a, 25                          ; Mask:          0001 1001
  %and2 = and i64 %b, 23                          ; Mask:          0001 0111
  %s = select i1 %c, i64 %and1, i64 %and2
  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @select_of_and_multiuse(i1 %c, i64 %a, i64 %b) {
; CHECK-LABEL: define void @select_of_and_multiuse(
; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[B]], 25
; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[AND2]]
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use2(i64 [[RET2]], i64 [[AND2]])
; CHECK-NEXT:    ret void
;
entry:
  %and1 = and i64 %a, 24                          ; Mask:          0001 1000
  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
  %s = select i1 %c, i64 %and1, i64 %and2
  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use2(i64 %ret2, i64 %and2)
  ret void
}

define void @select_of_and_different_demanded(i1 %c, i64 %a, i64 %b) {
; CHECK-LABEL: define void @select_of_and_different_demanded(
; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[AND1:%.*]] = and i64 0, 24
; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[B]], 25
; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[AND1]], i64 [[AND2]]
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 3
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 7
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %and1 = and i64 %a, 24                          ; Mask:          0001 1000
  %and2 = and i64 %b, 25                          ; Mask:          0001 1001
  %s = select i1 %c, i64 %and1, i64 %and2
  %ret1 = and i64 %s, 3                           ; Demanded bits: 0000 0011
  %ret2 = and i64 %s, 7                           ; Demanded bits: 0000 0111
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @select_of_or(i1 %c, i64 %a, i64 %b) {
; CHECK-LABEL: define void @select_of_or(
; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[B]]
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %or1 = or i64 %a, 3                             ; Mask:          0000 0011
  %or2 = or i64 %b, 192                           ; Mask:          1100 0000
  %s = select i1 %c, i64 %or1, i64 %or2
  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @select_of_xor(i1 %c, i64 %a, i64 %b) {
; CHECK-LABEL: define void @select_of_xor(
; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[B]]
; CHECK-NEXT:    [[RET1:%.*]] = and i64 [[S]], 8
; CHECK-NEXT:    [[RET2:%.*]] = and i64 [[S]], 16
; CHECK-NEXT:    call void @use(i64 [[RET1]])
; CHECK-NEXT:    call void @use(i64 [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %xor1 = xor i64 %a, 128                         ; Mask:          1000 0000
  %xor2 = xor i64 %b, 36                          ; Mask:          0010 0100
  %s = select i1 %c, i64 %xor1, i64 %xor2
  %ret1 = and i64 %s, 8                           ; Demanded bits: 0000 1000
  %ret2 = and i64 %s, 16                          ; Demanded bits: 0001 0000
  call void @use(i64 %ret1)
  call void @use(i64 %ret2)
  ret void
}

define void @select_vectorized(i1 %c, <2 x i8> %a, <2 x i8> %b) {
; CHECK-LABEL: define void @select_vectorized(
; CHECK-SAME: i1 [[C:%.*]], <2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[S:%.*]] = select i1 [[C]], <2 x i8> [[A]], <2 x i8> [[B]]
; CHECK-NEXT:    [[RET1:%.*]] = and <2 x i8> [[S]], <i8 4, i8 4>
; CHECK-NEXT:    [[RET2:%.*]] = and <2 x i8> [[S]], <i8 12, i8 12>
; CHECK-NEXT:    call void @use3(<2 x i8> [[RET1]])
; CHECK-NEXT:    call void @use3(<2 x i8> [[RET2]])
; CHECK-NEXT:    ret void
;
entry:
  %and1 = and <2 x i8> %a, <i8 28, i8 28>
  %and2 = and <2 x i8> %b, <i8 29, i8 29>
  %s = select i1 %c, <2 x i8> %and1, <2 x i8> %and2
  %ret1 = and <2 x i8> %s, <i8 4, i8 4>
  %ret2 = and <2 x i8> %s, <i8 12, i8 12>
  call void @use3(<2 x i8> %ret1)
  call void @use3(<2 x i8> %ret2)
  ret void
}

declare void @use(i64)
declare void @use2(i64, i64)
declare void @use3(<2 x i8>)