1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -S -passes=correlated-propagation < %s | FileCheck %s 3 4define <2 x i1> @cmp1(<2 x i8> %a) { 5; CHECK-LABEL: define <2 x i1> @cmp1( 6; CHECK-SAME: <2 x i8> [[A:%.*]]) { 7; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[A]], splat (i8 1) 8; CHECK-NEXT: ret <2 x i1> splat (i1 true) 9; 10 %add = add nuw <2 x i8> %a, splat (i8 1) 11 %cmp = icmp ne <2 x i8> %add, zeroinitializer 12 ret <2 x i1> %cmp 13} 14 15define <2 x i1> @cmp2(<2 x i8> %a) { 16; CHECK-LABEL: define <2 x i1> @cmp2( 17; CHECK-SAME: <2 x i8> [[A:%.*]]) { 18; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[A]], splat (i8 5) 19; CHECK-NEXT: ret <2 x i1> splat (i1 true) 20; 21 %add = add nuw <2 x i8> %a, splat (i8 5) 22 %cmp = icmp ugt <2 x i8> %add, splat (i8 2) 23 ret <2 x i1> %cmp 24} 25 26define <2 x i1> @cmp_nonsplat(<2 x i8> %a) { 27; CHECK-LABEL: define <2 x i1> @cmp_nonsplat( 28; CHECK-SAME: <2 x i8> [[A:%.*]]) { 29; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[A]], <i8 4, i8 5> 30; CHECK-NEXT: ret <2 x i1> splat (i1 true) 31; 32 %add = add nuw <2 x i8> %a, <i8 4, i8 5> 33 %cmp = icmp ugt <2 x i8> %add, <i8 2, i8 3> 34 ret <2 x i1> %cmp 35} 36 37; Handling this would require keeping track of ranges on a per-element basis. 38define <2 x i1> @cmp_nonsplat_fail(<2 x i8> %a) { 39; CHECK-LABEL: define <2 x i1> @cmp_nonsplat_fail( 40; CHECK-SAME: <2 x i8> [[A:%.*]]) { 41; CHECK-NEXT: [[ADD:%.*]] = add nuw <2 x i8> [[A]], <i8 3, i8 4> 42; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i8> [[ADD]], <i8 2, i8 3> 43; CHECK-NEXT: ret <2 x i1> [[CMP]] 44; 45 %add = add nuw <2 x i8> %a, <i8 3, i8 4> 46 %cmp = icmp ugt <2 x i8> %add, <i8 2, i8 3> 47 ret <2 x i1> %cmp 48} 49 50define <2 x i1> @cmp_signedness(<2 x i8> %a) { 51; CHECK-LABEL: define <2 x i1> @cmp_signedness( 52; CHECK-SAME: <2 x i8> [[A:%.*]]) { 53; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 54; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult <2 x i16> [[ZEXT]], splat (i16 5) 55; CHECK-NEXT: ret <2 x i1> [[CMP]] 56; 57 %zext = zext <2 x i8> %a to <2 x i16> 58 %cmp = icmp slt <2 x i16> %zext, splat (i16 5) 59 ret <2 x i1> %cmp 60} 61 62define <2 x i16> @infer_nowrap(<2 x i8> %a) { 63; CHECK-LABEL: define range(i16 1, 257) <2 x i16> @infer_nowrap( 64; CHECK-SAME: <2 x i8> [[A:%.*]]) { 65; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 66; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], splat (i16 1) 67; CHECK-NEXT: ret <2 x i16> [[RES]] 68; 69 %zext = zext <2 x i8> %a to <2 x i16> 70 %res = add <2 x i16> %zext, splat (i16 1) 71 ret <2 x i16> %res 72} 73 74define <2 x i16> @infer_nowrap_nonsplat(<2 x i8> %a) { 75; CHECK-LABEL: define range(i16 1, 258) <2 x i16> @infer_nowrap_nonsplat( 76; CHECK-SAME: <2 x i8> [[A:%.*]]) { 77; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 78; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], <i16 1, i16 2> 79; CHECK-NEXT: ret <2 x i16> [[RES]] 80; 81 %zext = zext <2 x i8> %a to <2 x i16> 82 %res = add <2 x i16> %zext, <i16 1, i16 2> 83 ret <2 x i16> %res 84} 85 86define <vscale x 2 x i16> @infer_nowrap_scalable(<vscale x 2 x i8> %a) { 87; CHECK-LABEL: define range(i16 1, 257) <vscale x 2 x i16> @infer_nowrap_scalable( 88; CHECK-SAME: <vscale x 2 x i8> [[A:%.*]]) { 89; CHECK-NEXT: [[ZEXT:%.*]] = zext <vscale x 2 x i8> [[A]] to <vscale x 2 x i16> 90; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <vscale x 2 x i16> [[ZEXT]], splat (i16 1) 91; CHECK-NEXT: ret <vscale x 2 x i16> [[RES]] 92; 93 %zext = zext <vscale x 2 x i8> %a to <vscale x 2 x i16> 94 %res = add <vscale x 2 x i16> %zext, splat (i16 1) 95 ret <vscale x 2 x i16> %res 96} 97 98define <2 x i16> @infer_nowrap_poison(<2 x i8> %a) { 99; CHECK-LABEL: define range(i16 1, 257) <2 x i16> @infer_nowrap_poison( 100; CHECK-SAME: <2 x i8> [[A:%.*]]) { 101; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 102; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], <i16 1, i16 poison> 103; CHECK-NEXT: ret <2 x i16> [[RES]] 104; 105 %zext = zext <2 x i8> %a to <2 x i16> 106 %res = add <2 x i16> %zext, <i16 1, i16 poison> 107 ret <2 x i16> %res 108} 109 110define <2 x i16> @infer_nowrap_nonsplat_nsw_only(<2 x i8> %a) { 111; CHECK-LABEL: define range(i16 -1, 257) <2 x i16> @infer_nowrap_nonsplat_nsw_only( 112; CHECK-SAME: <2 x i8> [[A:%.*]]) { 113; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 114; CHECK-NEXT: [[RES:%.*]] = add nsw <2 x i16> [[ZEXT]], <i16 1, i16 -1> 115; CHECK-NEXT: ret <2 x i16> [[RES]] 116; 117 %zext = zext <2 x i8> %a to <2 x i16> 118 %res = add <2 x i16> %zext, <i16 1, i16 -1> 119 ret <2 x i16> %res 120} 121 122define <2 x i16> @abs(<2 x i8> %a) { 123; CHECK-LABEL: define range(i16 0, 256) <2 x i16> @abs( 124; CHECK-SAME: <2 x i8> [[A:%.*]]) { 125; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 126; CHECK-NEXT: ret <2 x i16> [[ZEXT]] 127; 128 %zext = zext <2 x i8> %a to <2 x i16> 129 %res = call <2 x i16> @llvm.abs(<2 x i16> %zext, i1 false) 130 ret <2 x i16> %res 131} 132 133define <2 x i16> @saturating(<2 x i8> %a) { 134; CHECK-LABEL: define range(i16 1, 257) <2 x i16> @saturating( 135; CHECK-SAME: <2 x i8> [[A:%.*]]) { 136; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 137; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], splat (i16 1) 138; CHECK-NEXT: ret <2 x i16> [[RES]] 139; 140 %zext = zext <2 x i8> %a to <2 x i16> 141 %res = call <2 x i16> @llvm.uadd.sat(<2 x i16> %zext, <2 x i16> splat (i16 1)) 142 ret <2 x i16> %res 143} 144 145define {<2 x i16>, <2 x i1>} @with_overflow(<2 x i8> %a) { 146; CHECK-LABEL: define { <2 x i16>, <2 x i1> } @with_overflow( 147; CHECK-SAME: <2 x i8> [[A:%.*]]) { 148; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 149; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw <2 x i16> [[ZEXT]], splat (i16 1) 150; CHECK-NEXT: [[RES:%.*]] = insertvalue { <2 x i16>, <2 x i1> } { <2 x i16> poison, <2 x i1> zeroinitializer }, <2 x i16> [[RES1]], 0 151; CHECK-NEXT: ret { <2 x i16>, <2 x i1> } [[RES]] 152; 153 %zext = zext <2 x i8> %a to <2 x i16> 154 %res = call {<2 x i16>, <2 x i1>} @llvm.uadd.with.overflow(<2 x i16> %zext, <2 x i16> splat (i16 1)) 155 ret {<2 x i16>, <2 x i1>} %res 156} 157 158define <2 x i16> @srem1(<2 x i8> %a) { 159; CHECK-LABEL: define range(i16 0, 42) <2 x i16> @srem1( 160; CHECK-SAME: <2 x i8> [[A:%.*]]) { 161; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 162; CHECK-NEXT: [[RES1_LHS_TRUNC:%.*]] = trunc <2 x i16> [[ZEXT]] to <2 x i8> 163; CHECK-NEXT: [[RES12:%.*]] = urem <2 x i8> [[RES1_LHS_TRUNC]], splat (i8 42) 164; CHECK-NEXT: [[RES:%.*]] = zext <2 x i8> [[RES12]] to <2 x i16> 165; CHECK-NEXT: ret <2 x i16> [[RES]] 166; 167 %zext = zext <2 x i8> %a to <2 x i16> 168 %res = srem <2 x i16> %zext, splat (i16 42) 169 ret <2 x i16> %res 170} 171 172define <2 x i16> @srem2(<2 x i8> %a) { 173; CHECK-LABEL: define range(i16 -41, 42) <2 x i16> @srem2( 174; CHECK-SAME: <2 x i8> [[A:%.*]]) { 175; CHECK-NEXT: [[ZEXT:%.*]] = sext <2 x i8> [[A]] to <2 x i16> 176; CHECK-NEXT: [[RES_LHS_TRUNC:%.*]] = trunc <2 x i16> [[ZEXT]] to <2 x i8> 177; CHECK-NEXT: [[RES1:%.*]] = srem <2 x i8> [[RES_LHS_TRUNC]], splat (i8 42) 178; CHECK-NEXT: [[RES:%.*]] = sext <2 x i8> [[RES1]] to <2 x i16> 179; CHECK-NEXT: ret <2 x i16> [[RES]] 180; 181 %zext = sext <2 x i8> %a to <2 x i16> 182 %res = srem <2 x i16> %zext, splat (i16 42) 183 ret <2 x i16> %res 184} 185 186define <2 x i16> @ashr(<2 x i8> %a) { 187; CHECK-LABEL: define range(i16 0, 128) <2 x i16> @ashr( 188; CHECK-SAME: <2 x i8> [[A:%.*]]) { 189; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 190; CHECK-NEXT: [[RES:%.*]] = lshr <2 x i16> [[ZEXT]], splat (i16 1) 191; CHECK-NEXT: ret <2 x i16> [[RES]] 192; 193 %zext = zext <2 x i8> %a to <2 x i16> 194 %res = ashr <2 x i16> %zext, splat (i16 1) 195 ret <2 x i16> %res 196} 197 198define <2 x i32> @sext(<2 x i8> %a) { 199; CHECK-LABEL: define range(i32 0, 256) <2 x i32> @sext( 200; CHECK-SAME: <2 x i8> [[A:%.*]]) { 201; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 202; CHECK-NEXT: [[RES:%.*]] = zext nneg <2 x i16> [[ZEXT]] to <2 x i32> 203; CHECK-NEXT: ret <2 x i32> [[RES]] 204; 205 %zext = zext <2 x i8> %a to <2 x i16> 206 %res = sext <2 x i16> %zext to <2 x i32> 207 ret <2 x i32> %res 208} 209 210define <2 x float> @sitofp(<2 x i8> %a) { 211; CHECK-LABEL: define <2 x float> @sitofp( 212; CHECK-SAME: <2 x i8> [[A:%.*]]) { 213; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 214; CHECK-NEXT: [[RES:%.*]] = uitofp nneg <2 x i16> [[ZEXT]] to <2 x float> 215; CHECK-NEXT: ret <2 x float> [[RES]] 216; 217 %zext = zext <2 x i8> %a to <2 x i16> 218 %res = sitofp <2 x i16> %zext to <2 x float> 219 ret <2 x float> %res 220} 221 222define <2 x i16> @and(<2 x i8> %a) { 223; CHECK-LABEL: define range(i16 0, 256) <2 x i16> @and( 224; CHECK-SAME: <2 x i8> [[A:%.*]]) { 225; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 226; CHECK-NEXT: ret <2 x i16> [[ZEXT]] 227; 228 %zext = zext <2 x i8> %a to <2 x i16> 229 %res = and <2 x i16> %zext, splat (i16 u0xff) 230 ret <2 x i16> %res 231} 232 233define <2 x i16> @and_with_poison(<2 x i8> %a) { 234; CHECK-LABEL: define range(i16 0, 256) <2 x i16> @and_with_poison( 235; CHECK-SAME: <2 x i8> [[A:%.*]]) { 236; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 237; CHECK-NEXT: ret <2 x i16> [[ZEXT]] 238; 239 %zext = zext <2 x i8> %a to <2 x i16> 240 %res = and <2 x i16> %zext, <i16 u0xff, i16 poison> 241 ret <2 x i16> %res 242} 243 244define <4 x i64> @issue_97674_getConstantOnEdge(i1 %cond) { 245; CHECK-LABEL: define range(i64 0, 2) <4 x i64> @issue_97674_getConstantOnEdge( 246; CHECK-SAME: i1 [[COND:%.*]]) { 247; CHECK-NEXT: [[ENTRY:.*]]: 248; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_END:.*]] 249; CHECK: [[IF_THEN]]: 250; CHECK-NEXT: [[FOLDS:%.*]] = add nuw nsw <4 x i64> zeroinitializer, splat (i64 1) 251; CHECK-NEXT: br label %[[IF_END]] 252; CHECK: [[IF_END]]: 253; CHECK-NEXT: [[R:%.*]] = phi <4 x i64> [ splat (i64 1), %[[IF_THEN]] ], [ zeroinitializer, %[[ENTRY]] ] 254; CHECK-NEXT: ret <4 x i64> [[R]] 255; 256entry: 257 br i1 %cond, label %if.then, label %if.end 258 259if.then: 260 %folds = add <4 x i64> zeroinitializer, <i64 1, i64 1, i64 1, i64 1> 261 br label %if.end 262 263if.end: 264 %r = phi <4 x i64> [ %folds, %if.then ], [ zeroinitializer, %entry ] 265 ret <4 x i64> %r 266} 267 268define <4 x i64> @issue_97674_getConstant() { 269; CHECK-LABEL: define <4 x i64> @issue_97674_getConstant() { 270; CHECK-NEXT: [[ENTRY:.*:]] 271; CHECK-NEXT: [[FOLDS:%.*]] = add nuw nsw <4 x i64> zeroinitializer, zeroinitializer 272; CHECK-NEXT: ret <4 x i64> zeroinitializer 273; 274entry: 275 %folds = add <4 x i64> zeroinitializer, zeroinitializer 276 ret <4 x i64> %folds 277} 278 279define <2 x i16> @phi_merge1(i1 %c, <2 x i8> %a) { 280; CHECK-LABEL: define range(i16 2, 259) <2 x i16> @phi_merge1( 281; CHECK-SAME: i1 [[C:%.*]], <2 x i8> [[A:%.*]]) { 282; CHECK-NEXT: [[ENTRY:.*]]: 283; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 284; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[JOIN:.*]] 285; CHECK: [[IF]]: 286; CHECK-NEXT: br label %[[JOIN]] 287; CHECK: [[JOIN]]: 288; CHECK-NEXT: [[PHI:%.*]] = phi <2 x i16> [ [[ZEXT]], %[[ENTRY]] ], [ <i16 1, i16 2>, %[[IF]] ] 289; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw <2 x i16> [[PHI]], <i16 2, i16 3> 290; CHECK-NEXT: ret <2 x i16> [[ADD]] 291; 292entry: 293 %zext = zext <2 x i8> %a to <2 x i16> 294 br i1 %c, label %if, label %join 295 296if: 297 br label %join 298 299join: 300 %phi = phi <2 x i16> [ %zext, %entry ], [ <i16 1, i16 2>, %if ] 301 %add = add <2 x i16> %phi, <i16 2, i16 3> 302 ret <2 x i16> %add 303} 304 305define <2 x i16> @phi_merge2(i1 %c, <2 x i8> %a) { 306; CHECK-LABEL: define range(i16 2, 259) <2 x i16> @phi_merge2( 307; CHECK-SAME: i1 [[C:%.*]], <2 x i8> [[A:%.*]]) { 308; CHECK-NEXT: [[ENTRY:.*]]: 309; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i8> [[A]] to <2 x i16> 310; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[JOIN:.*]] 311; CHECK: [[IF]]: 312; CHECK-NEXT: br label %[[JOIN]] 313; CHECK: [[JOIN]]: 314; CHECK-NEXT: [[PHI:%.*]] = phi <2 x i16> [ <i16 1, i16 2>, %[[ENTRY]] ], [ [[ZEXT]], %[[IF]] ] 315; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw <2 x i16> [[PHI]], <i16 2, i16 3> 316; CHECK-NEXT: ret <2 x i16> [[ADD]] 317; 318entry: 319 %zext = zext <2 x i8> %a to <2 x i16> 320 br i1 %c, label %if, label %join 321 322if: 323 br label %join 324 325join: 326 %phi = phi <2 x i16> [ <i16 1, i16 2>, %entry ], [ %zext, %if ] 327 %add = add <2 x i16> %phi, <i16 2, i16 3> 328 ret <2 x i16> %add 329} 330 331;; Check if ICMP instruction is constant folded or not. 332define <2 x i1> @insertelement_fold1() { 333; CHECK-LABEL: define <2 x i1> @insertelement_fold1() { 334; CHECK-NEXT: [[IE1:%.*]] = insertelement <2 x i32> poison, i32 10, i64 0 335; CHECK-NEXT: [[IE2:%.*]] = insertelement <2 x i32> [[IE1]], i32 20, i64 1 336; CHECK-NEXT: ret <2 x i1> splat (i1 true) 337; 338 %ie1 = insertelement <2 x i32> poison, i32 10, i64 0 339 %ie2 = insertelement <2 x i32> %ie1, i32 20, i64 1 340 %icmp1 = icmp slt <2 x i32> %ie2, <i32 1024, i32 1024> 341 ret <2 x i1> %icmp1 342} 343 344;; Check if LVI is able to handle constant vector operands 345;; in InsertElementInst and CVP is able to fold ICMP instruction. 346define <2 x i1> @insertelement_fold2() { 347; CHECK-LABEL: define <2 x i1> @insertelement_fold2() { 348; CHECK-NEXT: [[IE1:%.*]] = insertelement <2 x i32> <i32 poison, i32 20>, i32 10, i64 0 349; CHECK-NEXT: ret <2 x i1> splat (i1 true) 350; 351 %ie1 = insertelement <2 x i32> <i32 poison, i32 20>, i32 10, i64 0 352 %icmp1 = icmp slt <2 x i32> %ie1, <i32 1024, i32 1024> 353 ret <2 x i1> %icmp1 354} 355 356@g = external global i32 357 358define <2 x i16> @insertelement_constexpr() { 359; CHECK-LABEL: define <2 x i16> @insertelement_constexpr() { 360; CHECK-NEXT: [[INS:%.*]] = insertelement <2 x i16> poison, i16 ptrtoint (ptr @g to i16), i32 0 361; CHECK-NEXT: ret <2 x i16> [[INS]] 362; 363 %ins = insertelement <2 x i16> poison, i16 ptrtoint (ptr @g to i16), i32 0 364 ret <2 x i16> %ins 365} 366