1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD 3; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI 4 5define <2 x i32> @and_extract_zext_idx0(<4 x i16> %vec) nounwind { 6; CHECK-SD-LABEL: and_extract_zext_idx0: 7; CHECK-SD: // %bb.0: 8; CHECK-SD-NEXT: ushll v0.4s, v0.4h, #0 9; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 10; CHECK-SD-NEXT: ret 11; 12; CHECK-GI-LABEL: and_extract_zext_idx0: 13; CHECK-GI: // %bb.0: 14; CHECK-GI-NEXT: movi d1, #0x00ffff0000ffff 15; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 16; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b 17; CHECK-GI-NEXT: ret 18 %zext = zext <4 x i16> %vec to <4 x i32> 19 %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 0) 20 %and = and <2 x i32> %extract, <i32 65535, i32 65535> 21 ret <2 x i32> %and 22} 23 24define <4 x i16> @and_extract_sext_idx0(<8 x i8> %vec) nounwind { 25; CHECK-SD-LABEL: and_extract_sext_idx0: 26; CHECK-SD: // %bb.0: 27; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #0 28; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 29; CHECK-SD-NEXT: ret 30; 31; CHECK-GI-LABEL: and_extract_sext_idx0: 32; CHECK-GI: // %bb.0: 33; CHECK-GI-NEXT: movi d1, #0xff00ff00ff00ff 34; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #0 35; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b 36; CHECK-GI-NEXT: ret 37 %sext = sext <8 x i8> %vec to <8 x i16> 38 %extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 0) 39 %and = and <4 x i16> %extract, <i16 255, i16 255, i16 255, i16 255> 40 ret <4 x i16> %and 41} 42 43define <2 x i32> @and_extract_zext_idx2(<4 x i16> %vec) nounwind { 44; CHECK-SD-LABEL: and_extract_zext_idx2: 45; CHECK-SD: // %bb.0: 46; CHECK-SD-NEXT: ushll v0.4s, v0.4h, #0 47; CHECK-SD-NEXT: ext v0.16b, v0.16b, v0.16b, #8 48; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 49; CHECK-SD-NEXT: ret 50; 51; CHECK-GI-LABEL: and_extract_zext_idx2: 52; CHECK-GI: // %bb.0: 53; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 54; CHECK-GI-NEXT: movi d1, #0x00ffff0000ffff 55; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #8 56; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b 57; CHECK-GI-NEXT: ret 58 %zext = zext <4 x i16> %vec to <4 x i32> 59 %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 2) 60 %and = and <2 x i32> %extract, <i32 65535, i32 65535> 61 ret <2 x i32> %and 62} 63 64define <4 x i16> @and_extract_sext_idx4(<8 x i8> %vec) nounwind { 65; CHECK-SD-LABEL: and_extract_sext_idx4: 66; CHECK-SD: // %bb.0: 67; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #0 68; CHECK-SD-NEXT: ext v0.16b, v0.16b, v0.16b, #8 69; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 70; CHECK-SD-NEXT: ret 71; 72; CHECK-GI-LABEL: and_extract_sext_idx4: 73; CHECK-GI: // %bb.0: 74; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #0 75; CHECK-GI-NEXT: movi d1, #0xff00ff00ff00ff 76; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #8 77; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b 78; CHECK-GI-NEXT: ret 79 %sext = sext <8 x i8> %vec to <8 x i16> 80 %extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 4) 81 %and = and <4 x i16> %extract, <i16 255, i16 255, i16 255, i16 255> 82 ret <4 x i16> %and 83} 84 85define <2 x i32> @sext_extract_zext_idx0(<4 x i16> %vec) nounwind { 86; CHECK-SD-LABEL: sext_extract_zext_idx0: 87; CHECK-SD: // %bb.0: 88; CHECK-SD-NEXT: sshll v0.4s, v0.4h, #0 89; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 90; CHECK-SD-NEXT: ret 91; 92; CHECK-GI-LABEL: sext_extract_zext_idx0: 93; CHECK-GI: // %bb.0: 94; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 95; CHECK-GI-NEXT: shl v0.2s, v0.2s, #16 96; CHECK-GI-NEXT: sshr v0.2s, v0.2s, #16 97; CHECK-GI-NEXT: ret 98 %zext = zext <4 x i16> %vec to <4 x i32> 99 %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 0) 100 %sext_inreg_step0 = shl <2 x i32> %extract, <i32 16, i32 16> 101 %sext_inreg = ashr <2 x i32> %sext_inreg_step0, <i32 16, i32 16> 102 ret <2 x i32> %sext_inreg 103} 104 105; Negative test, combine should not fire if sign extension is for a different width. 106define <2 x i32> @sext_extract_zext_idx0_negtest(<4 x i16> %vec) nounwind { 107; CHECK-LABEL: sext_extract_zext_idx0_negtest: 108; CHECK: // %bb.0: 109; CHECK-NEXT: ushll v0.4s, v0.4h, #0 110; CHECK-NEXT: shl v0.2s, v0.2s, #17 111; CHECK-NEXT: sshr v0.2s, v0.2s, #17 112; CHECK-NEXT: ret 113 %zext = zext <4 x i16> %vec to <4 x i32> 114 %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 0) 115 %sext_inreg_step0 = shl <2 x i32> %extract, <i32 17, i32 17> 116 %sext_inreg = ashr <2 x i32> %sext_inreg_step0, <i32 17, i32 17> 117 ret <2 x i32> %sext_inreg 118} 119 120define <4 x i16> @sext_extract_sext_idx0(<8 x i8> %vec) nounwind { 121; CHECK-SD-LABEL: sext_extract_sext_idx0: 122; CHECK-SD: // %bb.0: 123; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #0 124; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 125; CHECK-SD-NEXT: ret 126; 127; CHECK-GI-LABEL: sext_extract_sext_idx0: 128; CHECK-GI: // %bb.0: 129; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #0 130; CHECK-GI-NEXT: shl v0.4h, v0.4h, #8 131; CHECK-GI-NEXT: sshr v0.4h, v0.4h, #8 132; CHECK-GI-NEXT: ret 133 %sext = sext <8 x i8> %vec to <8 x i16> 134 %extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 0) 135 %sext_inreg_step0 = shl <4 x i16> %extract, <i16 8, i16 8, i16 8, i16 8> 136 %sext_inreg = ashr <4 x i16> %sext_inreg_step0, <i16 8, i16 8, i16 8, i16 8> 137 ret <4 x i16> %sext_inreg 138} 139 140define <2 x i32> @sext_extract_zext_idx2(<4 x i16> %vec) nounwind { 141; CHECK-SD-LABEL: sext_extract_zext_idx2: 142; CHECK-SD: // %bb.0: 143; CHECK-SD-NEXT: sshll v0.4s, v0.4h, #0 144; CHECK-SD-NEXT: ext v0.16b, v0.16b, v0.16b, #8 145; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 146; CHECK-SD-NEXT: ret 147; 148; CHECK-GI-LABEL: sext_extract_zext_idx2: 149; CHECK-GI: // %bb.0: 150; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 151; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #8 152; CHECK-GI-NEXT: shl v0.2s, v0.2s, #16 153; CHECK-GI-NEXT: sshr v0.2s, v0.2s, #16 154; CHECK-GI-NEXT: ret 155 %zext = zext <4 x i16> %vec to <4 x i32> 156 %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 2) 157 %sext_inreg_step0 = shl <2 x i32> %extract, <i32 16, i32 16> 158 %sext_inreg = ashr <2 x i32> %sext_inreg_step0, <i32 16, i32 16> 159 ret <2 x i32> %sext_inreg 160} 161 162define <4 x i16> @sext_extract_sext_idx4(<8 x i8> %vec) nounwind { 163; CHECK-SD-LABEL: sext_extract_sext_idx4: 164; CHECK-SD: // %bb.0: 165; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #0 166; CHECK-SD-NEXT: ext v0.16b, v0.16b, v0.16b, #8 167; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 168; CHECK-SD-NEXT: ret 169; 170; CHECK-GI-LABEL: sext_extract_sext_idx4: 171; CHECK-GI: // %bb.0: 172; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #0 173; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #8 174; CHECK-GI-NEXT: shl v0.4h, v0.4h, #8 175; CHECK-GI-NEXT: sshr v0.4h, v0.4h, #8 176; CHECK-GI-NEXT: ret 177 %sext = sext <8 x i8> %vec to <8 x i16> 178 %extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 4) 179 %sext_inreg_step0 = shl <4 x i16> %extract, <i16 8, i16 8, i16 8, i16 8> 180 %sext_inreg = ashr <4 x i16> %sext_inreg_step0, <i16 8, i16 8, i16 8, i16 8> 181 ret <4 x i16> %sext_inreg 182} 183 184define <8 x i8> @sext_extract_idx(<16 x i8> %vec) nounwind { 185; CHECK-LABEL: sext_extract_idx: 186; CHECK: // %bb.0: 187; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 188; CHECK-NEXT: ret 189 %extract = call <8 x i8> @llvm.vector.extract.v8i8.v16i8(<16 x i8> %vec, i64 0) 190 ret <8 x i8> %extract 191} 192 193declare <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32>, i64) 194declare <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16>, i64) 195declare <8 x i8> @llvm.vector.extract.v8i8.v16i8(<16 x i8>, i64) 196