@@ -81,6 +81,9 @@ namespace {
81
81
void convertLoadToGlobal (LoadInst* LI) const ;
82
82
bool isLoadGlobalCandidate (LoadInst* LI) const ;
83
83
84
+ SmallVector<llvm::Instruction*, 8 > branchInstInModule;
85
+ bool resolveAtomicBranches (Function*) const ;
86
+
84
87
bool canonicalizeAddrSpaceCasts (Function& F) const ;
85
88
};
86
89
@@ -211,6 +214,9 @@ bool GASResolving::runOnFunction(Function& F) {
211
214
LocalChanged = resolveOnFunction (&F);
212
215
Changed |= LocalChanged;
213
216
} while (LocalChanged);
217
+
218
+ Changed |= resolveAtomicBranches (&F);
219
+
214
220
return Changed;
215
221
}
216
222
@@ -324,6 +330,137 @@ void GASPropagator::populateResolvableLoopPHIs() {
324
330
}
325
331
}
326
332
333
+ // Before -
334
+ // %tobool = icmp eq i8 addrspace(3) * %3, null
335
+ // br i1 % tobool, label% if.else, label% if.then
336
+ //
337
+ // if.then:; preds = % for.body20
338
+ // %PtrDstToInt = ptrtoint i32 addrspace(3) * %arrayidx26 to i32,
339
+ // %call3 = call i32 @llvm.genx.GenISA.intatomicraw.i32.p3i32.i32(i32 addrspace(3) * %arrayidx26, i32 %PtrDstToInt, i32 1, i32 0),
340
+ // br label % _Z16atomic_inc_localPU3AS3j.exit,
341
+ //
342
+ // if.else:; preds = % for.body20
343
+ // %4 = addrspacecast i32 addrspace(4) * %2 to i32 addrspace(1)*,
344
+ // %call19 = call i32 @llvm.genx.GenISA.intatomicrawA64.i32.p1i32.p1i32(i32 addrspace(1) * %4, i32 addrspace(1) * %4, i32 1, i32 0),
345
+ // br label % _Z16atomic_inc_localPU3AS3j.exit,
346
+ //
347
+ // _Z16atomic_inc_localPU3AS3j.exit:; preds = %if.then, %if.else
348
+ // br label %for.inc28,
349
+ //
350
+ //
351
+ // After resolving generic addressspace statically.
352
+ //
353
+ // In case of local addresssspace//
354
+ //
355
+ // %PtrDstToInt = ptrtoint i32 addrspace(3) * %arrayidx26 to i32,
356
+ // %call3 = call i32 @llvm.genx.GenISA.intatomicraw.i32.p3i32.i32(i32 addrspace(3) * %arrayidx26, i32 %PtrDstToInt, i32 1, i32 0),
357
+ //
358
+ // In case of global addresssspace//
359
+ //
360
+ // %4 = addrspacecast i32 addrspace(4) * %2 to i32 addrspace(1)*,
361
+ // %call19 = call i32 @llvm.genx.GenISA.intatomicrawA64.i32.p1i32.p1i32(i32 addrspace(1) * %4, i32 addrspace(1) * %4, i32 1, i32 0),
362
+
363
+ bool GASResolving::resolveAtomicBranches (Function* F) const {
364
+ bool changed = false ;
365
+ for (auto FB = F->begin (), FE = F->end (); FB != FE; ++FB)
366
+ {
367
+ for (auto BI = FB->begin (), BE = FB->end (); BI != BE;)
368
+ {
369
+ Instruction* I = &(*BI++);
370
+ BranchInst* BrI = dyn_cast<BranchInst>(I);
371
+ bool isAtomicBrInstr = false ;
372
+ bool localAtomicCallInstFound = false ;
373
+ bool globalAtomicCallInstFound = false ;
374
+ // uint32_t numSuccessers = I.getNumSuccessors();
375
+ BasicBlock* toBeDeleted = nullptr ;
376
+ BasicBlock* toBeKept = nullptr ;
377
+
378
+ // check if the branch instruction is related to atomic op
379
+ if (BrI && BrI->isConditional ()) {
380
+ BasicBlock* trueDestBB = I->getSuccessor (0 );
381
+ BasicBlock* falseDestBB = I->getSuccessor (1 );
382
+
383
+ for (auto BTI = trueDestBB->begin (), BTE = trueDestBB->end (); BTI != BTE;) {
384
+ Instruction* I = &(*BTI++);
385
+ CallInst* CI = dyn_cast<CallInst>(I);
386
+ if (CI) {
387
+ Function* Callee = CI->getCalledFunction ();
388
+ // not quite right?
389
+ if (Callee->getName ().contains (" __builtin_IB_atomic" ))
390
+ globalAtomicCallInstFound = true ;
391
+ }
392
+ }
393
+ for (auto BFI = falseDestBB->begin (), BFE = falseDestBB->end (); BFI != BFE;) {
394
+ Instruction* I = &(*BFI++);
395
+ CallInst* CI = dyn_cast<CallInst>(I);
396
+ if (CI) {
397
+ Function* Callee = CI->getCalledFunction ();
398
+ // not quite right?
399
+ if (Callee->getName ().contains (" __builtin_IB_atomic" ))
400
+ localAtomicCallInstFound = true ;
401
+ }
402
+ }
403
+ isAtomicBrInstr = globalAtomicCallInstFound & localAtomicCallInstFound;
404
+
405
+ if (isAtomicBrInstr) {
406
+ Instruction* conditionInstruction = cast<Instruction>(BrI->getCondition ());
407
+
408
+ // get pointer in question
409
+ Value* ptr = conditionInstruction->getOperand (0 );
410
+
411
+ // check if pointer address space is local/global
412
+ // initial assumtion - local
413
+ bool isGlobalAtomic = false ;
414
+ toBeDeleted = BrI->getSuccessor (0 );
415
+ toBeKept = BrI->getSuccessor (1 );
416
+
417
+ // check statically if the address space is global/ local
418
+ if (ptr->getType ()->getPointerAddressSpace () == ADDRESS_SPACE_GLOBAL) {
419
+ isGlobalAtomic = true ;
420
+ toBeDeleted = BrI->getSuccessor (1 );
421
+ toBeKept = BrI->getSuccessor (0 );
422
+ }
423
+
424
+ // update phi node
425
+ // find uses of deleted branch
426
+ PHINode* PN;
427
+ BasicBlock* phiNodeBlock = toBeKept->getUniqueSuccessor ();
428
+ for (auto BUI = phiNodeBlock->begin (), BUE = phiNodeBlock->end (); BUI != BUE;) {
429
+ Instruction* I = &(*BUI++);
430
+ PN = dyn_cast<PHINode>(I);
431
+ if (PN) {
432
+ PN->removeIncomingValue (toBeDeleted, false );
433
+ }
434
+ }
435
+
436
+ // create new branch instruction
437
+ BranchInst* newBranchInst = BranchInst::Create (toBeKept);
438
+ newBranchInst->insertAfter (I);
439
+
440
+ // erase old branch instruction & unneccessary BB (could be either local or global)
441
+ BrI->eraseFromParent ();
442
+ toBeDeleted->eraseFromParent ();
443
+
444
+ // get successor BB
445
+ BasicBlock* CommonSuccessor = toBeKept->getUniqueSuccessor ();
446
+ if (CommonSuccessor != nullptr ){
447
+ // merge basic blocks
448
+ bool merged = MergeBlockIntoPredecessor (CommonSuccessor);
449
+ assert (merged);
450
+ merged = MergeBlockIntoPredecessor (toBeKept);
451
+ assert (merged);
452
+
453
+ // remove the condition instruction
454
+ conditionInstruction->eraseFromParent ();
455
+ changed = true ;
456
+ }
457
+ }
458
+ }
459
+ }
460
+ }
461
+ return changed;
462
+ }
463
+
327
464
void GASPropagator::populateResolvableLoopPHIsForLoop (const Loop* L) {
328
465
BasicBlock* H = L->getHeader ();
329
466
0 commit comments