[Clang][OpenMP] Add the codegen support for `atomic compare`
This patch adds the codegen support for `atomic compare` in clang. Reviewed By: ABataev Differential Revision: https://reviews.llvm.org/D118632
This commit is contained in:
parent
16994a2cfa
commit
104d9a6743
|
@ -2863,6 +2863,8 @@ class OMPAtomicDirective : public OMPExecutableDirective {
|
|||
POS_V,
|
||||
POS_E,
|
||||
POS_UpdateExpr,
|
||||
POS_D,
|
||||
POS_Cond,
|
||||
};
|
||||
|
||||
/// Set 'x' part of the associated expression/statement.
|
||||
|
@ -2877,6 +2879,10 @@ class OMPAtomicDirective : public OMPExecutableDirective {
|
|||
void setV(Expr *V) { Data->getChildren()[DataPositionTy::POS_V] = V; }
|
||||
/// Set 'expr' part of the associated expression/statement.
|
||||
void setExpr(Expr *E) { Data->getChildren()[DataPositionTy::POS_E] = E; }
|
||||
/// Set 'd' part of the associated expression/statement.
|
||||
void setD(Expr *D) { Data->getChildren()[DataPositionTy::POS_D] = D; }
|
||||
/// Set conditional expression in `atomic compare`.
|
||||
void setCond(Expr *C) { Data->getChildren()[DataPositionTy::POS_Cond] = C; }
|
||||
|
||||
public:
|
||||
/// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
|
||||
|
@ -2894,6 +2900,8 @@ public:
|
|||
/// \param UE Helper expression of the form
|
||||
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
|
||||
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
|
||||
/// \param D 'd' part of the associated expression/statement.
|
||||
/// \param Cond Conditional expression in `atomic compare` construct.
|
||||
/// \param IsXLHSInRHSPart true if \a UE has the first form and false if the
|
||||
/// second.
|
||||
/// \param IsPostfixUpdate true if original value of 'x' must be stored in
|
||||
|
@ -2901,7 +2909,8 @@ public:
|
|||
static OMPAtomicDirective *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
|
||||
Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate);
|
||||
Expr *E, Expr *UE, Expr *D, Expr *Cond, bool IsXLHSInRHSPart,
|
||||
bool IsPostfixUpdate);
|
||||
|
||||
/// Creates an empty directive with the place for \a NumClauses
|
||||
/// clauses.
|
||||
|
@ -2951,6 +2960,20 @@ public:
|
|||
const Expr *getExpr() const {
|
||||
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
|
||||
}
|
||||
/// Get 'd' part of the associated expression/statement.
|
||||
Expr *getD() {
|
||||
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
|
||||
}
|
||||
Expr *getD() const {
|
||||
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
|
||||
}
|
||||
/// Get the 'cond' part of the source atomic expression.
|
||||
Expr *getCondExpr() {
|
||||
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
|
||||
}
|
||||
Expr *getCondExpr() const {
|
||||
return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPAtomicDirectiveClass;
|
||||
|
|
|
@ -863,16 +863,20 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
|
|||
!IsStandalone);
|
||||
}
|
||||
|
||||
OMPAtomicDirective *OMPAtomicDirective::Create(
|
||||
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
|
||||
Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) {
|
||||
OMPAtomicDirective *
|
||||
OMPAtomicDirective::Create(const ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E,
|
||||
Expr *UE, Expr *D, Expr *Cond, bool IsXLHSInRHSPart,
|
||||
bool IsPostfixUpdate) {
|
||||
auto *Dir = createDirective<OMPAtomicDirective>(
|
||||
C, Clauses, AssociatedStmt, /*NumChildren=*/4, StartLoc, EndLoc);
|
||||
C, Clauses, AssociatedStmt, /*NumChildren=*/6, StartLoc, EndLoc);
|
||||
Dir->setX(X);
|
||||
Dir->setV(V);
|
||||
Dir->setExpr(E);
|
||||
Dir->setUpdateExpr(UE);
|
||||
Dir->setD(D);
|
||||
Dir->setCond(Cond);
|
||||
Dir->IsXLHSInRHSPart = IsXLHSInRHSPart;
|
||||
Dir->IsPostfixUpdate = IsPostfixUpdate;
|
||||
return Dir;
|
||||
|
@ -882,7 +886,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C,
|
|||
unsigned NumClauses,
|
||||
EmptyShell) {
|
||||
return createEmptyDirective<OMPAtomicDirective>(
|
||||
C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/4);
|
||||
C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/6);
|
||||
}
|
||||
|
||||
OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C,
|
||||
|
|
|
@ -6017,11 +6017,50 @@ static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF,
|
|||
}
|
||||
}
|
||||
|
||||
static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF,
|
||||
llvm::AtomicOrdering AO, const Expr *X,
|
||||
const Expr *E, const Expr *D,
|
||||
const Expr *CE, bool IsXBinopExpr,
|
||||
SourceLocation Loc) {
|
||||
llvm::OpenMPIRBuilder &OMPBuilder =
|
||||
CGF.CGM.getOpenMPRuntime().getOMPBuilder();
|
||||
|
||||
OMPAtomicCompareOp Op;
|
||||
assert(isa<BinaryOperator>(CE) && "CE is not a BinaryOperator");
|
||||
switch (cast<BinaryOperator>(CE)->getOpcode()) {
|
||||
case BO_EQ:
|
||||
Op = OMPAtomicCompareOp::EQ;
|
||||
break;
|
||||
case BO_LT:
|
||||
Op = OMPAtomicCompareOp::MIN;
|
||||
break;
|
||||
case BO_GT:
|
||||
Op = OMPAtomicCompareOp::MAX;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported atomic compare binary operator");
|
||||
}
|
||||
|
||||
LValue XLVal = CGF.EmitLValue(X);
|
||||
llvm::Value *XPtr = XLVal.getPointer(CGF);
|
||||
llvm::Value *EVal = CGF.EmitScalarExpr(E);
|
||||
llvm::Value *DVal = D ? CGF.EmitScalarExpr(D) : nullptr;
|
||||
|
||||
llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
|
||||
XPtr, XPtr->getType()->getPointerElementType(),
|
||||
X->getType().isVolatileQualified(),
|
||||
X->getType()->hasSignedIntegerRepresentation()};
|
||||
|
||||
CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare(
|
||||
CGF.Builder, XOpVal, EVal, DVal, AO, Op, IsXBinopExpr));
|
||||
}
|
||||
|
||||
static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
|
||||
llvm::AtomicOrdering AO, bool IsPostfixUpdate,
|
||||
const Expr *X, const Expr *V, const Expr *E,
|
||||
const Expr *UE, bool IsXLHSInRHSPart,
|
||||
bool IsCompareCapture, SourceLocation Loc) {
|
||||
const Expr *UE, const Expr *D, const Expr *CE,
|
||||
bool IsXLHSInRHSPart, bool IsCompareCapture,
|
||||
SourceLocation Loc) {
|
||||
switch (Kind) {
|
||||
case OMPC_read:
|
||||
emitOMPAtomicReadExpr(CGF, AO, X, V, Loc);
|
||||
|
@ -6045,11 +6084,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
|
|||
"'atomic compare capture' is not supported for now");
|
||||
CGF.CGM.getDiags().Report(DiagID);
|
||||
} else {
|
||||
// Emit an error here.
|
||||
unsigned DiagID = CGF.CGM.getDiags().getCustomDiagID(
|
||||
DiagnosticsEngine::Error,
|
||||
"'atomic compare' is not supported for now");
|
||||
CGF.CGM.getDiags().Report(DiagID);
|
||||
emitOMPAtomicCompareExpr(CGF, AO, X, E, D, CE, IsXLHSInRHSPart, Loc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -6202,8 +6237,8 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
|
|||
LexicalScope Scope(*this, S.getSourceRange());
|
||||
EmitStopPoint(S.getAssociatedStmt());
|
||||
emitOMPAtomicExpr(*this, Kind, AO, S.isPostfixUpdate(), S.getX(), S.getV(),
|
||||
S.getExpr(), S.getUpdateExpr(), S.isXLHSInRHSPart(),
|
||||
IsCompareCapture, S.getBeginLoc());
|
||||
S.getExpr(), S.getUpdateExpr(), S.getD(), S.getCondExpr(),
|
||||
S.isXLHSInRHSPart(), IsCompareCapture, S.getBeginLoc());
|
||||
}
|
||||
|
||||
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
|
||||
|
|
|
@ -11133,11 +11133,11 @@ bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
|
|||
switch (Cond->getOpcode()) {
|
||||
case BO_EQ: {
|
||||
C = Cond;
|
||||
D = BO->getRHS();
|
||||
D = BO->getRHS()->IgnoreImpCasts();
|
||||
if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
|
||||
E = Cond->getRHS();
|
||||
E = Cond->getRHS()->IgnoreImpCasts();
|
||||
} else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
|
||||
E = Cond->getLHS();
|
||||
E = Cond->getLHS()->IgnoreImpCasts();
|
||||
} else {
|
||||
ErrorInfo.Error = ErrorTy::InvalidComparison;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
|
||||
|
@ -11148,7 +11148,7 @@ bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
|
|||
}
|
||||
case BO_LT:
|
||||
case BO_GT: {
|
||||
E = BO->getRHS();
|
||||
E = BO->getRHS()->IgnoreImpCasts();
|
||||
if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
|
||||
checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
|
||||
C = Cond;
|
||||
|
@ -11228,11 +11228,11 @@ bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
|
|||
switch (Cond->getOpcode()) {
|
||||
case BO_EQ: {
|
||||
C = Cond;
|
||||
D = CO->getTrueExpr();
|
||||
D = CO->getTrueExpr()->IgnoreImpCasts();
|
||||
if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
|
||||
E = Cond->getRHS();
|
||||
E = Cond->getRHS()->IgnoreImpCasts();
|
||||
} else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
|
||||
E = Cond->getLHS();
|
||||
E = Cond->getLHS()->IgnoreImpCasts();
|
||||
} else {
|
||||
ErrorInfo.Error = ErrorTy::InvalidComparison;
|
||||
ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
|
||||
|
@ -11243,7 +11243,7 @@ bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
|
|||
}
|
||||
case BO_LT:
|
||||
case BO_GT: {
|
||||
E = CO->getTrueExpr();
|
||||
E = CO->getTrueExpr()->IgnoreImpCasts();
|
||||
if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
|
||||
checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
|
||||
C = Cond;
|
||||
|
@ -11843,6 +11843,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
|
|||
Expr *V = nullptr;
|
||||
Expr *E = nullptr;
|
||||
Expr *UE = nullptr;
|
||||
Expr *D = nullptr;
|
||||
Expr *CE = nullptr;
|
||||
bool IsXLHSInRHSPart = false;
|
||||
bool IsPostfixUpdate = false;
|
||||
// OpenMP [2.12.6, atomic Construct]
|
||||
|
@ -12252,15 +12254,19 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
|
|||
<< ErrorInfo.Error << ErrorInfo.NoteRange;
|
||||
return StmtError();
|
||||
}
|
||||
// TODO: We don't set X, D, E, etc. here because in code gen we will emit
|
||||
// error directly.
|
||||
X = Checker.getX();
|
||||
E = Checker.getE();
|
||||
D = Checker.getD();
|
||||
CE = Checker.getCond();
|
||||
// We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
|
||||
IsXLHSInRHSPart = Checker.isXBinopExpr();
|
||||
}
|
||||
}
|
||||
|
||||
setFunctionHasBranchProtectedScope();
|
||||
|
||||
return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
|
||||
X, V, E, UE, IsXLHSInRHSPart,
|
||||
X, V, E, UE, D, CE, IsXLHSInRHSPart,
|
||||
IsPostfixUpdate);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue