From 699892a1c882c727f4e0e990715a33a468f4bacd Mon Sep 17 00:00:00 2001 From: "John F. Carr" Date: Fri, 1 Sep 2023 14:45:05 -0400 Subject: [PATCH] __tapir_frame() builtin --- clang/include/clang/Basic/Builtins.def | 2 + clang/lib/CodeGen/CGBuiltin.cpp | 4 ++ clang/test/Cilk/tapir-frame.c | 29 ++++++++++ llvm/include/llvm/IR/Intrinsics.td | 4 ++ .../llvm/Transforms/Tapir/LoweringUtils.h | 3 + .../llvm/Transforms/Tapir/OpenCilkABI.h | 5 +- llvm/lib/CodeGen/IntrinsicLowering.cpp | 6 ++ .../SelectionDAG/SelectionDAGBuilder.cpp | 9 +++ llvm/lib/Transforms/Tapir/LoweringUtils.cpp | 1 + llvm/lib/Transforms/Tapir/OpenCilkABI.cpp | 18 ++++-- llvm/lib/Transforms/Tapir/TapirToTarget.cpp | 58 ++++++++++++------- 11 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 clang/test/Cilk/tapir-frame.c diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 23cb76973955..c5877e791036 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -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") diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index cb4c7944c335..1895cab14c11 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -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()); diff --git a/clang/test/Cilk/tapir-frame.c b/clang/test/Cilk/tapir-frame.c new file mode 100644 index 000000000000..253f9c8c402d --- /dev/null +++ b/clang/test/Cilk/tapir-frame.c @@ -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()); +} diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 60aaaf6ae3ec..a1f4e21e4933 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -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 diff --git a/llvm/include/llvm/Transforms/Tapir/LoweringUtils.h b/llvm/include/llvm/Transforms/Tapir/LoweringUtils.h index 27fa8f2e465c..b33df212e973 100644 --- a/llvm/include/llvm/Transforms/Tapir/LoweringUtils.h +++ b/llvm/include/llvm/Transforms/Tapir/LoweringUtils.h @@ -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) { } diff --git a/llvm/include/llvm/Transforms/Tapir/OpenCilkABI.h b/llvm/include/llvm/Transforms/Tapir/OpenCilkABI.h index a4bae8a902ca..4c7cd4a9ab1f 100644 --- a/llvm/include/llvm/Transforms/Tapir/OpenCilkABI.h +++ b/llvm/include/llvm/Transforms/Tapir/OpenCilkABI.h @@ -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 { diff --git a/llvm/lib/CodeGen/IntrinsicLowering.cpp b/llvm/lib/CodeGen/IntrinsicLowering.cpp index 61920a0e04ab..1d6788da2397 100644 --- a/llvm/lib/CodeGen/IntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/IntrinsicLowering.cpp @@ -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); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 7f800d2525bb..d83bf1b76e9c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -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; } } diff --git a/llvm/lib/Transforms/Tapir/LoweringUtils.cpp b/llvm/lib/Transforms/Tapir/LoweringUtils.cpp index 319083f81e1e..dd7883af9e50 100644 --- a/llvm/lib/Transforms/Tapir/LoweringUtils.cpp +++ b/llvm/lib/Transforms/Tapir/LoweringUtils.cpp @@ -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; diff --git a/llvm/lib/Transforms/Tapir/OpenCilkABI.cpp b/llvm/lib/Transforms/Tapir/OpenCilkABI.cpp index f60b202b755d..1028c5505b8e 100644 --- a/llvm/lib/Transforms/Tapir/OpenCilkABI.cpp +++ b/llvm/lib/Transforms/Tapir/OpenCilkABI.cpp @@ -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; @@ -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(DefaultSyncLandingpad[&F]); + if (Value *Sync = DefaultSyncLandingpad.lookup(&F)) + return cast(Sync); // Create a default cleanup landingpad block. LLVMContext &C = F.getContext(); @@ -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(); diff --git a/llvm/lib/Transforms/Tapir/TapirToTarget.cpp b/llvm/lib/Transforms/Tapir/TapirToTarget.cpp index d632c7113af3..5c4b16e82176 100644 --- a/llvm/lib/Transforms/Tapir/TapirToTarget.cpp +++ b/llvm/lib/Transforms/Tapir/TapirToTarget.cpp @@ -224,35 +224,45 @@ bool TapirToTargetImpl::processSimpleABI(Function &F, BasicBlock *TFEntry) { SmallVector TaskFrameAddrCalls; SmallVector TapirRTCalls; SmallVector ReducerOperations; + SmallVector TapirFrameCalls; for (BasicBlock &BB : F) { for (Instruction &I : BB) { - // Record calls to get Tapir-loop grainsizes. - if (IntrinsicInst *II = dyn_cast(&I)) - if (Intrinsic::tapir_loop_grainsize == II->getIntrinsicID()) + + // Record sync instructions in this function. + if (SyncInst *SI = dyn_cast(&I)) { + Syncs.push_back(SI); + continue; + } + + if (IntrinsicInst *II = dyn_cast(&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(&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(&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(&I)) - Syncs.push_back(SI); - - if (!dyn_cast(&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(&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(&I)); + } } } @@ -260,6 +270,12 @@ bool TapirToTargetImpl::processSimpleABI(Function &F, BasicBlock *TFEntry) { // 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();