1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -mtriple=armv7-apple-darwin < %s -codegenprepare -S | FileCheck -check-prefix=NEON %s 3; RUN: opt -mtriple=armv6-unknown-linux < %s -codegenprepare -S | FileCheck -check-prefix=NONEON %s 4 5define <8 x i16> @sink_zext(<8 x i8> %a, <8 x i8> %b, i1 %c) { 6; NEON-LABEL: @sink_zext( 7; NEON-NEXT: entry: 8; NEON-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 9; NEON: if.then: 10; NEON-NEXT: [[ZB_1:%.*]] = zext <8 x i8> [[B:%.*]] to <8 x i16> 11; NEON-NEXT: [[TMP0:%.*]] = zext <8 x i8> [[A:%.*]] to <8 x i16> 12; NEON-NEXT: [[RES_1:%.*]] = add <8 x i16> [[TMP0]], [[ZB_1]] 13; NEON-NEXT: ret <8 x i16> [[RES_1]] 14; NEON: if.else: 15; NEON-NEXT: [[ZB_2:%.*]] = zext <8 x i8> [[B]] to <8 x i16> 16; NEON-NEXT: [[TMP1:%.*]] = zext <8 x i8> [[A]] to <8 x i16> 17; NEON-NEXT: [[RES_2:%.*]] = sub <8 x i16> [[TMP1]], [[ZB_2]] 18; NEON-NEXT: ret <8 x i16> [[RES_2]] 19; 20; NONEON-LABEL: @sink_zext( 21; NONEON-NEXT: entry: 22; NONEON-NEXT: [[ZA:%.*]] = zext <8 x i8> [[A:%.*]] to <8 x i16> 23; NONEON-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 24; NONEON: if.then: 25; NONEON-NEXT: [[ZB_1:%.*]] = zext <8 x i8> [[B:%.*]] to <8 x i16> 26; NONEON-NEXT: [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[ZB_1]] 27; NONEON-NEXT: ret <8 x i16> [[RES_1]] 28; NONEON: if.else: 29; NONEON-NEXT: [[ZB_2:%.*]] = zext <8 x i8> [[B]] to <8 x i16> 30; NONEON-NEXT: [[RES_2:%.*]] = sub <8 x i16> [[ZA]], [[ZB_2]] 31; NONEON-NEXT: ret <8 x i16> [[RES_2]] 32; 33entry: 34 %za = zext <8 x i8> %a to <8 x i16> 35 br i1 %c, label %if.then, label %if.else 36 37if.then: 38 %zb.1 = zext <8 x i8> %b to <8 x i16> 39 %res.1 = add <8 x i16> %za, %zb.1 40 ret <8 x i16> %res.1 41 42if.else: 43 %zb.2 = zext <8 x i8> %b to <8 x i16> 44 %res.2 = sub <8 x i16> %za, %zb.2 45 ret <8 x i16> %res.2 46} 47 48define <8 x i16> @sink_sext(<8 x i8> %a, <8 x i8> %b, i1 %c) { 49; NEON-LABEL: @sink_sext( 50; NEON-NEXT: entry: 51; NEON-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 52; NEON: if.then: 53; NEON-NEXT: [[ZB_1:%.*]] = sext <8 x i8> [[B:%.*]] to <8 x i16> 54; NEON-NEXT: [[TMP0:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16> 55; NEON-NEXT: [[RES_1:%.*]] = add <8 x i16> [[TMP0]], [[ZB_1]] 56; NEON-NEXT: ret <8 x i16> [[RES_1]] 57; NEON: if.else: 58; NEON-NEXT: [[ZB_2:%.*]] = sext <8 x i8> [[B]] to <8 x i16> 59; NEON-NEXT: [[TMP1:%.*]] = sext <8 x i8> [[A]] to <8 x i16> 60; NEON-NEXT: [[RES_2:%.*]] = sub <8 x i16> [[TMP1]], [[ZB_2]] 61; NEON-NEXT: ret <8 x i16> [[RES_2]] 62; 63; NONEON-LABEL: @sink_sext( 64; NONEON-NEXT: entry: 65; NONEON-NEXT: [[ZA:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16> 66; NONEON-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 67; NONEON: if.then: 68; NONEON-NEXT: [[ZB_1:%.*]] = sext <8 x i8> [[B:%.*]] to <8 x i16> 69; NONEON-NEXT: [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[ZB_1]] 70; NONEON-NEXT: ret <8 x i16> [[RES_1]] 71; NONEON: if.else: 72; NONEON-NEXT: [[ZB_2:%.*]] = sext <8 x i8> [[B]] to <8 x i16> 73; NONEON-NEXT: [[RES_2:%.*]] = sub <8 x i16> [[ZA]], [[ZB_2]] 74; NONEON-NEXT: ret <8 x i16> [[RES_2]] 75; 76entry: 77 %za = sext <8 x i8> %a to <8 x i16> 78 br i1 %c, label %if.then, label %if.else 79 80if.then: 81 %zb.1 = sext <8 x i8> %b to <8 x i16> 82 %res.1 = add <8 x i16> %za, %zb.1 83 ret <8 x i16> %res.1 84 85if.else: 86 %zb.2 = sext <8 x i8> %b to <8 x i16> 87 %res.2 = sub <8 x i16> %za, %zb.2 88 ret <8 x i16> %res.2 89} 90 91define <8 x i16> @do_not_sink_nonfree_zext(<8 x i8> %a, <8 x i16> %b, i1 %c) { 92; 93; NEON-LABEL: @do_not_sink_nonfree_zext( 94; NEON-NEXT: entry: 95; NEON-NEXT: [[ZA:%.*]] = zext <8 x i8> [[A:%.*]] to <8 x i16> 96; NEON-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 97; NEON: if.then: 98; NEON-NEXT: [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[B:%.*]] 99; NEON-NEXT: ret <8 x i16> [[RES_1]] 100; NEON: if.else: 101; NEON-NEXT: ret <8 x i16> [[B]] 102; 103; NONEON-LABEL: @do_not_sink_nonfree_zext( 104; NONEON-NEXT: entry: 105; NONEON-NEXT: [[ZA:%.*]] = zext <8 x i8> [[A:%.*]] to <8 x i16> 106; NONEON-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 107; NONEON: if.then: 108; NONEON-NEXT: [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[B:%.*]] 109; NONEON-NEXT: ret <8 x i16> [[RES_1]] 110; NONEON: if.else: 111; NONEON-NEXT: ret <8 x i16> [[B]] 112; 113entry: 114 %za = zext <8 x i8> %a to <8 x i16> 115 br i1 %c, label %if.then, label %if.else 116 117if.then: 118 %res.1 = add <8 x i16> %za, %b 119 ret <8 x i16> %res.1 120 121if.else: 122 ret <8 x i16> %b 123} 124 125define <8 x i16> @do_not_sink_nonfree_sext(<8 x i8> %a, <8 x i16> %b, i1 %c) { 126; CHECK-LABEL: @do_not_sink_nonfree_sext( 127; CHECK-NEXT: entry: 128; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 129; CHECK: if.then: 130; CHECK-NEXT: [[ZB_1:%.*]] = sext <8 x i8> [[B:%.*]] to <8 x i16> 131; CHECK-NEXT: [[TMP0:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16> 132; CHECK-NEXT: [[RES_1:%.*]] = add <8 x i16> [[TMP0]], [[ZB_1]] 133; CHECK-NEXT: ret <8 x i16> [[RES_1]] 134; CHECK: if.else: 135; CHECK-NEXT: [[ZB_2:%.*]] = sext <8 x i8> [[B]] to <8 x i16> 136; CHECK-NEXT: ret <8 x i16> [[ZB_2]] 137; 138; NEON-LABEL: @do_not_sink_nonfree_sext( 139; NEON-NEXT: entry: 140; NEON-NEXT: [[ZA:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16> 141; NEON-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 142; NEON: if.then: 143; NEON-NEXT: [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[B:%.*]] 144; NEON-NEXT: ret <8 x i16> [[RES_1]] 145; NEON: if.else: 146; NEON-NEXT: ret <8 x i16> [[B]] 147; 148; NONEON-LABEL: @do_not_sink_nonfree_sext( 149; NONEON-NEXT: entry: 150; NONEON-NEXT: [[ZA:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16> 151; NONEON-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 152; NONEON: if.then: 153; NONEON-NEXT: [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[B:%.*]] 154; NONEON-NEXT: ret <8 x i16> [[RES_1]] 155; NONEON: if.else: 156; NONEON-NEXT: ret <8 x i16> [[B]] 157; 158entry: 159 %za = sext <8 x i8> %a to <8 x i16> 160 br i1 %c, label %if.then, label %if.else 161 162if.then: 163 %res.1 = add <8 x i16> %za, %b 164 ret <8 x i16> %res.1 165 166if.else: 167 ret <8 x i16> %b 168} 169 170declare void @user1(<8 x i16>) 171 172; Exts can be sunk. 173define <8 x i16> @sink_shufflevector_ext_subadd_multiuse(<16 x i8> %a, <16 x i8> %b) { 174; NEON-LABEL: @sink_shufflevector_ext_subadd_multiuse( 175; NEON-NEXT: entry: 176; NEON-NEXT: [[S1:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 177; NEON-NEXT: [[S3:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> 178; NEON-NEXT: [[Z3:%.*]] = sext <8 x i8> [[S3]] to <8 x i16> 179; NEON-NEXT: call void @user1(<8 x i16> [[Z3]]) 180; NEON-NEXT: br i1 undef, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 181; NEON: if.then: 182; NEON-NEXT: [[S2:%.*]] = shufflevector <16 x i8> [[B:%.*]], <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 183; NEON-NEXT: [[Z2:%.*]] = zext <8 x i8> [[S2]] to <8 x i16> 184; NEON-NEXT: [[TMP0:%.*]] = zext <8 x i8> [[S1]] to <8 x i16> 185; NEON-NEXT: [[RES1:%.*]] = add <8 x i16> [[TMP0]], [[Z2]] 186; NEON-NEXT: ret <8 x i16> [[RES1]] 187; NEON: if.else: 188; NEON-NEXT: [[S4:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> 189; NEON-NEXT: [[Z4:%.*]] = sext <8 x i8> [[S4]] to <8 x i16> 190; NEON-NEXT: [[TMP1:%.*]] = sext <8 x i8> [[S3]] to <8 x i16> 191; NEON-NEXT: [[RES2:%.*]] = sub <8 x i16> [[TMP1]], [[Z4]] 192; NEON-NEXT: ret <8 x i16> [[RES2]] 193; 194; NONEON-LABEL: @sink_shufflevector_ext_subadd_multiuse( 195; NONEON-NEXT: entry: 196; NONEON-NEXT: [[S1:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 197; NONEON-NEXT: [[Z1:%.*]] = zext <8 x i8> [[S1]] to <8 x i16> 198; NONEON-NEXT: [[S3:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> 199; NONEON-NEXT: [[Z3:%.*]] = sext <8 x i8> [[S3]] to <8 x i16> 200; NONEON-NEXT: call void @user1(<8 x i16> [[Z3]]) 201; NONEON-NEXT: br i1 undef, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 202; NONEON: if.then: 203; NONEON-NEXT: [[S2:%.*]] = shufflevector <16 x i8> [[B:%.*]], <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 204; NONEON-NEXT: [[Z2:%.*]] = zext <8 x i8> [[S2]] to <8 x i16> 205; NONEON-NEXT: [[RES1:%.*]] = add <8 x i16> [[Z1]], [[Z2]] 206; NONEON-NEXT: ret <8 x i16> [[RES1]] 207; NONEON: if.else: 208; NONEON-NEXT: [[S4:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> 209; NONEON-NEXT: [[Z4:%.*]] = sext <8 x i8> [[S4]] to <8 x i16> 210; NONEON-NEXT: [[RES2:%.*]] = sub <8 x i16> [[Z3]], [[Z4]] 211; NONEON-NEXT: ret <8 x i16> [[RES2]] 212; 213entry: 214 %s1 = shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 215 %z1 = zext <8 x i8> %s1 to <8 x i16> 216 %s3 = shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> 217 %z3 = sext <8 x i8> %s3 to <8 x i16> 218 call void @user1(<8 x i16> %z3) 219 br i1 undef, label %if.then, label %if.else 220 221if.then: 222 %s2 = shufflevector <16 x i8> %b, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 223 %z2 = zext <8 x i8> %s2 to <8 x i16> 224 %res1 = add <8 x i16> %z1, %z2 225 ret <8 x i16> %res1 226 227if.else: 228 %s4 = shufflevector <16 x i8> %b, <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> 229 %z4 = sext <8 x i8> %s4 to <8 x i16> 230 %res2 = sub <8 x i16> %z3, %z4 231 ret <8 x i16> %res2 232} 233