Skip to content

Commit

Permalink
[Tapir] Handle structure-return parameters correctly in outlined help…
Browse files Browse the repository at this point in the history
…er functions. This commit addresses issue llvm#38.
  • Loading branch information
neboat authored and tarunprabhu committed Apr 4, 2023
1 parent 665c8f3 commit ada2d0a
Show file tree
Hide file tree
Showing 3 changed files with 1,009 additions and 6 deletions.
30 changes: 28 additions & 2 deletions llvm/lib/Transforms/Tapir/LoopSpawning.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,12 +672,17 @@ void DACLoopSpawning::implementDACIterSpawnOnHelper(
IRBuilder<> Builder(&(RecurDet->front()));
SetVector<Value*> RecurInputs;
Function::arg_iterator AI = Helper->arg_begin();
// Handle an initial sret argument, if necessary. Based on how
// the Helper function is created, any sret parameter will be the
// first parameter.
if (Helper->hasParamAttribute(0, Attribute::StructRet))
RecurInputs.insert(&*AI++);
assert(cast<Argument>(CanonicalIVInput) == &*AI &&
"First argument does not match original input to canonical IV.");
"First non-sret argument does not match original input to canonical IV.");
RecurInputs.insert(CanonicalIVStart);
++AI;
assert(Limit == &*AI &&
"Second argument does not match original input to the loop limit.");
"Second non-sret argument does not match original input to the loop limit.");
RecurInputs.insert(MidIter);
++AI;
for (Function::arg_iterator AE = Helper->arg_end(); AI != AE; ++AI)
Expand Down Expand Up @@ -1103,6 +1108,7 @@ bool DACLoopSpawning::processLoop() {
SetVector<Value *> BodyInputs, BodyOutputs;
ValueToValueMapTy VMap, InputMap;
std::vector<BasicBlock *> LoopBlocks;
Value *SRetInput = nullptr;

// Get the sync region containing this Tapir loop.
const Instruction *InputSyncRegion;
Expand Down Expand Up @@ -1134,6 +1140,23 @@ bool DACLoopSpawning::processLoop() {
findInputsOutputs(Blocks, BodyInputs, BodyOutputs, &HandledExits, DT);
}

// Scan for any sret parameters in BodyInputs and add them first.
if (F->hasStructRetAttr()) {
Function::arg_iterator ArgIter = F->arg_begin();
if (F->hasParamAttribute(0, Attribute::StructRet))
if (BodyInputs.count(&*ArgIter))
SRetInput = &*ArgIter;
if (F->hasParamAttribute(1, Attribute::StructRet)) {
++ArgIter;
if (BodyInputs.count(&*ArgIter))
SRetInput = &*ArgIter;
}
}
if (SRetInput) {
DEBUG(dbgs() << "sret input " << *SRetInput << "\n");
Inputs.insert(SRetInput);
}

// Add argument for start of CanonicalIV.
DEBUG({
Value *CanonicalIVInput =
Expand Down Expand Up @@ -1407,6 +1430,9 @@ bool DACLoopSpawning::processLoop() {
{
// Setup arguments for call.
SmallVector<Value *, 4> TopCallArgs;
// Add sret input, if it exists.
if (SRetInput)
TopCallArgs.push_back(SRetInput);
// Add start iteration 0.
assert(CanonicalSCEV->getStart()->isZero() &&
"Canonical IV does not start at zero.");
Expand Down
28 changes: 24 additions & 4 deletions llvm/lib/Transforms/Tapir/TapirUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,30 @@ Function *llvm::extractDetachBodyToFunction(

// Fix up the inputs.
SetVector<Value *> Inputs;
for (Value *V : BodyInputs) {
if (V == SyncRegion) continue;
if (!Inputs.count(V))
Inputs.insert(V);
{
// Scan for any sret parameters in BodyInputs and add them first.
Value *SRetInput = nullptr;
if (F.hasStructRetAttr()) {
Function::arg_iterator ArgIter = F.arg_begin();
if (F.hasParamAttribute(0, Attribute::StructRet))
if (BodyInputs.count(&*ArgIter))
SRetInput = &*ArgIter;
if (F.hasParamAttribute(1, Attribute::StructRet)) {
++ArgIter;
if (BodyInputs.count(&*ArgIter))
SRetInput = &*ArgIter;
}
}
if (SRetInput) {
DEBUG(dbgs() << "sret input " << *SRetInput << "\n");
Inputs.insert(SRetInput);
}
// Add the remaining inputs.
for (Value *V : BodyInputs) {
if (V == SyncRegion) continue;
if (!Inputs.count(V))
Inputs.insert(V);
}
}

// Clone the detached CFG into a helper function.
Expand Down
Loading

0 comments on commit ada2d0a

Please sign in to comment.