1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 3 4define <4 x i32> @const_folding(<4 x i32> %x) { 5; CHECK-LABEL: @const_folding( 6; CHECK-NEXT: ret <4 x i32> zeroinitializer 7; 8 %shuf = shufflevector <4 x i32> %x, <4 x i32> zeroinitializer, <4 x i32> <i32 5, i32 4, i32 5, i32 4> 9 ret <4 x i32> %shuf 10} 11 12define <4 x i32> @const_folding1(<4 x i32> %x) { 13; CHECK-LABEL: @const_folding1( 14; CHECK-NEXT: ret <4 x i32> splat (i32 5) 15; 16 %shuf = shufflevector <4 x i32> <i32 5, i32 4, i32 5, i32 4>, <4 x i32> %x, <4 x i32> zeroinitializer 17 ret <4 x i32> %shuf 18} 19 20define <4 x i32> @const_folding_negative(<3 x i32> %x) { 21; CHECK-LABEL: @const_folding_negative( 22; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <3 x i32> [[X:%.*]], <3 x i32> zeroinitializer, <4 x i32> <i32 2, i32 4, i32 5, i32 4> 23; CHECK-NEXT: ret <4 x i32> [[SHUF]] 24; 25 %shuf = shufflevector <3 x i32> %x, <3 x i32> zeroinitializer, <4 x i32> <i32 2, i32 4, i32 5, i32 4> 26 ret <4 x i32> %shuf 27} 28 29define <4 x i32> @splat_operand(<4 x i32> %x) { 30; CHECK-LABEL: @splat_operand( 31; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer 32; CHECK-NEXT: ret <4 x i32> [[SPLAT]] 33; 34 %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 35 %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <4 x i32> <i32 0, i32 3, i32 2, i32 1> 36 ret <4 x i32> %shuf 37} 38 39define <4 x i32> @splat_operand_poison(<4 x i32> %x) { 40; CHECK-LABEL: @splat_operand_poison( 41; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer 42; CHECK-NEXT: ret <4 x i32> [[SPLAT]] 43; 44 %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 45 %shuf = shufflevector <4 x i32> %splat, <4 x i32> poison, <4 x i32> <i32 0, i32 3, i32 2, i32 1> 46 ret <4 x i32> %shuf 47} 48 49define <4 x i32> @splat_operand1(<4 x i32> %x, <4 x i32> %y) { 50; CHECK-LABEL: @splat_operand1( 51; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> zeroinitializer 52; CHECK-NEXT: ret <4 x i32> [[SPLAT]] 53; 54 %splat = shufflevector <4 x i32> %x, <4 x i32> %y, <4 x i32> zeroinitializer 55 %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <4 x i32> <i32 0, i32 3, i32 2, i32 1> 56 ret <4 x i32> %shuf 57} 58 59define <4 x i32> @splat_operand2(<4 x i32> %x, <4 x i32> %y) { 60; CHECK-LABEL: @splat_operand2( 61; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer 62; CHECK-NEXT: ret <4 x i32> [[SPLAT]] 63; 64 %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 65 %shuf = shufflevector <4 x i32> %splat, <4 x i32> %y, <4 x i32> <i32 0, i32 3, i32 2, i32 1> 66 ret <4 x i32> %shuf 67} 68 69define <4 x i32> @splat_operand3(<4 x i32> %x) { 70; CHECK-LABEL: @splat_operand3( 71; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer 72; CHECK-NEXT: ret <4 x i32> [[SPLAT]] 73; 74 %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 75 %shuf = shufflevector <4 x i32> zeroinitializer, <4 x i32> %splat, <4 x i32> <i32 7, i32 6, i32 5, i32 5> 76 ret <4 x i32> %shuf 77} 78 79define <8 x i32> @splat_operand_negative(<4 x i32> %x) { 80; CHECK-LABEL: @splat_operand_negative( 81; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer 82; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[SPLAT]], <4 x i32> undef, <8 x i32> <i32 0, i32 3, i32 2, i32 1, i32 poison, i32 poison, i32 poison, i32 poison> 83; CHECK-NEXT: ret <8 x i32> [[SHUF]] 84; 85 %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 86 %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <8 x i32> <i32 0, i32 3, i32 2, i32 1, i32 undef, i32 undef, i32 undef, i32 undef> 87 ret <8 x i32> %shuf 88} 89 90define <4 x i32> @splat_operand_negative2(<4 x i32> %x, <4 x i32> %y) { 91; CHECK-LABEL: @splat_operand_negative2( 92; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer 93; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[SPLAT]], <4 x i32> [[Y:%.*]], <4 x i32> <i32 0, i32 3, i32 4, i32 1> 94; CHECK-NEXT: ret <4 x i32> [[SHUF]] 95; 96 %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 97 %shuf = shufflevector <4 x i32> %splat, <4 x i32> %y, <4 x i32> <i32 0, i32 3, i32 4, i32 1> 98 ret <4 x i32> %shuf 99} 100 101define <4 x i32> @splat_operand_negative3(<4 x i32> %x, <4 x i32> %y) { 102; CHECK-LABEL: @splat_operand_negative3( 103; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> zeroinitializer 104; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[Y:%.*]], <4 x i32> [[SPLAT]], <4 x i32> <i32 0, i32 3, i32 4, i32 1> 105; CHECK-NEXT: ret <4 x i32> [[SHUF]] 106; 107 %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 108 %shuf = shufflevector <4 x i32> %y, <4 x i32> %splat, <4 x i32> <i32 0, i32 3, i32 4, i32 1> 109 ret <4 x i32> %shuf 110} 111 112define <4 x i32> @splat_operand_negative4(<4 x i32> %x) { 113; CHECK-LABEL: @splat_operand_negative4( 114; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> <i32 2, i32 poison, i32 2, i32 poison> 115; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[SPLAT]], <4 x i32> undef, <4 x i32> <i32 0, i32 2, i32 poison, i32 poison> 116; CHECK-NEXT: ret <4 x i32> [[SHUF]] 117; 118 %splat = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 2, i32 undef, i32 2, i32 undef> 119 %shuf = shufflevector <4 x i32> %splat, <4 x i32> undef, <4 x i32> <i32 0, i32 2, i32 undef, i32 undef> 120 ret <4 x i32> %shuf 121} 122 123define <4 x i32> @undef_mask(<4 x i32> %x) { 124; CHECK-LABEL: @undef_mask( 125; CHECK-NEXT: ret <4 x i32> poison 126; 127 %shuf = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> undef 128 ret <4 x i32> %shuf 129} 130 131define <4 x i32> @undef_mask_1(<4 x i32> %x, <4 x i32> %y) { 132; CHECK-LABEL: @undef_mask_1( 133; CHECK-NEXT: ret <4 x i32> poison 134; 135 %shuf = shufflevector <4 x i32> %x, <4 x i32> %y, <4 x i32> undef 136 ret <4 x i32> %shuf 137} 138 139define <4 x i32> @identity_mask_0(<4 x i32> %x) { 140; CHECK-LABEL: @identity_mask_0( 141; CHECK-NEXT: ret <4 x i32> [[X:%.*]] 142; 143 %shuf = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 144 ret <4 x i32> %shuf 145} 146 147define <4 x i32> @identity_mask_1(<4 x i32> %x) { 148; CHECK-LABEL: @identity_mask_1( 149; CHECK-NEXT: ret <4 x i32> [[X:%.*]] 150; 151 %shuf = shufflevector <4 x i32> undef, <4 x i32> %x, <4 x i32> <i32 4, i32 5, i32 6, i32 7> 152 ret <4 x i32> %shuf 153} 154 155define <4 x i32> @pseudo_identity_mask(<4 x i32> %x) { 156; CHECK-LABEL: @pseudo_identity_mask( 157; CHECK-NEXT: ret <4 x i32> [[X:%.*]] 158; 159 %shuf = shufflevector <4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 0, i32 1, i32 2, i32 7> 160 ret <4 x i32> %shuf 161} 162 163define <4 x i32> @not_identity_mask(<4 x i32> %x) { 164; CHECK-LABEL: @not_identity_mask( 165; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[X]], <4 x i32> <i32 0, i32 1, i32 2, i32 6> 166; CHECK-NEXT: ret <4 x i32> [[SHUF]] 167; 168 %shuf = shufflevector <4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 0, i32 1, i32 2, i32 6> 169 ret <4 x i32> %shuf 170} 171 172; TODO: Should we simplify if the mask has an undef element? 173 174define <4 x i32> @possible_identity_mask(<4 x i32> %x) { 175; CHECK-LABEL: @possible_identity_mask( 176; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 poison> 177; CHECK-NEXT: ret <4 x i32> [[SHUF]] 178; 179 %shuf = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef> 180 ret <4 x i32> %shuf 181} 182 183define <4 x i32> @const_operand(<4 x i32> %x) { 184; CHECK-LABEL: @const_operand( 185; CHECK-NEXT: ret <4 x i32> <i32 42, i32 45, i32 44, i32 43> 186; 187 %shuf = shufflevector <4 x i32> <i32 42, i32 43, i32 44, i32 45>, <4 x i32> %x, <4 x i32> <i32 0, i32 3, i32 2, i32 1> 188 ret <4 x i32> %shuf 189} 190 191define <4 x i32> @merge(<4 x i32> %x) { 192; CHECK-LABEL: @merge( 193; CHECK-NEXT: ret <4 x i32> [[X:%.*]] 194; 195 %lower = shufflevector <4 x i32> %x, <4 x i32> undef, <2 x i32> <i32 1, i32 0> 196 %upper = shufflevector <4 x i32> %x, <4 x i32> undef, <2 x i32> <i32 2, i32 3> 197 %merged = shufflevector <2 x i32> %upper, <2 x i32> %lower, <4 x i32> <i32 3, i32 2, i32 0, i32 1> 198 ret <4 x i32> %merged 199} 200 201; This crosses lanes from the source op. 202 203define <4 x i32> @not_merge(<4 x i32> %x) { 204; CHECK-LABEL: @not_merge( 205; CHECK-NEXT: [[L:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> undef, <2 x i32> <i32 0, i32 1> 206; CHECK-NEXT: [[U:%.*]] = shufflevector <4 x i32> [[X]], <4 x i32> undef, <2 x i32> <i32 2, i32 3> 207; CHECK-NEXT: [[MERGED:%.*]] = shufflevector <2 x i32> [[U]], <2 x i32> [[L]], <4 x i32> <i32 3, i32 2, i32 0, i32 1> 208; CHECK-NEXT: ret <4 x i32> [[MERGED]] 209; 210 %l = shufflevector <4 x i32> %x, <4 x i32> undef, <2 x i32> <i32 0, i32 1> 211 %u = shufflevector <4 x i32> %x, <4 x i32> undef, <2 x i32> <i32 2, i32 3> 212 %merged = shufflevector <2 x i32> %u, <2 x i32> %l, <4 x i32> <i32 3, i32 2, i32 0, i32 1> 213 ret <4 x i32> %merged 214} 215 216define <8 x double> @extract_and_concat(<8 x double> %x) { 217; CHECK-LABEL: @extract_and_concat( 218; CHECK-NEXT: ret <8 x double> [[X:%.*]] 219; 220 %s1 = shufflevector <8 x double> %x, <8 x double> undef, <2 x i32> <i32 0, i32 1> 221 %s2 = shufflevector <8 x double> %x, <8 x double> undef, <2 x i32> <i32 2, i32 3> 222 %s3 = shufflevector <8 x double> %x, <8 x double> undef, <2 x i32> <i32 4, i32 5> 223 %s4 = shufflevector <8 x double> %x, <8 x double> undef, <2 x i32> <i32 6, i32 7> 224 %s5 = shufflevector <2 x double> %s1, <2 x double> %s2, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 225 %s6 = shufflevector <2 x double> %s3, <2 x double> %s4, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 226 %s7 = shufflevector <4 x double> %s5, <4 x double> %s6, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 227 ret <8 x double> %s7 228} 229 230; This case has intermediate lane crossings. 231 232define <8 x i64> @PR30630(<8 x i64> %x) { 233; CHECK-LABEL: @PR30630( 234; CHECK-NEXT: ret <8 x i64> [[X:%.*]] 235; 236 %s1 = shufflevector <8 x i64> %x, <8 x i64> undef, <2 x i32> <i32 0, i32 4> 237 %s2 = shufflevector <8 x i64> %x, <8 x i64> undef, <2 x i32> <i32 1, i32 5> 238 %s3 = shufflevector <8 x i64> %x, <8 x i64> undef, <2 x i32> <i32 2, i32 6> 239 %s4 = shufflevector <8 x i64> %x, <8 x i64> undef, <2 x i32> <i32 3, i32 7> 240 %s5 = shufflevector <2 x i64> %s1, <2 x i64> %s2, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 241 %s6 = shufflevector <2 x i64> %s3, <2 x i64> %s4, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 242 %s7 = shufflevector <4 x i64> %s5, <4 x i64> %s6, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7> 243 ret <8 x i64> %s7 244} 245 246; This case covers internal canonicalization of shuffles with one constant input vector. 247 248;FIXME: Another issue exposed here, this whole function could be simplified to: 249; ret <2 x float> zeroinitializer 250define <2 x float> @PR32872(<2 x float> %x) { 251; CHECK-LABEL: @PR32872( 252; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> zeroinitializer, <4 x i32> <i32 2, i32 2, i32 0, i32 1> 253; CHECK-NEXT: [[SHUF2:%.*]] = shufflevector <4 x float> zeroinitializer, <4 x float> [[SHUF]], <2 x i32> <i32 4, i32 5> 254; CHECK-NEXT: ret <2 x float> [[SHUF2]] 255; 256 %shuf = shufflevector <2 x float> %x, <2 x float> zeroinitializer, <4 x i32> <i32 2, i32 2, i32 0, i32 1> 257 %shuf2 = shufflevector <4 x float> zeroinitializer, <4 x float> %shuf, <2 x i32> <i32 4, i32 5> 258 ret <2 x float> %shuf2 259} 260 261define <5 x i8> @splat_inserted_constant(<4 x i8> %x) { 262; CHECK-LABEL: @splat_inserted_constant( 263; CHECK-NEXT: ret <5 x i8> splat (i8 42) 264; 265 %ins3 = insertelement <4 x i8> %x, i8 42, i64 3 266 %splat5 = shufflevector <4 x i8> %ins3, <4 x i8> undef, <5 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3> 267 ret <5 x i8> %splat5 268} 269 270define <4 x float> @splat_inserted_constant_undef_elt(<4 x float> %x) { 271; CHECK-LABEL: @splat_inserted_constant_undef_elt( 272; CHECK-NEXT: ret <4 x float> <float 1.200000e+01, float 1.200000e+01, float poison, float 1.200000e+01> 273; 274 %ins1 = insertelement <4 x float> %x, float 12.0, i32 1 275 %splat1 = shufflevector <4 x float> %ins1, <4 x float> undef, <4 x i32> <i32 1, i32 1, i32 undef, i32 1> 276 ret <4 x float> %splat1 277} 278 279define <2 x i8> @splat_inserted_constant_not_canonical(<3 x i8> %x, <3 x i8> %y) { 280; CHECK-LABEL: @splat_inserted_constant_not_canonical( 281; CHECK-NEXT: ret <2 x i8> <i8 poison, i8 23> 282; 283 %ins2 = insertelement <3 x i8> %x, i8 23, i7 2 284 %splat2 = shufflevector <3 x i8> %y, <3 x i8> %ins2, <2 x i32> <i32 undef, i32 5> 285 ret <2 x i8> %splat2 286} 287 288define <4 x i32> @fold_identity(<4 x i32> %x) { 289; CHECK-LABEL: @fold_identity( 290; CHECK-NEXT: ret <4 x i32> [[X:%.*]] 291; 292 %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 293 %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 294 ret <4 x i32> %revshuf 295} 296 297define <4 x i32> @fold_identity2(<4 x i32> %x) { 298; CHECK-LABEL: @fold_identity2( 299; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], splat (i32 1) 300; CHECK-NEXT: ret <4 x i32> [[SHL]] 301; 302 %shl = shl <4 x i32> %x, <i32 1, i32 1, i32 1, i32 1> 303 %shuf = shufflevector <4 x i32> %shl, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 304 %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 305 ret <4 x i32> %revshuf 306} 307 308define <4 x i32> @fold_identity3(<4 x i32> %x) { 309; CHECK-LABEL: @fold_identity3( 310; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[X]] 311; CHECK-NEXT: ret <4 x i32> [[SHL]] 312; 313 %shl = shl <4 x i32> %x, %x 314 %shuf = shufflevector <4 x i32> %shl, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 315 %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 316 ret <4 x i32> %revshuf 317} 318 319define <4 x i32> @not_fold_identity(<4 x i32> %x) { 320; CHECK-LABEL: @not_fold_identity( 321; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 0, i32 1> 322; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i32> [[SHUF]], <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2> 323; CHECK-NEXT: ret <4 x i32> [[REVSHUF]] 324; 325 %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 0, i32 1> 326 %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2> 327 ret <4 x i32> %revshuf 328} 329 330define <4 x i32> @not_fold_identity2(<4 x i32> %x) { 331; CHECK-LABEL: @not_fold_identity2( 332; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 1, i32 0> 333; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i32> [[SHUF]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 334; CHECK-NEXT: ret <4 x i32> [[REVSHUF]] 335; 336 %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 1, i32 0> 337 %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 338 ret <4 x i32> %revshuf 339} 340