167 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' -S %s | FileCheck %s3 4target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"5target triple = "arm64-apple-ios"6 7; It's profitable to convert the zext to a shuffle, which in turn will be8; lowered to 4 tbl instructions. The masks are materialized outside the loop.9define void @zext_v16i8_to_v16i32_in_loop(ptr %src, ptr %dst) {10; CHECK-LABEL: @zext_v16i8_to_v16i32_in_loop(11; CHECK-NEXT: entry:12; CHECK-NEXT: br label [[LOOP:%.*]]13; CHECK: loop:14; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]15; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[IV]]16; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, ptr [[SRC_GEP]], align 1617; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[LOAD]], <16 x i8> <i8 0, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison>, <64 x i32> <i32 0, i32 16, i32 16, i32 16, i32 1, i32 16, i32 16, i32 16, i32 2, i32 16, i32 16, i32 16, i32 3, i32 16, i32 16, i32 16, i32 4, i32 16, i32 16, i32 16, i32 5, i32 16, i32 16, i32 16, i32 6, i32 16, i32 16, i32 16, i32 7, i32 16, i32 16, i32 16, i32 8, i32 16, i32 16, i32 16, i32 9, i32 16, i32 16, i32 16, i32 10, i32 16, i32 16, i32 16, i32 11, i32 16, i32 16, i32 16, i32 12, i32 16, i32 16, i32 16, i32 13, i32 16, i32 16, i32 16, i32 14, i32 16, i32 16, i32 16, i32 15, i32 16, i32 16, i32 16>18; CHECK-NEXT: [[TMP1:%.*]] = bitcast <64 x i8> [[TMP0]] to <16 x i32>19; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[IV]]20; CHECK-NEXT: store <16 x i32> [[TMP1]], ptr [[DST_GEP]], align 6421; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1622; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 12823; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]24; CHECK: exit:25; CHECK-NEXT: ret void26;27entry:28 br label %loop29 30loop:31 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]32 %src.gep = getelementptr i8, ptr %src, i64 %iv33 %load = load <16 x i8>, ptr %src.gep34 %ext = zext <16 x i8> %load to <16 x i32>35 %dst.gep = getelementptr i32, ptr %dst, i64 %iv36 store <16 x i32> %ext, ptr %dst.gep37 %iv.next = add nuw i64 %iv, 1638 %ec = icmp eq i64 %iv.next, 12839 br i1 %ec, label %exit, label %loop40 41exit:42 ret void43}44 45; Not profitable to use shuffle/tbl, as 4 tbls + materializing the masks46; require more instructions than lowering zext directly.47define void @zext_v16i8_to_v16i32_no_loop(ptr %src, ptr %dst) {48; CHECK-LABEL: @zext_v16i8_to_v16i32_no_loop(49; CHECK-NEXT: entry:50; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, ptr [[SRC:%.*]], align 1651; CHECK-NEXT: [[EXT:%.*]] = zext <16 x i8> [[LOAD]] to <16 x i32>52; CHECK-NEXT: store <16 x i32> [[EXT]], ptr [[DST:%.*]], align 6453; CHECK-NEXT: ret void54;55entry:56 %load = load <16 x i8>, ptr %src57 %ext = zext <16 x i8> %load to <16 x i32>58 store <16 x i32> %ext, ptr %dst59 ret void60}61 62define void @zext_v16i8_to_v16i16_in_loop(ptr %src, ptr %dst) {63; CHECK-LABEL: @zext_v16i8_to_v16i16_in_loop(64; CHECK-NEXT: entry:65; CHECK-NEXT: br label [[LOOP:%.*]]66; CHECK: loop:67; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]68; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[IV]]69; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, ptr [[SRC_GEP]], align 1670; CHECK-NEXT: [[EXT:%.*]] = zext <16 x i8> [[LOAD]] to <16 x i16>71; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i16, ptr [[DST:%.*]], i64 [[IV]]72; CHECK-NEXT: store <16 x i16> [[EXT]], ptr [[DST_GEP]], align 3273; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1674; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 12875; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]76; CHECK: exit:77; CHECK-NEXT: ret void78;79entry:80 br label %loop81 82loop:83 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]84 %src.gep = getelementptr i8, ptr %src, i64 %iv85 %load = load <16 x i8>, ptr %src.gep86 %ext = zext <16 x i8> %load to <16 x i16>87 %dst.gep = getelementptr i16, ptr %dst, i64 %iv88 store <16 x i16> %ext, ptr %dst.gep89 %iv.next = add nuw i64 %iv, 1690 %ec = icmp eq i64 %iv.next, 12891 br i1 %ec, label %exit, label %loop92 93exit:94 ret void95}96 97define void @zext_v8i8_to_v8i32_in_loop(ptr %src, ptr %dst) {98; CHECK-LABEL: @zext_v8i8_to_v8i32_in_loop(99; CHECK-NEXT: entry:100; CHECK-NEXT: br label [[LOOP:%.*]]101; CHECK: loop:102; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]103; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[IV]]104; CHECK-NEXT: [[LOAD:%.*]] = load <8 x i8>, ptr [[SRC_GEP]], align 8105; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i8> [[LOAD]], <8 x i8> <i8 0, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison>, <32 x i32> <i32 0, i32 8, i32 8, i32 8, i32 1, i32 8, i32 8, i32 8, i32 2, i32 8, i32 8, i32 8, i32 3, i32 8, i32 8, i32 8, i32 4, i32 8, i32 8, i32 8, i32 5, i32 8, i32 8, i32 8, i32 6, i32 8, i32 8, i32 8, i32 7, i32 8, i32 8, i32 8>106; CHECK-NEXT: [[TMP1:%.*]] = bitcast <32 x i8> [[TMP0]] to <8 x i32>107; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[IV]]108; CHECK-NEXT: store <8 x i32> [[TMP1]], ptr [[DST_GEP]], align 32109; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 16110; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 128111; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]112; CHECK: exit:113; CHECK-NEXT: ret void114;115entry:116 br label %loop117 118loop:119 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]120 %src.gep = getelementptr i8, ptr %src, i64 %iv121 %load = load <8 x i8>, ptr %src.gep122 %ext = zext <8 x i8> %load to <8 x i32>123 %dst.gep = getelementptr i32, ptr %dst, i64 %iv124 store <8 x i32> %ext, ptr %dst.gep125 %iv.next = add nuw i64 %iv, 16126 %ec = icmp eq i64 %iv.next, 128127 br i1 %ec, label %exit, label %loop128 129exit:130 ret void131}132 133define void @zext_v16i8_to_v16i64_in_loop(ptr %src, ptr %dst) {134; CHECK-LABEL: @zext_v16i8_to_v16i64_in_loop(135; CHECK-NEXT: entry:136; CHECK-NEXT: br label [[LOOP:%.*]]137; CHECK: loop:138; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]139; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[IV]]140; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, ptr [[SRC_GEP]], align 16141; CHECK-NEXT: [[EXT:%.*]] = zext <16 x i8> [[LOAD]] to <16 x i64>142; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i64, ptr [[DST:%.*]], i64 [[IV]]143; CHECK-NEXT: store <16 x i64> [[EXT]], ptr [[DST_GEP]], align 128144; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 16145; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 128146; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]147; CHECK: exit:148; CHECK-NEXT: ret void149;150entry:151 br label %loop152 153loop:154 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]155 %src.gep = getelementptr i8, ptr %src, i64 %iv156 %load = load <16 x i8>, ptr %src.gep157 %ext = zext <16 x i8> %load to <16 x i64>158 %dst.gep = getelementptr i64, ptr %dst, i64 %iv159 store <16 x i64> %ext, ptr %dst.gep160 %iv.next = add nuw i64 %iv, 16161 %ec = icmp eq i64 %iv.next, 128162 br i1 %ec, label %exit, label %loop163 164exit:165 ret void166}167