[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:
Shilei Tian 2022-02-22 12:59:56 -05:00
parent 16994a2cfa
commit 104d9a6743
5 changed files with 4116 additions and 27 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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