CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
1479 lines
49 KiB
LLVM
1479 lines
49 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
|
|
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
|
|
|
|
declare void @use(i1)
|
|
declare i1 @gen_i1()
|
|
declare <2 x i1> @gen_v2i1()
|
|
|
|
; Should not be converted to "and", which has different poison semantics.
|
|
;.
|
|
; CHECK: @g1 = external global i16
|
|
; CHECK: @g2 = external global i16
|
|
;.
|
|
define i1 @logical_and(i1 %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_and(
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 %b, i1 false
|
|
ret i1 %res
|
|
}
|
|
|
|
; Should not be converted to "or", which has different poison semantics.
|
|
define i1 @logical_or(i1 %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_or(
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 true, i1 %b
|
|
ret i1 %res
|
|
}
|
|
; Canonicalize to logical and form, even if that requires adding a "not".
|
|
define i1 @logical_and_not(i1 %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_and_not(
|
|
; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 [[B:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 false, i1 %b
|
|
ret i1 %res
|
|
}
|
|
|
|
; Canonicalize to logical or form, even if that requires adding a "not".
|
|
define i1 @logical_or_not(i1 %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_or_not(
|
|
; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 true, i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 %b, i1 true
|
|
ret i1 %res
|
|
}
|
|
|
|
; These are variants where condition or !condition is used to represent true
|
|
; or false in one of the select arms. It should be canonicalized to the
|
|
; constants.
|
|
|
|
define i1 @logical_and_cond_reuse(i1 %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_and_cond_reuse(
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 %b, i1 %a
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @logical_or_cond_reuse(i1 %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_or_cond_reuse(
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 %a, i1 %b
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @logical_and_not_cond_reuse(i1 %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_and_not_cond_reuse(
|
|
; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 true, i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a.not = xor i1 %a, true
|
|
%res = select i1 %a, i1 %b, i1 %a.not
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @logical_or_not_cond_reuse(i1 %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_or_not_cond_reuse(
|
|
; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 [[B:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a.not = xor i1 %a, true
|
|
%res = select i1 %a, i1 %a.not, i1 %b
|
|
ret i1 %res
|
|
}
|
|
|
|
; Safe to convert to or due to poison implication.
|
|
define i1 @logical_or_implies(i32 %x) {
|
|
; CHECK-LABEL: @logical_or_implies(
|
|
; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[X:%.*]], 0
|
|
; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X]], 42
|
|
; CHECK-NEXT: [[RES:%.*]] = or i1 [[C1]], [[C2]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%c1 = icmp eq i32 %x, 0
|
|
%c2 = icmp eq i32 %x, 42
|
|
%res = select i1 %c1, i1 true, i1 %c2
|
|
ret i1 %res
|
|
}
|
|
|
|
; Safe to convert to or due to poison implication.
|
|
define <vscale x 2 x i1> @logical_or_implies_scalablevec(<vscale x 2 x i32> %x) {
|
|
; CHECK-LABEL: @logical_or_implies_scalablevec(
|
|
; CHECK-NEXT: [[C1:%.*]] = icmp eq <vscale x 2 x i32> [[X:%.*]], zeroinitializer
|
|
; CHECK-NEXT: [[C2:%.*]] = icmp eq <vscale x 2 x i32> [[X]], splat (i32 42)
|
|
; CHECK-NEXT: [[RES:%.*]] = or <vscale x 2 x i1> [[C1]], [[C2]]
|
|
; CHECK-NEXT: ret <vscale x 2 x i1> [[RES]]
|
|
;
|
|
%c1 = icmp eq <vscale x 2 x i32> %x, zeroinitializer
|
|
%c2 = icmp eq <vscale x 2 x i32> %x, splat (i32 42)
|
|
%res = select <vscale x 2 x i1> %c1, <vscale x 2 x i1> splat (i1 true), <vscale x 2 x i1> %c2
|
|
ret <vscale x 2 x i1> %res
|
|
}
|
|
|
|
; Will fold after conversion to or.
|
|
define i1 @logical_or_implies_folds(i32 %x) {
|
|
; CHECK-LABEL: @logical_or_implies_folds(
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%c1 = icmp slt i32 %x, 0
|
|
%c2 = icmp sge i32 %x, 0
|
|
%res = select i1 %c1, i1 true, i1 %c2
|
|
ret i1 %res
|
|
}
|
|
|
|
; Safe to convert to and due to poison implication.
|
|
define i1 @logical_and_implies(i32 %x) {
|
|
; CHECK-LABEL: @logical_and_implies(
|
|
; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[X:%.*]], 0
|
|
; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[X]], 42
|
|
; CHECK-NEXT: [[RES:%.*]] = and i1 [[C1]], [[C2]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%c1 = icmp ne i32 %x, 0
|
|
%c2 = icmp ne i32 %x, 42
|
|
%res = select i1 %c1, i1 %c2, i1 false
|
|
ret i1 %res
|
|
}
|
|
|
|
; Safe to convert to and due to poison implication.
|
|
define <vscale x 2 x i1> @logical_and_implies_scalablevec(<vscale x 2 x i32> %x) {
|
|
; CHECK-LABEL: @logical_and_implies_scalablevec(
|
|
; CHECK-NEXT: [[C1:%.*]] = icmp ne <vscale x 2 x i32> [[X:%.*]], zeroinitializer
|
|
; CHECK-NEXT: [[C2:%.*]] = icmp ne <vscale x 2 x i32> [[X]], splat (i32 42)
|
|
; CHECK-NEXT: [[RES:%.*]] = and <vscale x 2 x i1> [[C1]], [[C2]]
|
|
; CHECK-NEXT: ret <vscale x 2 x i1> [[RES]]
|
|
;
|
|
%c1 = icmp ne <vscale x 2 x i32> %x, zeroinitializer
|
|
%c2 = icmp ne <vscale x 2 x i32> %x, splat (i32 42)
|
|
%res = select <vscale x 2 x i1> %c1, <vscale x 2 x i1> %c2, <vscale x 2 x i1> zeroinitializer
|
|
ret <vscale x 2 x i1> %res
|
|
}
|
|
|
|
; Will fold after conversion to and.
|
|
define i1 @logical_and_implies_folds(i32 %x) {
|
|
; CHECK-LABEL: @logical_and_implies_folds(
|
|
; CHECK-NEXT: [[C1:%.*]] = icmp ugt i32 [[X:%.*]], 42
|
|
; CHECK-NEXT: ret i1 [[C1]]
|
|
;
|
|
%c1 = icmp ugt i32 %x, 42
|
|
%c2 = icmp ne i32 %x, 0
|
|
%res = select i1 %c1, i1 %c2, i1 false
|
|
ret i1 %res
|
|
}
|
|
|
|
; Noundef on condition has no effect.
|
|
define i1 @logical_or_noundef_a(i1 noundef %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_or_noundef_a(
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 true, i1 %b
|
|
ret i1 %res
|
|
}
|
|
|
|
; Noundef on false value allows conversion to or.
|
|
define i1 @logical_or_noundef_b(i1 %a, i1 noundef %b) {
|
|
; CHECK-LABEL: @logical_or_noundef_b(
|
|
; CHECK-NEXT: [[RES:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 true, i1 %b
|
|
ret i1 %res
|
|
}
|
|
|
|
; Noundef on condition has no effect.
|
|
define i1 @logical_and_noundef_a(i1 noundef %a, i1 %b) {
|
|
; CHECK-LABEL: @logical_and_noundef_a(
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 %b, i1 false
|
|
ret i1 %res
|
|
}
|
|
|
|
; Noundef on false value allows conversion to and.
|
|
define i1 @logical_and_noundef_b(i1 %a, i1 noundef %b) {
|
|
; CHECK-LABEL: @logical_and_noundef_b(
|
|
; CHECK-NEXT: [[RES:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%res = select i1 %a, i1 %b, i1 false
|
|
ret i1 %res
|
|
}
|
|
|
|
; (!x && !y) || x --> x || !y
|
|
|
|
define i1 @not_not_true(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_not_true(
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[NOTY]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
%noty = xor i1 %y, true
|
|
%r = select i1 %notx, i1 %noty, i1 true
|
|
ret i1 %r
|
|
}
|
|
|
|
; (!x && !y) --> !(x || y)
|
|
|
|
define i1 @not_not_false(i1 %x, i1 %y) !prof !0 {
|
|
; CHECK-LABEL: @not_not_false(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]], !prof [[PROF1:![0-9]+]]
|
|
; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
%noty = xor i1 %y, true
|
|
%r = select i1 %notx, i1 %noty, i1 false, !prof !1
|
|
ret i1 %r
|
|
}
|
|
|
|
; (!x || !y) --> !(x && y)
|
|
|
|
define i1 @not_true_not(i1 %x, i1 %y) !prof !0 {
|
|
; CHECK-LABEL: @not_true_not(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false, !prof [[PROF1]]
|
|
; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
%noty = xor i1 %y, true
|
|
%r = select i1 %notx, i1 true, i1 %noty, !prof !1
|
|
ret i1 %r
|
|
}
|
|
|
|
; (!!x && !y) --> x && !y
|
|
|
|
define i1 @not_false_not(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_false_not(
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
%noty = xor i1 %y, true
|
|
%r = select i1 %notx, i1 false, i1 %noty
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_not_true_use1(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_not_true_use1(
|
|
; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTX]])
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 true, i1 [[NOTY]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
call void @use(i1 %notx)
|
|
%noty = xor i1 %y, true
|
|
%r = select i1 %notx, i1 %noty, i1 true
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_not_false_use1(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_not_false_use1(
|
|
; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTX]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X]], i1 true, i1 [[Y:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
call void @use(i1 %notx)
|
|
%noty = xor i1 %y, true
|
|
%r = select i1 %notx, i1 %noty, i1 false
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_true_not_use1(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_true_not_use1(
|
|
; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTX]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X]], i1 [[Y:%.*]], i1 false
|
|
; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
call void @use(i1 %notx)
|
|
%noty = xor i1 %y, true
|
|
%r = select i1 %notx, i1 true, i1 %noty
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_false_not_use1(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_false_not_use1(
|
|
; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTX]])
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 [[NOTY]], i1 false
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
call void @use(i1 %notx)
|
|
%noty = xor i1 %y, true
|
|
%r = select i1 %notx, i1 false, i1 %noty
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_not_true_use2(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_not_true_use2(
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTY]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[NOTY]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
%noty = xor i1 %y, true
|
|
call void @use(i1 %noty)
|
|
%r = select i1 %notx, i1 %noty, i1 true
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_not_false_use2(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_not_false_use2(
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTY]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y]]
|
|
; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
%noty = xor i1 %y, true
|
|
call void @use(i1 %noty)
|
|
%r = select i1 %notx, i1 %noty, i1 false
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_true_not_use2(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_true_not_use2(
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTY]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false
|
|
; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
%noty = xor i1 %y, true
|
|
call void @use(i1 %noty)
|
|
%r = select i1 %notx, i1 true, i1 %noty
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_false_not_use2(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_false_not_use2(
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTY]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
%noty = xor i1 %y, true
|
|
call void @use(i1 %noty)
|
|
%r = select i1 %notx, i1 false, i1 %noty
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_not_true_use3(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_not_true_use3(
|
|
; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTX]])
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTY]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 true, i1 [[NOTY]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
call void @use(i1 %notx)
|
|
%noty = xor i1 %y, true
|
|
call void @use(i1 %noty)
|
|
%r = select i1 %notx, i1 %noty, i1 true
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_not_false_use3(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_not_false_use3(
|
|
; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTX]])
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTY]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTX]], i1 [[NOTY]], i1 false
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
call void @use(i1 %notx)
|
|
%noty = xor i1 %y, true
|
|
call void @use(i1 %noty)
|
|
%r = select i1 %notx, i1 %noty, i1 false
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_true_not_use3(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_true_not_use3(
|
|
; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTX]])
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTY]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTX]], i1 true, i1 [[NOTY]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
call void @use(i1 %notx)
|
|
%noty = xor i1 %y, true
|
|
call void @use(i1 %noty)
|
|
%r = select i1 %notx, i1 true, i1 %noty
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @not_false_not_use3(i1 %x, i1 %y) {
|
|
; CHECK-LABEL: @not_false_not_use3(
|
|
; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTX]])
|
|
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
|
|
; CHECK-NEXT: call void @use(i1 [[NOTY]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 [[NOTY]], i1 false
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notx = xor i1 %x, true
|
|
call void @use(i1 %notx)
|
|
%noty = xor i1 %y, true
|
|
call void @use(i1 %noty)
|
|
%r = select i1 %notx, i1 false, i1 %noty
|
|
ret i1 %r
|
|
}
|
|
|
|
; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35399
|
|
|
|
@g1 = external global i16
|
|
@g2 = external global i16
|
|
|
|
define i1 @demorgan_select_infloop1(i1 %L) {
|
|
; CHECK-LABEL: @demorgan_select_infloop1(
|
|
; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true
|
|
; CHECK-NEXT: ret i1 [[NOT_L]]
|
|
;
|
|
%not.L = xor i1 %L, true
|
|
%cmp = icmp eq ptr getelementptr inbounds (i16, ptr @g2, i64 1), @g1
|
|
%add = add i1 %cmp, %cmp
|
|
%xor = xor i1 %add, true
|
|
%C15 = select i1 %not.L, i1 %xor, i1 false
|
|
ret i1 %C15
|
|
}
|
|
|
|
|
|
define i1 @demorgan_select_infloop2(i1 %L) {
|
|
; CHECK-LABEL: @demorgan_select_infloop2(
|
|
; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne ptr getelementptr inbounds nuw (i8, ptr @g2, i64 2), @g1
|
|
; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 [[CMP2]], i1 false
|
|
; CHECK-NEXT: ret i1 [[C15]]
|
|
;
|
|
%not.L = xor i1 %L, true
|
|
%cmp1 = icmp eq ptr getelementptr inbounds (i16, ptr @g1, i64 1), @g1
|
|
%cmp2 = icmp eq ptr getelementptr inbounds (i16, ptr @g2, i64 1), @g1
|
|
%add = add i1 %cmp1, %cmp2
|
|
%xor = xor i1 %add, true
|
|
%C15 = select i1 %not.L, i1 %xor, i1 false
|
|
ret i1 %C15
|
|
}
|
|
|
|
define i1 @and_or1(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @and_or1(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[B:%.*]], !prof [[PROF2:![0-9]+]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 [[TMP1]], i1 false, !prof [[PROF2]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%nota = xor i1 %a, true
|
|
%cond = or i1 %nota, %c
|
|
%r = select i1 %cond, i1 %a, i1 %b, !prof !1
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or2(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @and_or2(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[A:%.*]], !prof [[PROF2]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false, !prof [[PROF2]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notc = xor i1 %c, true
|
|
%cond = and i1 %notc, %b
|
|
%r = select i1 %cond, i1 %a, i1 %b, !prof !1
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or1_commuted(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @and_or1_commuted(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[B:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 [[TMP1]], i1 false
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%nota = xor i1 %a, true
|
|
%cond = or i1 %c, %nota
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or2_commuted(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @and_or2_commuted(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[A:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notc = xor i1 %c, true
|
|
%cond = and i1 %b, %notc
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or1_multiuse(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @and_or1_multiuse(
|
|
; CHECK-NEXT: [[NOTA:%.*]] = xor i1 [[A:%.*]], true
|
|
; CHECK-NEXT: [[COND:%.*]] = or i1 [[C:%.*]], [[NOTA]]
|
|
; CHECK-NEXT: call void @use(i1 [[COND]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%nota = xor i1 %a, true
|
|
%cond = or i1 %nota, %c
|
|
call void @use(i1 %cond)
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or2_multiuse(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @and_or2_multiuse(
|
|
; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true
|
|
; CHECK-NEXT: [[COND:%.*]] = and i1 [[B:%.*]], [[NOTC]]
|
|
; CHECK-NEXT: call void @use(i1 [[COND]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notc = xor i1 %c, true
|
|
%cond = and i1 %notc, %b
|
|
call void @use(i1 %cond)
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @and_or1_vec(<2 x i1> %a, <2 x i1> %b) {
|
|
; CHECK-LABEL: @and_or1_vec(
|
|
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> splat (i1 true), <2 x i1> [[B:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = call <2 x i1> @gen_v2i1()
|
|
%nota = xor <2 x i1> %a, <i1 true, i1 true>
|
|
%cond = or <2 x i1> %nota, %c
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @and_or2_vec(<2 x i1> %a, <2 x i1> %b) {
|
|
; CHECK-LABEL: @and_or2_vec(
|
|
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> splat (i1 true), <2 x i1> [[A:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = call <2 x i1> @gen_v2i1()
|
|
%notc = xor <2 x i1> %c, <i1 true, i1 true>
|
|
%cond = and <2 x i1> %notc, %b
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @and_or1_vec_commuted(<2 x i1> %a, <2 x i1> %b) {
|
|
; CHECK-LABEL: @and_or1_vec_commuted(
|
|
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> splat (i1 true), <2 x i1> [[B:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = call <2 x i1> @gen_v2i1()
|
|
%nota = xor <2 x i1> %a, <i1 true, i1 true>
|
|
%cond = or <2 x i1> %c, %nota
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @and_or2_vec_commuted(<2 x i1> %a, <2 x i1> %b) {
|
|
; CHECK-LABEL: @and_or2_vec_commuted(
|
|
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> splat (i1 true), <2 x i1> [[A:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = call <2 x i1> @gen_v2i1()
|
|
%notc = xor <2 x i1> %c, <i1 true, i1 true>
|
|
%cond = and <2 x i1> %b, %notc
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @and_or1_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) {
|
|
; CHECK-LABEL: @and_or1_wrong_operand(
|
|
; CHECK-NEXT: [[NOTA:%.*]] = xor i1 [[A:%.*]], true
|
|
; CHECK-NEXT: [[COND:%.*]] = or i1 [[C:%.*]], [[NOTA]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[D:%.*]], i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%nota = xor i1 %a, true
|
|
%cond = or i1 %nota, %c
|
|
%r = select i1 %cond, i1 %d, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or2_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) {
|
|
; CHECK-LABEL: @and_or2_wrong_operand(
|
|
; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true
|
|
; CHECK-NEXT: [[COND:%.*]] = and i1 [[B:%.*]], [[NOTC]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[D:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notc = xor i1 %c, true
|
|
%cond = and i1 %notc, %b
|
|
%r = select i1 %cond, i1 %a, i1 %d
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or3(i1 %a, i1 %b, i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @and_or3(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[A:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP2]], i1 false
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%c = icmp eq i32 %x, %y
|
|
%cond = and i1 %b, %c
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or3_commuted(i1 %a, i1 %b, i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @and_or3_commuted(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[A:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP2]], i1 false
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%c = icmp eq i32 %x, %y
|
|
%cond = and i1 %c, %b
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or3_not_free_to_invert(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @and_or3_not_free_to_invert(
|
|
; CHECK-NEXT: [[COND:%.*]] = and i1 [[B:%.*]], [[C:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%cond = and i1 %b, %c
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @and_or3_multiuse(i1 %a, i1 %b, i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @and_or3_multiuse(
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[COND:%.*]] = and i1 [[B:%.*]], [[C]]
|
|
; CHECK-NEXT: call void @use(i1 [[COND]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%c = icmp eq i32 %x, %y
|
|
%cond = and i1 %b, %c
|
|
call void @use(i1 %cond)
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @and_or3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @and_or3_vec(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> splat (i1 true), <2 x i1> [[A:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP2]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = icmp eq <2 x i32> %x, %y
|
|
%cond = and <2 x i1> %b, %c
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @and_or3_vec_commuted(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @and_or3_vec_commuted(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> splat (i1 true), <2 x i1> [[A:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP2]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = icmp eq <2 x i32> %x, %y
|
|
%cond = and <2 x i1> %c, %b
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @and_or3_wrong_operand(i1 %a, i1 %b, i32 %x, i32 %y, i1 %d) {
|
|
; CHECK-LABEL: @and_or3_wrong_operand(
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[COND:%.*]] = and i1 [[B:%.*]], [[C]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[D:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%c = icmp eq i32 %x, %y
|
|
%cond = and i1 %b, %c
|
|
%r = select i1 %cond, i1 %a, i1 %d
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @or_and1(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @or_and1(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 false, !prof [[PROF2]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[TMP1]], !prof [[PROF2]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notb = xor i1 %b, true
|
|
%cond = and i1 %notb, %c
|
|
%r = select i1 %cond, i1 %a, i1 %b, !prof !1
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @or_and2(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @or_and2(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 false, !prof [[PROF2]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]], !prof [[PROF2]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notc = xor i1 %c, true
|
|
%cond = or i1 %notc, %a
|
|
%r = select i1 %cond, i1 %a, i1 %b, !prof !1
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @or_and1_commuted(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @or_and1_commuted(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 false
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[TMP1]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notb = xor i1 %b, true
|
|
%cond = and i1 %c, %notb
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @or_and2_commuted(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @or_and2_commuted(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 false
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notc = xor i1 %c, true
|
|
%cond = or i1 %a, %notc
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @fold_or_of_ands_with_select_to_logical1(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @fold_or_of_ands_with_select_to_logical1(
|
|
; CHECK-NEXT: [[OR1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF1]]
|
|
; CHECK-NEXT: ret i1 [[OR1]]
|
|
;
|
|
%not = xor i1 %c, true
|
|
%and1 = and i1 %c, %a
|
|
%and2 = select i1 %not, i1 %b, i1 false, !prof !1
|
|
%or1 = or i1 %and1, %and2
|
|
ret i1 %or1
|
|
}
|
|
|
|
define i1 @fold_or_of_ands_with_select_to_logical2(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @fold_or_of_ands_with_select_to_logical2(
|
|
; CHECK-NEXT: [[OR1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF2]]
|
|
; CHECK-NEXT: ret i1 [[OR1]]
|
|
;
|
|
%not = xor i1 %c, true
|
|
%and1 = and i1 %c, %a
|
|
%and2 = select i1 %b, i1 %not, i1 false, !prof !1
|
|
%or1 = or i1 %and1, %and2
|
|
ret i1 %or1
|
|
}
|
|
|
|
define i1 @fold_or_of_ands_with_select_to_logical3(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @fold_or_of_ands_with_select_to_logical3(
|
|
; CHECK-NEXT: [[OR1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF1]]
|
|
; CHECK-NEXT: ret i1 [[OR1]]
|
|
;
|
|
%not = xor i1 %c, true
|
|
%and1 = and i1 %a, %c
|
|
%and2 = select i1 %not, i1 %b, i1 false, !prof !1
|
|
%or1 = or i1 %and1, %and2
|
|
ret i1 %or1
|
|
}
|
|
|
|
define i1 @fold_or_of_ands_with_select_to_logical4(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @fold_or_of_ands_with_select_to_logical4(
|
|
; CHECK-NEXT: [[OR1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF2]]
|
|
; CHECK-NEXT: ret i1 [[OR1]]
|
|
;
|
|
%not = xor i1 %c, true
|
|
%and1 = and i1 %a, %c
|
|
%and2 = select i1 %b, i1 %not, i1 false, !prof !1
|
|
%or1 = or i1 %and1, %and2
|
|
ret i1 %or1
|
|
}
|
|
|
|
define i1 @fold_or_of_ands_with_select_to_logical5(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @fold_or_of_ands_with_select_to_logical5(
|
|
; CHECK-NEXT: [[OR1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF2]]
|
|
; CHECK-NEXT: ret i1 [[OR1]]
|
|
;
|
|
%not = xor i1 %c, true
|
|
%and1 = select i1 %a, i1 %c, i1 false, !prof !1
|
|
%and2 = and i1 %not, %b
|
|
%or1 = or i1 %and1, %and2
|
|
ret i1 %or1
|
|
}
|
|
|
|
define i1 @fold_or_of_ands_with_select_to_logical6(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @fold_or_of_ands_with_select_to_logical6(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[C:%.*]]
|
|
; CHECK-NEXT: [[OR1:%.*]] = select i1 [[TMP1]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF2]]
|
|
; CHECK-NEXT: ret i1 [[OR1]]
|
|
;
|
|
%not = xor i1 %c, true
|
|
%and1 = select i1 %a, i1 %c, i1 false, !prof !1
|
|
%and2 = select i1 %b, i1 %not, i1 false, !prof !1
|
|
%or1 = or i1 %and1, %and2
|
|
ret i1 %or1
|
|
}
|
|
|
|
define i1 @fold_or_of_ands_with_select_to_logical7(i1 %a, i1 %b, i1 %c) !prof !0 {
|
|
; CHECK-LABEL: @fold_or_of_ands_with_select_to_logical7(
|
|
; CHECK-NEXT: [[OR1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF1]]
|
|
; CHECK-NEXT: ret i1 [[OR1]]
|
|
;
|
|
%not = xor i1 %c, true
|
|
%and1 = and i1 %c, %a
|
|
%and2 = select i1 %not, i1 %b, i1 false, !prof !1
|
|
%or1 = or i1 %and2, %and1
|
|
ret i1 %or1
|
|
}
|
|
|
|
define i8 @fold_or_of_ands_with_select_to_logical_neg(i8 %a, i8 %b, i8 %c) !prof !0 {
|
|
; CHECK-LABEL: @fold_or_of_ands_with_select_to_logical_neg(
|
|
; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[C:%.*]], 1
|
|
; CHECK-NEXT: [[AND1:%.*]] = and i8 [[C]], [[A:%.*]]
|
|
; CHECK-NEXT: [[AND2:%.*]] = and i8 [[NOT]], [[B:%.*]]
|
|
; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND1]], [[AND2]]
|
|
; CHECK-NEXT: ret i8 [[OR1]]
|
|
;
|
|
%not = xor i8 %c, 1
|
|
%and1 = and i8 %c, %a
|
|
%and2 = and i8 %not, %b
|
|
%or1 = or i8 %and1, %and2
|
|
ret i8 %or1
|
|
}
|
|
|
|
define <4 x i1> @fold_or_of_ands_with_select_to_logical9(<4 x i1> %a, <4 x i1> %b, <4 x i1> %c) !prof !0 {
|
|
; CHECK-LABEL: @fold_or_of_ands_with_select_to_logical9(
|
|
; CHECK-NEXT: [[OR1:%.*]] = select <4 x i1> [[C:%.*]], <4 x i1> [[A:%.*]], <4 x i1> [[B:%.*]], !prof [[PROF1]]
|
|
; CHECK-NEXT: ret <4 x i1> [[OR1]]
|
|
;
|
|
%not = xor <4 x i1> %c, splat (i1 true)
|
|
%and1 = and <4 x i1> %c, %a
|
|
%and2 = select <4 x i1> %not, <4 x i1> %b, <4 x i1> splat (i1 false), !prof !1
|
|
%or1 = or <4 x i1> %and1, %and2
|
|
ret <4 x i1> %or1
|
|
}
|
|
|
|
define i1 @or_and1_multiuse(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @or_and1_multiuse(
|
|
; CHECK-NEXT: [[NOTB:%.*]] = xor i1 [[B:%.*]], true
|
|
; CHECK-NEXT: [[COND:%.*]] = and i1 [[C:%.*]], [[NOTB]]
|
|
; CHECK-NEXT: call void @use(i1 [[COND]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notb = xor i1 %b, true
|
|
%cond = and i1 %notb, %c
|
|
call void @use(i1 %cond)
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @or_and2_multiuse(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @or_and2_multiuse(
|
|
; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true
|
|
; CHECK-NEXT: [[COND:%.*]] = or i1 [[A:%.*]], [[NOTC]]
|
|
; CHECK-NEXT: call void @use(i1 [[COND]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notc = xor i1 %c, true
|
|
%cond = or i1 %notc, %a
|
|
call void @use(i1 %cond)
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @or_and1_vec(<2 x i1> %a, <2 x i1> %b) {
|
|
; CHECK-LABEL: @or_and1_vec(
|
|
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[A:%.*]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> splat (i1 true), <2 x i1> [[TMP1]]
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = call <2 x i1> @gen_v2i1()
|
|
%notb = xor <2 x i1> %b, <i1 true, i1 true>
|
|
%cond = and <2 x i1> %c, %notb
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @or_and2_vec(<2 x i1> %a, <2 x i1> %b) {
|
|
; CHECK-LABEL: @or_and2_vec(
|
|
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> splat (i1 true), <2 x i1> [[TMP1]]
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = call <2 x i1> @gen_v2i1()
|
|
%notc = xor <2 x i1> %c, <i1 true, i1 true>
|
|
%cond = or <2 x i1> %a, %notc
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @or_and1_vec_commuted(<2 x i1> %a, <2 x i1> %b) {
|
|
; CHECK-LABEL: @or_and1_vec_commuted(
|
|
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[A:%.*]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> splat (i1 true), <2 x i1> [[TMP1]]
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = call <2 x i1> @gen_v2i1()
|
|
%notb = xor <2 x i1> %b, <i1 true, i1 true>
|
|
%cond = and <2 x i1> %notb, %c
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @or_and2_vec_commuted(<2 x i1> %a, <2 x i1> %b) {
|
|
; CHECK-LABEL: @or_and2_vec_commuted(
|
|
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> splat (i1 true), <2 x i1> [[TMP1]]
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = call <2 x i1> @gen_v2i1()
|
|
%notc = xor <2 x i1> %c, <i1 true, i1 true>
|
|
%cond = or <2 x i1> %notc, %a
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @or_and1_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) {
|
|
; CHECK-LABEL: @or_and1_wrong_operand(
|
|
; CHECK-NEXT: [[NOTB:%.*]] = xor i1 [[B:%.*]], true
|
|
; CHECK-NEXT: [[COND:%.*]] = and i1 [[C:%.*]], [[NOTB]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[D:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notb = xor i1 %b, true
|
|
%cond = and i1 %c, %notb
|
|
%r = select i1 %cond, i1 %a, i1 %d
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @or_and2_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) {
|
|
; CHECK-LABEL: @or_and2_wrong_operand(
|
|
; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true
|
|
; CHECK-NEXT: [[COND:%.*]] = or i1 [[A:%.*]], [[NOTC]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[D:%.*]], i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%notc = xor i1 %c, true
|
|
%cond = or i1 %a, %notc
|
|
%r = select i1 %cond, i1 %d, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @pr64558(i1 noundef %a, i1 noundef %b) {
|
|
; CHECK-LABEL: @pr64558(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[COND_V:%.*]] = or i1 [[B:%.*]], [[A:%.*]]
|
|
; CHECK-NEXT: ret i1 [[COND_V]]
|
|
;
|
|
entry:
|
|
%lnot = xor i1 %b, true
|
|
%and11 = and i1 %lnot, %a
|
|
%cond.v = select i1 %and11, i1 %a, i1 %b
|
|
ret i1 %cond.v
|
|
}
|
|
|
|
define i1 @or_and3(i1 %a, i1 %b, i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @or_and3(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 [[B:%.*]], i1 false
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP2]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%c = icmp eq i32 %x, %y
|
|
%cond = or i1 %a, %c
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @or_and3_commuted(i1 %a, i1 %b, i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @or_and3_commuted(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 [[B:%.*]], i1 false
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP2]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%c = icmp eq i32 %x, %y
|
|
%cond = or i1 %c, %a
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @or_and3_not_free_to_invert(i1 %a, i1 %b, i1 %c) {
|
|
; CHECK-LABEL: @or_and3_not_free_to_invert(
|
|
; CHECK-NEXT: [[COND:%.*]] = or i1 [[A:%.*]], [[C:%.*]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%cond = or i1 %a, %c
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @or_and3_multiuse(i1 %a, i1 %b, i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @or_and3_multiuse(
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[COND:%.*]] = or i1 [[A:%.*]], [[C]]
|
|
; CHECK-NEXT: call void @use(i1 [[COND]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%c = icmp eq i32 %x, %y
|
|
%cond = or i1 %a, %c
|
|
call void @use(i1 %cond)
|
|
%r = select i1 %cond, i1 %a, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @or_and3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @or_and3_vec(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> splat (i1 true), <2 x i1> [[TMP2]]
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = icmp eq <2 x i32> %x, %y
|
|
%cond = or <2 x i1> %a, %c
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @or_and3_vec_commuted(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @or_and3_vec_commuted(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> splat (i1 true), <2 x i1> [[TMP2]]
|
|
; CHECK-NEXT: ret <2 x i1> [[R]]
|
|
;
|
|
%c = icmp eq <2 x i32> %x, %y
|
|
%cond = or <2 x i1> %c, %a
|
|
%r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @or_and3_wrong_operand(i1 %a, i1 %b, i32 %x, i32 %y, i1 %d) {
|
|
; CHECK-LABEL: @or_and3_wrong_operand(
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[COND:%.*]] = or i1 [[A:%.*]], [[C]]
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[D:%.*]], i1 [[B:%.*]]
|
|
; CHECK-NEXT: ret i1 [[R]]
|
|
;
|
|
%c = icmp eq i32 %x, %y
|
|
%cond = or i1 %a, %c
|
|
%r = select i1 %cond, i1 %d, i1 %b
|
|
ret i1 %r
|
|
}
|
|
|
|
define i8 @test_or_umax(i8 %x, i8 %y, i1 %cond) !prof !0 {
|
|
; CHECK-LABEL: @test_or_umax(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[X]], i8 [[TMP1]], !prof [[PROF1]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%or = select i1 %cond, i1 true, i1 %cmp
|
|
%ret = select i1 %or, i8 %x, i8 %y, !prof !2
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_or_umin(i8 %x, i8 %y, i1 %cond) {
|
|
; CHECK-LABEL: @test_or_umin(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[Y]], i8 [[TMP1]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%or = select i1 %cond, i1 true, i1 %cmp
|
|
%ret = select i1 %or, i8 %y, i8 %x
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_and_umax(i8 %x, i8 %y, i1 %cond) {
|
|
; CHECK-LABEL: @test_and_umax(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[TMP1]], i8 [[Y]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%and = select i1 %cond, i1 %cmp, i1 false
|
|
%ret = select i1 %and, i8 %x, i8 %y
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_and_umin(i8 %x, i8 %y, i1 %cond) {
|
|
; CHECK-LABEL: @test_and_umin(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[TMP1]], i8 [[X]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%and = select i1 %cond, i1 %cmp, i1 false
|
|
%ret = select i1 %and, i8 %y, i8 %x
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_or_umax_bitwise1(i8 %x, i8 %y, i8 %val) {
|
|
; CHECK-LABEL: @test_or_umax_bitwise1(
|
|
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[VAL:%.*]], 0
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[TMP1]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cond = icmp eq i8 %val, 0 ; thwart complexity-based ordering
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%or = or i1 %cond, %cmp
|
|
%ret = select i1 %or, i8 %x, i8 %y
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_or_umax_bitwise2(i8 %x, i8 %y, i8 %val) {
|
|
; CHECK-LABEL: @test_or_umax_bitwise2(
|
|
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[VAL:%.*]], 0
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[TMP1]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cond = icmp eq i8 %val, 0 ; thwart complexity-based ordering
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%or = or i1 %cmp, %cond
|
|
%ret = select i1 %or, i8 %x, i8 %y
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_and_umax_bitwise1(i8 %x, i8 %y, i8 %val) {
|
|
; CHECK-LABEL: @test_and_umax_bitwise1(
|
|
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[VAL:%.*]], 0
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND]], i8 [[TMP1]], i8 [[Y]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cond = icmp eq i8 %val, 0 ; thwart complexity-based ordering
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%and = and i1 %cond, %cmp
|
|
%ret = select i1 %and, i8 %x, i8 %y
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_and_umax_bitwise2(i8 %x, i8 %y, i8 %val) {
|
|
; CHECK-LABEL: @test_and_umax_bitwise2(
|
|
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[VAL:%.*]], 0
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND]], i8 [[TMP1]], i8 [[Y]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cond = icmp eq i8 %val, 0 ; thwart complexity-based ordering
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%and = and i1 %cmp, %cond
|
|
%ret = select i1 %and, i8 %x, i8 %y
|
|
ret i8 %ret
|
|
}
|
|
|
|
; Other SPFs
|
|
|
|
define i8 @test_or_smax(i8 %x, i8 %y, i1 %cond) {
|
|
; CHECK-LABEL: @test_or_smax(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[X]], i8 [[TMP1]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cmp = icmp sgt i8 %x, %y
|
|
%or = select i1 %cond, i1 true, i1 %cmp
|
|
%ret = select i1 %or, i8 %x, i8 %y
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_or_abs(i8 %x, i1 %cond) {
|
|
; CHECK-LABEL: @test_or_abs(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[X]], i8 [[TMP1]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cmp = icmp sgt i8 %x, -1
|
|
%neg = sub nsw i8 0, %x
|
|
%or = select i1 %cond, i1 true, i1 %cmp
|
|
%ret = select i1 %or, i8 %x, i8 %neg
|
|
ret i8 %ret
|
|
}
|
|
|
|
; TODO: fold SPF_FMAXNUM
|
|
define float @test_or_fmaxnum(float %x, float %y, i1 %cond) {
|
|
; CHECK-LABEL: @test_or_fmaxnum(
|
|
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = select i1 [[COND:%.*]], i1 true, i1 [[CMP]]
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[OR]], float [[X]], float [[Y]]
|
|
; CHECK-NEXT: ret float [[RET]]
|
|
;
|
|
%cmp = fcmp nnan ogt float %x, %y
|
|
%or = select i1 %cond, i1 true, i1 %cmp
|
|
%ret = select i1 %or, float %x, float %y
|
|
ret float %ret
|
|
}
|
|
|
|
; Negative tests
|
|
|
|
define i8 @test_or_umax_invalid_logical(i8 %x, i8 %y, i1 %cond) {
|
|
; CHECK-LABEL: @test_or_umax_invalid_logical(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP]], i1 true, i1 [[COND:%.*]]
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[OR]], i8 [[X]], i8 [[Y]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%or = select i1 %cmp, i1 true, i1 %cond
|
|
%ret = select i1 %or, i8 %x, i8 %y
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_and_umax_invalid_logical(i8 %x, i8 %y, i1 %cond) {
|
|
; CHECK-LABEL: @test_and_umax_invalid_logical(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP]], i1 [[COND:%.*]], i1 false
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[AND]], i8 [[X]], i8 [[Y]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%and = select i1 %cmp, i1 %cond, i1 false
|
|
%ret = select i1 %and, i8 %x, i8 %y
|
|
ret i8 %ret
|
|
}
|
|
|
|
define i8 @test_or_umax_multiuse_cond(i8 %x, i8 %y, i1 %cond) {
|
|
; CHECK-LABEL: @test_or_umax_multiuse_cond(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = select i1 [[COND:%.*]], i1 true, i1 [[CMP]]
|
|
; CHECK-NEXT: call void @use(i1 [[OR]])
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[OR]], i8 [[X]], i8 [[Y]]
|
|
; CHECK-NEXT: ret i8 [[RET]]
|
|
;
|
|
%cmp = icmp ugt i8 %x, %y
|
|
%or = select i1 %cond, i1 true, i1 %cmp
|
|
call void @use(i1 %or)
|
|
%ret = select i1 %or, i8 %x, i8 %y
|
|
ret i8 %ret
|
|
}
|
|
|
|
; Tests from PR76203
|
|
|
|
define i8 @test_or_eq_a_b(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_or_eq_a_b(
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp eq i8 %a, %b
|
|
%cond = or i1 %other_cond, %cmp
|
|
%select = select i1 %cond, i8 %a, i8 %b
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_and_ne_a_b(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_and_ne_a_b(
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp ne i8 %a, %b
|
|
%cond = and i1 %other_cond, %cmp
|
|
%select = select i1 %cond, i8 %a, i8 %b
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_or_eq_a_b_commuted(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_or_eq_a_b_commuted(
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[B:%.*]], i8 [[A:%.*]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp eq i8 %a, %b
|
|
%cond = or i1 %other_cond, %cmp
|
|
%select = select i1 %cond, i8 %b, i8 %a
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_and_ne_a_b_commuted(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_and_ne_a_b_commuted(
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[B:%.*]], i8 [[A:%.*]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp ne i8 %a, %b
|
|
%cond = and i1 %other_cond, %cmp
|
|
%select = select i1 %cond, i8 %b, i8 %a
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_or_eq_different_operands(i8 %a, i8 %b, i8 %c) {
|
|
; CHECK-LABEL: @test_or_eq_different_operands(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A:%.*]], [[C:%.*]]
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i8 [[A]], i8 [[B:%.*]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp eq i8 %a, %c
|
|
%cmp1 = icmp eq i8 %b, %a
|
|
%cond = or i1 %cmp, %cmp1
|
|
%select = select i1 %cond, i8 %a, i8 %b
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_or_eq_a_b_multi_use(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_or_eq_a_b_multi_use(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A:%.*]], [[B:%.*]]
|
|
; CHECK-NEXT: [[COND:%.*]] = or i1 [[OTHER_COND:%.*]], [[CMP]]
|
|
; CHECK-NEXT: call void @use(i1 [[CMP]])
|
|
; CHECK-NEXT: call void @use(i1 [[COND]])
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND]], i8 [[A]], i8 [[B]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp eq i8 %a, %b
|
|
%cond = or i1 %other_cond, %cmp
|
|
call void @use(i1 %cmp)
|
|
call void @use(i1 %cond)
|
|
%select = select i1 %cond, i8 %a, i8 %b
|
|
ret i8 %select
|
|
}
|
|
|
|
define <2 x i8> @test_or_eq_a_b_vec(<2 x i1> %other_cond, <2 x i8> %a, <2 x i8> %b) {
|
|
; CHECK-LABEL: @test_or_eq_a_b_vec(
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[OTHER_COND:%.*]], <2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]
|
|
; CHECK-NEXT: ret <2 x i8> [[SELECT]]
|
|
;
|
|
%cmp = icmp eq <2 x i8> %a, %b
|
|
%cond = or <2 x i1> %other_cond, %cmp
|
|
%select = select <2 x i1> %cond, <2 x i8> %a, <2 x i8> %b
|
|
ret <2 x i8> %select
|
|
}
|
|
|
|
define i8 @test_or_ne_a_b(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_or_ne_a_b(
|
|
; CHECK-NEXT: ret i8 [[A:%.*]]
|
|
;
|
|
%cmp = icmp ne i8 %a, %b
|
|
%cond = or i1 %other_cond, %cmp
|
|
%select = select i1 %cond, i8 %a, i8 %b
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_and_ne_different_operands_fail(i8 %a, i8 %b, i8 %c) {
|
|
; CHECK-LABEL: @test_and_ne_different_operands_fail(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[A:%.*]], [[C:%.*]]
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[B:%.*]], [[C]]
|
|
; CHECK-NEXT: [[COND:%.*]] = and i1 [[CMP]], [[CMP1]]
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i8 [[B]], i8 [[A]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp ne i8 %a, %c
|
|
%cmp1 = icmp ne i8 %b, %c
|
|
%cond = and i1 %cmp, %cmp1
|
|
%select = select i1 %cond, i8 %b, i8 %a
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_logical_or_eq_a_b(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_logical_or_eq_a_b(
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp eq i8 %a, %b
|
|
%or.cond = select i1 %other_cond, i1 true, i1 %cmp
|
|
%select = select i1 %or.cond, i8 %a, i8 %b
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_logical_commuted_or_eq_a_b(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_logical_commuted_or_eq_a_b(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A:%.*]], [[B:%.*]]
|
|
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[OTHER_COND:%.*]]
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i8 [[A]], i8 [[B]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp eq i8 %a, %b
|
|
%or.cond = select i1 %cmp, i1 true, i1 %other_cond
|
|
%select = select i1 %or.cond, i8 %a, i8 %b
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_logical_and_ne_a_b(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_logical_and_ne_a_b(
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp ne i8 %a, %b
|
|
%or.cond = select i1 %other_cond, i1 %cmp, i1 false
|
|
%select = select i1 %or.cond, i8 %a, i8 %b
|
|
ret i8 %select
|
|
}
|
|
|
|
define i8 @test_logical_commuted_and_ne_a_b(i1 %other_cond, i8 %a, i8 %b) {
|
|
; CHECK-LABEL: @test_logical_commuted_and_ne_a_b(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[A:%.*]], [[B:%.*]]
|
|
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[OTHER_COND:%.*]], i1 false
|
|
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i8 [[A]], i8 [[B]]
|
|
; CHECK-NEXT: ret i8 [[SELECT]]
|
|
;
|
|
%cmp = icmp ne i8 %a, %b
|
|
%or.cond = select i1 %cmp, i1 %other_cond, i1 false
|
|
%select = select i1 %or.cond, i8 %a, i8 %b
|
|
ret i8 %select
|
|
}
|
|
|
|
!0 = !{!"function_entry_count", i64 1000}
|
|
!1 = !{!"branch_weights", i32 2, i32 3}
|
|
!2 = !{!"branch_weights", i32 3, i32 2}
|
|
;.
|
|
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
|
|
; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
|
|
;.
|
|
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
|
|
; CHECK: [[PROF1]] = !{!"branch_weights", i32 3, i32 2}
|
|
; CHECK: [[PROF2]] = !{!"unknown", !"instcombine"}
|
|
;.
|