Skip to content

Commit 108b0ce

Browse files
committed
IR Builder Changes to Support Scan Operation
1 parent a557550 commit 108b0ce

File tree

3 files changed

+623
-5
lines changed

3 files changed

+623
-5
lines changed

llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h

+135-4
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,31 @@ class OpenMPIRBuilder {
503503
return allocaInst;
504504
}
505505
};
506+
507+
struct ScanInformation {
508+
public:
509+
/// Dominates the body of the loop before scan directive
510+
llvm::BasicBlock *OMPBeforeScanBlock = nullptr;
511+
/// Dominates the body of the loop before scan directive
512+
llvm::BasicBlock *OMPAfterScanBlock = nullptr;
513+
/// Controls the flow to before or after scan blocks
514+
llvm::BasicBlock *OMPScanDispatch = nullptr;
515+
/// Exit block of loop body
516+
llvm::BasicBlock *OMPScanLoopExit = nullptr;
517+
/// Block before loop body where scan initializations are done
518+
llvm::BasicBlock *OMPScanInit = nullptr;
519+
/// Block after loop body where scan finalizations are done
520+
llvm::BasicBlock *OMPScanFinish = nullptr;
521+
/// If true, it indicates Input phase is lowered; else it indicates
522+
/// ScanPhase is lowered
523+
bool OMPFirstScanLoop = false;
524+
// Maps the private reduction variable to the pointer of the temporary
525+
// buffer
526+
llvm::SmallDenseMap<llvm::Value *, llvm::Value *> ScanBuffPtrs;
527+
llvm::Value *IV;
528+
llvm::Value *Span;
529+
} ScanInfo;
530+
506531
/// Initialize the internal state, this will put structures types and
507532
/// potentially other helpers into the underlying module. Must be called
508533
/// before any other method and only once! This internal state includes types
@@ -729,6 +754,35 @@ class OpenMPIRBuilder {
729754
LoopBodyGenCallbackTy BodyGenCB, Value *TripCount,
730755
const Twine &Name = "loop");
731756

