Skip to content

Commit

Permalink
__tapir_frame() builtin
Browse files Browse the repository at this point in the history
  • Loading branch information
VoxSciurorum committed Oct 12, 2023
1 parent 03a724d commit 699892a
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 27 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -1721,6 +1721,8 @@ BUILTIN(__builtin_ms_va_copy, "vc*&c*&", "n")
// Arithmetic Fence: to prevent FP reordering and reassociation optimizations
LANGBUILTIN(__arithmetic_fence, "v.", "tE", ALL_LANGUAGES)

BUILTIN(__tapir_frame, "v*", "n")

// Tapir. Rewriting of reducer references happens during sema
// and needs a builtin to carry the information to codegen.
BUILTIN(__hyper_lookup, "v*vC*z.", "nU")
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5429,6 +5429,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Str.getPointer(), Zeros);
return RValue::get(Ptr);
}
case Builtin::BI__tapir_frame: {
Function *FF = CGM.getIntrinsic(Intrinsic::tapir_frame);
return RValue::get(Builder.CreateCall(FF, {}));
}
case Builtin::BI__hyper_lookup: {
llvm::Value *Size = EmitScalarExpr(E->getArg(1));
Function *F = CGM.getIntrinsic(Intrinsic::hyper_lookup, Size->getType());
Expand Down
29 changes: 29 additions & 0 deletions clang/test/Cilk/tapir-frame.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: %clang_cc1 %s -x c -O1 -fopencilk -mllvm -use-opencilk-runtime-bc=false -mllvm -debug-abi-calls=true -verify -S -emit-llvm -o - | FileCheck %s
// expected-no-diagnostics

// CHECK-LABEL: zero
int zero()
{
return __tapir_frame() != 0;
// CHECK: ret i32 0
}

// CHECK-LABEL: one
int one()
{
extern void f(int);
_Cilk_spawn f(0);
_Cilk_spawn f(1);
// CHECK: ret i32 1
return __tapir_frame() != 0;
}

// CHECK-LABEL: function3
int function3()
{
extern void f(int);
extern int g(void *);
_Cilk_spawn f(0);
// CHECK: call i32 @g(ptr noundef nonnull %__cilkrts_sf)
return g(__tapir_frame());
}
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,10 @@ def int_tapir_loop_grainsize
def int_task_frameaddress
: Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrWillReturn]>;

// Return the stack_frame in an OpenCilk function, otherwise null.
def int_tapir_frame
: Intrinsic<[llvm_ptr_ty], [], [IntrWillReturn,IntrReadMem]>;

