-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[CIR] Upstream lowering of conditional operators to TernaryOp #138156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
522da72
aa24a35
b101a5b
b773953
b7c3d8d
69d3087
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,13 +15,15 @@ | |
#include "CIRGenModule.h" | ||
#include "CIRGenValue.h" | ||
#include "mlir/IR/BuiltinAttributes.h" | ||
#include "mlir/IR/Value.h" | ||
#include "clang/AST/Attr.h" | ||
#include "clang/AST/CharUnits.h" | ||
#include "clang/AST/Decl.h" | ||
#include "clang/AST/Expr.h" | ||
#include "clang/AST/ExprCXX.h" | ||
#include "clang/CIR/Dialect/IR/CIRDialect.h" | ||
#include "clang/CIR/MissingFeatures.h" | ||
#include <optional> | ||
|
||
using namespace clang; | ||
using namespace clang::CIRGen; | ||
|
@@ -229,7 +231,7 @@ void CIRGenFunction::emitStoreThroughLValue(RValue src, LValue dst, | |
|
||
static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e, | ||
const VarDecl *vd) { | ||
QualType T = e->getType(); | ||
QualType t = e->getType(); | ||
|
||
// If it's thread_local, emit a call to its wrapper function instead. | ||
assert(!cir::MissingFeatures::opGlobalThreadLocal()); | ||
|
@@ -259,7 +261,7 @@ static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e, | |
cgf.cgm.errorNYI(e->getSourceRange(), | ||
"emitGlobalVarDeclLValue: reference type"); | ||
else | ||
lv = cgf.makeAddrLValue(addr, T, AlignmentSource::Decl); | ||
lv = cgf.makeAddrLValue(addr, t, AlignmentSource::Decl); | ||
assert(!cir::MissingFeatures::setObjCGCLValueClass()); | ||
return lv; | ||
} | ||
|
@@ -1259,10 +1261,28 @@ mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc, | |
// cir.ternary(!x, t, f) -> cir.ternary(x, f, t) | ||
assert(!cir::MissingFeatures::shouldReverseUnaryCondOnBoolExpr()); | ||
|
||
if (isa<ConditionalOperator>(cond)) { | ||
cgm.errorNYI(cond->getExprLoc(), "Ternary NYI"); | ||
assert(!cir::MissingFeatures::ternaryOp()); | ||
return createDummyValue(loc, cond->getType()); | ||
if (const ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(cond)) { | ||
Expr *trueExpr = condOp->getTrueExpr(); | ||
Expr *falseExpr = condOp->getFalseExpr(); | ||
mlir::Value condV = emitOpOnBoolExpr(loc, condOp->getCond()); | ||
|
||
mlir::Value ternaryOpRes = | ||
builder | ||
.create<cir::TernaryOp>( | ||
loc, condV, /*thenBuilder=*/ | ||
[this, trueExpr](mlir::OpBuilder &b, mlir::Location loc) { | ||
mlir::Value lhs = emitScalarExpr(trueExpr); | ||
b.create<cir::YieldOp>(loc, lhs); | ||
}, | ||
/*elseBuilder=*/ | ||
[this, falseExpr](mlir::OpBuilder &b, mlir::Location loc) { | ||
mlir::Value rhs = emitScalarExpr(falseExpr); | ||
b.create<cir::YieldOp>(loc, rhs); | ||
}) | ||
.getResult(); | ||
|
||
return emitScalarConversion(ternaryOpRes, condOp->getType(), | ||
getContext().BoolTy, condOp->getExprLoc()); | ||
} | ||
|
||
if (isa<CXXThrowExpr>(cond)) { | ||
|
@@ -1394,13 +1414,84 @@ mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc, | |
return builder.createDummyValue(loc, t, alignment); | ||
} | ||
|
||
/// This creates an alloca and inserts it into the entry block if | ||
/// \p insertIntoFnEntryBlock is true, otherwise it inserts it at the current | ||
/// insertion point of the builder. | ||
//===----------------------------------------------------------------------===// | ||
// CIR builder helpers | ||
//===----------------------------------------------------------------------===// | ||
|
||
Address CIRGenFunction::createMemTemp(QualType ty, mlir::Location loc, | ||
const Twine &name, Address *alloca, | ||
mlir::OpBuilder::InsertPoint ip) { | ||
// FIXME: Should we prefer the preferred type alignment here? | ||
return createMemTemp(ty, getContext().getTypeAlignInChars(ty), loc, name, | ||
alloca, ip); | ||
} | ||
|
||
Address CIRGenFunction::createMemTemp(QualType ty, CharUnits align, | ||
mlir::Location loc, const Twine &name, | ||
Address *alloca, | ||
mlir::OpBuilder::InsertPoint ip) { | ||
Address result = createTempAlloca(convertTypeForMem(ty), align, loc, name, | ||
/*ArraySize=*/nullptr, alloca, ip); | ||
if (ty->isConstantMatrixType()) { | ||
assert(!cir::MissingFeatures::matrixType()); | ||
cgm.errorNYI(loc, "temporary matrix value"); | ||
} | ||
return result; | ||
} | ||
|
||
/// This creates a alloca and inserts it into the entry block of the | ||
/// current region. | ||
Address CIRGenFunction::createTempAllocaWithoutCast( | ||
mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name, | ||
mlir::Value arraySize, mlir::OpBuilder::InsertPoint ip) { | ||
cir::AllocaOp alloca = ip.isSet() | ||
? createTempAlloca(ty, loc, name, ip, arraySize) | ||
: createTempAlloca(ty, loc, name, arraySize); | ||
alloca.setAlignmentAttr(cgm.getSize(align)); | ||
return Address(alloca, ty, align); | ||
} | ||
|
||
/// This creates a alloca and inserts it into the entry block. The alloca is | ||
/// casted to default address space if necessary. | ||
Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align, | ||
mlir::Location loc, const Twine &name, | ||
bool insertIntoFnEntryBlock) { | ||
mlir::Value alloca = | ||
emitAlloca(name.str(), ty, loc, align, insertIntoFnEntryBlock); | ||
return Address(alloca, ty, align); | ||
mlir::Value arraySize, | ||
Address *allocaAddr, | ||
mlir::OpBuilder::InsertPoint ip) { | ||
Address alloca = | ||
createTempAllocaWithoutCast(ty, align, loc, name, arraySize, ip); | ||
if (allocaAddr) | ||
*allocaAddr = alloca; | ||
mlir::Value v = alloca.getPointer(); | ||
// Alloca always returns a pointer in alloca address space, which may | ||
// be different from the type defined by the language. For example, | ||
// in C++ the auto variables are in the default address space. Therefore | ||
// cast alloca to the default address space when necessary. | ||
assert(!cir::MissingFeatures::addressSpace()); | ||
return Address(v, ty, align); | ||
} | ||
|
||
/// This creates an alloca and inserts it into the entry block if \p ArraySize | ||
/// is nullptr, otherwise inserts it at the current insertion point of the | ||
/// builder. | ||
cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty, | ||
mlir::Location loc, | ||
const Twine &name, | ||
mlir::Value arraySize, | ||
bool insertIntoFnEntryBlock) { | ||
return cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like this should be doing something to get the alignment based on the type. Looking at the equivalent classic codegen, if |
||
insertIntoFnEntryBlock, arraySize) | ||
.getDefiningOp()); | ||
} | ||
|
||
/// This creates an alloca and inserts it into the provided insertion point | ||
cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty, | ||
mlir::Location loc, | ||
const Twine &name, | ||
mlir::OpBuilder::InsertPoint ip, | ||
mlir::Value arraySize) { | ||
assert(ip.isSet() && "Insertion point is not set"); | ||
return cast<cir::AllocaOp>( | ||
emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize) | ||
.getDefiningOp()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears these will only work if lhs and rhs are bool values. I guess the assert above will force that, but it initially surprised me.