diff --git a/llvm/include/llvm/IR/Assumptions.h b/llvm/include/llvm/IR/Assumptions.h --- a/llvm/include/llvm/IR/Assumptions.h +++ b/llvm/include/llvm/IR/Assumptions.h @@ -33,6 +33,10 @@ /// Helper that allows to insert a new assumption string in the known assumption /// set by creating a (static) object. struct KnownAssumptionString { + KnownAssumptionString(const char *AssumptionStr) + : AssumptionStr(AssumptionStr) { + KnownAssumptionStrings.insert(AssumptionStr); + } KnownAssumptionString(StringRef AssumptionStr) : AssumptionStr(AssumptionStr) { KnownAssumptionStrings.insert(AssumptionStr); diff --git a/llvm/lib/IR/Assumptions.cpp b/llvm/lib/IR/Assumptions.cpp --- a/llvm/lib/IR/Assumptions.cpp +++ b/llvm/lib/IR/Assumptions.cpp @@ -52,4 +52,5 @@ "omp_no_openmp_routines", // OpenMP 5.1 "omp_no_parallelism", // OpenMP 5.1 "ompx_spmd_amenable", // OpenMPOpt extension + "ompx_no_call_asm", // OpenMPOpt extension }); diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -30,6 +30,7 @@ #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Argument.h" +#include "llvm/IR/Assumptions.h" #include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" @@ -9696,7 +9697,9 @@ CallBase *CB = static_cast(getCtxI()); if (CB->isInlineAsm()) { - setHasUnknownCallee(false, Change); + if (!hasAssumption(*CB->getCaller(), "ompx_no_call_asm") && + !hasAssumption(*CB, "ompx_no_call_asm")) + setHasUnknownCallee(false, Change); return Change; } diff --git a/llvm/test/Transforms/Attributor/reachability.ll b/llvm/test/Transforms/Attributor/reachability.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Attributor/reachability.ll @@ -0,0 +1,20 @@ + +define dso_local void @non_recursive_asm_fn() #0 { +entry: + call void asm sideeffect "barrier.sync $0;", "r,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 1) + ret void +} + +define dso_local void @non_recursive_asm_cs() { +entry: + call void asm sideeffect "barrier.sync $0;", "r,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 1) #0 + ret void +} + +define dso_local void @recursive_asm() { +entry: + call void asm sideeffect "barrier.sync $0;", "r,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 1) + ret void +} + +attributes #0 = { "llvm.assume"="ompx_no_call_asm" } diff --git a/openmp/libomptarget/DeviceRTL/include/Types.h b/openmp/libomptarget/DeviceRTL/include/Types.h --- a/openmp/libomptarget/DeviceRTL/include/Types.h +++ b/openmp/libomptarget/DeviceRTL/include/Types.h @@ -12,6 +12,15 @@ #ifndef OMPTARGET_TYPES_H #define OMPTARGET_TYPES_H +// Tell the compiler that we do not have any "call-like" inline assembly in the +// device rutime. That means we cannot have inline assembly which will call +// another function but only inline assembly that performs some operation or +// side-effect and then continues execution with something on the existing call +// stack. +// +// TODO: Find a good place for this +#pragma omp assumes ext_no_call_asm + /// Base type declarations for freestanding mode /// ///{