1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=vector-combine -data-layout=e < %s | FileCheck %s 3; RUN: opt -S -passes=vector-combine -data-layout=E < %s | FileCheck %s 4 5define void @insert_store(ptr %q, i8 zeroext %s) { 6; CHECK-LABEL: @insert_store( 7; CHECK-NEXT: entry: 8; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 3 9; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 10; CHECK-NEXT: ret void 11; 12entry: 13 %0 = load <16 x i8>, ptr %q 14 %vecins = insertelement <16 x i8> %0, i8 %s, i32 3 15 store <16 x i8> %vecins, ptr %q, align 16 16 ret void 17} 18 19define void @insert_store_i16_align1(ptr %q, i16 zeroext %s) { 20; CHECK-LABEL: @insert_store_i16_align1( 21; CHECK-NEXT: entry: 22; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <8 x i16>, ptr [[Q:%.*]], i32 0, i32 3 23; CHECK-NEXT: store i16 [[S:%.*]], ptr [[TMP0]], align 2 24; CHECK-NEXT: ret void 25; 26entry: 27 %0 = load <8 x i16>, ptr %q 28 %vecins = insertelement <8 x i16> %0, i16 %s, i32 3 29 store <8 x i16> %vecins, ptr %q, align 1 30 ret void 31} 32 33; To verify case when index is out of bounds 34define void @insert_store_outofbounds(ptr %q, i16 zeroext %s) { 35; CHECK-LABEL: @insert_store_outofbounds( 36; CHECK-NEXT: entry: 37; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16 38; CHECK-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 9 39; CHECK-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 40; CHECK-NEXT: ret void 41; 42entry: 43 %0 = load <8 x i16>, ptr %q 44 %vecins = insertelement <8 x i16> %0, i16 %s, i32 9 45 store <8 x i16> %vecins, ptr %q 46 ret void 47} 48 49define void @insert_store_vscale(ptr %q, i16 zeroext %s) { 50; CHECK-LABEL: @insert_store_vscale( 51; CHECK-NEXT: entry: 52; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <vscale x 8 x i16>, ptr [[Q:%.*]], i32 0, i32 3 53; CHECK-NEXT: store i16 [[S:%.*]], ptr [[TMP0]], align 2 54; CHECK-NEXT: ret void 55; 56entry: 57 %0 = load <vscale x 8 x i16>, ptr %q 58 %vecins = insertelement <vscale x 8 x i16> %0, i16 %s, i32 3 59 store <vscale x 8 x i16> %vecins, ptr %q 60 ret void 61} 62 63; To verify the case that index exceeds the minimum number 64; of elements of a scalable vector type. 65define void @insert_store_vscale_exceeds(ptr %q, i16 zeroext %s) { 66; CHECK-LABEL: @insert_store_vscale_exceeds( 67; CHECK-NEXT: entry: 68; CHECK-NEXT: [[TMP0:%.*]] = load <vscale x 8 x i16>, ptr [[Q:%.*]], align 16 69; CHECK-NEXT: [[VECINS:%.*]] = insertelement <vscale x 8 x i16> [[TMP0]], i16 [[S:%.*]], i32 9 70; CHECK-NEXT: store <vscale x 8 x i16> [[VECINS]], ptr [[Q]], align 16 71; CHECK-NEXT: ret void 72; 73entry: 74 %0 = load <vscale x 8 x i16>, ptr %q 75 %vecins = insertelement <vscale x 8 x i16> %0, i16 %s, i32 9 76 store <vscale x 8 x i16> %vecins, ptr %q 77 ret void 78} 79 80define void @insert_store_v9i4(ptr %q, i4 zeroext %s) { 81; CHECK-LABEL: @insert_store_v9i4( 82; CHECK-NEXT: entry: 83; CHECK-NEXT: [[TMP0:%.*]] = load <9 x i4>, ptr [[Q:%.*]], align 8 84; CHECK-NEXT: [[VECINS:%.*]] = insertelement <9 x i4> [[TMP0]], i4 [[S:%.*]], i32 3 85; CHECK-NEXT: store <9 x i4> [[VECINS]], ptr [[Q]], align 1 86; CHECK-NEXT: ret void 87; 88entry: 89 %0 = load <9 x i4>, ptr %q 90 %vecins = insertelement <9 x i4> %0, i4 %s, i32 3 91 store <9 x i4> %vecins, ptr %q, align 1 92 ret void 93} 94 95define void @insert_store_v4i27(ptr %q, i27 zeroext %s) { 96; CHECK-LABEL: @insert_store_v4i27( 97; CHECK-NEXT: entry: 98; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i27>, ptr [[Q:%.*]], align 16 99; CHECK-NEXT: [[VECINS:%.*]] = insertelement <4 x i27> [[TMP0]], i27 [[S:%.*]], i32 3 100; CHECK-NEXT: store <4 x i27> [[VECINS]], ptr [[Q]], align 1 101; CHECK-NEXT: ret void 102; 103entry: 104 %0 = load <4 x i27>, ptr %q 105 %vecins = insertelement <4 x i27> %0, i27 %s, i32 3 106 store <4 x i27> %vecins, ptr %q, align 1 107 ret void 108} 109 110define void @insert_store_v32i1(ptr %p) { 111; CHECK-LABEL: @insert_store_v32i1( 112; CHECK-NEXT: [[VEC:%.*]] = load <32 x i1>, ptr [[P:%.*]], align 4 113; CHECK-NEXT: [[INS:%.*]] = insertelement <32 x i1> [[VEC]], i1 true, i64 0 114; CHECK-NEXT: store <32 x i1> [[INS]], ptr [[P]], align 4 115; CHECK-NEXT: ret void 116; 117 %vec = load <32 x i1>, ptr %p 118 %ins = insertelement <32 x i1> %vec, i1 true, i64 0 119 store <32 x i1> %ins, ptr %p 120 ret void 121} 122 123define void @insert_store_blk_differ(ptr %q, i16 zeroext %s) { 124; CHECK-LABEL: @insert_store_blk_differ( 125; CHECK-NEXT: entry: 126; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16 127; CHECK-NEXT: br label [[CONT:%.*]] 128; CHECK: cont: 129; CHECK-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 3 130; CHECK-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 131; CHECK-NEXT: ret void 132; 133entry: 134 %0 = load <8 x i16>, ptr %q 135 br label %cont 136cont: 137 %vecins = insertelement <8 x i16> %0, i16 %s, i32 3 138 store <8 x i16> %vecins, ptr %q 139 ret void 140} 141 142define void @insert_store_nonconst(ptr %q, i8 zeroext %s, i32 %idx) { 143; CHECK-LABEL: @insert_store_nonconst( 144; CHECK-NEXT: entry: 145; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 146; CHECK-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX:%.*]] 147; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 148; CHECK-NEXT: ret void 149; 150entry: 151 %0 = load <16 x i8>, ptr %q 152 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx 153 store <16 x i8> %vecins, ptr %q 154 ret void 155} 156 157; To verify the case that the index is not a constant, and 158; the vector type is scalable. 159define void @insert_store_vscale_nonconst(ptr %q, i8 zeroext %s, i32 %idx) { 160; CHECK-LABEL: @insert_store_vscale_nonconst( 161; CHECK-NEXT: entry: 162; CHECK-NEXT: [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[Q:%.*]], align 16 163; CHECK-NEXT: [[VECINS:%.*]] = insertelement <vscale x 16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX:%.*]] 164; CHECK-NEXT: store <vscale x 16 x i8> [[VECINS]], ptr [[Q]], align 16 165; CHECK-NEXT: ret void 166; 167entry: 168 %0 = load <vscale x 16 x i8>, ptr %q 169 %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx 170 store <vscale x 16 x i8> %vecins, ptr %q 171 ret void 172} 173 174; To verify align here is narrowed to scalar store size 175define void @insert_store_nonconst_large_alignment(ptr %q, i32 zeroext %s, i32 %idx) { 176; CHECK-LABEL: @insert_store_nonconst_large_alignment( 177; CHECK-NEXT: entry: 178; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 179; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 180; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <4 x i32>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] 181; CHECK-NEXT: store i32 [[S:%.*]], ptr [[TMP0]], align 4 182; CHECK-NEXT: ret void 183; 184entry: 185 %cmp = icmp ult i32 %idx, 4 186 call void @llvm.assume(i1 %cmp) 187 %i = load <4 x i32>, ptr %q, align 128 188 %vecins = insertelement <4 x i32> %i, i32 %s, i32 %idx 189 store <4 x i32> %vecins, ptr %q, align 128 190 ret void 191} 192 193define void @insert_store_nonconst_align_maximum_8(ptr %q, i64 %s, i32 %idx) { 194; CHECK-LABEL: @insert_store_nonconst_align_maximum_8( 195; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2 196; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 197; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] 198; CHECK-NEXT: store i64 [[S:%.*]], ptr [[TMP1]], align 8 199; CHECK-NEXT: ret void 200; 201 %cmp = icmp ult i32 %idx, 2 202 call void @llvm.assume(i1 %cmp) 203 %i = load <8 x i64>, ptr %q, align 8 204 %vecins = insertelement <8 x i64> %i, i64 %s, i32 %idx 205 store <8 x i64> %vecins, ptr %q, align 8 206 ret void 207} 208 209define void @insert_store_nonconst_align_maximum_4(ptr %q, i64 %s, i32 %idx) { 210; CHECK-LABEL: @insert_store_nonconst_align_maximum_4( 211; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2 212; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 213; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] 214; CHECK-NEXT: store i64 [[S:%.*]], ptr [[TMP1]], align 4 215; CHECK-NEXT: ret void 216; 217 %cmp = icmp ult i32 %idx, 2 218 call void @llvm.assume(i1 %cmp) 219 %i = load <8 x i64>, ptr %q, align 4 220 %vecins = insertelement <8 x i64> %i, i64 %s, i32 %idx 221 store <8 x i64> %vecins, ptr %q, align 4 222 ret void 223} 224 225define void @insert_store_nonconst_align_larger(ptr %q, i64 %s, i32 %idx) { 226; CHECK-LABEL: @insert_store_nonconst_align_larger( 227; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2 228; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 229; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] 230; CHECK-NEXT: store i64 [[S:%.*]], ptr [[TMP1]], align 4 231; CHECK-NEXT: ret void 232; 233 %cmp = icmp ult i32 %idx, 2 234 call void @llvm.assume(i1 %cmp) 235 %i = load <8 x i64>, ptr %q, align 4 236 %vecins = insertelement <8 x i64> %i, i64 %s, i32 %idx 237 store <8 x i64> %vecins, ptr %q, align 2 238 ret void 239} 240 241define void @insert_store_nonconst_index_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) { 242; CHECK-LABEL: @insert_store_nonconst_index_known_valid_by_assume( 243; CHECK-NEXT: entry: 244; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 245; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 246; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] 247; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 248; CHECK-NEXT: ret void 249; 250entry: 251 %cmp = icmp ult i32 %idx, 4 252 call void @llvm.assume(i1 %cmp) 253 %0 = load <16 x i8>, ptr %q 254 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx 255 store <16 x i8> %vecins, ptr %q 256 ret void 257} 258 259; To verify the index is not a constant but valid by assume, 260; for scalable vector types. 261define void @insert_store_vscale_nonconst_index_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) { 262; CHECK-LABEL: @insert_store_vscale_nonconst_index_known_valid_by_assume( 263; CHECK-NEXT: entry: 264; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 265; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 266; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <vscale x 16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] 267; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 268; CHECK-NEXT: ret void 269; 270entry: 271 %cmp = icmp ult i32 %idx, 4 272 call void @llvm.assume(i1 %cmp) 273 %0 = load <vscale x 16 x i8>, ptr %q 274 %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx 275 store <vscale x 16 x i8> %vecins, ptr %q 276 ret void 277} 278 279declare void @maythrow() readnone 280 281define void @insert_store_nonconst_index_not_known_valid_by_assume_after_load(ptr %q, i8 zeroext %s, i32 %idx) { 282; CHECK-LABEL: @insert_store_nonconst_index_not_known_valid_by_assume_after_load( 283; CHECK-NEXT: entry: 284; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 285; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 286; CHECK-NEXT: call void @maythrow() 287; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 288; CHECK-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] 289; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 290; CHECK-NEXT: ret void 291; 292entry: 293 %cmp = icmp ult i32 %idx, 4 294 %0 = load <16 x i8>, ptr %q 295 call void @maythrow() 296 call void @llvm.assume(i1 %cmp) 297 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx 298 store <16 x i8> %vecins, ptr %q 299 ret void 300} 301 302define void @insert_store_nonconst_index_not_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) { 303; CHECK-LABEL: @insert_store_nonconst_index_not_known_valid_by_assume( 304; CHECK-NEXT: entry: 305; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 17 306; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 307; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 308; CHECK-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] 309; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 310; CHECK-NEXT: ret void 311; 312entry: 313 %cmp = icmp ult i32 %idx, 17 314 call void @llvm.assume(i1 %cmp) 315 %0 = load <16 x i8>, ptr %q 316 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx 317 store <16 x i8> %vecins, ptr %q 318 ret void 319} 320 321; To verify the index is not a constant and may not be valid by assume, 322; for scalable vector types. 323define void @insert_store_vscale_nonconst_index_not_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) { 324; CHECK-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_assume( 325; CHECK-NEXT: entry: 326; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 17 327; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 328; CHECK-NEXT: [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[Q:%.*]], align 16 329; CHECK-NEXT: [[VECINS:%.*]] = insertelement <vscale x 16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] 330; CHECK-NEXT: store <vscale x 16 x i8> [[VECINS]], ptr [[Q]], align 16 331; CHECK-NEXT: ret void 332; 333entry: 334 %cmp = icmp ult i32 %idx, 17 335 call void @llvm.assume(i1 %cmp) 336 %0 = load <vscale x 16 x i8>, ptr %q 337 %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx 338 store <vscale x 16 x i8> %vecins, ptr %q 339 ret void 340} 341 342declare void @llvm.assume(i1) 343 344define void @insert_store_nonconst_index_known_noundef_and_valid_by_and(ptr %q, i8 zeroext %s, i32 noundef %idx) { 345; CHECK-LABEL: @insert_store_nonconst_index_known_noundef_and_valid_by_and( 346; CHECK-NEXT: entry: 347; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 348; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]] 349; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 350; CHECK-NEXT: ret void 351; 352entry: 353 %0 = load <16 x i8>, ptr %q 354 %idx.clamped = and i32 %idx, 7 355 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 356 store <16 x i8> %vecins, ptr %q 357 ret void 358} 359 360; To verify the index is not a constant but valid by and, 361; for scalable vector types. 362define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and(ptr %q, i8 zeroext %s, i32 noundef %idx) { 363; CHECK-LABEL: @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and( 364; CHECK-NEXT: entry: 365; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 366; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <vscale x 16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]] 367; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 368; CHECK-NEXT: ret void 369; 370entry: 371 %0 = load <vscale x 16 x i8>, ptr %q 372 %idx.clamped = and i32 %idx, 7 373 %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx.clamped 374 store <vscale x 16 x i8> %vecins, ptr %q 375 ret void 376} 377 378define void @insert_store_nonconst_index_base_frozen_and_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) { 379; CHECK-LABEL: @insert_store_nonconst_index_base_frozen_and_valid_by_and( 380; CHECK-NEXT: entry: 381; CHECK-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]] 382; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX_FROZEN]], 7 383; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]] 384; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 385; CHECK-NEXT: ret void 386; 387entry: 388 %0 = load <16 x i8>, ptr %q 389 %idx.frozen = freeze i32 %idx 390 %idx.clamped = and i32 %idx.frozen, 7 391 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 392 store <16 x i8> %vecins, ptr %q 393 ret void 394} 395 396define void @insert_store_nonconst_index_frozen_and_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) { 397; CHECK-LABEL: @insert_store_nonconst_index_frozen_and_valid_by_and( 398; CHECK-NEXT: entry: 399; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 400; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 401; CHECK-NEXT: [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]] 402; CHECK-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED_FROZEN]] 403; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 404; CHECK-NEXT: ret void 405; 406entry: 407 %0 = load <16 x i8>, ptr %q 408 %idx.clamped = and i32 %idx, 7 409 %idx.clamped.frozen = freeze i32 %idx.clamped 410 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped.frozen 411 store <16 x i8> %vecins, ptr %q 412 ret void 413} 414 415define void @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison(ptr %q, i8 zeroext %s, i32 %idx) { 416; CHECK-LABEL: @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison( 417; CHECK-NEXT: entry: 418; CHECK-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]] 419; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX_FROZEN]], 7 420; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]] 421; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 422; CHECK-NEXT: ret void 423; 424entry: 425 %0 = load <16 x i8>, ptr %q 426 %idx.clamped = and i32 %idx, 7 427 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 428 store <16 x i8> %vecins, ptr %q 429 ret void 430} 431 432define void @insert_store_nonconst_index_not_known_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) { 433; CHECK-LABEL: @insert_store_nonconst_index_not_known_valid_by_and( 434; CHECK-NEXT: entry: 435; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 436; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 16 437; CHECK-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] 438; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 439; CHECK-NEXT: ret void 440; 441entry: 442 %0 = load <16 x i8>, ptr %q 443 %idx.clamped = and i32 %idx, 16 444 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 445 store <16 x i8> %vecins, ptr %q 446 ret void 447} 448 449define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_and(ptr %q, i8 zeroext %s, i32 noundef %idx) { 450; CHECK-LABEL: @insert_store_nonconst_index_known_noundef_not_known_valid_by_and( 451; CHECK-NEXT: entry: 452; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 453; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 16 454; CHECK-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] 455; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 456; CHECK-NEXT: ret void 457; 458entry: 459 %0 = load <16 x i8>, ptr %q 460 %idx.clamped = and i32 %idx, 16 461 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 462 store <16 x i8> %vecins, ptr %q 463 ret void 464} 465 466; To verify the index is not a constant and may not be valid by and, 467; for scalable vector types. 468define void @insert_store_vscale_nonconst_index_not_known_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) { 469; CHECK-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_and( 470; CHECK-NEXT: entry: 471; CHECK-NEXT: [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[Q:%.*]], align 16 472; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 31 473; CHECK-NEXT: [[VECINS:%.*]] = insertelement <vscale x 16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] 474; CHECK-NEXT: store <vscale x 16 x i8> [[VECINS]], ptr [[Q]], align 16 475; CHECK-NEXT: ret void 476; 477entry: 478 %0 = load <vscale x 16 x i8>, ptr %q 479 %idx.clamped = and i32 %idx, 31 480 %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx.clamped 481 store <vscale x 16 x i8> %vecins, ptr %q 482 ret void 483} 484 485define void @insert_store_nonconst_index_known_noundef_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 noundef %idx) { 486; CHECK-LABEL: @insert_store_nonconst_index_known_noundef_and_valid_by_urem( 487; CHECK-NEXT: entry: 488; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 489; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]] 490; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 491; CHECK-NEXT: ret void 492; 493entry: 494 %0 = load <16 x i8>, ptr %q 495 %idx.clamped = urem i32 %idx, 16 496 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 497 store <16 x i8> %vecins, ptr %q 498 ret void 499} 500 501; To verify the index is not a constant but valid by urem, 502; for scalable vector types. 503define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 noundef %idx) { 504; CHECK-LABEL: @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem( 505; CHECK-NEXT: entry: 506; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 507; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <vscale x 16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]] 508; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 509; CHECK-NEXT: ret void 510; 511entry: 512 %0 = load <vscale x 16 x i8>, ptr %q 513 %idx.clamped = urem i32 %idx, 16 514 %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx.clamped 515 store <vscale x 16 x i8> %vecins, ptr %q 516 ret void 517} 518 519define void @insert_store_nonconst_index_base_frozen_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) { 520; CHECK-LABEL: @insert_store_nonconst_index_base_frozen_and_valid_by_urem( 521; CHECK-NEXT: entry: 522; CHECK-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]] 523; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX_FROZEN]], 16 524; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]] 525; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 526; CHECK-NEXT: ret void 527; 528entry: 529 %0 = load <16 x i8>, ptr %q 530 %idx.frozen = freeze i32 %idx 531 %idx.clamped = urem i32 %idx.frozen, 16 532 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 533 store <16 x i8> %vecins, ptr %q 534 ret void 535} 536 537define void @insert_store_nonconst_index_frozen_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) { 538; CHECK-LABEL: @insert_store_nonconst_index_frozen_and_valid_by_urem( 539; CHECK-NEXT: entry: 540; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 541; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 542; CHECK-NEXT: [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]] 543; CHECK-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED_FROZEN]] 544; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 545; CHECK-NEXT: ret void 546; 547entry: 548 %0 = load <16 x i8>, ptr %q 549 %idx.clamped = urem i32 %idx, 16 550 %idx.clamped.frozen = freeze i32 %idx.clamped 551 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped.frozen 552 store <16 x i8> %vecins, ptr %q 553 ret void 554} 555 556define void @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison(ptr %q, i8 zeroext %s, i32 %idx) { 557; CHECK-LABEL: @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison( 558; CHECK-NEXT: entry: 559; CHECK-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]] 560; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX_FROZEN]], 16 561; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]] 562; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 563; CHECK-NEXT: ret void 564; 565entry: 566 %0 = load <16 x i8>, ptr %q 567 %idx.clamped = urem i32 %idx, 16 568 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 569 store <16 x i8> %vecins, ptr %q 570 ret void 571} 572 573define void @insert_store_nonconst_index_not_known_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) { 574; CHECK-LABEL: @insert_store_nonconst_index_not_known_valid_by_urem( 575; CHECK-NEXT: entry: 576; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 577; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17 578; CHECK-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] 579; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 580; CHECK-NEXT: ret void 581; 582entry: 583 %0 = load <16 x i8>, ptr %q 584 %idx.clamped = urem i32 %idx, 17 585 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 586 store <16 x i8> %vecins, ptr %q 587 ret void 588} 589 590; To verify the index is not a constant and may not be vaild by urem, 591; for scalable vector types. 592define void @insert_store_vscale_nonconst_index_not_known_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) { 593; CHECK-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_urem( 594; CHECK-NEXT: entry: 595; CHECK-NEXT: [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[Q:%.*]], align 16 596; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17 597; CHECK-NEXT: [[VECINS:%.*]] = insertelement <vscale x 16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] 598; CHECK-NEXT: store <vscale x 16 x i8> [[VECINS]], ptr [[Q]], align 16 599; CHECK-NEXT: ret void 600; 601entry: 602 %0 = load <vscale x 16 x i8>, ptr %q 603 %idx.clamped = urem i32 %idx, 17 604 %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx.clamped 605 store <vscale x 16 x i8> %vecins, ptr %q 606 ret void 607} 608 609define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem(ptr %q, i8 zeroext %s, i32 noundef %idx) { 610; CHECK-LABEL: @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem( 611; CHECK-NEXT: entry: 612; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 613; CHECK-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17 614; CHECK-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] 615; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 616; CHECK-NEXT: ret void 617; 618entry: 619 %0 = load <16 x i8>, ptr %q 620 %idx.clamped = urem i32 %idx, 17 621 %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped 622 store <16 x i8> %vecins, ptr %q 623 ret void 624} 625 626define void @insert_store_ptr_strip(ptr %q, i8 zeroext %s) { 627; CHECK-LABEL: @insert_store_ptr_strip( 628; CHECK-NEXT: entry: 629; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 3 630; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 631; CHECK-NEXT: ret void 632; 633entry: 634 %0 = load <16 x i8>, ptr %q 635 %vecins = insertelement <16 x i8> %0, i8 %s, i32 3 636 store <16 x i8> %vecins, ptr %q 637 ret void 638} 639 640define void @volatile_update(ptr %q, ptr %p, i8 zeroext %s) { 641; CHECK-LABEL: @volatile_update( 642; CHECK-NEXT: entry: 643; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 644; CHECK-NEXT: [[VECINS0:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 3 645; CHECK-NEXT: store volatile <16 x i8> [[VECINS0]], ptr [[Q]], align 16 646; CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr [[P:%.*]], align 16 647; CHECK-NEXT: [[VECINS1:%.*]] = insertelement <16 x i8> [[TMP1]], i8 [[S]], i32 1 648; CHECK-NEXT: store <16 x i8> [[VECINS1]], ptr [[P]], align 16 649; CHECK-NEXT: ret void 650; 651entry: 652 %0 = load <16 x i8>, ptr %q 653 %vecins0 = insertelement <16 x i8> %0, i8 %s, i32 3 654 store volatile <16 x i8> %vecins0, ptr %q 655 656 %1 = load volatile <16 x i8>, ptr %p 657 %vecins1 = insertelement <16 x i8> %1, i8 %s, i32 1 658 store <16 x i8> %vecins1, ptr %p 659 ret void 660} 661 662define void @insert_store_addr_differ(ptr %p, ptr %q, i8 %s) { 663; CHECK-LABEL: @insert_store_addr_differ( 664; CHECK-NEXT: entry: 665; CHECK-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16 666; CHECK-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3 667; CHECK-NEXT: store <16 x i8> [[INS]], ptr [[Q:%.*]], align 16 668; CHECK-NEXT: ret void 669; 670entry: 671 %ld = load <16 x i8>, ptr %p 672 %ins = insertelement <16 x i8> %ld, i8 %s, i32 3 673 store <16 x i8> %ins, ptr %q 674 ret void 675} 676 677; We can't transform if any instr could modify memory in between. 678define void @insert_store_mem_modify(ptr %p, ptr %q, ptr noalias %r, i8 %s, i32 %m) { 679; CHECK-LABEL: @insert_store_mem_modify( 680; CHECK-NEXT: entry: 681; CHECK-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16 682; CHECK-NEXT: store <16 x i8> zeroinitializer, ptr [[Q:%.*]], align 16 683; CHECK-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3 684; CHECK-NEXT: store <16 x i8> [[INS]], ptr [[P]], align 16 685; CHECK-NEXT: store <16 x i8> zeroinitializer, ptr [[R:%.*]], align 16 686; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q]], i32 0, i32 7 687; CHECK-NEXT: store i8 [[S]], ptr [[TMP0]], align 1 688; CHECK-NEXT: [[LD3:%.*]] = load <4 x i32>, ptr [[P]], align 16 689; CHECK-NEXT: store <16 x i8> zeroinitializer, ptr [[P]], align 16 690; CHECK-NEXT: [[INS3:%.*]] = insertelement <4 x i32> [[LD3]], i32 [[M:%.*]], i32 0 691; CHECK-NEXT: store <4 x i32> [[INS3]], ptr [[P]], align 16 692; CHECK-NEXT: ret void 693; 694entry: 695 ; p may alias q 696 %ld = load <16 x i8>, ptr %p 697 store <16 x i8> zeroinitializer, ptr %q 698 %ins = insertelement <16 x i8> %ld, i8 %s, i32 3 699 store <16 x i8> %ins, ptr %p 700 701 ; p never aliases r 702 %ld2 = load <16 x i8>, ptr %q 703 store <16 x i8> zeroinitializer, ptr %r 704 %ins2 = insertelement <16 x i8> %ld2, i8 %s, i32 7 705 store <16 x i8> %ins2, ptr %q 706 707 ; p must alias ptr0 708 %ld3 = load <4 x i32>, ptr %p 709 store <16 x i8> zeroinitializer, ptr %p 710 %ins3 = insertelement <4 x i32> %ld3, i32 %m, i32 0 711 store <4 x i32> %ins3, ptr %p 712 713 ret void 714} 715 716; Check cases when calls may modify memory 717define void @insert_store_with_call(ptr %p, ptr %q, i8 %s) { 718; CHECK-LABEL: @insert_store_with_call( 719; CHECK-NEXT: entry: 720; CHECK-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16 721; CHECK-NEXT: call void @maywrite(ptr [[P]]) 722; CHECK-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3 723; CHECK-NEXT: store <16 x i8> [[INS]], ptr [[P]], align 16 724; CHECK-NEXT: call void @foo() 725; CHECK-NEXT: call void @nowrite(ptr [[P]]) 726; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[P]], i32 0, i32 7 727; CHECK-NEXT: store i8 [[S]], ptr [[TMP0]], align 1 728; CHECK-NEXT: ret void 729; 730entry: 731 %ld = load <16 x i8>, ptr %p 732 call void @maywrite(ptr %p) 733 %ins = insertelement <16 x i8> %ld, i8 %s, i32 3 734 store <16 x i8> %ins, ptr %p 735 call void @foo() ; Barrier 736 %ld2 = load <16 x i8>, ptr %p 737 call void @nowrite(ptr %p) 738 %ins2 = insertelement <16 x i8> %ld2, i8 %s, i32 7 739 store <16 x i8> %ins2, ptr %p 740 ret void 741} 742 743declare void @foo() 744declare void @maywrite(ptr) 745declare void @nowrite(ptr) readonly 746 747; To test if number of instructions in-between exceeds the limit (default 30), 748; the combine will quit. 749define i32 @insert_store_maximum_scan_instrs(i32 %arg, ptr %arg1, ptr %arg2, i8 zeroext %arg3) { 750; CHECK-LABEL: @insert_store_maximum_scan_instrs( 751; CHECK-NEXT: bb: 752; CHECK-NEXT: [[I:%.*]] = or i32 [[ARG:%.*]], 1 753; CHECK-NEXT: [[I4:%.*]] = load <16 x i8>, ptr [[ARG2:%.*]], align 16 754; CHECK-NEXT: [[I5:%.*]] = tail call i32 @bar(i32 [[I]], i1 true) 755; CHECK-NEXT: [[I6:%.*]] = shl i32 [[ARG]], [[I5]] 756; CHECK-NEXT: [[I7:%.*]] = lshr i32 [[I6]], 26 757; CHECK-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 758; CHECK-NEXT: [[I9:%.*]] = and i8 [[I8]], 31 759; CHECK-NEXT: [[I10:%.*]] = lshr i32 [[I6]], 11 760; CHECK-NEXT: [[I11:%.*]] = and i32 [[I10]], 32767 761; CHECK-NEXT: [[I12:%.*]] = zext i8 [[I9]] to i64 762; CHECK-NEXT: [[I13:%.*]] = getelementptr inbounds i16, ptr [[ARG1:%.*]], i64 [[I12]] 763; CHECK-NEXT: [[I14:%.*]] = load i16, ptr [[I13]], align 2 764; CHECK-NEXT: [[I15:%.*]] = zext i16 [[I14]] to i32 765; CHECK-NEXT: [[I16:%.*]] = add nuw nsw i8 [[I9]], 1 766; CHECK-NEXT: [[I17:%.*]] = zext i8 [[I16]] to i64 767; CHECK-NEXT: [[I18:%.*]] = getelementptr inbounds i16, ptr [[ARG1]], i64 [[I17]] 768; CHECK-NEXT: [[I19:%.*]] = load i16, ptr [[I18]], align 2 769; CHECK-NEXT: [[I20:%.*]] = zext i16 [[I19]] to i32 770; CHECK-NEXT: [[I21:%.*]] = sub nsw i32 [[I20]], [[I15]] 771; CHECK-NEXT: [[I22:%.*]] = mul nsw i32 [[I11]], [[I21]] 772; CHECK-NEXT: [[I23:%.*]] = ashr i32 [[I22]], 15 773; CHECK-NEXT: [[I24:%.*]] = shl nuw nsw i32 [[I5]], 15 774; CHECK-NEXT: [[I25:%.*]] = xor i32 [[I24]], 1015808 775; CHECK-NEXT: [[I26:%.*]] = add nuw nsw i32 [[I25]], [[I15]] 776; CHECK-NEXT: [[I27:%.*]] = add nsw i32 [[I26]], [[I23]] 777; CHECK-NEXT: [[I28:%.*]] = sitofp i32 [[ARG]] to double 778; CHECK-NEXT: [[I29:%.*]] = tail call double @llvm.log2.f64(double [[I28]]) 779; CHECK-NEXT: [[I30:%.*]] = fptosi double [[I29]] to i32 780; CHECK-NEXT: [[I31:%.*]] = shl nsw i32 [[I30]], 15 781; CHECK-NEXT: [[I32:%.*]] = or i32 [[I31]], 4 782; CHECK-NEXT: [[I33:%.*]] = icmp eq i32 [[I27]], [[I32]] 783; CHECK-NEXT: [[I34:%.*]] = select i1 [[I33]], i32 [[ARG]], i32 [[I31]] 784; CHECK-NEXT: [[I35:%.*]] = lshr i32 [[I34]], 1 785; CHECK-NEXT: [[I36:%.*]] = insertelement <16 x i8> [[I4]], i8 [[ARG3:%.*]], i32 3 786; CHECK-NEXT: store <16 x i8> [[I36]], ptr [[ARG2]], align 16 787; CHECK-NEXT: ret i32 [[I35]] 788; 789bb: 790 %i = or i32 %arg, 1 791 %i4 = load <16 x i8>, ptr %arg2, align 16 792 %i5 = tail call i32 @bar(i32 %i, i1 true) 793 %i6 = shl i32 %arg, %i5 794 %i7 = lshr i32 %i6, 26 795 %i8 = trunc i32 %i7 to i8 796 %i9 = and i8 %i8, 31 797 %i10 = lshr i32 %i6, 11 798 %i11 = and i32 %i10, 32767 799 %i12 = zext i8 %i9 to i64 800 %i13 = getelementptr inbounds i16, ptr %arg1, i64 %i12 801 %i14 = load i16, ptr %i13, align 2 802 %i15 = zext i16 %i14 to i32 803 %i16 = add nuw nsw i8 %i9, 1 804 %i17 = zext i8 %i16 to i64 805 %i18 = getelementptr inbounds i16, ptr %arg1, i64 %i17 806 %i19 = load i16, ptr %i18, align 2 807 %i20 = zext i16 %i19 to i32 808 %i21 = sub nsw i32 %i20, %i15 809 %i22 = mul nsw i32 %i11, %i21 810 %i23 = ashr i32 %i22, 15 811 %i24 = shl nuw nsw i32 %i5, 15 812 %i25 = xor i32 %i24, 1015808 813 %i26 = add nuw nsw i32 %i25, %i15 814 %i27 = add nsw i32 %i26, %i23 815 %i28 = sitofp i32 %arg to double 816 %i29 = tail call double @llvm.log2.f64(double %i28) 817 %i30 = fptosi double %i29 to i32 818 %i31 = shl nsw i32 %i30, 15 819 %i32 = or i32 %i31, 4 820 %i33 = icmp eq i32 %i27, %i32 821 %i34 = select i1 %i33, i32 %arg, i32 %i31 822 %i35 = lshr i32 %i34, 1 823 %i36 = insertelement <16 x i8> %i4, i8 %arg3, i32 3 824 store <16 x i8> %i36, ptr %arg2, align 16 825 ret i32 %i35 826} 827 828declare i32 @bar(i32, i1) readonly 829declare double @llvm.log2.f64(double) 830