@@ -568,23 +568,47 @@ class OpLowerer {
568568 return make_error<StringError>(
569569 " typedBufferStore data must be a vector of 4 elements" ,
570570 inconvertibleErrorCode ());
571- Value *Data0 =
572- IRB.CreateExtractElement (Data, ConstantInt::get (Int32Ty, 0 ));
573- Value *Data1 =
574- IRB.CreateExtractElement (Data, ConstantInt::get (Int32Ty, 1 ));
575- Value *Data2 =
576- IRB.CreateExtractElement (Data, ConstantInt::get (Int32Ty, 2 ));
577- Value *Data3 =
578- IRB.CreateExtractElement (Data, ConstantInt::get (Int32Ty, 3 ));
579-
580- std::array<Value *, 8 > Args{Handle, Index0, Index1, Data0,
581- Data1, Data2, Data3, Mask};
571+
572+ // Since we're post-scalarizer, we likely have a vector that's constructed
573+ // solely for the argument of the store. If so, just use the scalar values
574+ // from before they're inserted into the temporary.
575+ std::array<Value *, 4 > DataElements{nullptr , nullptr , nullptr , nullptr };
576+ auto *IEI = dyn_cast<InsertElementInst>(Data);
577+ while (IEI) {
578+ auto *IndexOp = dyn_cast<ConstantInt>(IEI->getOperand (2 ));
579+ if (!IndexOp)
580+ break ;
581+ size_t IndexVal = IndexOp->getZExtValue ();
582+ assert (IndexVal < 4 && " Too many elements for buffer store" );
583+ DataElements[IndexVal] = IEI->getOperand (1 );
584+ IEI = dyn_cast<InsertElementInst>(IEI->getOperand (0 ));
585+ }
586+
587+ // If for some reason we weren't able to forward the arguments from the
588+ // scalarizer artifact, then we need to actually extract elements from the
589+ // vector.
590+ for (int I = 0 , E = 4 ; I != E; ++I)
591+ if (DataElements[I] == nullptr )
592+ DataElements[I] =
593+ IRB.CreateExtractElement (Data, ConstantInt::get (Int32Ty, I));
594+
595+ std::array<Value *, 8 > Args{
596+ Handle, Index0, Index1, DataElements[0 ],
597+ DataElements[1 ], DataElements[2 ], DataElements[3 ], Mask};
582598 Expected<CallInst *> OpCall =
583599 OpBuilder.tryCreateOp (OpCode::BufferStore, Args, CI->getName ());
584600 if (Error E = OpCall.takeError ())
585601 return E;
586602
587603 CI->eraseFromParent ();
604+ // Clean up any leftover `insertelement`s
605+ IEI = dyn_cast<InsertElementInst>(Data);
606+ while (IEI && IEI->use_empty ()) {
607+ InsertElementInst *Tmp = IEI;
608+ IEI = dyn_cast<InsertElementInst>(IEI->getOperand (0 ));
609+ Tmp->eraseFromParent ();
610+ }
611+
588612 return Error::success ();
589613 });
590614 }
0 commit comments