@@ -4078,73 +4078,121 @@ Constant *OpenMPIRBuilder::registerTargetRegionFunction(
4078
4078
}
4079
4079
4080
4080
OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createTargetData (
4081
- const LocationDescription &Loc, OpenMPIRBuilder::InsertPointTy CodeGenIP,
4082
- SmallVectorImpl<uint64_t > &MapTypeFlags,
4083
- SmallVectorImpl<Constant *> &MapNames, struct MapperAllocas &MapperAllocas,
4084
- bool IsBegin, int64_t DeviceID, Value *IfCond,
4085
- BodyGenCallbackTy ProcessMapOpCB, BodyGenCallbackTy BodyGenCB) {
4081
+ const LocationDescription &Loc, InsertPointTy AllocaIP,
4082
+ InsertPointTy CodeGenIP, Value *DeviceID, Value *IfCond,
4083
+ TargetDataInfo &Info,
4084
+ function_ref<MapInfosTy &(InsertPointTy CodeGenIP)> GenMapInfoCB,
4085
+ omp::RuntimeFunction *MapperFunc,
4086
+ function_ref<InsertPointTy(InsertPointTy CodeGenIP, BodyGenTy BodyGenType)>
4087
+ BodyGenCB) {
4086
4088
if (!updateToLocation (Loc))
4087
4089
return InsertPointTy ();
4088
4090
4089
4091
Builder.restoreIP (CodeGenIP);
4092
+ bool IsStandAlone = !BodyGenCB;
4090
4093
4091
- // LLVM utilities like blocks with terminators.
4092
- // The UI acts as a resume point for code insertion after the BodyGen
4093
- auto *UI = Builder.CreateUnreachable ();
4094
- if (IfCond) {
4095
- auto *ThenTI =
4096
- SplitBlockAndInsertIfThen (IfCond, UI, /* Unreachable */ false );
4097
- ThenTI->getParent ()->setName (" omp_if.then" );
4098
- Builder.SetInsertPoint (ThenTI);
4099
- } else {
4100
- Builder.SetInsertPoint (UI);
4101
- }
4094
+ // Generate the code for the opening of the data environment. Capture all the
4095
+ // arguments of the runtime call by reference because they are used in the
4096
+ // closing of the region.
4097
+ auto BeginThenGen = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) {
4098
+ emitOffloadingArrays (AllocaIP, Builder.saveIP (),
4099
+ GenMapInfoCB (Builder.saveIP ()), Info,
4100
+ /* IsNonContiguous=*/ true );
4102
4101
4103
- ProcessMapOpCB (Builder.saveIP (), Builder.saveIP ());
4102
+ TargetDataRTArgs RTArgs;
4103
+ emitOffloadingArraysArgument (Builder, RTArgs, Info);
4104
4104
4105
- uint32_t SrcLocStrSize;
4106
- Constant *SrcLocStr = getOrCreateSrcLocStr (Loc, SrcLocStrSize);
4107
- Value *srcLocInfo = getOrCreateIdent (SrcLocStr, SrcLocStrSize);
4105
+ // Emit the number of elements in the offloading arrays.
4106
+ Value *PointerNum = Builder.getInt32 (Info.NumberOfPtrs );
4108
4107
4109
- GlobalVariable *MapTypesGV =
4110
- createOffloadMaptypes (MapTypeFlags, " .offload_maptypes" );
4111
- Value *MapTypesArg = Builder.CreateConstInBoundsGEP2_32 (
4112
- ArrayType::get (Builder.getInt64Ty (), MapTypeFlags.size ()), MapTypesGV,
4113
- /* Idx0=*/ 0 , /* Idx1=*/ 0 );
4108
+ // Source location for the ident struct
4109
+ uint32_t SrcLocStrSize;
4110
+ Constant *SrcLocStr = getOrCreateSrcLocStr (Loc, SrcLocStrSize);
4111
+ Value *SrcLocInfo = getOrCreateIdent (SrcLocStr, SrcLocStrSize);
4112
+
4113
+ Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
4114
+ PointerNum, RTArgs.BasePointersArray ,
4115
+ RTArgs.PointersArray , RTArgs.SizesArray ,
4116
+ RTArgs.MapTypesArray , RTArgs.MapNamesArray ,
4117
+ RTArgs.MappersArray };
4118
+
4119
+ if (IsStandAlone) {
4120
+ assert (MapperFunc && " MapperFunc missing for standalone target data" );
4121
+ Builder.CreateCall (getOrCreateRuntimeFunctionPtr (*MapperFunc),
4122
+ OffloadingArgs);
4123
+ } else {
4124
+ Function *BeginMapperFunc = getOrCreateRuntimeFunctionPtr (
4125
+ omp::OMPRTL___tgt_target_data_begin_mapper);
4114
4126
4115
- GlobalVariable *MapNamesGV =
4116
- createOffloadMapnames (MapNames, " .offload_mapnames" );
4117
- Value *MapNamesArg = Builder.CreateConstInBoundsGEP2_32 (
4118
- ArrayType::get (Builder.getInt8PtrTy (), MapNames.size ()), MapNamesGV,
4119
- /* Idx0=*/ 0 , /* Idx1=*/ 0 );
4127
+ Builder.CreateCall (BeginMapperFunc, OffloadingArgs);
4128
+
4129
+ // If device pointer privatization is required, emit the body of the
4130
+ // region here. It will have to be duplicated: with and without
4131
+ // privatization.
4132
+ Builder.restoreIP (BodyGenCB (Builder.saveIP (), BodyGenTy::Priv));
4133
+ }
4134
+ };
4135
+
4136
+ // If we need device pointer privatization, we need to emit the body of the
4137
+ // region with no privatization in the 'else' branch of the conditional.
4138
+ // Otherwise, we don't have to do anything.
4139
+ auto BeginElseGen = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) {
4140
+ Builder.restoreIP (BodyGenCB (Builder.saveIP (), BodyGenTy::DupNoPriv));
4141
+ };
4142
+
4143
+ // Generate code for the closing of the data region.
4144
+ auto EndThenGen = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) {
4145
+ TargetDataRTArgs RTArgs;
4146
+ emitOffloadingArraysArgument (Builder, RTArgs, Info, /* EmitDebug=*/ false ,
4147
+ /* ForEndCall=*/ true );
4148
+
4149
+ // Emit the number of elements in the offloading arrays.
4150
+ Value *PointerNum = Builder.getInt32 (Info.NumberOfPtrs );
4151
+
4152
+ // Source location for the ident struct
4153
+ uint32_t SrcLocStrSize;
4154
+ Constant *SrcLocStr = getOrCreateSrcLocStr (Loc, SrcLocStrSize);
4155
+ Value *SrcLocInfo = getOrCreateIdent (SrcLocStr, SrcLocStrSize);
4156
+
4157
+ Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
4158
+ PointerNum, RTArgs.BasePointersArray ,
4159
+ RTArgs.PointersArray , RTArgs.SizesArray ,
4160
+ RTArgs.MapTypesArray , RTArgs.MapNamesArray ,
4161
+ RTArgs.MappersArray };
4162
+ Function *EndMapperFunc =
4163
+ getOrCreateRuntimeFunctionPtr (omp::OMPRTL___tgt_target_data_end_mapper);
4164
+
4165
+ Builder.CreateCall (EndMapperFunc, OffloadingArgs);
4166
+ };
4120
4167
4121
- Function *beginMapperFunc =
4122
- getOrCreateRuntimeFunctionPtr (omp::OMPRTL___tgt_target_data_begin_mapper);
4123
- Function *endMapperFunc =
4124
- getOrCreateRuntimeFunctionPtr (omp::OMPRTL___tgt_target_data_end_mapper);
4168
+ // We don't have to do anything to close the region if the if clause evaluates
4169
+ // to false.
4170
+ auto EndElseGen = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) {};
4125
4171
4126
4172
if (BodyGenCB) {
4127
- // Create call to start the data region.
4128
- emitMapperCall (Builder.saveIP (), beginMapperFunc, srcLocInfo, MapTypesArg,
4129
- MapNamesArg, MapperAllocas, DeviceID, MapTypeFlags.size ());
4173
+ if (IfCond) {
4174
+ emitIfClause (IfCond, BeginThenGen, BeginElseGen, AllocaIP);
4175
+ } else {
4176
+ BeginThenGen (AllocaIP, Builder.saveIP ());
4177
+ }
4130
4178
4131
- BodyGenCB (Builder.saveIP (), Builder.saveIP ());
4179
+ // If we don't require privatization of device pointers, we emit the body in
4180
+ // between the runtime calls. This avoids duplicating the body code.
4181
+ Builder.restoreIP (BodyGenCB (Builder.saveIP (), BodyGenTy::NoPriv));
4132
4182
4133
- Builder.SetInsertPoint (UI->getParent ());
4134
- // Create call to end the data region.
4135
- emitMapperCall (Builder.saveIP (), endMapperFunc, srcLocInfo, MapTypesArg,
4136
- MapNamesArg, MapperAllocas, DeviceID, MapTypeFlags.size ());
4183
+ if (IfCond) {
4184
+ emitIfClause (IfCond, EndThenGen, EndElseGen, AllocaIP);
4185
+ } else {
4186
+ EndThenGen (AllocaIP, Builder.saveIP ());
4187
+ }
4137
4188
} else {
4138
- emitMapperCall (Builder.saveIP (), IsBegin ? beginMapperFunc : endMapperFunc,
4139
- srcLocInfo, MapTypesArg, MapNamesArg, MapperAllocas,
4140
- DeviceID, MapTypeFlags.size ());
4189
+ if (IfCond) {
4190
+ emitIfClause (IfCond, BeginThenGen, EndElseGen, AllocaIP);
4191
+ } else {
4192
+ BeginThenGen (AllocaIP, Builder.saveIP ());
4193
+ }
4141
4194
}
4142
4195
4143
- // Update the insertion point and remove the terminator we introduced.
4144
- Builder.SetInsertPoint (UI->getParent ());
4145
- if (IfCond)
4146
- UI->getParent ()->setName (" omp_if.end" );
4147
- UI->eraseFromParent ();
4148
4196
return Builder.saveIP ();
4149
4197
}
4150
4198
@@ -4668,6 +4716,77 @@ void OpenMPIRBuilder::emitOffloadingArrays(
4668
4716
emitNonContiguousDescriptor (AllocaIP, CodeGenIP, CombinedInfo, Info);
4669
4717
}
4670
4718
4719
+ void OpenMPIRBuilder::emitBranch (BasicBlock *Target) {
4720
+ BasicBlock *CurBB = Builder.GetInsertBlock ();
4721
+
4722
+ if (!CurBB || CurBB->getTerminator ()) {
4723
+ // If there is no insert point or the previous block is already
4724
+ // terminated, don't touch it.
4725
+ } else {
4726
+ // Otherwise, create a fall-through branch.
4727
+ Builder.CreateBr (Target);
4728
+ }
4729
+
4730
+ Builder.ClearInsertionPoint ();
4731
+ }
4732
+
4733
+ void OpenMPIRBuilder::emitBlock (BasicBlock *BB, Function *CurFn,
4734
+ bool IsFinished) {
4735
+ BasicBlock *CurBB = Builder.GetInsertBlock ();
4736
+
4737
+ // Fall out of the current block (if necessary).
4738
+ emitBranch (BB);
4739
+
4740
+ if (IsFinished && BB->use_empty ()) {
4741
+ BB->eraseFromParent ();
4742
+ return ;
4743
+ }
4744
+
4745
+ // Place the block after the current block, if possible, or else at
4746
+ // the end of the function.
4747
+ if (CurBB && CurBB->getParent ())
4748
+ CurFn->insert (std::next (CurBB->getIterator ()), BB);
4749
+ else
4750
+ CurFn->insert (CurFn->end (), BB);
4751
+ Builder.SetInsertPoint (BB);
4752
+ }
4753
+
4754
+ void OpenMPIRBuilder::emitIfClause (Value *Cond, BodyGenCallbackTy ThenGen,
4755
+ BodyGenCallbackTy ElseGen,
4756
+ InsertPointTy AllocaIP) {
4757
+ // If the condition constant folds and can be elided, try to avoid emitting
4758
+ // the condition and the dead arm of the if/else.
4759
+ if (auto *CI = dyn_cast<ConstantInt>(Cond)) {
4760
+ auto CondConstant = CI->getSExtValue ();
4761
+ if (CondConstant)
4762
+ ThenGen (AllocaIP, Builder.saveIP ());
4763
+ else
4764
+ ElseGen (AllocaIP, Builder.saveIP ());
4765
+ return ;
4766
+ }
4767
+
4768
+ Function *CurFn = Builder.GetInsertBlock ()->getParent ();
4769
+
4770
+ // Otherwise, the condition did not fold, or we couldn't elide it. Just
4771
+ // emit the conditional branch.
4772
+ BasicBlock *ThenBlock = BasicBlock::Create (M.getContext (), " omp_if.then" );
4773
+ BasicBlock *ElseBlock = BasicBlock::Create (M.getContext (), " omp_if.else" );
4774
+ BasicBlock *ContBlock = BasicBlock::Create (M.getContext (), " omp_if.end" );
4775
+ Builder.CreateCondBr (Cond, ThenBlock, ElseBlock);
4776
+ // Emit the 'then' code.
4777
+ emitBlock (ThenBlock, CurFn);
4778
+ ThenGen (AllocaIP, Builder.saveIP ());
4779
+ emitBranch (ContBlock);
4780
+ // Emit the 'else' code if present.
4781
+ // There is no need to emit line number for unconditional branch.
4782
+ emitBlock (ElseBlock, CurFn);
4783
+ ElseGen (AllocaIP, Builder.saveIP ());
4784
+ // There is no need to emit line number for unconditional branch.
4785
+ emitBranch (ContBlock);
4786
+ // Emit the continuation block for code after the if.
4787
+ emitBlock (ContBlock, CurFn, /* IsFinished=*/ true );
4788
+ }
4789
+
4671
4790
bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic (
4672
4791
const LocationDescription &Loc, llvm::AtomicOrdering AO, AtomicKind AK) {
4673
4792
assert (!(AO == AtomicOrdering::NotAtomic ||
0 commit comments