\#163412 touched this last and directly propagated the profile information. This was not correct for the motivating example: %a = icmp eq i32 %z, 0 %b = icmp eq i32 %z, 1 %v2 = select i1 %b, i1 true, i1 %pred, !prof !18 %v3 = and i1 %a, %v2 to %a = icmp eq i32 %z, 0 %v3 = select i1 %a, i1 %pred, i1 false z == 1 does not imply that z == 0 for i8. In general for the and case, we need a => b, which means that b must be equivalent or more restrictive than a, which means we cannot propagate profile information without additional information on the value distribution of z. For the or case we need !a => b. We again cannot derive profile information for a/!a without additional value distribution information.
268 lines
9.1 KiB
LLVM
268 lines
9.1 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
|
|
|
|
define i1 @a_true_implies_b_true(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_true_implies_b_true(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 20
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 [[X:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 20
|
|
%b = icmp ugt i8 %z, 10
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = select i1 %a, i1 %sel, i1 false
|
|
ret i1 %res
|
|
}
|
|
|
|
define <2 x i1> @a_true_implies_b_true_vec(i8 %z0, <2 x i1> %X, <2 x i1> %Y) {
|
|
; CHECK-LABEL: @a_true_implies_b_true_vec(
|
|
; CHECK-NEXT: [[A0:%.*]] = insertelement <2 x i8> poison, i8 [[Z0:%.*]], i64 0
|
|
; CHECK-NEXT: [[Z:%.*]] = shufflevector <2 x i8> [[A0]], <2 x i8> poison, <2 x i32> zeroinitializer
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt <2 x i8> [[Z]], <i8 20, i8 19>
|
|
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[Z0]], 10
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[B]], <2 x i1> [[X:%.*]], <2 x i1> [[Y:%.*]]
|
|
; CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[A]], <2 x i1> [[SEL]], <2 x i1> zeroinitializer
|
|
; CHECK-NEXT: ret <2 x i1> [[RES]]
|
|
;
|
|
|
|
%a0 = insertelement <2 x i8> poison, i8 %z0, i8 0
|
|
%z = shufflevector <2 x i8> %a0, <2 x i8> poison, <2 x i32> zeroinitializer
|
|
%a = icmp ugt <2 x i8> %z, <i8 20, i8 19>
|
|
%b = icmp ugt i8 %z0, 10
|
|
%sel = select i1 %b, <2 x i1> %X, <2 x i1> %Y
|
|
%res = select <2 x i1> %a, <2 x i1> %sel, <2 x i1> zeroinitializer
|
|
ret <2 x i1> %res
|
|
}
|
|
|
|
define i1 @a_true_implies_b_true2(i8 %z, i1 %X, i1 %Y) !prof !0 {
|
|
; CHECK-LABEL: @a_true_implies_b_true2(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 20
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 [[X:%.*]], i1 false, !prof [[PROF1:![0-9]+]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 20
|
|
%b = icmp ugt i8 %z, 10
|
|
%sel = select i1 %b, i1 %X, i1 %Y, !prof !1
|
|
%res = and i1 %a, %sel
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_true_implies_b_true2_comm(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_true_implies_b_true2_comm(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 20
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 [[X:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 20
|
|
%b = icmp ugt i8 %z, 10
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = and i1 %sel, %a
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_true_implies_b_false(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_true_implies_b_false(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 20
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 [[Y:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 20
|
|
%b = icmp ult i8 %z, 10
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = select i1 %a, i1 %sel, i1 false
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_true_implies_b_false2(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_true_implies_b_false2(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 20
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 [[Y:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 20
|
|
%b = icmp eq i8 %z, 10
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = and i1 %a, %sel
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_true_implies_b_false2_comm(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_true_implies_b_false2_comm(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 20
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 [[Y:%.*]], i1 false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 20
|
|
%b = icmp eq i8 %z, 10
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = and i1 %sel, %a
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_false_implies_b_true(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_false_implies_b_true(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 10
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 true, i1 [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 10
|
|
%b = icmp ult i8 %z, 20
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = select i1 %a, i1 true, i1 %sel
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_false_implies_b_true2(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_false_implies_b_true2(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 10
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 true, i1 [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 10
|
|
%b = icmp ult i8 %z, 20
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = or i1 %a, %sel
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_false_implies_b_true2_comm(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_false_implies_b_true2_comm(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 10
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 true, i1 [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 10
|
|
%b = icmp ult i8 %z, 20
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = or i1 %sel, %a
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_false_implies_b_false(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_false_implies_b_false(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 10
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 true, i1 [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 10
|
|
%b = icmp ugt i8 %z, 20
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = select i1 %a, i1 true, i1 %sel
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_false_implies_b_false2(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_false_implies_b_false2(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 10
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 true, i1 [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 10
|
|
%b = icmp ugt i8 %z, 20
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = or i1 %a, %sel
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @a_false_implies_b_false2_comm(i8 %z, i1 %X, i1 %Y) {
|
|
; CHECK-LABEL: @a_false_implies_b_false2_comm(
|
|
; CHECK-NEXT: [[A:%.*]] = icmp ugt i8 [[Z:%.*]], 10
|
|
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A]], i1 true, i1 [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
%a = icmp ugt i8 %z, 10
|
|
%b = icmp ugt i8 %z, 20
|
|
%sel = select i1 %b, i1 %X, i1 %Y
|
|
%res = or i1 %sel, %a
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @trunc_nuw_implies_icmp_eq(i8 %x, i1 %c) {
|
|
; CHECK-LABEL: @trunc_nuw_implies_icmp_eq(
|
|
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X:%.*]] to i1
|
|
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[TRUNC]], i1 true, i1 [[C:%.*]]
|
|
; CHECK-NEXT: ret i1 [[SEL2]]
|
|
;
|
|
%trunc = trunc nuw i8 %x to i1
|
|
%cmp = icmp eq i8 %x, 0
|
|
%sel1 = select i1 %cmp, i1 %c, i1 false
|
|
%sel2 = select i1 %trunc, i1 true, i1 %sel1
|
|
ret i1 %sel2
|
|
}
|
|
|
|
define i1 @icmp_eq_implies_trunc_nuw(i8 %x, i1 %c) {
|
|
; CHECK-LABEL: @icmp_eq_implies_trunc_nuw(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 0
|
|
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CMP]], i1 true, i1 [[C:%.*]]
|
|
; CHECK-NEXT: ret i1 [[SEL2]]
|
|
;
|
|
%trunc = trunc nuw i8 %x to i1
|
|
%cmp = icmp eq i8 %x, 0
|
|
%sel1 = select i1 %trunc, i1 %c, i1 false
|
|
%sel2 = select i1 %cmp, i1 true, i1 %sel1
|
|
ret i1 %sel2
|
|
}
|
|
|
|
define <2 x i1> @trunc_nuw_implies_icmp_eq_vec(<2 x i8> %x, <2 x i1> %c) {
|
|
; CHECK-LABEL: @trunc_nuw_implies_icmp_eq_vec(
|
|
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw <2 x i8> [[X:%.*]] to <2 x i1>
|
|
; CHECK-NEXT: [[SEL2:%.*]] = select <2 x i1> [[TRUNC]], <2 x i1> splat (i1 true), <2 x i1> [[C:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[SEL2]]
|
|
;
|
|
%trunc = trunc nuw <2 x i8> %x to <2 x i1>
|
|
%cmp = icmp eq <2 x i8> %x, splat (i8 0)
|
|
%sel1 = select <2 x i1> %cmp, <2 x i1> %c, <2 x i1> splat (i1 false)
|
|
%sel2 = select <2 x i1> %trunc, <2 x i1> splat (i1 true), <2 x i1> %sel1
|
|
ret <2 x i1> %sel2
|
|
}
|
|
|
|
define <2 x i1> @icmp_eq_implies_trunc_nuw_vec(<2 x i8> %x, <2 x i1> %c) {
|
|
; CHECK-LABEL: @icmp_eq_implies_trunc_nuw_vec(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
|
|
; CHECK-NEXT: [[SEL2:%.*]] = select <2 x i1> [[CMP]], <2 x i1> splat (i1 true), <2 x i1> [[C:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[SEL2]]
|
|
;
|
|
%trunc = trunc nuw <2 x i8> %x to <2 x i1>
|
|
%cmp = icmp eq <2 x i8> %x, splat (i8 0)
|
|
%sel1 = select <2 x i1> %trunc, <2 x i1> %c, <2 x i1> splat (i1 false)
|
|
%sel2 = select <2 x i1> %cmp, <2 x i1> splat (i1 true), <2 x i1> %sel1
|
|
ret <2 x i1> %sel2
|
|
}
|
|
|
|
define i1 @neg_trunc_implies_icmp_eq(i8 %x, i1 %c) {
|
|
; CHECK-LABEL: @neg_trunc_implies_icmp_eq(
|
|
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 0
|
|
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CMP]], i1 [[C:%.*]], i1 false
|
|
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[TRUNC]], i1 true, i1 [[SEL1]]
|
|
; CHECK-NEXT: ret i1 [[SEL2]]
|
|
;
|
|
%trunc = trunc i8 %x to i1
|
|
%cmp = icmp eq i8 %x, 0
|
|
%sel1 = select i1 %cmp, i1 %c, i1 false
|
|
%sel2 = select i1 %trunc, i1 true, i1 %sel1
|
|
ret i1 %sel2
|
|
}
|
|
|
|
define i1 @neg_icmp_eq_implies_trunc(i8 %x, i1 %c) {
|
|
; CHECK-LABEL: @neg_icmp_eq_implies_trunc(
|
|
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 0
|
|
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[TRUNC]], i1 [[C:%.*]], i1 false
|
|
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CMP]], i1 true, i1 [[SEL1]]
|
|
; CHECK-NEXT: ret i1 [[SEL2]]
|
|
;
|
|
%trunc = trunc i8 %x to i1
|
|
%cmp = icmp eq i8 %x, 0
|
|
%sel1 = select i1 %trunc, i1 %c, i1 false
|
|
%sel2 = select i1 %cmp, i1 true, i1 %sel1
|
|
ret i1 %sel2
|
|
}
|
|
|
|
!0 = !{!"function_entry_count", i64 1000}
|
|
!1 = !{!"branch_weights", i32 2, i32 3}
|
|
;.
|
|
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
|
|
; CHECK: [[PROF1]] = !{!"unknown", !"instcombine"}
|
|
;.
|