From 301305e4c4b16836c38927c85e14105d12bca069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Wed, 23 Jul 2025 14:43:41 +0200 Subject: [PATCH 1/6] [VectorCombine] Prevent extract/ins rewrite to GEP Using GEP to index into a vector is not disallowed, but not recommended. The SPIR-V backend needs to generate structured access into types, which is impossible with an untyped GEP instruction unless we add more info to the IR. Finding a solution is a work-in-progress, but in the meantime, we'd like to reduce the amount of failures. Preventing this optimizations from rewritting extract/insert instructions into a GEP helps us lower more code to SPIR-V. This change should be OK as it's only active when targeting SPIR-V and disabling a non-recommended transformation. Related to #145002 --- .../Transforms/Vectorize/VectorCombine.cpp | 11 +- .../VectorCombine/load-insert-store.ll | 382 ++++++++++++++++++ 2 files changed, 389 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index 6252f4f0507cb..3752d9d88129d 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -3866,8 +3866,9 @@ bool VectorCombine::run() { LLVM_DEBUG(dbgs() << "\n\nVECTORCOMBINE on " << F.getName() << "\n"); + const bool isSPIRV = F.getParent()->getTargetTriple().isSPIRV(); bool MadeChange = false; - auto FoldInst = [this, &MadeChange](Instruction &I) { + auto FoldInst = [this, &MadeChange, isSPIRV](Instruction &I) { Builder.SetInsertPoint(&I); bool IsVectorType = isa(I.getType()); bool IsFixedVectorType = isa(I.getType()); @@ -3896,13 +3897,15 @@ bool VectorCombine::run() { // TODO: Identify and allow other scalable transforms if (IsVectorType) { MadeChange |= scalarizeOpOrCmp(I); - MadeChange |= scalarizeLoadExtract(I); - MadeChange |= scalarizeExtExtract(I); + if (!isSPIRV) { + MadeChange |= scalarizeLoadExtract(I); + MadeChange |= scalarizeExtExtract(I); + } MadeChange |= scalarizeVPIntrinsic(I); MadeChange |= foldInterleaveIntrinsics(I); } - if (Opcode == Instruction::Store) + if (Opcode == Instruction::Store && !isSPIRV) MadeChange |= foldSingleElementStore(I); // If this is an early pipeline invocation of this pass, we are done. diff --git a/llvm/test/Transforms/VectorCombine/load-insert-store.ll b/llvm/test/Transforms/VectorCombine/load-insert-store.ll index 93565c1a708eb..0181ec76088bd 100644 --- a/llvm/test/Transforms/VectorCombine/load-insert-store.ll +++ b/llvm/test/Transforms/VectorCombine/load-insert-store.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes=vector-combine -data-layout=e < %s | FileCheck %s ; RUN: opt -S -passes=vector-combine -data-layout=E < %s | FileCheck %s +; RUN: opt -S -passes=vector-combine -data-layout=E -mtriple=spirv-unknown-vulkan1.3-library %s | FileCheck %s --check-prefix=SPIRV define void @insert_store(ptr %q, i8 zeroext %s) { ; CHECK-LABEL: @insert_store( @@ -9,6 +10,13 @@ define void @insert_store(ptr %q, i8 zeroext %s) { ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %vecins = insertelement <16 x i8> %0, i8 %s, i32 3 @@ -23,6 +31,13 @@ define void @insert_store_i16_align1(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store i16 [[S:%.*]], ptr [[TMP0]], align 2 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_i16_align1( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 3 +; SPIRV-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 1 +; SPIRV-NEXT: ret void +; entry: %0 = load <8 x i16>, ptr %q %vecins = insertelement <8 x i16> %0, i16 %s, i32 3 @@ -39,6 +54,13 @@ define void @insert_store_outofbounds(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_outofbounds( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 9 +; SPIRV-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <8 x i16>, ptr %q %vecins = insertelement <8 x i16> %0, i16 %s, i32 9 @@ -53,6 +75,13 @@ define void @insert_store_vscale(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store i16 [[S:%.*]], ptr [[TMP0]], align 2 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_vscale( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i16 [[S:%.*]], i32 3 +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load , ptr %q %vecins = insertelement %0, i16 %s, i32 3 @@ -70,6 +99,13 @@ define void @insert_store_vscale_exceeds(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_vscale_exceeds( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i16 [[S:%.*]], i32 9 +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load , ptr %q %vecins = insertelement %0, i16 %s, i32 9 @@ -85,6 +121,13 @@ define void @insert_store_v9i4(ptr %q, i4 zeroext %s) { ; CHECK-NEXT: store <9 x i4> [[VECINS]], ptr [[Q]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_v9i4( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <9 x i4>, ptr [[Q:%.*]], align 8 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <9 x i4> [[TMP0]], i4 [[S:%.*]], i32 3 +; SPIRV-NEXT: store <9 x i4> [[VECINS]], ptr [[Q]], align 1 +; SPIRV-NEXT: ret void +; entry: %0 = load <9 x i4>, ptr %q %vecins = insertelement <9 x i4> %0, i4 %s, i32 3 @@ -100,6 +143,13 @@ define void @insert_store_v4i27(ptr %q, i27 zeroext %s) { ; CHECK-NEXT: store <4 x i27> [[VECINS]], ptr [[Q]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_v4i27( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <4 x i27>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <4 x i27> [[TMP0]], i27 [[S:%.*]], i32 3 +; SPIRV-NEXT: store <4 x i27> [[VECINS]], ptr [[Q]], align 1 +; SPIRV-NEXT: ret void +; entry: %0 = load <4 x i27>, ptr %q %vecins = insertelement <4 x i27> %0, i27 %s, i32 3 @@ -113,6 +163,12 @@ define void @insert_store_v32i1(ptr %p) { ; CHECK-NEXT: [[INS:%.*]] = insertelement <32 x i1> [[VEC]], i1 true, i64 0 ; CHECK-NEXT: store <32 x i1> [[INS]], ptr [[P]], align 4 ; CHECK-NEXT: ret void +; +; SPIRV-LABEL: @insert_store_v32i1( +; SPIRV-NEXT: [[VEC:%.*]] = load <32 x i1>, ptr [[P:%.*]], align 4 +; SPIRV-NEXT: [[INS:%.*]] = insertelement <32 x i1> [[VEC]], i1 true, i64 0 +; SPIRV-NEXT: store <32 x i1> [[INS]], ptr [[P]], align 4 +; SPIRV-NEXT: ret void ; %vec = load <32 x i1>, ptr %p %ins = insertelement <32 x i1> %vec, i1 true, i64 0 @@ -130,6 +186,15 @@ define void @insert_store_blk_differ(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_blk_differ( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: br label [[CONT:%.*]] +; SPIRV: cont: +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 3 +; SPIRV-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <8 x i16>, ptr %q br label %cont @@ -147,6 +212,13 @@ define void @insert_store_nonconst(ptr %q, i8 zeroext %s, i32 %idx) { ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX:%.*]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx @@ -164,6 +236,13 @@ define void @insert_store_vscale_nonconst(ptr %q, i8 zeroext %s, i32 %idx) { ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_vscale_nonconst( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX:%.*]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load , ptr %q %vecins = insertelement %0, i8 %s, i32 %idx @@ -181,6 +260,15 @@ define void @insert_store_nonconst_large_alignment(ptr %q, i32 zeroext %s, i32 % ; CHECK-NEXT: store i32 [[S:%.*]], ptr [[TMP0]], align 4 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_large_alignment( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[I:%.*]] = load <4 x i32>, ptr [[Q:%.*]], align 128 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <4 x i32> [[I]], i32 [[S:%.*]], i32 [[IDX]] +; SPIRV-NEXT: store <4 x i32> [[VECINS]], ptr [[Q]], align 128 +; SPIRV-NEXT: ret void +; entry: %cmp = icmp ult i32 %idx, 4 call void @llvm.assume(i1 %cmp) @@ -197,6 +285,14 @@ define void @insert_store_nonconst_align_maximum_8(ptr %q, i64 %s, i32 %idx) { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] ; CHECK-NEXT: store i64 [[S:%.*]], ptr [[TMP1]], align 8 ; CHECK-NEXT: ret void +; +; SPIRV-LABEL: @insert_store_nonconst_align_maximum_8( +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[I:%.*]] = load <8 x i64>, ptr [[Q:%.*]], align 8 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i64> [[I]], i64 [[S:%.*]], i32 [[IDX]] +; SPIRV-NEXT: store <8 x i64> [[VECINS]], ptr [[Q]], align 8 +; SPIRV-NEXT: ret void ; %cmp = icmp ult i32 %idx, 2 call void @llvm.assume(i1 %cmp) @@ -213,6 +309,14 @@ define void @insert_store_nonconst_align_maximum_4(ptr %q, i64 %s, i32 %idx) { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] ; CHECK-NEXT: store i64 [[S:%.*]], ptr [[TMP1]], align 4 ; CHECK-NEXT: ret void +; +; SPIRV-LABEL: @insert_store_nonconst_align_maximum_4( +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[I:%.*]] = load <8 x i64>, ptr [[Q:%.*]], align 4 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i64> [[I]], i64 [[S:%.*]], i32 [[IDX]] +; SPIRV-NEXT: store <8 x i64> [[VECINS]], ptr [[Q]], align 4 +; SPIRV-NEXT: ret void ; %cmp = icmp ult i32 %idx, 2 call void @llvm.assume(i1 %cmp) @@ -229,6 +333,14 @@ define void @insert_store_nonconst_align_larger(ptr %q, i64 %s, i32 %idx) { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] ; CHECK-NEXT: store i64 [[S:%.*]], ptr [[TMP1]], align 4 ; CHECK-NEXT: ret void +; +; SPIRV-LABEL: @insert_store_nonconst_align_larger( +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[I:%.*]] = load <8 x i64>, ptr [[Q:%.*]], align 4 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i64> [[I]], i64 [[S:%.*]], i32 [[IDX]] +; SPIRV-NEXT: store <8 x i64> [[VECINS]], ptr [[Q]], align 2 +; SPIRV-NEXT: ret void ; %cmp = icmp ult i32 %idx, 2 call void @llvm.assume(i1 %cmp) @@ -247,6 +359,15 @@ define void @insert_store_nonconst_index_known_valid_by_assume(ptr %q, i8 zeroex ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_known_valid_by_assume( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %cmp = icmp ult i32 %idx, 4 call void @llvm.assume(i1 %cmp) @@ -267,6 +388,15 @@ define void @insert_store_vscale_nonconst_index_known_valid_by_assume(ptr %q, i8 ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_vscale_nonconst_index_known_valid_by_assume( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %cmp = icmp ult i32 %idx, 4 call void @llvm.assume(i1 %cmp) @@ -289,6 +419,16 @@ define void @insert_store_nonconst_index_not_known_valid_by_assume_after_load(pt ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_not_known_valid_by_assume_after_load( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: call void @maythrow() +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %cmp = icmp ult i32 %idx, 4 %0 = load <16 x i8>, ptr %q @@ -309,6 +449,15 @@ define void @insert_store_nonconst_index_not_known_valid_by_assume(ptr %q, i8 ze ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_not_known_valid_by_assume( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 17 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %cmp = icmp ult i32 %idx, 17 call void @llvm.assume(i1 %cmp) @@ -330,6 +479,15 @@ define void @insert_store_vscale_nonconst_index_not_known_valid_by_assume(ptr %q ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_assume( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 17 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %cmp = icmp ult i32 %idx, 17 call void @llvm.assume(i1 %cmp) @@ -349,6 +507,14 @@ define void @insert_store_nonconst_index_known_noundef_and_valid_by_and(ptr %q, ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_known_noundef_and_valid_by_and( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 7 @@ -367,6 +533,14 @@ define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and(p ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load , ptr %q %idx.clamped = and i32 %idx, 7 @@ -384,6 +558,15 @@ define void @insert_store_nonconst_index_base_frozen_and_valid_by_and(ptr %q, i8 ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_base_frozen_and_valid_by_and( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]] +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX_FROZEN]], 7 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.frozen = freeze i32 %idx @@ -403,6 +586,15 @@ define void @insert_store_nonconst_index_frozen_and_valid_by_and(ptr %q, i8 zero ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_frozen_and_valid_by_and( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 +; SPIRV-NEXT: [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED_FROZEN]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 7 @@ -421,6 +613,14 @@ define void @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison(pt ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 7 @@ -438,6 +638,14 @@ define void @insert_store_nonconst_index_not_known_valid_by_and(ptr %q, i8 zeroe ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_not_known_valid_by_and( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 16 @@ -455,6 +663,14 @@ define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_and(pt ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_known_noundef_not_known_valid_by_and( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 16 @@ -474,6 +690,14 @@ define void @insert_store_vscale_nonconst_index_not_known_valid_by_and(ptr %q, i ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_and( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 31 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load , ptr %q %idx.clamped = and i32 %idx, 31 @@ -490,6 +714,14 @@ define void @insert_store_nonconst_index_known_noundef_and_valid_by_urem(ptr %q, ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_known_noundef_and_valid_by_urem( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 16 @@ -508,6 +740,14 @@ define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem( ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load , ptr %q %idx.clamped = urem i32 %idx, 16 @@ -525,6 +765,15 @@ define void @insert_store_nonconst_index_base_frozen_and_valid_by_urem(ptr %q, i ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_base_frozen_and_valid_by_urem( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]] +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX_FROZEN]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.frozen = freeze i32 %idx @@ -544,6 +793,15 @@ define void @insert_store_nonconst_index_frozen_and_valid_by_urem(ptr %q, i8 zer ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_frozen_and_valid_by_urem( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 +; SPIRV-NEXT: [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED_FROZEN]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 16 @@ -562,6 +820,14 @@ define void @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison(p ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 16 @@ -579,6 +845,14 @@ define void @insert_store_nonconst_index_not_known_valid_by_urem(ptr %q, i8 zero ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_not_known_valid_by_urem( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 17 @@ -598,6 +872,14 @@ define void @insert_store_vscale_nonconst_index_not_known_valid_by_urem(ptr %q, ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_urem( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load , ptr %q %idx.clamped = urem i32 %idx, 17 @@ -615,6 +897,14 @@ define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem(p ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 17 @@ -630,6 +920,13 @@ define void @insert_store_ptr_strip(ptr %q, i8 zeroext %s) { ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_ptr_strip( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %vecins = insertelement <16 x i8> %0, i8 %s, i32 3 @@ -648,6 +945,16 @@ define void @volatile_update(ptr %q, ptr %p, i8 zeroext %s) { ; CHECK-NEXT: store <16 x i8> [[VECINS1]], ptr [[P]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @volatile_update( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[VECINS0:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 3 +; SPIRV-NEXT: store volatile <16 x i8> [[VECINS0]], ptr [[Q]], align 16 +; SPIRV-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr [[P:%.*]], align 16 +; SPIRV-NEXT: [[VECINS1:%.*]] = insertelement <16 x i8> [[TMP1]], i8 [[S]], i32 1 +; SPIRV-NEXT: store <16 x i8> [[VECINS1]], ptr [[P]], align 16 +; SPIRV-NEXT: ret void +; entry: %0 = load <16 x i8>, ptr %q %vecins0 = insertelement <16 x i8> %0, i8 %s, i32 3 @@ -667,6 +974,13 @@ define void @insert_store_addr_differ(ptr %p, ptr %q, i8 %s) { ; CHECK-NEXT: store <16 x i8> [[INS]], ptr [[Q:%.*]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_addr_differ( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16 +; SPIRV-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[INS]], ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: ret void +; entry: %ld = load <16 x i8>, ptr %p %ins = insertelement <16 x i8> %ld, i8 %s, i32 3 @@ -691,6 +1005,22 @@ define void @insert_store_mem_modify(ptr %p, ptr %q, ptr noalias %r, i8 %s, i32 ; CHECK-NEXT: store <4 x i32> [[INS3]], ptr [[P]], align 16 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_mem_modify( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16 +; SPIRV-NEXT: store <16 x i8> zeroinitializer, ptr [[Q:%.*]], align 16 +; SPIRV-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[INS]], ptr [[P]], align 16 +; SPIRV-NEXT: [[LD2:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: store <16 x i8> zeroinitializer, ptr [[R:%.*]], align 16 +; SPIRV-NEXT: [[INS2:%.*]] = insertelement <16 x i8> [[LD2]], i8 [[S]], i32 7 +; SPIRV-NEXT: store <16 x i8> [[INS2]], ptr [[Q]], align 16 +; SPIRV-NEXT: [[LD3:%.*]] = load <4 x i32>, ptr [[P]], align 16 +; SPIRV-NEXT: store <16 x i8> zeroinitializer, ptr [[P]], align 16 +; SPIRV-NEXT: [[INS3:%.*]] = insertelement <4 x i32> [[LD3]], i32 [[M:%.*]], i32 0 +; SPIRV-NEXT: store <4 x i32> [[INS3]], ptr [[P]], align 16 +; SPIRV-NEXT: ret void +; entry: ; p may alias q %ld = load <16 x i8>, ptr %p @@ -727,6 +1057,19 @@ define void @insert_store_with_call(ptr %p, ptr %q, i8 %s) { ; CHECK-NEXT: store i8 [[S]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; +; SPIRV-LABEL: @insert_store_with_call( +; SPIRV-NEXT: entry: +; SPIRV-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16 +; SPIRV-NEXT: call void @maywrite(ptr [[P]]) +; SPIRV-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[INS]], ptr [[P]], align 16 +; SPIRV-NEXT: call void @foo() +; SPIRV-NEXT: [[LD2:%.*]] = load <16 x i8>, ptr [[P]], align 16 +; SPIRV-NEXT: call void @nowrite(ptr [[P]]) +; SPIRV-NEXT: [[INS2:%.*]] = insertelement <16 x i8> [[LD2]], i8 [[S]], i32 7 +; SPIRV-NEXT: store <16 x i8> [[INS2]], ptr [[P]], align 16 +; SPIRV-NEXT: ret void +; entry: %ld = load <16 x i8>, ptr %p call void @maywrite(ptr %p) @@ -786,6 +1129,45 @@ define i32 @insert_store_maximum_scan_instrs(i32 %arg, ptr %arg1, ptr %arg2, i8 ; CHECK-NEXT: store <16 x i8> [[I36]], ptr [[ARG2]], align 16 ; CHECK-NEXT: ret i32 [[I35]] ; +; SPIRV-LABEL: @insert_store_maximum_scan_instrs( +; SPIRV-NEXT: bb: +; SPIRV-NEXT: [[I:%.*]] = or i32 [[ARG:%.*]], 1 +; SPIRV-NEXT: [[I4:%.*]] = load <16 x i8>, ptr [[ARG2:%.*]], align 16 +; SPIRV-NEXT: [[I5:%.*]] = tail call i32 @bar(i32 [[I]], i1 true) +; SPIRV-NEXT: [[I6:%.*]] = shl i32 [[ARG]], [[I5]] +; SPIRV-NEXT: [[I7:%.*]] = lshr i32 [[I6]], 26 +; SPIRV-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 +; SPIRV-NEXT: [[I9:%.*]] = and i8 [[I8]], 31 +; SPIRV-NEXT: [[I10:%.*]] = lshr i32 [[I6]], 11 +; SPIRV-NEXT: [[I11:%.*]] = and i32 [[I10]], 32767 +; SPIRV-NEXT: [[I12:%.*]] = zext i8 [[I9]] to i64 +; SPIRV-NEXT: [[I13:%.*]] = getelementptr inbounds i16, ptr [[ARG1:%.*]], i64 [[I12]] +; SPIRV-NEXT: [[I14:%.*]] = load i16, ptr [[I13]], align 2 +; SPIRV-NEXT: [[I15:%.*]] = zext i16 [[I14]] to i32 +; SPIRV-NEXT: [[I16:%.*]] = add nuw nsw i8 [[I9]], 1 +; SPIRV-NEXT: [[I17:%.*]] = zext i8 [[I16]] to i64 +; SPIRV-NEXT: [[I18:%.*]] = getelementptr inbounds i16, ptr [[ARG1]], i64 [[I17]] +; SPIRV-NEXT: [[I19:%.*]] = load i16, ptr [[I18]], align 2 +; SPIRV-NEXT: [[I20:%.*]] = zext i16 [[I19]] to i32 +; SPIRV-NEXT: [[I21:%.*]] = sub nsw i32 [[I20]], [[I15]] +; SPIRV-NEXT: [[I22:%.*]] = mul nsw i32 [[I11]], [[I21]] +; SPIRV-NEXT: [[I23:%.*]] = ashr i32 [[I22]], 15 +; SPIRV-NEXT: [[I24:%.*]] = shl nuw nsw i32 [[I5]], 15 +; SPIRV-NEXT: [[I25:%.*]] = xor i32 [[I24]], 1015808 +; SPIRV-NEXT: [[I26:%.*]] = add nuw nsw i32 [[I25]], [[I15]] +; SPIRV-NEXT: [[I27:%.*]] = add nsw i32 [[I26]], [[I23]] +; SPIRV-NEXT: [[I28:%.*]] = sitofp i32 [[ARG]] to double +; SPIRV-NEXT: [[I29:%.*]] = tail call double @llvm.log2.f64(double [[I28]]) +; SPIRV-NEXT: [[I30:%.*]] = fptosi double [[I29]] to i32 +; SPIRV-NEXT: [[I31:%.*]] = shl nsw i32 [[I30]], 15 +; SPIRV-NEXT: [[I32:%.*]] = or i32 [[I31]], 4 +; SPIRV-NEXT: [[I33:%.*]] = icmp eq i32 [[I27]], [[I32]] +; SPIRV-NEXT: [[I34:%.*]] = select i1 [[I33]], i32 [[ARG]], i32 [[I31]] +; SPIRV-NEXT: [[I35:%.*]] = lshr i32 [[I34]], 1 +; SPIRV-NEXT: [[I36:%.*]] = insertelement <16 x i8> [[I4]], i8 [[ARG3:%.*]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[I36]], ptr [[ARG2]], align 16 +; SPIRV-NEXT: ret i32 [[I35]] +; bb: %i = or i32 %arg, 1 %i4 = load <16 x i8>, ptr %arg2, align 16 From e581c35ea2652795284ca2baded170b800b30846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Tue, 29 Jul 2025 15:56:25 +0200 Subject: [PATCH 2/6] add TTI hook --- .../llvm/Analysis/TargetTransformInfo.h | 4 ++++ .../llvm/Analysis/TargetTransformInfoImpl.h | 2 ++ llvm/lib/Analysis/TargetTransformInfo.cpp | 4 ++++ .../Target/SPIRV/SPIRVTargetTransformInfo.h | 2 ++ .../lib/Transforms/Vectorize/VectorCombine.cpp | 18 +++++++++++------- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h index 7928835f7f84d..be0529754a116 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -1950,6 +1950,10 @@ class TargetTransformInfo { const Function &F, SmallVectorImpl> &LB) const; + /// Returns true if GEP should not be used to index into vectors for this + /// target. + LLVM_ABI bool isVectorElementIndexingUsingGEPAllowed() const; + private: std::unique_ptr TTIImpl; }; diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index 2ea87b3c62895..0e705cc8258f2 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -1145,6 +1145,8 @@ class TargetTransformInfoImplBase { const Function &F, SmallVectorImpl> &LB) const {} + virtual bool isVectorElementIndexingUsingGEPAllowed() const { return true; } + protected: // Obtain the minimum required size to hold the value (without the sign) // In case of a vector it returns the min required size for one element. diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp index 55ba52a1079ce..50c1993eb35a2 100644 --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -1486,6 +1486,10 @@ void TargetTransformInfo::collectKernelLaunchBounds( return TTIImpl->collectKernelLaunchBounds(F, LB); } +bool TargetTransformInfo::isVectorElementIndexingUsingGEPAllowed() const { + return TTIImpl->isVectorElementIndexingUsingGEPAllowed(); +} + TargetTransformInfoImplBase::~TargetTransformInfoImplBase() = default; TargetIRAnalysis::TargetIRAnalysis() : TTICallback(&getDefaultTTI) {} diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h b/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h index 43bf6e9dd2a6e..bd066873a28af 100644 --- a/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h +++ b/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h @@ -59,6 +59,8 @@ class SPIRVTTIImpl final : public BasicTTIImplBase { Intrinsic::ID IID) const override; Value *rewriteIntrinsicWithAddressSpace(IntrinsicInst *II, Value *OldV, Value *NewV) const override; + + bool isVectorElementIndexingUsingGEPAllowed() const override { return false; } }; } // namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index 3752d9d88129d..0d9a93fd5f99b 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -1664,6 +1664,8 @@ static Align computeAlignmentAfterScalarization(Align VectorAlignment, // %1 = getelementptr inbounds i32, i32* %0, i64 0, i64 1 // store i32 %b, i32* %1 bool VectorCombine::foldSingleElementStore(Instruction &I) { + if (!TTI.isVectorElementIndexingUsingGEPAllowed()) + return false; auto *SI = cast(&I); if (!SI->isSimple() || !isa(SI->getValueOperand()->getType())) return false; @@ -1719,6 +1721,9 @@ bool VectorCombine::foldSingleElementStore(Instruction &I) { /// Try to scalarize vector loads feeding extractelement instructions. bool VectorCombine::scalarizeLoadExtract(Instruction &I) { + if (!TTI.isVectorElementIndexingUsingGEPAllowed()) + return false; + Value *Ptr; if (!match(&I, m_Load(m_Value(Ptr)))) return false; @@ -1827,6 +1832,8 @@ bool VectorCombine::scalarizeLoadExtract(Instruction &I) { } bool VectorCombine::scalarizeExtExtract(Instruction &I) { + if (!TTI.isVectorElementIndexingUsingGEPAllowed()) + return false; auto *Ext = dyn_cast(&I); if (!Ext) return false; @@ -3866,9 +3873,8 @@ bool VectorCombine::run() { LLVM_DEBUG(dbgs() << "\n\nVECTORCOMBINE on " << F.getName() << "\n"); - const bool isSPIRV = F.getParent()->getTargetTriple().isSPIRV(); bool MadeChange = false; - auto FoldInst = [this, &MadeChange, isSPIRV](Instruction &I) { + auto FoldInst = [this, &MadeChange](Instruction &I) { Builder.SetInsertPoint(&I); bool IsVectorType = isa(I.getType()); bool IsFixedVectorType = isa(I.getType()); @@ -3897,15 +3903,13 @@ bool VectorCombine::run() { // TODO: Identify and allow other scalable transforms if (IsVectorType) { MadeChange |= scalarizeOpOrCmp(I); - if (!isSPIRV) { - MadeChange |= scalarizeLoadExtract(I); - MadeChange |= scalarizeExtExtract(I); - } + MadeChange |= scalarizeLoadExtract(I); + MadeChange |= scalarizeExtExtract(I); MadeChange |= scalarizeVPIntrinsic(I); MadeChange |= foldInterleaveIntrinsics(I); } - if (Opcode == Instruction::Store && !isSPIRV) + if (Opcode == Instruction::Store) MadeChange |= foldSingleElementStore(I); // If this is an early pipeline invocation of this pass, we are done. From 5c3e2add5fb85fccd7dfb38ec6503b8390a417d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Tue, 29 Jul 2025 17:38:21 +0200 Subject: [PATCH 3/6] move test to SPIRV subfolder --- .../VectorCombine/SPIRV/lit.local.cfg | 2 + .../VectorCombine/SPIRV/load-insert-store.ll | 889 ++++++++++++++++++ .../VectorCombine/load-insert-store.ll | 1 - 3 files changed, 891 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/VectorCombine/SPIRV/lit.local.cfg create mode 100644 llvm/test/Transforms/VectorCombine/SPIRV/load-insert-store.ll diff --git a/llvm/test/Transforms/VectorCombine/SPIRV/lit.local.cfg b/llvm/test/Transforms/VectorCombine/SPIRV/lit.local.cfg new file mode 100644 index 0000000000000..78dd74cd6dc63 --- /dev/null +++ b/llvm/test/Transforms/VectorCombine/SPIRV/lit.local.cfg @@ -0,0 +1,2 @@ +if not "SPIRV" in config.root.targets: + config.unsupported = True diff --git a/llvm/test/Transforms/VectorCombine/SPIRV/load-insert-store.ll b/llvm/test/Transforms/VectorCombine/SPIRV/load-insert-store.ll new file mode 100644 index 0000000000000..6f4c80d5d89a6 --- /dev/null +++ b/llvm/test/Transforms/VectorCombine/SPIRV/load-insert-store.ll @@ -0,0 +1,889 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S -passes=vector-combine -data-layout=E -mtriple=spirv-unknown-vulkan1.3-library %s | FileCheck %s --check-prefix=SPIRV + +define void @insert_store(ptr %q, i8 zeroext %s) { +; SPIRV-LABEL: define void @insert_store( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %vecins = insertelement <16 x i8> %0, i8 %s, i32 3 + store <16 x i8> %vecins, ptr %q, align 16 + ret void +} + +define void @insert_store_i16_align1(ptr %q, i16 zeroext %s) { +; SPIRV-LABEL: define void @insert_store_i16_align1( +; SPIRV-SAME: ptr [[Q:%.*]], i16 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S]], i32 3 +; SPIRV-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 1 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <8 x i16>, ptr %q + %vecins = insertelement <8 x i16> %0, i16 %s, i32 3 + store <8 x i16> %vecins, ptr %q, align 1 + ret void +} + +; To verify case when index is out of bounds +define void @insert_store_outofbounds(ptr %q, i16 zeroext %s) { +; SPIRV-LABEL: define void @insert_store_outofbounds( +; SPIRV-SAME: ptr [[Q:%.*]], i16 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S]], i32 9 +; SPIRV-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <8 x i16>, ptr %q + %vecins = insertelement <8 x i16> %0, i16 %s, i32 9 + store <8 x i16> %vecins, ptr %q + ret void +} + +define void @insert_store_vscale(ptr %q, i16 zeroext %s) { +; SPIRV-LABEL: define void @insert_store_vscale( +; SPIRV-SAME: ptr [[Q:%.*]], i16 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i16 [[S]], i32 3 +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load , ptr %q + %vecins = insertelement %0, i16 %s, i32 3 + store %vecins, ptr %q + ret void +} + +; To verify the case that index exceeds the minimum number +; of elements of a scalable vector type. +define void @insert_store_vscale_exceeds(ptr %q, i16 zeroext %s) { +; SPIRV-LABEL: define void @insert_store_vscale_exceeds( +; SPIRV-SAME: ptr [[Q:%.*]], i16 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i16 [[S]], i32 9 +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load , ptr %q + %vecins = insertelement %0, i16 %s, i32 9 + store %vecins, ptr %q + ret void +} + +define void @insert_store_v9i4(ptr %q, i4 zeroext %s) { +; SPIRV-LABEL: define void @insert_store_v9i4( +; SPIRV-SAME: ptr [[Q:%.*]], i4 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <9 x i4>, ptr [[Q]], align 8 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <9 x i4> [[TMP0]], i4 [[S]], i32 3 +; SPIRV-NEXT: store <9 x i4> [[VECINS]], ptr [[Q]], align 1 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <9 x i4>, ptr %q + %vecins = insertelement <9 x i4> %0, i4 %s, i32 3 + store <9 x i4> %vecins, ptr %q, align 1 + ret void +} + +define void @insert_store_v4i27(ptr %q, i27 zeroext %s) { +; SPIRV-LABEL: define void @insert_store_v4i27( +; SPIRV-SAME: ptr [[Q:%.*]], i27 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <4 x i27>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <4 x i27> [[TMP0]], i27 [[S]], i32 3 +; SPIRV-NEXT: store <4 x i27> [[VECINS]], ptr [[Q]], align 1 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <4 x i27>, ptr %q + %vecins = insertelement <4 x i27> %0, i27 %s, i32 3 + store <4 x i27> %vecins, ptr %q, align 1 + ret void +} + +define void @insert_store_v32i1(ptr %p) { +; SPIRV-LABEL: define void @insert_store_v32i1( +; SPIRV-SAME: ptr [[P:%.*]]) { +; SPIRV-NEXT: [[VEC:%.*]] = load <32 x i1>, ptr [[P]], align 4 +; SPIRV-NEXT: [[INS:%.*]] = insertelement <32 x i1> [[VEC]], i1 true, i64 0 +; SPIRV-NEXT: store <32 x i1> [[INS]], ptr [[P]], align 4 +; SPIRV-NEXT: ret void +; + %vec = load <32 x i1>, ptr %p + %ins = insertelement <32 x i1> %vec, i1 true, i64 0 + store <32 x i1> %ins, ptr %p + ret void +} + +define void @insert_store_blk_differ(ptr %q, i16 zeroext %s) { +; SPIRV-LABEL: define void @insert_store_blk_differ( +; SPIRV-SAME: ptr [[Q:%.*]], i16 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q]], align 16 +; SPIRV-NEXT: br label %[[CONT:.*]] +; SPIRV: [[CONT]]: +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S]], i32 3 +; SPIRV-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <8 x i16>, ptr %q + br label %cont +cont: + %vecins = insertelement <8 x i16> %0, i16 %s, i32 3 + store <8 x i16> %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx + store <16 x i8> %vecins, ptr %q + ret void +} + +; To verify the case that the index is not a constant, and +; the vector type is scalable. +define void @insert_store_vscale_nonconst(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_vscale_nonconst( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load , ptr %q + %vecins = insertelement %0, i8 %s, i32 %idx + store %vecins, ptr %q + ret void +} + +; To verify align here is narrowed to scalar store size +define void @insert_store_nonconst_large_alignment(ptr %q, i32 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_large_alignment( +; SPIRV-SAME: ptr [[Q:%.*]], i32 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 4 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[I:%.*]] = load <4 x i32>, ptr [[Q]], align 128 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <4 x i32> [[I]], i32 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store <4 x i32> [[VECINS]], ptr [[Q]], align 128 +; SPIRV-NEXT: ret void +; +entry: + %cmp = icmp ult i32 %idx, 4 + call void @llvm.assume(i1 %cmp) + %i = load <4 x i32>, ptr %q, align 128 + %vecins = insertelement <4 x i32> %i, i32 %s, i32 %idx + store <4 x i32> %vecins, ptr %q, align 128 + ret void +} + +define void @insert_store_nonconst_align_maximum_8(ptr %q, i64 %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_align_maximum_8( +; SPIRV-SAME: ptr [[Q:%.*]], i64 [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 2 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[I:%.*]] = load <8 x i64>, ptr [[Q]], align 8 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i64> [[I]], i64 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store <8 x i64> [[VECINS]], ptr [[Q]], align 8 +; SPIRV-NEXT: ret void +; + %cmp = icmp ult i32 %idx, 2 + call void @llvm.assume(i1 %cmp) + %i = load <8 x i64>, ptr %q, align 8 + %vecins = insertelement <8 x i64> %i, i64 %s, i32 %idx + store <8 x i64> %vecins, ptr %q, align 8 + ret void +} + +define void @insert_store_nonconst_align_maximum_4(ptr %q, i64 %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_align_maximum_4( +; SPIRV-SAME: ptr [[Q:%.*]], i64 [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 2 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[I:%.*]] = load <8 x i64>, ptr [[Q]], align 4 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i64> [[I]], i64 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store <8 x i64> [[VECINS]], ptr [[Q]], align 4 +; SPIRV-NEXT: ret void +; + %cmp = icmp ult i32 %idx, 2 + call void @llvm.assume(i1 %cmp) + %i = load <8 x i64>, ptr %q, align 4 + %vecins = insertelement <8 x i64> %i, i64 %s, i32 %idx + store <8 x i64> %vecins, ptr %q, align 4 + ret void +} + +define void @insert_store_nonconst_align_larger(ptr %q, i64 %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_align_larger( +; SPIRV-SAME: ptr [[Q:%.*]], i64 [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 2 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[I:%.*]] = load <8 x i64>, ptr [[Q]], align 4 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i64> [[I]], i64 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store <8 x i64> [[VECINS]], ptr [[Q]], align 2 +; SPIRV-NEXT: ret void +; + %cmp = icmp ult i32 %idx, 2 + call void @llvm.assume(i1 %cmp) + %i = load <8 x i64>, ptr %q, align 4 + %vecins = insertelement <8 x i64> %i, i64 %s, i32 %idx + store <8 x i64> %vecins, ptr %q, align 2 + ret void +} + +define void @insert_store_nonconst_index_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_known_valid_by_assume( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 4 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %cmp = icmp ult i32 %idx, 4 + call void @llvm.assume(i1 %cmp) + %0 = load <16 x i8>, ptr %q + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx + store <16 x i8> %vecins, ptr %q + ret void +} + +; To verify the index is not a constant but valid by assume, +; for scalable vector types. +define void @insert_store_vscale_nonconst_index_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_vscale_nonconst_index_known_valid_by_assume( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 4 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %cmp = icmp ult i32 %idx, 4 + call void @llvm.assume(i1 %cmp) + %0 = load , ptr %q + %vecins = insertelement %0, i8 %s, i32 %idx + store %vecins, ptr %q + ret void +} + +declare void @maythrow() readnone + +define void @insert_store_nonconst_index_not_known_valid_by_assume_after_load(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_not_known_valid_by_assume_after_load( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 4 +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: call void @maythrow() +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %cmp = icmp ult i32 %idx, 4 + %0 = load <16 x i8>, ptr %q + call void @maythrow() + call void @llvm.assume(i1 %cmp) + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_not_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_not_known_valid_by_assume( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 17 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %cmp = icmp ult i32 %idx, 17 + call void @llvm.assume(i1 %cmp) + %0 = load <16 x i8>, ptr %q + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx + store <16 x i8> %vecins, ptr %q + ret void +} + +; To verify the index is not a constant and may not be valid by assume, +; for scalable vector types. +define void @insert_store_vscale_nonconst_index_not_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_vscale_nonconst_index_not_known_valid_by_assume( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 17 +; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S]], i32 [[IDX]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %cmp = icmp ult i32 %idx, 17 + call void @llvm.assume(i1 %cmp) + %0 = load , ptr %q + %vecins = insertelement %0, i8 %s, i32 %idx + store %vecins, ptr %q + ret void +} + +declare void @llvm.assume(i1) + +define void @insert_store_nonconst_index_known_noundef_and_valid_by_and(ptr %q, i8 zeroext %s, i32 noundef %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_known_noundef_and_valid_by_and( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 noundef [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX]], 7 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = and i32 %idx, 7 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +; To verify the index is not a constant but valid by and, +; for scalable vector types. +define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and(ptr %q, i8 zeroext %s, i32 noundef %idx) { +; SPIRV-LABEL: define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 noundef [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX]], 7 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load , ptr %q + %idx.clamped = and i32 %idx, 7 + %vecins = insertelement %0, i8 %s, i32 %idx.clamped + store %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_base_frozen_and_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_base_frozen_and_valid_by_and( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX]] +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX_FROZEN]], 7 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.frozen = freeze i32 %idx + %idx.clamped = and i32 %idx.frozen, 7 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_frozen_and_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_frozen_and_valid_by_and( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX]], 7 +; SPIRV-NEXT: [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED_FROZEN]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = and i32 %idx, 7 + %idx.clamped.frozen = freeze i32 %idx.clamped + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped.frozen + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX]], 7 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = and i32 %idx, 7 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_not_known_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_not_known_valid_by_and( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = and i32 %idx, 16 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_and(ptr %q, i8 zeroext %s, i32 noundef %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_and( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 noundef [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = and i32 %idx, 16 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +; To verify the index is not a constant and may not be valid by and, +; for scalable vector types. +define void @insert_store_vscale_nonconst_index_not_known_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_vscale_nonconst_index_not_known_valid_by_and( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX]], 31 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load , ptr %q + %idx.clamped = and i32 %idx, 31 + %vecins = insertelement %0, i8 %s, i32 %idx.clamped + store %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_known_noundef_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 noundef %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_known_noundef_and_valid_by_urem( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 noundef [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = urem i32 %idx, 16 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +; To verify the index is not a constant but valid by urem, +; for scalable vector types. +define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 noundef %idx) { +; SPIRV-LABEL: define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 noundef [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load , ptr %q + %idx.clamped = urem i32 %idx, 16 + %vecins = insertelement %0, i8 %s, i32 %idx.clamped + store %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_base_frozen_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_base_frozen_and_valid_by_urem( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX]] +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX_FROZEN]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.frozen = freeze i32 %idx + %idx.clamped = urem i32 %idx.frozen, 16 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_frozen_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_frozen_and_valid_by_urem( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX]], 16 +; SPIRV-NEXT: [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED_FROZEN]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = urem i32 %idx, 16 + %idx.clamped.frozen = freeze i32 %idx.clamped + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped.frozen + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX]], 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = urem i32 %idx, 16 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_not_known_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_not_known_valid_by_urem( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX]], 17 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = urem i32 %idx, 17 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +; To verify the index is not a constant and may not be vaild by urem, +; for scalable vector types. +define void @insert_store_vscale_nonconst_index_not_known_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) { +; SPIRV-LABEL: define void @insert_store_vscale_nonconst_index_not_known_valid_by_urem( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX]], 17 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load , ptr %q + %idx.clamped = urem i32 %idx, 17 + %vecins = insertelement %0, i8 %s, i32 %idx.clamped + store %vecins, ptr %q + ret void +} + +define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem(ptr %q, i8 zeroext %s, i32 noundef %idx) { +; SPIRV-LABEL: define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]], i32 noundef [[IDX:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX]], 17 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 [[IDX_CLAMPED]] +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %idx.clamped = urem i32 %idx, 17 + %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @insert_store_ptr_strip(ptr %q, i8 zeroext %s) { +; SPIRV-LABEL: define void @insert_store_ptr_strip( +; SPIRV-SAME: ptr [[Q:%.*]], i8 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %vecins = insertelement <16 x i8> %0, i8 %s, i32 3 + store <16 x i8> %vecins, ptr %q + ret void +} + +define void @volatile_update(ptr %q, ptr %p, i8 zeroext %s) { +; SPIRV-LABEL: define void @volatile_update( +; SPIRV-SAME: ptr [[Q:%.*]], ptr [[P:%.*]], i8 zeroext [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: [[VECINS0:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S]], i32 3 +; SPIRV-NEXT: store volatile <16 x i8> [[VECINS0]], ptr [[Q]], align 16 +; SPIRV-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr [[P]], align 16 +; SPIRV-NEXT: [[VECINS1:%.*]] = insertelement <16 x i8> [[TMP1]], i8 [[S]], i32 1 +; SPIRV-NEXT: store <16 x i8> [[VECINS1]], ptr [[P]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %0 = load <16 x i8>, ptr %q + %vecins0 = insertelement <16 x i8> %0, i8 %s, i32 3 + store volatile <16 x i8> %vecins0, ptr %q + + %1 = load volatile <16 x i8>, ptr %p + %vecins1 = insertelement <16 x i8> %1, i8 %s, i32 1 + store <16 x i8> %vecins1, ptr %p + ret void +} + +define void @insert_store_addr_differ(ptr %p, ptr %q, i8 %s) { +; SPIRV-LABEL: define void @insert_store_addr_differ( +; SPIRV-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P]], align 16 +; SPIRV-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[INS]], ptr [[Q]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %ld = load <16 x i8>, ptr %p + %ins = insertelement <16 x i8> %ld, i8 %s, i32 3 + store <16 x i8> %ins, ptr %q + ret void +} + +; We can't transform if any instr could modify memory in between. +define void @insert_store_mem_modify(ptr %p, ptr %q, ptr noalias %r, i8 %s, i32 %m) { +; SPIRV-LABEL: define void @insert_store_mem_modify( +; SPIRV-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], ptr noalias [[R:%.*]], i8 [[S:%.*]], i32 [[M:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P]], align 16 +; SPIRV-NEXT: store <16 x i8> zeroinitializer, ptr [[Q]], align 16 +; SPIRV-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[INS]], ptr [[P]], align 16 +; SPIRV-NEXT: [[LD2:%.*]] = load <16 x i8>, ptr [[Q]], align 16 +; SPIRV-NEXT: store <16 x i8> zeroinitializer, ptr [[R]], align 16 +; SPIRV-NEXT: [[INS2:%.*]] = insertelement <16 x i8> [[LD2]], i8 [[S]], i32 7 +; SPIRV-NEXT: store <16 x i8> [[INS2]], ptr [[Q]], align 16 +; SPIRV-NEXT: [[LD3:%.*]] = load <4 x i32>, ptr [[P]], align 16 +; SPIRV-NEXT: store <16 x i8> zeroinitializer, ptr [[P]], align 16 +; SPIRV-NEXT: [[INS3:%.*]] = insertelement <4 x i32> [[LD3]], i32 [[M]], i32 0 +; SPIRV-NEXT: store <4 x i32> [[INS3]], ptr [[P]], align 16 +; SPIRV-NEXT: ret void +; +entry: + ; p may alias q + %ld = load <16 x i8>, ptr %p + store <16 x i8> zeroinitializer, ptr %q + %ins = insertelement <16 x i8> %ld, i8 %s, i32 3 + store <16 x i8> %ins, ptr %p + + ; p never aliases r + %ld2 = load <16 x i8>, ptr %q + store <16 x i8> zeroinitializer, ptr %r + %ins2 = insertelement <16 x i8> %ld2, i8 %s, i32 7 + store <16 x i8> %ins2, ptr %q + + ; p must alias ptr0 + %ld3 = load <4 x i32>, ptr %p + store <16 x i8> zeroinitializer, ptr %p + %ins3 = insertelement <4 x i32> %ld3, i32 %m, i32 0 + store <4 x i32> %ins3, ptr %p + + ret void +} + +; Check cases when calls may modify memory +define void @insert_store_with_call(ptr %p, ptr %q, i8 %s) { +; SPIRV-LABEL: define void @insert_store_with_call( +; SPIRV-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i8 [[S:%.*]]) { +; SPIRV-NEXT: [[ENTRY:.*:]] +; SPIRV-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P]], align 16 +; SPIRV-NEXT: call void @maywrite(ptr [[P]]) +; SPIRV-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[INS]], ptr [[P]], align 16 +; SPIRV-NEXT: call void @foo() +; SPIRV-NEXT: [[LD2:%.*]] = load <16 x i8>, ptr [[P]], align 16 +; SPIRV-NEXT: call void @nowrite(ptr [[P]]) +; SPIRV-NEXT: [[INS2:%.*]] = insertelement <16 x i8> [[LD2]], i8 [[S]], i32 7 +; SPIRV-NEXT: store <16 x i8> [[INS2]], ptr [[P]], align 16 +; SPIRV-NEXT: ret void +; +entry: + %ld = load <16 x i8>, ptr %p + call void @maywrite(ptr %p) + %ins = insertelement <16 x i8> %ld, i8 %s, i32 3 + store <16 x i8> %ins, ptr %p + call void @foo() ; Barrier + %ld2 = load <16 x i8>, ptr %p + call void @nowrite(ptr %p) + %ins2 = insertelement <16 x i8> %ld2, i8 %s, i32 7 + store <16 x i8> %ins2, ptr %p + ret void +} + +declare void @foo() +declare void @maywrite(ptr) +declare void @nowrite(ptr) readonly + +; To test if number of instructions in-between exceeds the limit (default 30), +; the combine will quit. +define i32 @insert_store_maximum_scan_instrs(i32 %arg, ptr %arg1, ptr %arg2, i8 zeroext %arg3) { +; SPIRV-LABEL: define i32 @insert_store_maximum_scan_instrs( +; SPIRV-SAME: i32 [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]], i8 zeroext [[ARG3:%.*]]) { +; SPIRV-NEXT: [[BB:.*:]] +; SPIRV-NEXT: [[I:%.*]] = or i32 [[ARG]], 1 +; SPIRV-NEXT: [[I4:%.*]] = load <16 x i8>, ptr [[ARG2]], align 16 +; SPIRV-NEXT: [[I5:%.*]] = tail call i32 @bar(i32 [[I]], i1 true) +; SPIRV-NEXT: [[I6:%.*]] = shl i32 [[ARG]], [[I5]] +; SPIRV-NEXT: [[I7:%.*]] = lshr i32 [[I6]], 26 +; SPIRV-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 +; SPIRV-NEXT: [[I9:%.*]] = and i8 [[I8]], 31 +; SPIRV-NEXT: [[I10:%.*]] = lshr i32 [[I6]], 11 +; SPIRV-NEXT: [[I11:%.*]] = and i32 [[I10]], 32767 +; SPIRV-NEXT: [[I12:%.*]] = zext i8 [[I9]] to i64 +; SPIRV-NEXT: [[I13:%.*]] = getelementptr inbounds i16, ptr [[ARG1]], i64 [[I12]] +; SPIRV-NEXT: [[I14:%.*]] = load i16, ptr [[I13]], align 2 +; SPIRV-NEXT: [[I15:%.*]] = zext i16 [[I14]] to i32 +; SPIRV-NEXT: [[I16:%.*]] = add nuw nsw i8 [[I9]], 1 +; SPIRV-NEXT: [[I17:%.*]] = zext i8 [[I16]] to i64 +; SPIRV-NEXT: [[I18:%.*]] = getelementptr inbounds i16, ptr [[ARG1]], i64 [[I17]] +; SPIRV-NEXT: [[I19:%.*]] = load i16, ptr [[I18]], align 2 +; SPIRV-NEXT: [[I20:%.*]] = zext i16 [[I19]] to i32 +; SPIRV-NEXT: [[I21:%.*]] = sub nsw i32 [[I20]], [[I15]] +; SPIRV-NEXT: [[I22:%.*]] = mul nsw i32 [[I11]], [[I21]] +; SPIRV-NEXT: [[I23:%.*]] = ashr i32 [[I22]], 15 +; SPIRV-NEXT: [[I24:%.*]] = shl nuw nsw i32 [[I5]], 15 +; SPIRV-NEXT: [[I25:%.*]] = xor i32 [[I24]], 1015808 +; SPIRV-NEXT: [[I26:%.*]] = add nuw nsw i32 [[I25]], [[I15]] +; SPIRV-NEXT: [[I27:%.*]] = add nsw i32 [[I26]], [[I23]] +; SPIRV-NEXT: [[I28:%.*]] = sitofp i32 [[ARG]] to double +; SPIRV-NEXT: [[I29:%.*]] = tail call double @llvm.log2.f64(double [[I28]]) +; SPIRV-NEXT: [[I30:%.*]] = fptosi double [[I29]] to i32 +; SPIRV-NEXT: [[I31:%.*]] = shl nsw i32 [[I30]], 15 +; SPIRV-NEXT: [[I32:%.*]] = or i32 [[I31]], 4 +; SPIRV-NEXT: [[I33:%.*]] = icmp eq i32 [[I27]], [[I32]] +; SPIRV-NEXT: [[I34:%.*]] = select i1 [[I33]], i32 [[ARG]], i32 [[I31]] +; SPIRV-NEXT: [[I35:%.*]] = lshr i32 [[I34]], 1 +; SPIRV-NEXT: [[I36:%.*]] = insertelement <16 x i8> [[I4]], i8 [[ARG3]], i32 3 +; SPIRV-NEXT: store <16 x i8> [[I36]], ptr [[ARG2]], align 16 +; SPIRV-NEXT: ret i32 [[I35]] +; +bb: + %i = or i32 %arg, 1 + %i4 = load <16 x i8>, ptr %arg2, align 16 + %i5 = tail call i32 @bar(i32 %i, i1 true) + %i6 = shl i32 %arg, %i5 + %i7 = lshr i32 %i6, 26 + %i8 = trunc i32 %i7 to i8 + %i9 = and i8 %i8, 31 + %i10 = lshr i32 %i6, 11 + %i11 = and i32 %i10, 32767 + %i12 = zext i8 %i9 to i64 + %i13 = getelementptr inbounds i16, ptr %arg1, i64 %i12 + %i14 = load i16, ptr %i13, align 2 + %i15 = zext i16 %i14 to i32 + %i16 = add nuw nsw i8 %i9, 1 + %i17 = zext i8 %i16 to i64 + %i18 = getelementptr inbounds i16, ptr %arg1, i64 %i17 + %i19 = load i16, ptr %i18, align 2 + %i20 = zext i16 %i19 to i32 + %i21 = sub nsw i32 %i20, %i15 + %i22 = mul nsw i32 %i11, %i21 + %i23 = ashr i32 %i22, 15 + %i24 = shl nuw nsw i32 %i5, 15 + %i25 = xor i32 %i24, 1015808 + %i26 = add nuw nsw i32 %i25, %i15 + %i27 = add nsw i32 %i26, %i23 + %i28 = sitofp i32 %arg to double + %i29 = tail call double @llvm.log2.f64(double %i28) + %i30 = fptosi double %i29 to i32 + %i31 = shl nsw i32 %i30, 15 + %i32 = or i32 %i31, 4 + %i33 = icmp eq i32 %i27, %i32 + %i34 = select i1 %i33, i32 %arg, i32 %i31 + %i35 = lshr i32 %i34, 1 + %i36 = insertelement <16 x i8> %i4, i8 %arg3, i32 3 + store <16 x i8> %i36, ptr %arg2, align 16 + ret i32 %i35 +} + +declare i32 @bar(i32, i1) readonly +declare double @llvm.log2.f64(double) + diff --git a/llvm/test/Transforms/VectorCombine/load-insert-store.ll b/llvm/test/Transforms/VectorCombine/load-insert-store.ll index 0181ec76088bd..9864bb8964e75 100644 --- a/llvm/test/Transforms/VectorCombine/load-insert-store.ll +++ b/llvm/test/Transforms/VectorCombine/load-insert-store.ll @@ -1,7 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes=vector-combine -data-layout=e < %s | FileCheck %s ; RUN: opt -S -passes=vector-combine -data-layout=E < %s | FileCheck %s -; RUN: opt -S -passes=vector-combine -data-layout=E -mtriple=spirv-unknown-vulkan1.3-library %s | FileCheck %s --check-prefix=SPIRV define void @insert_store(ptr %q, i8 zeroext %s) { ; CHECK-LABEL: @insert_store( From 8f49a51b7ec99ae50151abc77fd7c77e990fabbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Tue, 29 Jul 2025 17:39:45 +0200 Subject: [PATCH 4/6] rename to allowVectorElementIndexingUsingGEP --- llvm/include/llvm/Analysis/TargetTransformInfo.h | 2 +- llvm/lib/Analysis/TargetTransformInfo.cpp | 4 ++-- llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h | 2 +- llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h index be0529754a116..aa4550de455e0 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -1952,7 +1952,7 @@ class TargetTransformInfo { /// Returns true if GEP should not be used to index into vectors for this /// target. - LLVM_ABI bool isVectorElementIndexingUsingGEPAllowed() const; + LLVM_ABI bool allowVectorElementIndexingUsingGEP() const; private: std::unique_ptr TTIImpl; diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp index 50c1993eb35a2..c7eb2ec18c679 100644 --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -1486,8 +1486,8 @@ void TargetTransformInfo::collectKernelLaunchBounds( return TTIImpl->collectKernelLaunchBounds(F, LB); } -bool TargetTransformInfo::isVectorElementIndexingUsingGEPAllowed() const { - return TTIImpl->isVectorElementIndexingUsingGEPAllowed(); +bool TargetTransformInfo::allowVectorElementIndexingUsingGEP() const { + return TTIImpl->allowVectorElementIndexingUsingGEP(); } TargetTransformInfoImplBase::~TargetTransformInfoImplBase() = default; diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h b/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h index bd066873a28af..60c4e2de2fb23 100644 --- a/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h +++ b/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h @@ -60,7 +60,7 @@ class SPIRVTTIImpl final : public BasicTTIImplBase { Value *rewriteIntrinsicWithAddressSpace(IntrinsicInst *II, Value *OldV, Value *NewV) const override; - bool isVectorElementIndexingUsingGEPAllowed() const override { return false; } + bool allowVectorElementIndexingUsingGEP() const override { return false; } }; } // namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index 0d9a93fd5f99b..6345b18b809a6 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -1664,7 +1664,7 @@ static Align computeAlignmentAfterScalarization(Align VectorAlignment, // %1 = getelementptr inbounds i32, i32* %0, i64 0, i64 1 // store i32 %b, i32* %1 bool VectorCombine::foldSingleElementStore(Instruction &I) { - if (!TTI.isVectorElementIndexingUsingGEPAllowed()) + if (!TTI.allowVectorElementIndexingUsingGEP()) return false; auto *SI = cast(&I); if (!SI->isSimple() || !isa(SI->getValueOperand()->getType())) @@ -1721,7 +1721,7 @@ bool VectorCombine::foldSingleElementStore(Instruction &I) { /// Try to scalarize vector loads feeding extractelement instructions. bool VectorCombine::scalarizeLoadExtract(Instruction &I) { - if (!TTI.isVectorElementIndexingUsingGEPAllowed()) + if (!TTI.allowVectorElementIndexingUsingGEP()) return false; Value *Ptr; @@ -1832,7 +1832,7 @@ bool VectorCombine::scalarizeLoadExtract(Instruction &I) { } bool VectorCombine::scalarizeExtExtract(Instruction &I) { - if (!TTI.isVectorElementIndexingUsingGEPAllowed()) + if (!TTI.allowVectorElementIndexingUsingGEP()) return false; auto *Ext = dyn_cast(&I); if (!Ext) From 37d4fb110d93604a258b26c0c122084ab85eab1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Tue, 29 Jul 2025 17:41:12 +0200 Subject: [PATCH 5/6] fix one missing rename --- llvm/include/llvm/Analysis/TargetTransformInfoImpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index 0e705cc8258f2..abdbca04488db 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -1145,7 +1145,7 @@ class TargetTransformInfoImplBase { const Function &F, SmallVectorImpl> &LB) const {} - virtual bool isVectorElementIndexingUsingGEPAllowed() const { return true; } + virtual bool allowVectorElementIndexingUsingGEP() const { return true; } protected: // Obtain the minimum required size to hold the value (without the sign) From 775680905e7d38f359d60d26c32e800ba658f021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Wed, 30 Jul 2025 19:33:59 +0200 Subject: [PATCH 6/6] remove obsolete test lines --- .../VectorCombine/load-insert-store.ll | 381 ------------------ 1 file changed, 381 deletions(-) diff --git a/llvm/test/Transforms/VectorCombine/load-insert-store.ll b/llvm/test/Transforms/VectorCombine/load-insert-store.ll index 9864bb8964e75..93565c1a708eb 100644 --- a/llvm/test/Transforms/VectorCombine/load-insert-store.ll +++ b/llvm/test/Transforms/VectorCombine/load-insert-store.ll @@ -9,13 +9,6 @@ define void @insert_store(ptr %q, i8 zeroext %s) { ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 3 -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %vecins = insertelement <16 x i8> %0, i8 %s, i32 3 @@ -30,13 +23,6 @@ define void @insert_store_i16_align1(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store i16 [[S:%.*]], ptr [[TMP0]], align 2 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_i16_align1( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 3 -; SPIRV-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 1 -; SPIRV-NEXT: ret void -; entry: %0 = load <8 x i16>, ptr %q %vecins = insertelement <8 x i16> %0, i16 %s, i32 3 @@ -53,13 +39,6 @@ define void @insert_store_outofbounds(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_outofbounds( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 9 -; SPIRV-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <8 x i16>, ptr %q %vecins = insertelement <8 x i16> %0, i16 %s, i32 9 @@ -74,13 +53,6 @@ define void @insert_store_vscale(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store i16 [[S:%.*]], ptr [[TMP0]], align 2 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_vscale( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i16 [[S:%.*]], i32 3 -; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load , ptr %q %vecins = insertelement %0, i16 %s, i32 3 @@ -98,13 +70,6 @@ define void @insert_store_vscale_exceeds(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_vscale_exceeds( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i16 [[S:%.*]], i32 9 -; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load , ptr %q %vecins = insertelement %0, i16 %s, i32 9 @@ -120,13 +85,6 @@ define void @insert_store_v9i4(ptr %q, i4 zeroext %s) { ; CHECK-NEXT: store <9 x i4> [[VECINS]], ptr [[Q]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_v9i4( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <9 x i4>, ptr [[Q:%.*]], align 8 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <9 x i4> [[TMP0]], i4 [[S:%.*]], i32 3 -; SPIRV-NEXT: store <9 x i4> [[VECINS]], ptr [[Q]], align 1 -; SPIRV-NEXT: ret void -; entry: %0 = load <9 x i4>, ptr %q %vecins = insertelement <9 x i4> %0, i4 %s, i32 3 @@ -142,13 +100,6 @@ define void @insert_store_v4i27(ptr %q, i27 zeroext %s) { ; CHECK-NEXT: store <4 x i27> [[VECINS]], ptr [[Q]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_v4i27( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <4 x i27>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <4 x i27> [[TMP0]], i27 [[S:%.*]], i32 3 -; SPIRV-NEXT: store <4 x i27> [[VECINS]], ptr [[Q]], align 1 -; SPIRV-NEXT: ret void -; entry: %0 = load <4 x i27>, ptr %q %vecins = insertelement <4 x i27> %0, i27 %s, i32 3 @@ -162,12 +113,6 @@ define void @insert_store_v32i1(ptr %p) { ; CHECK-NEXT: [[INS:%.*]] = insertelement <32 x i1> [[VEC]], i1 true, i64 0 ; CHECK-NEXT: store <32 x i1> [[INS]], ptr [[P]], align 4 ; CHECK-NEXT: ret void -; -; SPIRV-LABEL: @insert_store_v32i1( -; SPIRV-NEXT: [[VEC:%.*]] = load <32 x i1>, ptr [[P:%.*]], align 4 -; SPIRV-NEXT: [[INS:%.*]] = insertelement <32 x i1> [[VEC]], i1 true, i64 0 -; SPIRV-NEXT: store <32 x i1> [[INS]], ptr [[P]], align 4 -; SPIRV-NEXT: ret void ; %vec = load <32 x i1>, ptr %p %ins = insertelement <32 x i1> %vec, i1 true, i64 0 @@ -185,15 +130,6 @@ define void @insert_store_blk_differ(ptr %q, i16 zeroext %s) { ; CHECK-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_blk_differ( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: br label [[CONT:%.*]] -; SPIRV: cont: -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 3 -; SPIRV-NEXT: store <8 x i16> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <8 x i16>, ptr %q br label %cont @@ -211,13 +147,6 @@ define void @insert_store_nonconst(ptr %q, i8 zeroext %s, i32 %idx) { ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX:%.*]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx @@ -235,13 +164,6 @@ define void @insert_store_vscale_nonconst(ptr %q, i8 zeroext %s, i32 %idx) { ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_vscale_nonconst( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX:%.*]] -; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load , ptr %q %vecins = insertelement %0, i8 %s, i32 %idx @@ -259,15 +181,6 @@ define void @insert_store_nonconst_large_alignment(ptr %q, i32 zeroext %s, i32 % ; CHECK-NEXT: store i32 [[S:%.*]], ptr [[TMP0]], align 4 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_large_alignment( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 -; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) -; SPIRV-NEXT: [[I:%.*]] = load <4 x i32>, ptr [[Q:%.*]], align 128 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <4 x i32> [[I]], i32 [[S:%.*]], i32 [[IDX]] -; SPIRV-NEXT: store <4 x i32> [[VECINS]], ptr [[Q]], align 128 -; SPIRV-NEXT: ret void -; entry: %cmp = icmp ult i32 %idx, 4 call void @llvm.assume(i1 %cmp) @@ -284,14 +197,6 @@ define void @insert_store_nonconst_align_maximum_8(ptr %q, i64 %s, i32 %idx) { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] ; CHECK-NEXT: store i64 [[S:%.*]], ptr [[TMP1]], align 8 ; CHECK-NEXT: ret void -; -; SPIRV-LABEL: @insert_store_nonconst_align_maximum_8( -; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2 -; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) -; SPIRV-NEXT: [[I:%.*]] = load <8 x i64>, ptr [[Q:%.*]], align 8 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i64> [[I]], i64 [[S:%.*]], i32 [[IDX]] -; SPIRV-NEXT: store <8 x i64> [[VECINS]], ptr [[Q]], align 8 -; SPIRV-NEXT: ret void ; %cmp = icmp ult i32 %idx, 2 call void @llvm.assume(i1 %cmp) @@ -308,14 +213,6 @@ define void @insert_store_nonconst_align_maximum_4(ptr %q, i64 %s, i32 %idx) { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] ; CHECK-NEXT: store i64 [[S:%.*]], ptr [[TMP1]], align 4 ; CHECK-NEXT: ret void -; -; SPIRV-LABEL: @insert_store_nonconst_align_maximum_4( -; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2 -; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) -; SPIRV-NEXT: [[I:%.*]] = load <8 x i64>, ptr [[Q:%.*]], align 4 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i64> [[I]], i64 [[S:%.*]], i32 [[IDX]] -; SPIRV-NEXT: store <8 x i64> [[VECINS]], ptr [[Q]], align 4 -; SPIRV-NEXT: ret void ; %cmp = icmp ult i32 %idx, 2 call void @llvm.assume(i1 %cmp) @@ -332,14 +229,6 @@ define void @insert_store_nonconst_align_larger(ptr %q, i64 %s, i32 %idx) { ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]] ; CHECK-NEXT: store i64 [[S:%.*]], ptr [[TMP1]], align 4 ; CHECK-NEXT: ret void -; -; SPIRV-LABEL: @insert_store_nonconst_align_larger( -; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2 -; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) -; SPIRV-NEXT: [[I:%.*]] = load <8 x i64>, ptr [[Q:%.*]], align 4 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <8 x i64> [[I]], i64 [[S:%.*]], i32 [[IDX]] -; SPIRV-NEXT: store <8 x i64> [[VECINS]], ptr [[Q]], align 2 -; SPIRV-NEXT: ret void ; %cmp = icmp ult i32 %idx, 2 call void @llvm.assume(i1 %cmp) @@ -358,15 +247,6 @@ define void @insert_store_nonconst_index_known_valid_by_assume(ptr %q, i8 zeroex ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_known_valid_by_assume( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 -; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %cmp = icmp ult i32 %idx, 4 call void @llvm.assume(i1 %cmp) @@ -387,15 +267,6 @@ define void @insert_store_vscale_nonconst_index_known_valid_by_assume(ptr %q, i8 ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_vscale_nonconst_index_known_valid_by_assume( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 -; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) -; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] -; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %cmp = icmp ult i32 %idx, 4 call void @llvm.assume(i1 %cmp) @@ -418,16 +289,6 @@ define void @insert_store_nonconst_index_not_known_valid_by_assume_after_load(pt ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_not_known_valid_by_assume_after_load( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4 -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: call void @maythrow() -; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %cmp = icmp ult i32 %idx, 4 %0 = load <16 x i8>, ptr %q @@ -448,15 +309,6 @@ define void @insert_store_nonconst_index_not_known_valid_by_assume(ptr %q, i8 ze ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_not_known_valid_by_assume( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 17 -; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %cmp = icmp ult i32 %idx, 17 call void @llvm.assume(i1 %cmp) @@ -478,15 +330,6 @@ define void @insert_store_vscale_nonconst_index_not_known_valid_by_assume(ptr %q ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_assume( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 17 -; SPIRV-NEXT: call void @llvm.assume(i1 [[CMP]]) -; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX]] -; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %cmp = icmp ult i32 %idx, 17 call void @llvm.assume(i1 %cmp) @@ -506,14 +349,6 @@ define void @insert_store_nonconst_index_known_noundef_and_valid_by_and(ptr %q, ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_known_noundef_and_valid_by_and( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 7 @@ -532,14 +367,6 @@ define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and(p ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load , ptr %q %idx.clamped = and i32 %idx, 7 @@ -557,15 +384,6 @@ define void @insert_store_nonconst_index_base_frozen_and_valid_by_and(ptr %q, i8 ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_base_frozen_and_valid_by_and( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]] -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX_FROZEN]], 7 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.frozen = freeze i32 %idx @@ -585,15 +403,6 @@ define void @insert_store_nonconst_index_frozen_and_valid_by_and(ptr %q, i8 zero ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_frozen_and_valid_by_and( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 -; SPIRV-NEXT: [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED_FROZEN]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 7 @@ -612,14 +421,6 @@ define void @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison(pt ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 7 @@ -637,14 +438,6 @@ define void @insert_store_nonconst_index_not_known_valid_by_and(ptr %q, i8 zeroe ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_not_known_valid_by_and( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 16 @@ -662,14 +455,6 @@ define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_and(pt ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_known_noundef_not_known_valid_by_and( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = and i32 %idx, 16 @@ -689,14 +474,6 @@ define void @insert_store_vscale_nonconst_index_not_known_valid_by_and(ptr %q, i ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_and( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 31 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load , ptr %q %idx.clamped = and i32 %idx, 31 @@ -713,14 +490,6 @@ define void @insert_store_nonconst_index_known_noundef_and_valid_by_urem(ptr %q, ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_known_noundef_and_valid_by_urem( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 16 @@ -739,14 +508,6 @@ define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem( ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load , ptr %q %idx.clamped = urem i32 %idx, 16 @@ -764,15 +525,6 @@ define void @insert_store_nonconst_index_base_frozen_and_valid_by_urem(ptr %q, i ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_base_frozen_and_valid_by_urem( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]] -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX_FROZEN]], 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.frozen = freeze i32 %idx @@ -792,15 +544,6 @@ define void @insert_store_nonconst_index_frozen_and_valid_by_urem(ptr %q, i8 zer ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_frozen_and_valid_by_urem( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 -; SPIRV-NEXT: [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED_FROZEN]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 16 @@ -819,14 +562,6 @@ define void @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison(p ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 16 @@ -844,14 +579,6 @@ define void @insert_store_nonconst_index_not_known_valid_by_urem(ptr %q, i8 zero ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_not_known_valid_by_urem( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 17 @@ -871,14 +598,6 @@ define void @insert_store_vscale_nonconst_index_not_known_valid_by_urem(ptr %q, ; CHECK-NEXT: store [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_urem( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load , ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load , ptr %q %idx.clamped = urem i32 %idx, 17 @@ -896,14 +615,6 @@ define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem(p ; CHECK-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]] -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %idx.clamped = urem i32 %idx, 17 @@ -919,13 +630,6 @@ define void @insert_store_ptr_strip(ptr %q, i8 zeroext %s) { ; CHECK-NEXT: store i8 [[S:%.*]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_ptr_strip( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 3 -; SPIRV-NEXT: store <16 x i8> [[VECINS]], ptr [[Q]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %vecins = insertelement <16 x i8> %0, i8 %s, i32 3 @@ -944,16 +648,6 @@ define void @volatile_update(ptr %q, ptr %p, i8 zeroext %s) { ; CHECK-NEXT: store <16 x i8> [[VECINS1]], ptr [[P]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @volatile_update( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[VECINS0:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 3 -; SPIRV-NEXT: store volatile <16 x i8> [[VECINS0]], ptr [[Q]], align 16 -; SPIRV-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr [[P:%.*]], align 16 -; SPIRV-NEXT: [[VECINS1:%.*]] = insertelement <16 x i8> [[TMP1]], i8 [[S]], i32 1 -; SPIRV-NEXT: store <16 x i8> [[VECINS1]], ptr [[P]], align 16 -; SPIRV-NEXT: ret void -; entry: %0 = load <16 x i8>, ptr %q %vecins0 = insertelement <16 x i8> %0, i8 %s, i32 3 @@ -973,13 +667,6 @@ define void @insert_store_addr_differ(ptr %p, ptr %q, i8 %s) { ; CHECK-NEXT: store <16 x i8> [[INS]], ptr [[Q:%.*]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_addr_differ( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16 -; SPIRV-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3 -; SPIRV-NEXT: store <16 x i8> [[INS]], ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: ret void -; entry: %ld = load <16 x i8>, ptr %p %ins = insertelement <16 x i8> %ld, i8 %s, i32 3 @@ -1004,22 +691,6 @@ define void @insert_store_mem_modify(ptr %p, ptr %q, ptr noalias %r, i8 %s, i32 ; CHECK-NEXT: store <4 x i32> [[INS3]], ptr [[P]], align 16 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_mem_modify( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16 -; SPIRV-NEXT: store <16 x i8> zeroinitializer, ptr [[Q:%.*]], align 16 -; SPIRV-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3 -; SPIRV-NEXT: store <16 x i8> [[INS]], ptr [[P]], align 16 -; SPIRV-NEXT: [[LD2:%.*]] = load <16 x i8>, ptr [[Q]], align 16 -; SPIRV-NEXT: store <16 x i8> zeroinitializer, ptr [[R:%.*]], align 16 -; SPIRV-NEXT: [[INS2:%.*]] = insertelement <16 x i8> [[LD2]], i8 [[S]], i32 7 -; SPIRV-NEXT: store <16 x i8> [[INS2]], ptr [[Q]], align 16 -; SPIRV-NEXT: [[LD3:%.*]] = load <4 x i32>, ptr [[P]], align 16 -; SPIRV-NEXT: store <16 x i8> zeroinitializer, ptr [[P]], align 16 -; SPIRV-NEXT: [[INS3:%.*]] = insertelement <4 x i32> [[LD3]], i32 [[M:%.*]], i32 0 -; SPIRV-NEXT: store <4 x i32> [[INS3]], ptr [[P]], align 16 -; SPIRV-NEXT: ret void -; entry: ; p may alias q %ld = load <16 x i8>, ptr %p @@ -1056,19 +727,6 @@ define void @insert_store_with_call(ptr %p, ptr %q, i8 %s) { ; CHECK-NEXT: store i8 [[S]], ptr [[TMP0]], align 1 ; CHECK-NEXT: ret void ; -; SPIRV-LABEL: @insert_store_with_call( -; SPIRV-NEXT: entry: -; SPIRV-NEXT: [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16 -; SPIRV-NEXT: call void @maywrite(ptr [[P]]) -; SPIRV-NEXT: [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3 -; SPIRV-NEXT: store <16 x i8> [[INS]], ptr [[P]], align 16 -; SPIRV-NEXT: call void @foo() -; SPIRV-NEXT: [[LD2:%.*]] = load <16 x i8>, ptr [[P]], align 16 -; SPIRV-NEXT: call void @nowrite(ptr [[P]]) -; SPIRV-NEXT: [[INS2:%.*]] = insertelement <16 x i8> [[LD2]], i8 [[S]], i32 7 -; SPIRV-NEXT: store <16 x i8> [[INS2]], ptr [[P]], align 16 -; SPIRV-NEXT: ret void -; entry: %ld = load <16 x i8>, ptr %p call void @maywrite(ptr %p) @@ -1128,45 +786,6 @@ define i32 @insert_store_maximum_scan_instrs(i32 %arg, ptr %arg1, ptr %arg2, i8 ; CHECK-NEXT: store <16 x i8> [[I36]], ptr [[ARG2]], align 16 ; CHECK-NEXT: ret i32 [[I35]] ; -; SPIRV-LABEL: @insert_store_maximum_scan_instrs( -; SPIRV-NEXT: bb: -; SPIRV-NEXT: [[I:%.*]] = or i32 [[ARG:%.*]], 1 -; SPIRV-NEXT: [[I4:%.*]] = load <16 x i8>, ptr [[ARG2:%.*]], align 16 -; SPIRV-NEXT: [[I5:%.*]] = tail call i32 @bar(i32 [[I]], i1 true) -; SPIRV-NEXT: [[I6:%.*]] = shl i32 [[ARG]], [[I5]] -; SPIRV-NEXT: [[I7:%.*]] = lshr i32 [[I6]], 26 -; SPIRV-NEXT: [[I8:%.*]] = trunc i32 [[I7]] to i8 -; SPIRV-NEXT: [[I9:%.*]] = and i8 [[I8]], 31 -; SPIRV-NEXT: [[I10:%.*]] = lshr i32 [[I6]], 11 -; SPIRV-NEXT: [[I11:%.*]] = and i32 [[I10]], 32767 -; SPIRV-NEXT: [[I12:%.*]] = zext i8 [[I9]] to i64 -; SPIRV-NEXT: [[I13:%.*]] = getelementptr inbounds i16, ptr [[ARG1:%.*]], i64 [[I12]] -; SPIRV-NEXT: [[I14:%.*]] = load i16, ptr [[I13]], align 2 -; SPIRV-NEXT: [[I15:%.*]] = zext i16 [[I14]] to i32 -; SPIRV-NEXT: [[I16:%.*]] = add nuw nsw i8 [[I9]], 1 -; SPIRV-NEXT: [[I17:%.*]] = zext i8 [[I16]] to i64 -; SPIRV-NEXT: [[I18:%.*]] = getelementptr inbounds i16, ptr [[ARG1]], i64 [[I17]] -; SPIRV-NEXT: [[I19:%.*]] = load i16, ptr [[I18]], align 2 -; SPIRV-NEXT: [[I20:%.*]] = zext i16 [[I19]] to i32 -; SPIRV-NEXT: [[I21:%.*]] = sub nsw i32 [[I20]], [[I15]] -; SPIRV-NEXT: [[I22:%.*]] = mul nsw i32 [[I11]], [[I21]] -; SPIRV-NEXT: [[I23:%.*]] = ashr i32 [[I22]], 15 -; SPIRV-NEXT: [[I24:%.*]] = shl nuw nsw i32 [[I5]], 15 -; SPIRV-NEXT: [[I25:%.*]] = xor i32 [[I24]], 1015808 -; SPIRV-NEXT: [[I26:%.*]] = add nuw nsw i32 [[I25]], [[I15]] -; SPIRV-NEXT: [[I27:%.*]] = add nsw i32 [[I26]], [[I23]] -; SPIRV-NEXT: [[I28:%.*]] = sitofp i32 [[ARG]] to double -; SPIRV-NEXT: [[I29:%.*]] = tail call double @llvm.log2.f64(double [[I28]]) -; SPIRV-NEXT: [[I30:%.*]] = fptosi double [[I29]] to i32 -; SPIRV-NEXT: [[I31:%.*]] = shl nsw i32 [[I30]], 15 -; SPIRV-NEXT: [[I32:%.*]] = or i32 [[I31]], 4 -; SPIRV-NEXT: [[I33:%.*]] = icmp eq i32 [[I27]], [[I32]] -; SPIRV-NEXT: [[I34:%.*]] = select i1 [[I33]], i32 [[ARG]], i32 [[I31]] -; SPIRV-NEXT: [[I35:%.*]] = lshr i32 [[I34]], 1 -; SPIRV-NEXT: [[I36:%.*]] = insertelement <16 x i8> [[I4]], i8 [[ARG3:%.*]], i32 3 -; SPIRV-NEXT: store <16 x i8> [[I36]], ptr [[ARG2]], align 16 -; SPIRV-NEXT: ret i32 [[I35]] -; bb: %i = or i32 %arg, 1 %i4 = load <16 x i8>, ptr %arg2, align 16