| ; 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]], splat (i8 1) |
| ; CHECK-NEXT: ret <2 x i1> splat (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]], splat (i8 5) |
| ; CHECK-NEXT: ret <2 x i1> splat (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> splat (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 samesign ult <2 x i16> [[ZEXT]], splat (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]], splat (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]], splat (i16 1) |
| ; 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]], splat (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]], splat (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]], splat (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]], splat (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]], splat (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, splat (i64 1) |
| ; CHECK-NEXT: br label %[[IF_END]] |
| ; CHECK: [[IF_END]]: |
| ; CHECK-NEXT: [[R:%.*]] = phi <4 x i64> [ splat (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> splat (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> splat (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 |
| } |
| |
| @g = external global i32 |
| |
| define <2 x i16> @insertelement_constexpr() { |
| ; CHECK-LABEL: define <2 x i16> @insertelement_constexpr() { |
| ; CHECK-NEXT: [[INS:%.*]] = insertelement <2 x i16> poison, i16 ptrtoint (ptr @g to i16), i32 0 |
| ; CHECK-NEXT: ret <2 x i16> [[INS]] |
| ; |
| %ins = insertelement <2 x i16> poison, i16 ptrtoint (ptr @g to i16), i32 0 |
| ret <2 x i16> %ins |
| } |