757+
/// Generator for the control flow structure of an OpenMP canonical loops if
758+
/// the parent directive has an `inscan` modifier specified.
759+
/// If the `inscan` modifier is specified, the region of the parent is
760+
/// expected to have a `scan` directive. Based on the clauses in
761+
/// scan directive, the body of the loop is split into two loops: Input loop
762+
/// and Scan Loop. Input loop contains the code generated for input phase of
763+
/// scan and Scan loop contains the code generated for scan phase of scan.
764+
///
765+
/// \param Loc The insert and source location description.
766+
/// \param BodyGenCB Callback that will generate the loop body code.
767+
/// \param Start Value of the loop counter for the first iterations.
768+
/// \param Stop Loop counter values past this will stop the loop.
769+
/// \param Step Loop counter increment after each iteration; negative
770+
/// means counting down.
771+
/// \param IsSigned Whether Start, Stop and Step are signed integers.
772+
/// \param InclusiveStop Whether \p Stop itself is a valid value for the loop
773+
/// counter.
774+
/// \param ComputeIP Insertion point for instructions computing the trip
775+
/// count. Can be used to ensure the trip count is available
776+
/// at the outermost loop of a loop nest. If not set,
777+
/// defaults to the preheader of the generated loop.
778+
/// \param Name Base name used to derive BB and instruction names.
779+
///
780+
/// \returns A vector containing Loop Info of Input Loop and Scan Loop.
781+
Expected<SmallVector<llvm::CanonicalLoopInfo *>> createCanonicalScanLoops(
782+
const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB,
783+
Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop,
784+
InsertPointTy ComputeIP, const Twine &Name);
785+
732786
/// Calculate the trip count of a canonical loop.
733787
///
734788
/// This allows specifying user-defined loop counter values using increment,
@@ -798,13 +852,16 @@ class OpenMPIRBuilder {
798852
/// at the outermost loop of a loop nest. If not set,
799853
/// defaults to the preheader of the generated loop.
800854
/// \param Name Base name used to derive BB and instruction names.
855+
/// \param InScan Whether loop has a scan reduction specified.
801856
///
802857
/// \returns An object representing the created control flow structure which
803858
/// can be used for loop-associated directives.
804-
Expected<CanonicalLoopInfo *> createCanonicalLoop(
805-
const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB,
806-
Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop,
807-
InsertPointTy ComputeIP = {}, const Twine &Name = "loop");
859+
Expected<CanonicalLoopInfo *>
860+
createCanonicalLoop(const LocationDescription &Loc,
861+
LoopBodyGenCallbackTy BodyGenCB, Value *Start,
862+
Value *Stop, Value *Step, bool IsSigned,
863+
bool InclusiveStop, InsertPointTy ComputeIP = {},
864+
const Twine &Name = "loop", bool InScan = false);
808865

809866
/// Collapse a loop nest into a single loop.
810867
///
@@ -1532,6 +1589,45 @@ class OpenMPIRBuilder {
15321589
ArrayRef<OpenMPIRBuilder::ReductionInfo> ReductionInfos,
15331590
Function *ReduceFn, AttributeList FuncAttrs);
15341591

1592+
/// Creates the runtime call specified
1593+
/// \param Callee Function Declaration Value
1594+
/// \param Args Arguments passed to the call
1595+
/// \param Name Optional param to specify the name of the call Instruction.
1596+
///
1597+
/// \return The Runtime call instruction created.
1598+
llvm::CallInst *emitNoUnwindRuntimeCall(llvm::FunctionCallee Callee,
1599+
ArrayRef<llvm::Value *> Args,
1600+
const llvm::Twine &Name);
1601+
1602+
/// Helper function for CreateCanonicalScanLoops to create InputLoop
1603+
/// in the firstGen and Scan Loop in the SecondGen
1604+
/// \param InputLoopGen Callback for generating the loop for input phase
1605+
/// \param ScanLoopGen Callback for generating the loop for scan phase
1606+
///
1607+
/// \return error if any produced, else return success.
1608+
Error emitScanBasedDirectiveIR(
1609+
llvm::function_ref<Error()> InputLoopGen,
1610+
llvm::function_ref<Error(LocationDescription Loc)> ScanLoopGen);
1611+
1612+
/// Creates the basic blocks required for scan reduction.
1613+
void createScanBBs();
1614+
1615+
/// Dynamically allocates the buffer needed for scan reduction.
1616+
/// \param AllocaIP The IP where possibly-shared pointer of buffer needs to be
1617+
/// declared. \param ScanVars Scan Variables.
1618+
///
1619+
/// \return error if any produced, else return success.
1620+
Error emitScanBasedDirectiveDeclsIR(InsertPointTy AllocaIP,
1621+
ArrayRef<llvm::Value *> ScanVars,
1622+
ArrayRef<llvm::Type *> ScanVarsType);
1623+
1624+
/// Copies the result back to the reduction variable.
1625+
/// \param ReductionInfos Array type containing the ReductionOps.
1626+
///
1627+
/// \return error if any produced, else return success.
1628+
Error emitScanBasedDirectiveFinalsIR(
1629+
SmallVector<llvm::OpenMPIRBuilder::ReductionInfo> ReductionInfos);
1630+
15351631
/// This function emits a helper that gathers Reduce lists from the first
15361632
/// lane of every active warp to lanes in the first warp.
15371633
///
@@ -2607,6 +2703,41 @@ class OpenMPIRBuilder {
26072703
BodyGenCallbackTy BodyGenCB,
26082704
FinalizeCallbackTy FiniCB, Value *Filter);
26092705

2706+
/// This function performs the scan reduction of the values updated in
2707+
/// the input phase. The reduction logic needs to be emitted between input
2708+
/// and scan loop returned by `CreateCanonicalScanLoops`. The following
2709+
/// is the code that is generated, `buffer` and `span` are expected to be
2710+
/// populated before executing the generated code.
2711+
///
2712+
/// for (int k = 0; k != ceil(log2(span)); ++k) {
2713+
/// i=pow(2,k)
2714+
/// for (size cnt = last_iter; cnt >= i; --cnt)
2715+
/// buffer[cnt] op= buffer[cnt-i];
2716+
/// }
2717+
/// \param Loc The insert and source location description.
2718+
/// \param ReductionInfos Array type containing the ReductionOps.
2719+
///
2720+
/// \returns The insertion position *after* the masked.
2721+
InsertPointOrErrorTy emitScanReduction(
2722+
const LocationDescription &Loc,
2723+
SmallVector<llvm::OpenMPIRBuilder::ReductionInfo> ReductionInfos);
2724+
2725+
/// This directive split and directs the control flow to input phase
2726+
/// blocks or scan phase blocks based on 1. whether input loop or scan loop
2727+
/// is executed, 2. whether exclusive or inclusive scan is used.
2728+
///
2729+
/// \param Loc The insert and source location description.
2730+
/// \param AllocaIP The IP where the temporary buffer for scan reduction
2731+
// needs to be allocated.
2732+
/// \param ScanVars Scan Variables.
2733+
/// \param IsInclusive Whether it is an inclusive or exclusive scan.
2734+
///
2735+
/// \returns The insertion position *after* the scan.
2736+
InsertPointOrErrorTy createScan(const LocationDescription &Loc,
2737+
InsertPointTy AllocaIP,
2738+
ArrayRef<llvm::Value *> ScanVars,
2739+
ArrayRef<llvm::Type *> ScanVarsType,
2740+
bool IsInclusive);
26102741
/// Generator for '#omp critical'
26112742
///
26122743
/// \param Loc The insert and source location description.

0 commit comments

Comments
 (0)