; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=correlated-propagation < %s | FileCheck %s
define <2 x i1> @cmp1(<2 x i8> %a) {
; CHECK-LABEL: define <2 x i1> @cmp1(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[A]], <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%add = add nuw <2 x i8> %a, splat (i8 1)
%cmp = icmp ne <2 x i8> %add, zeroinitializer
ret <2 x i1> %cmp
}
define <2 x i1> @cmp2(<2 x i8> %a) {
; CHECK-LABEL: define <2 x i1> @cmp2(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[A]], <i8 5, i8 5>
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%add = add nuw <2 x i8> %a, splat (i8 5)
%cmp = icmp ugt <2 x i8> %add, splat (i8 2)
ret <2 x i1> %cmp
}
define <2 x i1> @cmp_nonsplat(<2 x i8> %a) {
; CHECK-LABEL: define <2 x i1> @cmp_nonsplat(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[A]], <i8 4, i8 5>
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%add = add nuw <2 x i8> %a, <i8 4, i8 5>
%cmp = icmp ugt <2 x i8> %add, <i8 2, i8 3>
ret <2 x i1> %cmp
}
; Handling this would require keeping track of ranges on a per-element basis.
define <2 x i1> @cmp_nonsplat_fail(<2 x i8> %a) {
; CHECK-LABEL: define <2 x i1> @cmp_nonsplat_fail(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[A]], <i8 3, i8 4>
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i8> [[ADD]], <i8 2, i8 3>
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%add = add nuw <2 x i8> %a, <i8 3, i8 4>
%cmp = icmp ugt <2 x i8> %add, <i8 2, i8 3>
ret <2 x i1> %cmp
}
define <2 x i1> @cmp_signedness(<2 x i8> %a) {
; CHECK-LABEL: define <2 x i1> @cmp_signedness(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i16> [[ZEXT]], <i16 5, i16 5>
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%cmp = icmp slt <2 x i16> %zext, splat (i16 5)
ret <2 x i1> %cmp
}
define <2 x i16> @infer_nowrap(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 1, 257) <2 x i16> @infer_nowrap(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], <i16 1, i16 1>
; CHECK-NEXT: ret <2 x i16> [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = add <2 x i16> %zext, splat (i16 1)
ret <2 x i16> %res
}
define <2 x i16> @infer_nowrap_nonsplat(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 1, 258) <2 x i16> @infer_nowrap_nonsplat(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], <i16 1, i16 2>
; CHECK-NEXT: ret <2 x i16> [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = add <2 x i16> %zext, <i16 1, i16 2>
ret <2 x i16> %res
}
define <vscale x 2 x i16> @infer_nowrap_scalable(<vscale x 2 x i8> %a) {
; CHECK-LABEL: define range(i16 1, 257) <vscale x 2 x i16> @infer_nowrap_scalable(
; CHECK-SAME: <vscale x 2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <vscale x 2 x i8> [[A]] to <vscale x 2 x i16>
; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <vscale x 2 x i16> [[ZEXT]], shufflevector (<vscale x 2 x i16> insertelement (<vscale x 2 x i16> poison, i16 1, i64 0), <vscale x 2 x i16> poison, <vscale x 2 x i32> zeroinitializer)
; CHECK-NEXT: ret <vscale x 2 x i16> [[RES]]
;
%zext = zext <vscale x 2 x i8> %a to <vscale x 2 x i16>
%res = add <vscale x 2 x i16> %zext, splat (i16 1)
ret <vscale x 2 x i16> %res
}
define <2 x i16> @infer_nowrap_poison(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 1, 257) <2 x i16> @infer_nowrap_poison(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], <i16 1, i16 poison>
; CHECK-NEXT: ret <2 x i16> [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = add <2 x i16> %zext, <i16 1, i16 poison>
ret <2 x i16> %res
}
define <2 x i16> @infer_nowrap_nonsplat_nsw_only(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 -1, 257) <2 x i16> @infer_nowrap_nonsplat_nsw_only(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES:%.*]] = add nsw <2 x i16> [[ZEXT]], <i16 1, i16 -1>
; CHECK-NEXT: ret <2 x i16> [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = add <2 x i16> %zext, <i16 1, i16 -1>
ret <2 x i16> %res
}
define <2 x i16> @abs(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 0, 256) <2 x i16> @abs(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: ret <2 x i16> [[ZEXT]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = call <2 x i16> @llvm.abs(<2 x i16> %zext, i1 false)
ret <2 x i16> %res
}
define <2 x i16> @saturating(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 1, 257) <2 x i16> @saturating(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], <i16 1, i16 1>
; CHECK-NEXT: ret <2 x i16> [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = call <2 x i16> @llvm.uadd.sat(<2 x i16> %zext, <2 x i16> splat (i16 1))
ret <2 x i16> %res
}
define {<2 x i16>, <2 x i1>} @with_overflow(<2 x i8> %a) {
; CHECK-LABEL: define { <2 x i16>, <2 x i1> } @with_overflow(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], <i16 1, i16 1>
; CHECK-NEXT: [[RES:%.*]] = insertvalue { <2 x i16>, <2 x i1> } { <2 x i16> poison, <2 x i1> zeroinitializer }, <2 x i16> [[RES1]], 0
; CHECK-NEXT: ret { <2 x i16>, <2 x i1> } [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = call {<2 x i16>, <2 x i1>} @llvm.uadd.with.overflow(<2 x i16> %zext, <2 x i16> splat (i16 1))
ret {<2 x i16>, <2 x i1>} %res
}
define <2 x i16> @srem1(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 0, 42) <2 x i16> @srem1(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES1_LHS_TRUNC:%.*]] = trunc <2 x i16> [[ZEXT]] to <2 x i8>
; CHECK-NEXT: [[RES12:%.*]] = urem <2 x i8> [[RES1_LHS_TRUNC]], <i8 42, i8 42>
; CHECK-NEXT: [[RES:%.*]] = zext <2 x i8> [[RES12]] to <2 x i16>
; CHECK-NEXT: ret <2 x i16> [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = srem <2 x i16> %zext, splat (i16 42)
ret <2 x i16> %res
}
define <2 x i16> @srem2(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 -41, 42) <2 x i16> @srem2(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = sext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES_LHS_TRUNC:%.*]] = trunc <2 x i16> [[ZEXT]] to <2 x i8>
; CHECK-NEXT: [[RES1:%.*]] = srem <2 x i8> [[RES_LHS_TRUNC]], <i8 42, i8 42>
; CHECK-NEXT: [[RES:%.*]] = sext <2 x i8> [[RES1]] to <2 x i16>
; CHECK-NEXT: ret <2 x i16> [[RES]]
;
%zext = sext <2 x i8> %a to <2 x i16>
%res = srem <2 x i16> %zext, splat (i16 42)
ret <2 x i16> %res
}
define <2 x i16> @ashr(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 0, 128) <2 x i16> @ashr(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES:%.*]] = lshr <2 x i16> [[ZEXT]], <i16 1, i16 1>
; CHECK-NEXT: ret <2 x i16> [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = ashr <2 x i16> %zext, splat (i16 1)
ret <2 x i16> %res
}
define <2 x i32> @sext(<2 x i8> %a) {
; CHECK-LABEL: define range(i32 0, 256) <2 x i32> @sext(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES:%.*]] = zext nneg <2 x i16> [[ZEXT]] to <2 x i32>
; CHECK-NEXT: ret <2 x i32> [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = sext <2 x i16> %zext to <2 x i32>
ret <2 x i32> %res
}
define <2 x float> @sitofp(<2 x i8> %a) {
; CHECK-LABEL: define <2 x float> @sitofp(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: [[RES:%.*]] = uitofp nneg <2 x i16> [[ZEXT]] to <2 x float>
; CHECK-NEXT: ret <2 x float> [[RES]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = sitofp <2 x i16> %zext to <2 x float>
ret <2 x float> %res
}
define <2 x i16> @and(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 0, 256) <2 x i16> @and(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: ret <2 x i16> [[ZEXT]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = and <2 x i16> %zext, splat (i16 u0xff)
ret <2 x i16> %res
}
define <2 x i16> @and_with_poison(<2 x i8> %a) {
; CHECK-LABEL: define range(i16 0, 256) <2 x i16> @and_with_poison(
; CHECK-SAME: <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: ret <2 x i16> [[ZEXT]]
;
%zext = zext <2 x i8> %a to <2 x i16>
%res = and <2 x i16> %zext, <i16 u0xff, i16 poison>
ret <2 x i16> %res
}
define <4 x i64> @issue_97674_getConstantOnEdge(i1 %cond) {
; CHECK-LABEL: define range(i64 0, 2) <4 x i64> @issue_97674_getConstantOnEdge(
; CHECK-SAME: i1 [[COND:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
; CHECK: [[IF_THEN]]:
; CHECK-NEXT: [[FOLDS:%.*]] = add nuw nsw <4 x i64> zeroinitializer, <i64 1, i64 1, i64 1, i64 1>
; CHECK-NEXT: br label %[[IF_END]]
; CHECK: [[IF_END]]:
; CHECK-NEXT: [[R:%.*]] = phi <4 x i64> [ <i64 1, i64 1, i64 1, i64 1>, %[[IF_THEN]] ], [ zeroinitializer, %[[ENTRY]] ]
; CHECK-NEXT: ret <4 x i64> [[R]]
;
entry:
br i1 %cond, label %if.then, label %if.end
if.then:
%folds = add <4 x i64> zeroinitializer, <i64 1, i64 1, i64 1, i64 1>
br label %if.end
if.end:
%r = phi <4 x i64> [ %folds, %if.then ], [ zeroinitializer, %entry ]
ret <4 x i64> %r
}
define <4 x i64> @issue_97674_getConstant() {
; CHECK-LABEL: define <4 x i64> @issue_97674_getConstant() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[FOLDS:%.*]] = add nuw nsw <4 x i64> zeroinitializer, zeroinitializer
; CHECK-NEXT: ret <4 x i64> zeroinitializer
;
entry:
%folds = add <4 x i64> zeroinitializer, zeroinitializer
ret <4 x i64> %folds
}
define <2 x i16> @phi_merge1(i1 %c, <2 x i8> %a) {
; CHECK-LABEL: define range(i16 2, 259) <2 x i16> @phi_merge1(
; CHECK-SAME: i1 [[C:%.*]], <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[JOIN:.*]]
; CHECK: [[IF]]:
; CHECK-NEXT: br label %[[JOIN]]
; CHECK: [[JOIN]]:
; CHECK-NEXT: [[PHI:%.*]] = phi <2 x i16> [ [[ZEXT]], %[[ENTRY]] ], [ <i16 1, i16 2>, %[[IF]] ]
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw <2 x i16> [[PHI]], <i16 2, i16 3>
; CHECK-NEXT: ret <2 x i16> [[ADD]]
;
entry:
%zext = zext <2 x i8> %a to <2 x i16>
br i1 %c, label %if, label %join
if:
br label %join
join:
%phi = phi <2 x i16> [ %zext, %entry ], [ <i16 1, i16 2>, %if ]
%add = add <2 x i16> %phi, <i16 2, i16 3>
ret <2 x i16> %add
}
define <2 x i16> @phi_merge2(i1 %c, <2 x i8> %a) {
; CHECK-LABEL: define range(i16 2, 259) <2 x i16> @phi_merge2(
; CHECK-SAME: i1 [[C:%.*]], <2 x i8> [[A:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16>
; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[JOIN:.*]]
; CHECK: [[IF]]:
; CHECK-NEXT: br label %[[JOIN]]
; CHECK: [[JOIN]]:
; CHECK-NEXT: [[PHI:%.*]] = phi <2 x i16> [ <i16 1, i16 2>, %[[ENTRY]] ], [ [[ZEXT]], %[[IF]] ]
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw <2 x i16> [[PHI]], <i16 2, i16 3>
; CHECK-NEXT: ret <2 x i16> [[ADD]]
;
entry:
%zext = zext <2 x i8> %a to <2 x i16>
br i1 %c, label %if, label %join
if:
br label %join
join:
%phi = phi <2 x i16> [ <i16 1, i16 2>, %entry ], [ %zext, %if ]
%add = add <2 x i16> %phi, <i16 2, i16 3>
ret <2 x i16> %add
}
;; Check if ICMP instruction is constant folded or not.
define <2 x i1> @insertelement_fold1() {
; CHECK-LABEL: define <2 x i1> @insertelement_fold1() {
; CHECK-NEXT: [[IE1:%.*]] = insertelement <2 x i32> poison, i32 10, i64 0
; CHECK-NEXT: [[IE2:%.*]] = insertelement <2 x i32> [[IE1]], i32 20, i64 1
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%ie1 = insertelement <2 x i32> poison, i32 10, i64 0
%ie2 = insertelement <2 x i32> %ie1, i32 20, i64 1
%icmp1 = icmp slt <2 x i32> %ie2, <i32 1024, i32 1024>
ret <2 x i1> %icmp1
}
;; Check if LVI is able to handle constant vector operands
;; in InsertElementInst and CVP is able to fold ICMP instruction.
define <2 x i1> @insertelement_fold2() {
; CHECK-LABEL: define <2 x i1> @insertelement_fold2() {
; CHECK-NEXT: [[IE1:%.*]] = insertelement <2 x i32> <i32 poison, i32 20>, i32 10, i64 0
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%ie1 = insertelement <2 x i32> <i32 poison, i32 20>, i32 10, i64 0
%icmp1 = icmp slt <2 x i32> %ie1, <i32 1024, i32 1024>
ret <2 x i1> %icmp1
}