// Ideally the types would be [llvm_anyptr_ty], [LLVMMatchType<0>]
// but that does not work, so rely on the front end to insert bitcasts.
def int_hyper_lookup
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/Transforms/Tapir/LoweringUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ class TapirTarget {
/// Lower a Tapir sync instruction SI.
virtual void lowerSync(SyncInst &SI) = 0;

virtual void lowerFrameCall(CallBase *MagicCall) {
}

virtual void lowerReducerOperation(CallBase *Call) {
}

Expand Down
5 changes: 3 additions & 2 deletions llvm/include/llvm/Transforms/Tapir/OpenCilkABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,9 @@ class OpenCilkABI final : public TapirTarget {
void setOptions(const TapirTargetOptions &Options) override final;

void prepareModule() override final;
Value *lowerGrainsizeCall(CallInst *GrainsizeCall) override final;
void lowerSync(SyncInst &SI) override final;
Value *lowerGrainsizeCall(CallInst *GrainsizeCall) override;
void lowerSync(SyncInst &SI) override;
void lowerFrameCall(CallBase *CI) override;
void lowerReducerOperation(CallBase *CI) override;

ArgStructMode getArgStructMode() const override final {
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/CodeGen/IntrinsicLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,12 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
report_fatal_error("Code generator does not support intrinsic function '"+
Callee->getName()+"'!");

case Intrinsic::tapir_frame:
CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
break;

case Intrinsic::hyper_lookup:
// hyper_lookup, if not replaced by now, returns its first argument
case Intrinsic::expect: {
// Just replace __builtin_expect(exp, c) with EXP.
Value *V = CI->getArgOperand(0);
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7427,6 +7427,15 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
TLI.getFrameIndexTy(DAG.getDataLayout()),
getValue(I.getArgOperand(0))));
return;
case Intrinsic::hyper_lookup:
// Return the first argument.
setValue(&I, getValue(I.getArgOperand(0)));
return;
case Intrinsic::tapir_frame:
// Return null.
setValue(&I,
DAG.getConstant(0, sdl, TLI.getPointerTy(DAG.getDataLayout())));
return;
}
}

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Tapir/LoweringUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,7 @@ bool TapirTarget::shouldProcessFunction(const Function &F) const {
case Intrinsic::reducer_unregister:
case Intrinsic::tapir_loop_grainsize:
case Intrinsic::task_frameaddress:
case Intrinsic::tapir_frame:
case Intrinsic::tapir_runtime_start:
case Intrinsic::tapir_runtime_end:
return true;
Expand Down
18 changes: 14 additions & 4 deletions llvm/lib/Transforms/Tapir/OpenCilkABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@ Value *OpenCilkABI::CreateStackFrame(Function &F) {
}

Value* OpenCilkABI::GetOrCreateCilkStackFrame(Function &F) {
if (DetachCtxToStackFrame.count(&F))
return DetachCtxToStackFrame[&F];
if (Value *Frame = DetachCtxToStackFrame.lookup(&F))
return Frame;

Value *SF = CreateStackFrame(F);
DetachCtxToStackFrame[&F] = SF;
Expand Down Expand Up @@ -641,8 +641,8 @@ Value *OpenCilkABI::lowerGrainsizeCall(CallInst *GrainsizeCall) {
BasicBlock *OpenCilkABI::GetDefaultSyncLandingpad(Function &F, Value *SF,
DebugLoc Loc) {
// Return an existing default sync landingpad, if there is one.
if (DefaultSyncLandingpad.count(&F))
return cast<BasicBlock>(DefaultSyncLandingpad[&F]);
if (Value *Sync = DefaultSyncLandingpad.lookup(&F))
return cast<BasicBlock>(Sync);

// Create a default cleanup landingpad block.
LLVMContext &C = F.getContext();
Expand Down Expand Up @@ -1118,6 +1118,16 @@ LoopOutlineProcessor *OpenCilkABI::getLoopOutlineProcessor(
return nullptr;
}

void OpenCilkABI::lowerFrameCall(CallBase *FrameCall) {
assert(FrameCall->data_operands_size() == 0);
Function *F = FrameCall->getFunction();
Value *Replacement = DetachCtxToStackFrame.lookup(F);
if (!Replacement)
Replacement = Constant::getNullValue(FrameCall->getType());
FrameCall->replaceAllUsesWith(Replacement);
FrameCall->eraseFromParent();
}

void OpenCilkABI::lowerReducerOperation(CallBase *CI) {
FunctionCallee Fn = nullptr;
const Function *Called = CI->getCalledFunction();
Expand Down
58 changes: 37 additions & 21 deletions llvm/lib/Transforms/Tapir/TapirToTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,42 +224,58 @@ bool TapirToTargetImpl::processSimpleABI(Function &F, BasicBlock *TFEntry) {
SmallVector<CallInst *, 8> TaskFrameAddrCalls;
SmallVector<CallInst *, 8> TapirRTCalls;
SmallVector<CallBase *, 8> ReducerOperations;
SmallVector<CallInst *, 8> TapirFrameCalls;
for (BasicBlock &BB : F) {
for (Instruction &I : BB) {
// Record calls to get Tapir-loop grainsizes.
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I))
if (Intrinsic::tapir_loop_grainsize == II->getIntrinsicID())

// Record sync instructions in this function.
if (SyncInst *SI = dyn_cast<SyncInst>(&I)) {
Syncs.push_back(SI);
continue;
}

if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) {
switch (II->getIntrinsicID()) {
case Intrinsic::tapir_loop_grainsize:
GrainsizeCalls.push_back(II);
break;

// Record calls to task_frameaddr intrinsics.
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I))
if (Intrinsic::task_frameaddress == II->getIntrinsicID())
case Intrinsic::task_frameaddress:
TaskFrameAddrCalls.push_back(II);
break;

// Record calls to tapir_runtime_start intrinsics. We rely on analyzing
// uses of these intrinsic calls to find calls to tapir_runtime_end.
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I))
if (Intrinsic::tapir_runtime_start == II->getIntrinsicID())
// Record calls to tapir_runtime_start intrinsics.
// We rely on analyzing uses of these intrinsic calls
// to find calls to tapir_runtime_end.
case Intrinsic::tapir_runtime_start:
TapirRTCalls.push_back(II);

// Record sync instructions in this function.
if (SyncInst *SI = dyn_cast<SyncInst>(&I))
Syncs.push_back(SI);

if (!dyn_cast<CallBase>(&I))
break;

case Intrinsic::tapir_frame:
TapirFrameCalls.push_back(II);
break;

case Intrinsic::hyper_lookup:
case Intrinsic::reducer_register:
case Intrinsic::reducer_unregister:
ReducerOperations.push_back(cast<CallInst>(&I));
break;
}
continue;

if (isTapirIntrinsic(Intrinsic::hyper_lookup, &I, nullptr) ||
isTapirIntrinsic(Intrinsic::reducer_register, &I, nullptr) ||
isTapirIntrinsic(Intrinsic::reducer_unregister, &I, nullptr))
ReducerOperations.push_back(cast<CallInst>(&I));
}
}
}

// Lower simple Tapir instructions in this function. Collect the set of
// helper functions generated by this process.
bool Changed = false;

while (!TapirFrameCalls.empty()) {
CallInst *CI = TapirFrameCalls.pop_back_val();
Target->lowerFrameCall(CI);
Changed = true;
}

// Lower calls to get Tapir-loop grainsizes.
while (!GrainsizeCalls.empty()) {
CallInst *GrainsizeCall = GrainsizeCalls.pop_back_val();
Expand Down

0 comments on commit 699892a

Please sign in to comment.