aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bolt/utils/dot2html/d3-graphviz-template.html6
-rw-r--r--clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h7
-rw-r--r--clang/include/clang/CIR/Dialect/IR/CIROps.td10
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenAtomic.cpp20
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCall.cpp26
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCall.h2
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp14
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp20
-rw-r--r--clang/lib/CIR/Dialect/IR/CIRDialect.cpp13
-rw-r--r--clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp15
-rw-r--r--clang/lib/Sema/SemaTemplateDeductionGuide.cpp19
-rw-r--r--clang/test/CIR/CodeGen/complex.cpp62
-rw-r--r--clang/test/CIR/CodeGen/paren-init-list.cpp30
-rw-r--r--clang/test/CIR/CodeGen/struct.cpp64
-rw-r--r--flang/include/flang/Parser/message.h2
-rw-r--r--flang/lib/Evaluate/check-expression.cpp18
-rw-r--r--flang/lib/Parser/message.cpp24
-rw-r--r--flang/test/Semantics/associated.f902
-rw-r--r--flang/test/Semantics/intrinsics03.f902
-rw-r--r--flang/test/Semantics/intrinsics04.f902
-rw-r--r--flang/test/Semantics/type-parameter-constant.f9015
-rw-r--r--llvm/docs/ProgrammersManual.rst18
-rw-r--r--llvm/include/llvm/ADT/BitmaskEnum.h7
-rw-r--r--llvm/include/llvm/ADT/PointerUnion.h2
-rw-r--r--llvm/include/llvm/ADT/bit.h17
-rw-r--r--llvm/include/llvm/IR/ValueMap.h88
-rw-r--r--llvm/include/llvm/Support/ScopedPrinter.h16
-rw-r--r--llvm/include/llvm/TableGen/CodeGenHelpers.h67
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td4
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp6
-rw-r--r--llvm/lib/Transforms/InstCombine/InstructionCombining.cpp6
-rw-r--r--llvm/test/CodeGen/AMDGPU/wait-xcnt.mir40
-rw-r--r--llvm/unittests/ADT/BitTest.cpp23
-rw-r--r--llvm/utils/TableGen/Basic/DirectiveEmitter.cpp73
-rw-r--r--llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp36
-rw-r--r--llvm/utils/TableGen/CompressInstEmitter.cpp2
-rw-r--r--llvm/utils/profcheck-xfail.txt10
-rw-r--r--mlir/include/mlir/TableGen/CodeGenHelpers.h42
-rw-r--r--mlir/include/mlir/TableGen/Dialect.h1
-rw-r--r--mlir/lib/TableGen/CodeGenHelpers.cpp1
-rw-r--r--mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp20
-rw-r--r--mlir/tools/mlir-tblgen/DialectGen.cpp4
-rw-r--r--mlir/tools/mlir-tblgen/OmpOpGen.cpp2
-rw-r--r--mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp11
-rw-r--r--mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp3
45 files changed, 564 insertions, 308 deletions
diff --git a/bolt/utils/dot2html/d3-graphviz-template.html b/bolt/utils/dot2html/d3-graphviz-template.html
index c86f779..46fdf2a 100644
--- a/bolt/utils/dot2html/d3-graphviz-template.html
+++ b/bolt/utils/dot2html/d3-graphviz-template.html
@@ -1,9 +1,9 @@
<!DOCTYPE html>
<meta charset="utf-8">
<body>
-<script src="https://d3js.org/d3.v5.min.js"></script>
-<script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
-<script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>
+<script src="https://d3js.org/d3.v7.min.js"></script>
+<script src="https://unpkg.com/@hpcc-js/wasm@2.20.0/dist/graphviz.umd.js"></script>
+<script src="https://unpkg.com/d3-graphviz@5.6.0/build/d3-graphviz.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>
var dotSrc = `
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 93d81e3..569491a 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -178,9 +178,10 @@ public:
}
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
- auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());
- return cir::ComplexImagOp::create(*this, loc, operandTy.getElementType(),
- operand);
+ auto resultType = operand.getType();
+ if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
+ resultType = complexResultType.getElementType();
+ return cir::ComplexImagOp::create(*this, loc, resultType, operand);
}
cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 7f2e55d..c81f64d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3308,18 +3308,20 @@ def CIR_ComplexRealOp : CIR_Op<"complex.real", [Pure]> {
def CIR_ComplexImagOp : CIR_Op<"complex.imag", [Pure]> {
let summary = "Extract the imaginary part of a complex value";
let description = [{
- `cir.complex.imag` operation takes an operand of `!cir.complex` type and
- yields the imaginary part of it.
+ `cir.complex.imag` operation takes an operand of `!cir.complex`, `!cir.int`
+ or `!cir.float`. If the operand is `!cir.complex`, the imag part of it will
+ be returned, otherwise a zero value will be returned.
Example:
```mlir
- %1 = cir.complex.imag %0 : !cir.complex<!cir.float> -> !cir.float
+ %imag = cir.complex.imag %complex : !cir.complex<!cir.float> -> !cir.float
+ %imag = cir.complex.imag %scalar : !cir.float -> !cir.float
```
}];
let results = (outs CIR_AnyIntOrFloatType:$result);
- let arguments = (ins CIR_ComplexType:$operand);
+ let arguments = (ins CIR_AnyComplexOrIntOrFloatType:$operand);
let assemblyFormat = [{
$operand `:` qualified(type($operand)) `->` qualified(type($result))
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index e943b02..0f4d6d2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -718,10 +718,26 @@ void CIRGenFunction::emitAtomicInit(Expr *init, LValue dest) {
return;
}
- case cir::TEK_Aggregate:
- cgm.errorNYI(init->getSourceRange(), "emitAtomicInit: aggregate type");
+ case cir::TEK_Aggregate: {
+ // Fix up the destination if the initializer isn't an expression
+ // of atomic type.
+ bool zeroed = false;
+ if (!init->getType()->isAtomicType()) {
+ zeroed = atomics.emitMemSetZeroIfNecessary();
+ dest = atomics.projectValue();
+ }
+
+ // Evaluate the expression directly into the destination.
+ assert(!cir::MissingFeatures::aggValueSlotGC());
+ AggValueSlot slot = AggValueSlot::forLValue(
+ dest, AggValueSlot::IsNotDestructed, AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap,
+ zeroed ? AggValueSlot::IsZeroed : AggValueSlot::IsNotZeroed);
+
+ emitAggExpr(init, slot);
return;
}
+ }
llvm_unreachable("bad evaluation kind");
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 2970b36..61072f0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -522,7 +522,8 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
assert(!cir::MissingFeatures::opCallPaddingArgs());
mlir::Type argType = convertType(canQualArgType);
- if (!mlir::isa<cir::RecordType>(argType)) {
+ if (!mlir::isa<cir::RecordType>(argType) &&
+ !mlir::isa<cir::ComplexType>(argType)) {
mlir::Value v;
if (arg.isAggregate())
cgm.errorNYI(loc, "emitCall: aggregate call argument");
@@ -540,15 +541,16 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
cirCallArgs[argNo] = v;
} else {
Address src = Address::invalid();
- if (!arg.isAggregate())
- cgm.errorNYI(loc, "emitCall: non-aggregate call argument");
- else
+ if (!arg.isAggregate()) {
+ src = createMemTemp(arg.ty, loc, "coerce");
+ arg.copyInto(*this, src, loc);
+ } else {
src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
: arg.getKnownRValue().getAggregateAddress();
+ }
// Fast-isel and the optimizer generally like scalar values better than
// FCAs, so we flatten them if this is safe to do for this argument.
- auto argRecordTy = cast<cir::RecordType>(argType);
mlir::Type srcTy = src.getElementType();
// FIXME(cir): get proper location for each argument.
mlir::Location argLoc = loc;
@@ -564,7 +566,7 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
// uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
// if (SrcSize < DstSize) {
assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());
- if (srcTy != argRecordTy) {
+ if (srcTy != argType) {
cgm.errorNYI(loc, "emitCall: source type does not match argument type");
} else {
// FIXME(cir): this currently only runs when the types are exactly the
@@ -676,6 +678,18 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
llvm_unreachable("Invalid evaluation kind");
}
+void CallArg::copyInto(CIRGenFunction &cgf, Address addr,
+ mlir::Location loc) const {
+ LValue dst = cgf.makeAddrLValue(addr, ty);
+ if (!hasLV && rv.isScalar())
+ cgf.cgm.errorNYI(loc, "copyInto scalar value");
+ else if (!hasLV && rv.isComplex())
+ cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
+ else
+ cgf.cgm.errorNYI(loc, "copyInto hasLV");
+ isUsed = true;
+}
+
void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
clang::QualType argType) {
assert(argType->isReferenceType() == e->isGLValue() &&
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h b/clang/lib/CIR/CodeGen/CIRGenCall.h
index 52d541f..55b3d97 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.h
@@ -224,6 +224,8 @@ public:
}
bool isAggregate() const { return hasLV || rv.isAggregate(); }
+
+ void copyInto(CIRGenFunction &cgf, Address addr, mlir::Location loc) const;
};
class CallArgList : public llvm::SmallVector<CallArg, 8> {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 1e987f3..e51c3fc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -144,10 +144,7 @@ public:
void VisitUnaryCoawait(UnaryOperator *e) {
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitUnaryCoawait");
}
- void VisitUnaryExtension(UnaryOperator *e) {
- cgf.cgm.errorNYI(e->getSourceRange(),
- "AggExprEmitter: VisitUnaryExtension");
- }
+ void VisitUnaryExtension(UnaryOperator *e) { Visit(e->getSubExpr()); }
void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
cgf.cgm.errorNYI(e->getSourceRange(),
"AggExprEmitter: VisitSubstNonTypeTemplateParmExpr");
@@ -184,7 +181,8 @@ public:
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitBinAssign");
}
void VisitBinComma(const BinaryOperator *e) {
- cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitBinComma");
+ cgf.emitIgnoredExpr(e->getLHS());
+ Visit(e->getRHS());
}
void VisitBinCmp(const BinaryOperator *e) {
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitBinCmp");
@@ -212,9 +210,11 @@ public:
}
void VisitChooseExpr(const ChooseExpr *e) { Visit(e->getChosenSubExpr()); }
void VisitCXXParenListInitExpr(CXXParenListInitExpr *e) {
- cgf.cgm.errorNYI(e->getSourceRange(),
- "AggExprEmitter: VisitCXXParenListInitExpr");
+ visitCXXParenListOrInitListExpr(e, e->getInitExprs(),
+ e->getInitializedFieldInUnion(),
+ e->getArrayFiller());
}
+
void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *e,
llvm::Value *outerBegin = nullptr) {
cgf.cgm.errorNYI(e->getSourceRange(),
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 500007f..768d75d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2159,16 +2159,16 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,
// __imag on a scalar returns zero. Emit the subexpr to ensure side
// effects are evaluated, but not the actual value.
- if (op->isGLValue())
- cgf.emitLValue(op);
- else if (!promotionTy.isNull())
- cgf.emitPromotedScalarExpr(op, promotionTy);
- else
- cgf.emitScalarExpr(op);
-
- mlir::Type valueTy =
- cgf.convertType(promotionTy.isNull() ? e->getType() : promotionTy);
- return builder.getNullValue(valueTy, loc);
+ mlir::Value operand;
+ if (op->isGLValue()) {
+ operand = cgf.emitLValue(op).getPointer();
+ operand = cir::LoadOp::create(builder, loc, operand);
+ } else if (!promotionTy.isNull()) {
+ operand = cgf.emitPromotedScalarExpr(op, promotionTy);
+ } else {
+ operand = cgf.emitScalarExpr(op);
+ }
+ return builder.createComplexImag(loc, operand);
}
/// Return the size or alignment of the type of argument of the sizeof
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index fba094f..cdd4e3c 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2402,9 +2402,8 @@ OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
LogicalResult cir::ComplexRealOp::verify() {
mlir::Type operandTy = getOperand().getType();
- if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy)) {
+ if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
operandTy = complexOperandTy.getElementType();
- }
if (getType() != operandTy) {
emitOpError() << ": result type does not match operand type";
@@ -2431,14 +2430,22 @@ OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
//===----------------------------------------------------------------------===//
LogicalResult cir::ComplexImagOp::verify() {
- if (getType() != getOperand().getType().getElementType()) {
+ mlir::Type operandTy = getOperand().getType();
+ if (auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
+ operandTy = complexOperandTy.getElementType();
+
+ if (getType() != operandTy) {
emitOpError() << ": result type does not match operand type";
return failure();
}
+
return success();
}
OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
+ if (!mlir::isa<cir::ComplexType>(getOperand().getType()))
+ return nullptr;
+
if (auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
return complexCreateOp.getOperand(1);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index bfb1262..1ff8cc5 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -3061,8 +3061,19 @@ mlir::LogicalResult CIRToLLVMComplexImagOpLowering::matchAndRewrite(
cir::ComplexImagOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
- rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
- op, resultLLVMTy, adaptor.getOperand(), llvm::ArrayRef<std::int64_t>{1});
+ mlir::Value operand = adaptor.getOperand();
+ mlir::Location loc = op.getLoc();
+
+ if (mlir::isa<cir::ComplexType>(op.getOperand().getType())) {
+ operand = mlir::LLVM::ExtractValueOp::create(
+ rewriter, loc, resultLLVMTy, operand, llvm::ArrayRef<std::int64_t>{1});
+ } else {
+ mlir::TypedAttr zeroAttr = rewriter.getZeroAttr(resultLLVMTy);
+ operand =
+ mlir::LLVM::ConstantOp::create(rewriter, loc, resultLLVMTy, zeroAttr);
+ }
+
+ rewriter.replaceOp(op, operand);
return mlir::success();
}
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 9a61888..8ba23aa 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -1189,14 +1189,13 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
// parameter list of a synthesized CTAD guide. See also the FIXME in
// test/SemaCXX/cxx20-ctad-type-alias.cpp:test25.
Sema::CheckTemplateArgumentInfo CTAI;
+ for (auto TA : Output.arguments())
+ if (SemaRef.CheckTemplateArgument(
+ TP, TA, F, F->getLocation(), F->getLocation(),
+ /*ArgumentPackIndex=*/-1, CTAI,
+ Sema::CheckTemplateArgumentKind::CTAK_Specified))
+ return nullptr;
if (Input.getArgument().getKind() == TemplateArgument::Pack) {
- for (auto TA : Output.arguments()) {
- if (SemaRef.CheckTemplateArgument(
- TP, TA, F, F->getLocation(), F->getLocation(),
- /*ArgumentPackIndex=*/-1, CTAI,
- Sema::CheckTemplateArgumentKind::CTAK_Specified))
- return nullptr;
- }
// We will substitute the non-deduced template arguments with these
// transformed (unpacked at this point) arguments, where that substitution
// requires a pack for the corresponding parameter packs.
@@ -1204,12 +1203,6 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
TemplateArgument::CreatePackCopy(Context, CTAI.SugaredConverted);
} else {
assert(Output.arguments().size() == 1);
- TemplateArgumentLoc Transformed = Output.arguments()[0];
- if (SemaRef.CheckTemplateArgument(
- TP, Transformed, F, F->getLocation(), F->getLocation(),
- /*ArgumentPackIndex=*/-1, CTAI,
- Sema::CheckTemplateArgumentKind::CTAK_Specified))
- return nullptr;
TemplateArgsForBuildingFPrime[Index] = CTAI.SugaredConverted[0];
}
}
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index ae69b24..3524b8b 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -1160,8 +1160,9 @@ void imag_on_scalar_glvalue() {
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"]
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]
-// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
-// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
+// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.float>, !cir.float
+// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.float -> !cir.float
+// CIR: cir.store{{.*}} %[[A_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
// LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4
// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4
@@ -1205,9 +1206,10 @@ void imag_on_scalar_with_type_promotion() {
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["a"]
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.f16, !cir.ptr<!cir.f16>, ["b", init]
-// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
-// CIR: %[[CONST_ZERO_F16:.*]] = cir.cast floating %[[CONST_ZERO]] : !cir.float -> !cir.f16
-// CIR: cir.store{{.*}} %[[CONST_ZERO_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>
+// CIR: %[[TMP_A:.*]] = cir.load %[[A_ADDR]] : !cir.ptr<!cir.f16>, !cir.f16
+// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.f16 -> !cir.f16
+// CIR: %[[A_IMAG_F16:.*]] = cir.cast floating %[[A_IMAG]] : !cir.f16 -> !cir.f16
+// CIR: cir.store{{.*}} %[[A_IMAG_F16]], %[[B_ADDR]] : !cir.f16, !cir.ptr<!cir.f16>
// LLVM: %[[A_ADDR:.*]] = alloca half, i64 1, align 2
// LLVM: %[[B_ADDR:.*]] = alloca half, i64 1, align 2
@@ -1225,8 +1227,8 @@ void imag_on_const_scalar() {
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["a"]
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]
// CIR: %[[CONST_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
-// CIR: %[[CONST_ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.float
-// CIR: cir.store{{.*}} %[[CONST_ZERO]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
+// CIR: %[[CONST_IMAG:.*]] = cir.complex.imag %[[CONST_ONE]] : !cir.float -> !cir.float
+// CIR: cir.store{{.*}} %[[CONST_IMAG]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
// LLVM: %[[A_ADDR:.*]] = alloca float, i64 1, align 4
// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4
@@ -1311,3 +1313,49 @@ void real_on_scalar_from_imag_with_type_promotion() {
// OGCG: %[[A_IMAG_F32:.*]] = fpext half %[[A_IMAG]] to float
// OGCG: %[[A_IMAG_F16:.*]] = fptrunc float %[[A_IMAG_F32]] to half
// OGCG: store half %[[A_IMAG_F16]], ptr %[[B_ADDR]], align 2
+
+void complex_type_parameter(float _Complex a) {}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init]
+// CIR: cir.store %{{.*}}, %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+
+// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering,
+// Test will be updated when that is implemented
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: store { float, float } %{{.*}}, ptr %[[A_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: store <2 x float> %a.coerce, ptr %[[A_ADDR]], align 4
+
+void complex_type_argument() {
+ float _Complex a;
+ complex_type_parameter(a);
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
+// CIR: %[[ARG_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["coerce"]
+// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: cir.store{{.*}} %[[TMP_A]], %[[ARG_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR: %[[TMP_ARG:.*]] = cir.load{{.*}} %[[ARG_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: cir.call @_Z22complex_type_parameterCf(%[[TMP_ARG]]) : (!cir.complex<!cir.float>) -> ()
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: %[[ARG_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
+// LLVM: store { float, float } %[[TMP_A]], ptr %[[ARG_ADDR]], align 4
+// LLVM: %[[TMP_ARG:.*]] = load { float, float }, ptr %[[ARG_ADDR]], align 4
+// LLVM: call void @_Z22complex_type_parameterCf({ float, float } %[[TMP_ARG]])
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[ARG_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[ARG_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 0
+// OGCG: %[[ARG_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[ARG_ADDR]], i32 0, i32 1
+// OGCG: store float %[[A_REAL]], ptr %[[ARG_REAL_PTR]], align 4
+// OGCG: store float %[[A_IMAG]], ptr %[[ARG_IMAG_PTR]], align 4
+// OGCG: %[[TMP_ARG:.*]] = load <2 x float>, ptr %[[ARG_ADDR]], align 4
+// OGCG: call void @_Z22complex_type_parameterCf(<2 x float> noundef %[[TMP_ARG]])
diff --git a/clang/test/CIR/CodeGen/paren-init-list.cpp b/clang/test/CIR/CodeGen/paren-init-list.cpp
new file mode 100644
index 0000000..0efa363
--- /dev/null
+++ b/clang/test/CIR/CodeGen/paren-init-list.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+struct CompleteS {
+ int a;
+ char b;
+};
+
+void cxx_paren_list_init_expr() { CompleteS a(1, 'a'); }
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init]
+// CIR: %[[ELEM_0_PTR:.*]] = cir.get_member %[[A_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i>
+// CIR: %[[ELEM_0_VAL:.*]] = cir.const #cir.int<1> : !s32i
+// CIR: cir.store{{.*}} %[[ELEM_0_VAL]], %[[ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[ELEM_1_PTR:.*]] = cir.get_member %[[A_ADDR]][1] {name = "b"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s8i>
+// CIR: %[[ELEM_1_VAL:.*]] = cir.const #cir.int<97> : !s8i
+// CIR: cir.store{{.*}} %[[ELEM_1_VAL]], %[[ELEM_1_PTR]] : !s8i, !cir.ptr<!s8i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
+// LLVM: %[[ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0
+// LLVM: store i32 1, ptr %[[ELEM_0_PTR]], align 4
+// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1
+// LLVM: store i8 97, ptr %[[ELEM_1_PTR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4
+// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[A_ADDR]], ptr align 4 @__const._Z24cxx_paren_list_init_exprv.a, i64 8, i1 false)
diff --git a/clang/test/CIR/CodeGen/struct.cpp b/clang/test/CIR/CodeGen/struct.cpp
index 96db82a..c68f742 100644
--- a/clang/test/CIR/CodeGen/struct.cpp
+++ b/clang/test/CIR/CodeGen/struct.cpp
@@ -183,3 +183,67 @@ void generic_selection() {
// OGCG: %[[C_ADDR:.*]] = alloca i32, align 4
// OGCG: %[[D_ADDR:.*]] = alloca %struct.CompleteS, align 4
// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[D_ADDR]], ptr align 4 %[[A_ADDR]], i64 8, i1 false)
+
+void atomic_init() {
+ _Atomic CompleteS a;
+ __c11_atomic_init(&a, {});
+}
+
+// CIR: cir.func{{.*}} @_Z11atomic_initv()
+// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a"]
+// CIR: %[[ELEM_0_PTR:.*]] = cir.get_member %[[A_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i>
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i
+// CIR: cir.store{{.*}} %[[CONST_0]], %[[ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[ELEM_1_PTR:.*]] = cir.get_member %[[A_ADDR]][1] {name = "b"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s8i>
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s8i
+// CIR: cir.store{{.*}} %[[CONST_0]], %[[ELEM_1_PTR]] : !s8i, !cir.ptr<!s8i>
+
+// LLVM: define{{.*}} void @_Z11atomic_initv()
+// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 8
+// LLVM: %[[ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0
+// LLVM: store i32 0, ptr %[[ELEM_0_PTR]], align 8
+// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1
+// LLVM: store i8 0, ptr %[[ELEM_1_PTR]], align 4
+
+// OGCG: define{{.*}} void @_Z11atomic_initv()
+// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 8
+// OGCG: %[[ELEM_0_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: store i32 0, ptr %[[ELEM_0_PTR]], align 8
+// OGCG: %[[ELEM_1_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: store i8 0, ptr %[[ELEM_1_PTR]], align 4
+
+void unary_extension() {
+ CompleteS a = __extension__ CompleteS();
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init]
+// CIR: %[[ZERO_INIT:.*]] = cir.const #cir.zero : !rec_CompleteS
+// CIR: cir.store{{.*}} %[[ZERO_INIT]], %[[A_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS>
+
+// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
+// LLVM: store %struct.CompleteS zeroinitializer, ptr %[[A_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4
+// OGCG: call void @llvm.memset.p0.i64(ptr align 4 %[[A_ADDR]], i8 0, i64 8, i1 false)
+
+void bin_comma() {
+ CompleteS a = (CompleteS(), CompleteS());
+}
+
+// CIR: cir.func{{.*}} @_Z9bin_commav()
+// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init]
+// CIR: %[[TMP_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["agg.tmp0"]
+// CIR: %[[ZERO:.*]] = cir.const #cir.zero : !rec_CompleteS
+// CIR: cir.store{{.*}} %[[ZERO]], %[[TMP_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS>
+// CIR: %[[ZERO:.*]] = cir.const #cir.zero : !rec_CompleteS
+// CIR: cir.store{{.*}} %[[ZERO]], %[[A_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS>
+
+// LLVM: define{{.*}} void @_Z9bin_commav()
+// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
+// LLVM: %[[TMP_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
+// LLVM: store %struct.CompleteS zeroinitializer, ptr %[[TMP_ADDR]], align 4
+// LLVM: store %struct.CompleteS zeroinitializer, ptr %[[A_ADDR]], align 4
+
+// OGCG: define{{.*}} void @_Z9bin_commav()
+// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4
+// OGCG: call void @llvm.memset.p0.i64(ptr align 4 %[[A_ADDR]], i8 0, i64 8, i1 false)
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index 224263e..7c639ef 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -307,9 +307,9 @@ public:
bool Merge(const Message &);
bool operator==(const Message &that) const;
bool operator!=(const Message &that) const { return !(*this == that); }
+ bool AtSameLocation(const Message &) const;
private:
- bool AtSameLocation(const Message &) const;
std::variant<ProvenanceRange, CharBlock> location_;
std::variant<MessageFixedText, MessageFormattedText, MessageExpectedText>
text_;
diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp
index 8931cbe..647eebaaa0 100644
--- a/flang/lib/Evaluate/check-expression.cpp
+++ b/flang/lib/Evaluate/check-expression.cpp
@@ -135,16 +135,22 @@ bool IsConstantExprHelper<INVARIANT>::operator()(
} else if (proc.IsPure()) {
std::size_t j{0};
for (const auto &arg : call.arguments()) {
- if (const auto *dataDummy{j < proc.dummyArguments.size()
- ? std::get_if<characteristics::DummyDataObject>(
- &proc.dummyArguments[j].u)
- : nullptr};
- dataDummy &&
+ const auto *dataDummy{j < proc.dummyArguments.size()
+ ? std::get_if<characteristics::DummyDataObject>(
+ &proc.dummyArguments[j].u)
+ : nullptr};
+ if (dataDummy &&
dataDummy->attrs.test(
characteristics::DummyDataObject::Attr::OnlyIntrinsicInquiry)) {
// The value of the argument doesn't matter
} else if (!arg) {
- return false;
+ if (dataDummy &&
+ dataDummy->attrs.test(
+ characteristics::DummyDataObject::Attr::Optional)) {
+ // Missing optional arguments are okay.
+ } else {
+ return false;
+ }
} else if (const auto *expr{arg->UnwrapExpr()};
!expr || !(*this)(*expr)) {
return false;
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 2c4f930..cfcd08b 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -477,15 +477,31 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
}
std::stable_sort(sorted.begin(), sorted.end(),
[](const Message *x, const Message *y) { return x->SortBefore(*y); });
- const Message *lastMsg{nullptr};
+ std::vector<const Message *> msgsWithLastLocation;
std::size_t errorsEmitted{0};
for (const Message *msg : sorted) {
- if (lastMsg && *msg == *lastMsg) {
- // Don't emit two identical messages for the same location
+ bool shouldSkipMsg{false};
+ // Don't emit two identical messages for the same location.
+ // At the same location, messages are sorted by the order they were
+ // added to the Messages buffer, which is a decent proxy for the
+ // causality of the messages.
+ if (!msgsWithLastLocation.empty()) {
+ if (msgsWithLastLocation[0]->AtSameLocation(*msg)) {
+ for (const Message *msgAtThisLocation : msgsWithLastLocation) {
+ if (*msg == *msgAtThisLocation) {
+ shouldSkipMsg = true; // continue loop over sorted messages
+ break;
+ }
+ }
+ } else {
+ msgsWithLastLocation.clear();
+ }
+ }
+ if (shouldSkipMsg) {
continue;
}
+ msgsWithLastLocation.push_back(msg);
msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr);
- lastMsg = msg;
if (warningsAreErrors || msg->IsFatal()) {
++errorsEmitted;
}
diff --git a/flang/test/Semantics/associated.f90 b/flang/test/Semantics/associated.f90
index 7cb6c24..731f2d8 100644
--- a/flang/test/Semantics/associated.f90
+++ b/flang/test/Semantics/associated.f90
@@ -253,8 +253,6 @@ subroutine assoc()
lvar = associated(intPointerVar1, targetIntCoarray[1])
!ERROR: 'neverdeclared' is not a procedure
!ERROR: Could not characterize intrinsic function actual argument 'badpointer'
- !ERROR: 'neverdeclared' is not a procedure
- !ERROR: Could not characterize intrinsic function actual argument 'badpointer'
lvar = associated(badPointer)
end subroutine test
end subroutine assoc
diff --git a/flang/test/Semantics/intrinsics03.f90 b/flang/test/Semantics/intrinsics03.f90
index a5b13b6..1a42698 100644
--- a/flang/test/Semantics/intrinsics03.f90
+++ b/flang/test/Semantics/intrinsics03.f90
@@ -129,6 +129,6 @@ subroutine ichar_tests()
!Without -Wportability, the warning isn't emitted and the parameter is constant.
integer, parameter :: a2 = ichar('B ')
!ERROR: Character in intrinsic function ichar must have length one
- !ERROR: Must be a constant value
+ !ERROR: Value of named constant 'a3' (ichar("")) cannot be computed as a constant value
integer, parameter :: a3 = ichar('')
end subroutine
diff --git a/flang/test/Semantics/intrinsics04.f90 b/flang/test/Semantics/intrinsics04.f90
index abb8fe3..e733067 100644
--- a/flang/test/Semantics/intrinsics04.f90
+++ b/flang/test/Semantics/intrinsics04.f90
@@ -29,6 +29,6 @@ subroutine ichar_tests()
!WARNING: Character in intrinsic function ichar should have length one [-Wportability]
integer, parameter :: a2 = ichar('B ')
!ERROR: Character in intrinsic function ichar must have length one
- !ERROR: Must be a constant value
+ !ERROR: Value of named constant 'a3' (ichar("")) cannot be computed as a constant value
integer, parameter :: a3 = ichar('')
end subroutine
diff --git a/flang/test/Semantics/type-parameter-constant.f90 b/flang/test/Semantics/type-parameter-constant.f90
new file mode 100644
index 0000000..376bffd
--- /dev/null
+++ b/flang/test/Semantics/type-parameter-constant.f90
@@ -0,0 +1,15 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+type A (p, r)
+ integer, kind :: p, r
+ !ERROR: KIND parameter expression (int(selected_real_kind(six,twenty_three),kind=8)) of intrinsic type REAL did not resolve to a constant value
+ real (selected_real_kind(p, r)) :: data
+end type
+ integer :: six = 6, twenty_three = 23
+ type(a(6,23)) :: a1
+ !ERROR: Value of KIND type parameter 'p' must be constant
+ !ERROR: Value of KIND type parameter 'r' must be constant
+ !WARNING: specification expression refers to local object 'six' (initialized and saved) [-Wsaved-local-in-spec-expr]
+ !WARNING: specification expression refers to local object 'twenty_three' (initialized and saved) [-Wsaved-local-in-spec-expr]
+ type(a(six, twenty_three)) :: a2
+ print *, a1%data%kind
+end \ No newline at end of file
diff --git a/llvm/docs/ProgrammersManual.rst b/llvm/docs/ProgrammersManual.rst
index f2b3121..9cdac9c 100644
--- a/llvm/docs/ProgrammersManual.rst
+++ b/llvm/docs/ProgrammersManual.rst
@@ -463,7 +463,7 @@ recovery.
situations where you absolutely must emit a non-programmatic error and
the ``Error`` model isn't workable you can call ``reportFatalUsageError``,
which will call installed error handlers, print a message, and exit the
- program. The use of `reportFatalUsageError` in this case is discouraged.
+ program. The use of ``reportFatalUsageError`` in this case is discouraged.
Recoverable errors are modeled using LLVM's ``Error`` scheme. This scheme
represents errors using function return values, similar to classic C integer
@@ -579,7 +579,7 @@ This second form is often more readable for functions that involve multiple
If an ``Expected<T>`` value will be moved into an existing variable then the
``moveInto()`` method avoids the need to name an extra variable. This is
-useful to enable ``operator->()`` the ``Expected<T>`` value has pointer-like
+useful to enable ``operator->()`` if the ``Expected<T>`` value has pointer-like
semantics. For example:
.. code-block:: c++
@@ -957,7 +957,7 @@ Concatenating Errors with joinErrors
""""""""""""""""""""""""""""""""""""
In the archive walking example above, ``BadFileFormat`` errors are simply
-consumed and ignored. If the client had wanted report these errors after
+consumed and ignored. If the client had wanted to report these errors after
completing the walk over the archive they could use the ``joinErrors`` utility:
.. code-block:: c++
@@ -989,7 +989,7 @@ Building fallible iterators and iterator ranges
"""""""""""""""""""""""""""""""""""""""""""""""
The archive walking examples above retrieve archive members by index; however,
-this requires considerable boiler-plate for iteration and error checking. We can
+this requires considerable boilerplate for iteration and error checking. We can
clean this up by using the "fallible iterator" pattern, which supports the
following natural iteration idiom for fallible containers like Archive:
@@ -1039,7 +1039,7 @@ fallible_iterator utility which provides ``operator++`` and ``operator--``,
returning any errors via a reference passed in to the wrapper at construction
time. The fallible_iterator wrapper takes care of (a) jumping to the end of the
range on error, and (b) marking the error as checked whenever an iterator is
-compared to ``end`` and found to be inequal (in particular, this marks the
+compared to ``end`` and found to be unequal (in particular, this marks the
error as checked throughout the body of a range-based for loop), enabling early
exit from the loop without redundant error checking.
@@ -1452,7 +1452,7 @@ A more general utility is provided in `llvm/tools/reduce-chunk-list/reduce-chunk
How to use reduce-chunk-list:
First, Figure out the number of calls to the debug counter you want to minimize.
To do so, run the compilation command causing you want to minimize with `-print-debug-counter` adding a `-mllvm` if needed.
-Than find the line with the counter of interest. it should look like:
+Then find the line with the counter of interest. it should look like:
.. code-block:: none
@@ -1460,7 +1460,7 @@ Than find the line with the counter of interest. it should look like:
The number of calls to `my-counter` is 5678
-Than Find the minimum set of chunks that is interesting, with `reduce-chunk-list`.
+Then find the minimum set of chunks that is interesting, with `reduce-chunk-list`.
Build a reproducer script like:
.. code-block:: bash
@@ -1469,7 +1469,7 @@ Build a reproducer script like:
opt -debug-counter=my-counter=$1
# ... Test result of the command. Failure of the script is considered interesting
-Than run `reduce-chunk-list my-script.sh 0-5678 2>&1 | tee dump_bisect`
+Then run `reduce-chunk-list my-script.sh 0-5678 2>&1 | tee dump_bisect`
This command may take some time.
but when it is done, it will print the result like: `Minimal Chunks = 0:1:5:11-12:33-34`
@@ -1528,7 +1528,7 @@ LLVM has a plethora of data structures in the ``llvm/ADT/`` directory, and we
commonly use STL data structures. This section describes the trade-offs you
should consider when you pick one.
-The first step is a choose your own adventure: do you want a sequential
+The first step is to choose your own adventure: do you want a sequential
container, a set-like container, or a map-like container? The most important
thing when choosing a container is the algorithmic properties of how you plan to
access the container. Based on that, you should use:
diff --git a/llvm/include/llvm/ADT/BitmaskEnum.h b/llvm/include/llvm/ADT/BitmaskEnum.h
index 7214f25..d464cbc 100644
--- a/llvm/include/llvm/ADT/BitmaskEnum.h
+++ b/llvm/include/llvm/ADT/BitmaskEnum.h
@@ -14,6 +14,7 @@
#include <utility>
#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/bit.h"
#include "llvm/Support/MathExtras.h"
/// LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can
@@ -138,10 +139,6 @@ template <typename E> constexpr std::underlying_type_t<E> Underlying(E Val) {
return U;
}
-constexpr unsigned bitWidth(uint64_t Value) {
- return Value ? 1 + bitWidth(Value >> 1) : 0;
-}
-
template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
constexpr bool operator!(E Val) {
return Val == static_cast<E>(0);
@@ -220,7 +217,7 @@ e &operator>>=(e &lhs, e rhs) {
// Enable bitmask enums in namespace ::llvm and all nested namespaces.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
-constexpr unsigned BitWidth = BitmaskEnumDetail::bitWidth(
+constexpr unsigned BitWidth = llvm::bit_width_constexpr(
uint64_t{llvm::to_underlying(E::LLVM_BITMASK_LARGEST_ENUMERATOR)});
} // namespace llvm
diff --git a/llvm/include/llvm/ADT/PointerUnion.h b/llvm/include/llvm/ADT/PointerUnion.h
index ca0e1ed..7b66177 100644
--- a/llvm/include/llvm/ADT/PointerUnion.h
+++ b/llvm/include/llvm/ADT/PointerUnion.h
@@ -31,7 +31,7 @@ namespace pointer_union_detail {
/// Determine the number of bits required to store integers with values < n.
/// This is ceil(log2(n)).
constexpr int bitsRequired(unsigned n) {
- return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0;
+ return n == 0 ? 0 : llvm::bit_width_constexpr(n - 1);
}
template <typename... Ts> constexpr int lowBitsAvailable() {
diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h
index 67c0a1c..66c4f94 100644
--- a/llvm/include/llvm/ADT/bit.h
+++ b/llvm/include/llvm/ADT/bit.h
@@ -292,6 +292,23 @@ template <typename T> [[nodiscard]] int bit_width(T Value) {
return std::numeric_limits<T>::digits - llvm::countl_zero(Value);
}
+/// Returns the number of bits needed to represent Value if Value is nonzero.
+/// Returns 0 otherwise.
+///
+/// A constexpr version of bit_width.
+///
+/// Ex. bit_width_constexpr(5) == 3.
+template <typename T> [[nodiscard]] constexpr int bit_width_constexpr(T Value) {
+ static_assert(std::is_unsigned_v<T>,
+ "Only unsigned integral types are allowed.");
+ int Width = 0;
+ while (Value > 0) {
+ Value >>= 1;
+ ++Width;
+ }
+ return Width;
+}
+
/// Returns the largest integral power of two no greater than Value if Value is
/// nonzero. Returns 0 otherwise.
///
diff --git a/llvm/include/llvm/IR/ValueMap.h b/llvm/include/llvm/IR/ValueMap.h
index 97653c2..9ab7d8b 100644
--- a/llvm/include/llvm/IR/ValueMap.h
+++ b/llvm/include/llvm/IR/ValueMap.h
@@ -44,8 +44,8 @@ namespace llvm {
template <typename KeyT, typename ValueT, typename Config>
class ValueMapCallbackVH;
-template <typename DenseMapT, typename KeyT> class ValueMapIterator;
-template <typename DenseMapT, typename KeyT> class ValueMapConstIterator;
+template <typename DenseMapT, typename KeyT, bool IsConst>
+class ValueMapIteratorImpl;
/// This class defines the default behavior for configurable aspects of
/// ValueMap<>. User Configs should inherit from this class to be as compatible
@@ -132,8 +132,8 @@ public:
return Where->second.get();
}
- using iterator = ValueMapIterator<MapT, KeyT>;
- using const_iterator = ValueMapConstIterator<MapT, KeyT>;
+ using iterator = ValueMapIteratorImpl<MapT, KeyT, false>;
+ using const_iterator = ValueMapIteratorImpl<MapT, KeyT, true>;
inline iterator begin() { return iterator(Map.begin()); }
inline iterator end() { return iterator(Map.end()); }
@@ -318,8 +318,10 @@ struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config>> {
}
};
-template <typename DenseMapT, typename KeyT> class ValueMapIterator {
- using BaseT = typename DenseMapT::iterator;
+template <typename DenseMapT, typename KeyT, bool IsConst>
+class ValueMapIteratorImpl {
+ using BaseT = std::conditional_t<IsConst, typename DenseMapT::const_iterator,
+ typename DenseMapT::iterator>;
using ValueT = typename DenseMapT::mapped_type;
BaseT I;
@@ -331,14 +333,20 @@ public:
using pointer = value_type *;
using reference = value_type &;
- ValueMapIterator() : I() {}
- ValueMapIterator(BaseT I) : I(I) {}
+ ValueMapIteratorImpl() = default;
+ ValueMapIteratorImpl(BaseT I) : I(I) {}
+
+ // Allow conversion from iterator to const_iterator.
+ template <bool C = IsConst, typename = std::enable_if_t<C>>
+ ValueMapIteratorImpl(
+ const ValueMapIteratorImpl<DenseMapT, KeyT, false> &Other)
+ : I(Other.base()) {}
BaseT base() const { return I; }
struct ValueTypeProxy {
const KeyT first;
- ValueT &second;
+ std::conditional_t<IsConst, const ValueT &, ValueT &> second;
ValueTypeProxy *operator->() { return this; }
@@ -354,69 +362,25 @@ public:
ValueTypeProxy operator->() const { return operator*(); }
- bool operator==(const ValueMapIterator &RHS) const { return I == RHS.I; }
- bool operator!=(const ValueMapIterator &RHS) const { return I != RHS.I; }
+ bool operator==(const ValueMapIteratorImpl &RHS) const { return I == RHS.I; }
+ bool operator!=(const ValueMapIteratorImpl &RHS) const { return I != RHS.I; }
- inline ValueMapIterator &operator++() { // Preincrement
+ inline ValueMapIteratorImpl &operator++() { // Preincrement
++I;
return *this;
}
- ValueMapIterator operator++(int) { // Postincrement
- ValueMapIterator tmp = *this;
+ ValueMapIteratorImpl operator++(int) { // Postincrement
+ ValueMapIteratorImpl tmp = *this;
++*this;
return tmp;
}
};
-template <typename DenseMapT, typename KeyT> class ValueMapConstIterator {
- using BaseT = typename DenseMapT::const_iterator;
- using ValueT = typename DenseMapT::mapped_type;
-
- BaseT I;
-
-public:
- using iterator_category = std::forward_iterator_tag;
- using value_type = std::pair<KeyT, typename DenseMapT::mapped_type>;
- using difference_type = std::ptrdiff_t;
- using pointer = value_type *;
- using reference = value_type &;
-
- ValueMapConstIterator() : I() {}
- ValueMapConstIterator(BaseT I) : I(I) {}
- ValueMapConstIterator(ValueMapIterator<DenseMapT, KeyT> Other)
- : I(Other.base()) {}
-
- BaseT base() const { return I; }
+template <typename DenseMapT, typename KeyT>
+using ValueMapIterator = ValueMapIteratorImpl<DenseMapT, KeyT, false>;
- struct ValueTypeProxy {
- const KeyT first;
- const ValueT &second;
- ValueTypeProxy *operator->() { return this; }
- operator std::pair<KeyT, ValueT>() const {
- return std::make_pair(first, second);
- }
- };
-
- ValueTypeProxy operator*() const {
- ValueTypeProxy Result = {I->first.Unwrap(), I->second};
- return Result;
- }
-
- ValueTypeProxy operator->() const { return operator*(); }
-
- bool operator==(const ValueMapConstIterator &RHS) const { return I == RHS.I; }
- bool operator!=(const ValueMapConstIterator &RHS) const { return I != RHS.I; }
-
- inline ValueMapConstIterator &operator++() { // Preincrement
- ++I;
- return *this;
- }
- ValueMapConstIterator operator++(int) { // Postincrement
- ValueMapConstIterator tmp = *this;
- ++*this;
- return tmp;
- }
-};
+template <typename DenseMapT, typename KeyT>
+using ValueMapConstIterator = ValueMapIteratorImpl<DenseMapT, KeyT, true>;
} // end namespace llvm
diff --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h
index a08cc8f..94080e8 100644
--- a/llvm/include/llvm/Support/ScopedPrinter.h
+++ b/llvm/include/llvm/Support/ScopedPrinter.h
@@ -284,9 +284,11 @@ public:
startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
}
- template <typename... T> void printVersion(StringRef Label, T... Version) {
+ template <typename T, typename... TArgs>
+ void printVersion(StringRef Label, T MajorVersion, TArgs... MinorVersions) {
startLine() << Label << ": ";
- printVersionInternal(Version...);
+ getOStream() << MajorVersion;
+ ((getOStream() << '.' << MinorVersions), ...);
getOStream() << "\n";
}
@@ -454,16 +456,6 @@ public:
virtual raw_ostream &getOStream() { return OS; }
private:
- template <typename T> void printVersionInternal(T Value) {
- getOStream() << Value;
- }
-
- template <typename S, typename T, typename... TArgs>
- void printVersionInternal(S Value, T Value2, TArgs... Args) {
- getOStream() << Value << ".";
- printVersionInternal(Value2, Args...);
- }
-
static bool flagName(const FlagEntry &LHS, const FlagEntry &RHS) {
return LHS.Name < RHS.Name;
}
diff --git a/llvm/include/llvm/TableGen/CodeGenHelpers.h b/llvm/include/llvm/TableGen/CodeGenHelpers.h
new file mode 100644
index 0000000..7dca6a0
--- /dev/null
+++ b/llvm/include/llvm/TableGen/CodeGenHelpers.h
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines common utilities for generating C++ code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TABLEGEN_CODEGENHELPERS_H
+#define LLVM_TABLEGEN_CODEGENHELPERS_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace llvm {
+// Simple RAII helper for emitting ifdef-undef-endif scope.
+class IfDefEmitter {
+public:
+ IfDefEmitter(raw_ostream &OS, StringRef Name) : Name(Name.str()), OS(OS) {
+ OS << "#ifdef " << Name << "\n"
+ << "#undef " << Name << "\n\n";
+ }
+ ~IfDefEmitter() { OS << "\n#endif // " << Name << "\n\n"; }
+
+private:
+ std::string Name;
+ raw_ostream &OS;
+};
+
+// Simple RAII helper for emitting namespace scope. Name can be a single
+// namespace (empty for anonymous namespace) or nested namespace.
+class NamespaceEmitter {
+public:
+ NamespaceEmitter(raw_ostream &OS, StringRef Name) : OS(OS) {
+ emitNamespaceStarts(Name);
+ }
+
+ ~NamespaceEmitter() { close(); }
+
+ // Explicit function to close the namespace scopes.
+ void close() {
+ for (StringRef NS : llvm::reverse(Namespaces))
+ OS << "} // namespace " << NS << "\n";
+ Namespaces.clear();
+ }
+
+private:
+ void emitNamespaceStarts(StringRef Name) {
+ llvm::SplitString(Name, Namespaces, "::");
+ for (StringRef NS : Namespaces)
+ OS << "namespace " << NS << " {\n";
+ }
+
+ SmallVector<StringRef, 2> Namespaces;
+ raw_ostream &OS;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TABLEGEN_CODEGENHELPERS_H
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index efdbd12..447f05c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1417,9 +1417,9 @@ class SelectQCbi<CondCode Cond, DAGOperand InTyImm, Pseudo OpNode >
let Predicates = [HasVendorXqciac, IsRV32] in {
def : Pat<(i32 (add GPRNoX0:$rd, (mul GPRNoX0:$rs1, simm12_lo:$imm12))),
(QC_MULIADD GPRNoX0:$rd, GPRNoX0:$rs1, simm12_lo:$imm12)>;
-def : Pat<(i32 (add_like_non_imm12 (shl GPRNoX0:$rs1, uimm5gt3:$imm), GPRNoX0:$rs2)),
+def : Pat<(i32 (add_like_non_imm12 (shl GPRNoX0:$rs1, (i32 uimm5gt3:$imm)), GPRNoX0:$rs2)),
(QC_SHLADD GPRNoX0:$rs1, GPRNoX0:$rs2, uimm5gt3:$imm)>;
-def : Pat<(i32 (riscv_shl_add GPRNoX0:$rs1, uimm5gt3:$imm, GPRNoX0:$rs2)),
+def : Pat<(i32 (riscv_shl_add GPRNoX0:$rs1, (i32 uimm5gt3:$imm), GPRNoX0:$rs2)),
(QC_SHLADD GPRNoX0:$rs1, GPRNoX0:$rs2, uimm5gt3:$imm)>;
} // Predicates = [HasVendorXqciac, IsRV32]
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp
index cba282c..a2e8c69 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp
@@ -15,13 +15,12 @@
using namespace llvm;
-namespace {
/// Return true if and only if the given instruction does not modify the memory
/// location referenced. Note that an idemptent atomicrmw may still have
/// ordering effects on nearby instructions, or be volatile.
/// TODO: Common w/ the version in AtomicExpandPass, and change the term used.
/// Idemptotent is confusing in this context.
-bool isIdempotentRMW(AtomicRMWInst& RMWI) {
+static bool isIdempotentRMW(AtomicRMWInst &RMWI) {
if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
switch(RMWI.getOperation()) {
case AtomicRMWInst::FAdd: // -0.0
@@ -59,7 +58,7 @@ bool isIdempotentRMW(AtomicRMWInst& RMWI) {
/// Return true if the given instruction always produces a value in memory
/// equivalent to its value operand.
-bool isSaturating(AtomicRMWInst& RMWI) {
+static bool isSaturating(AtomicRMWInst &RMWI) {
if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
switch (RMWI.getOperation()) {
case AtomicRMWInst::FMax:
@@ -98,7 +97,6 @@ bool isSaturating(AtomicRMWInst& RMWI) {
return C->isMaxValue(false);
};
}
-} // namespace
Instruction *InstCombinerImpl::visitAtomicRMWInst(AtomicRMWInst &RMWI) {
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 917004c..048cdf4 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -132,8 +132,6 @@ STATISTIC(NumReassoc , "Number of reassociations");
DEBUG_COUNTER(VisitCounter, "instcombine-visit",
"Controls which instructions are visited");
-namespace llvm {
-
static cl::opt<bool> EnableCodeSinking("instcombine-code-sinking",
cl::desc("Enable code sinking"),
cl::init(true));
@@ -146,7 +144,9 @@ static cl::opt<unsigned>
MaxArraySize("instcombine-maxarray-size", cl::init(1024),
cl::desc("Maximum array size considered when doing a combine"));
+namespace llvm {
extern cl::opt<bool> ProfcheckDisableMetadataFixes;
+} // end namespace llvm
// FIXME: Remove this flag when it is no longer necessary to convert
// llvm.dbg.declare to avoid inaccurate debug info. Setting this to false
@@ -158,8 +158,6 @@ extern cl::opt<bool> ProfcheckDisableMetadataFixes;
static cl::opt<unsigned> ShouldLowerDbgDeclare("instcombine-lower-dbg-declare",
cl::Hidden, cl::init(true));
-} // end namespace llvm
-
std::optional<Instruction *>
InstCombiner::targetInstCombineIntrinsic(IntrinsicInst &II) {
// Handle target specific intrinsics
diff --git a/llvm/test/CodeGen/AMDGPU/wait-xcnt.mir b/llvm/test/CodeGen/AMDGPU/wait-xcnt.mir
index 6fe99d8..1b8e126 100644
--- a/llvm/test/CodeGen/AMDGPU/wait-xcnt.mir
+++ b/llvm/test/CodeGen/AMDGPU/wait-xcnt.mir
@@ -945,6 +945,46 @@ body: |
$vgpr0 = V_MOV_B32_e32 0, implicit $exec
...
+# FIXME: Missing S_WAIT_XCNT before overwriting vgpr0.
+---
+name: wait_kmcnt_with_outstanding_vmem_2
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+body: |
+ ; GCN-LABEL: name: wait_kmcnt_with_outstanding_vmem_2
+ ; GCN: bb.0:
+ ; GCN-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
+ ; GCN-NEXT: liveins: $vgpr0_vgpr1, $sgpr0_sgpr1, $scc
+ ; GCN-NEXT: {{ $}}
+ ; GCN-NEXT: $sgpr2 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 0, 0
+ ; GCN-NEXT: S_CBRANCH_SCC1 %bb.2, implicit $scc
+ ; GCN-NEXT: {{ $}}
+ ; GCN-NEXT: bb.1:
+ ; GCN-NEXT: successors: %bb.2(0x80000000)
+ ; GCN-NEXT: liveins: $vgpr0_vgpr1, $sgpr2
+ ; GCN-NEXT: {{ $}}
+ ; GCN-NEXT: $vgpr2 = GLOBAL_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec
+ ; GCN-NEXT: {{ $}}
+ ; GCN-NEXT: bb.2:
+ ; GCN-NEXT: liveins: $sgpr2
+ ; GCN-NEXT: {{ $}}
+ ; GCN-NEXT: S_WAIT_KMCNT 0
+ ; GCN-NEXT: $sgpr2 = S_MOV_B32 $sgpr2
+ ; GCN-NEXT: $vgpr0 = V_MOV_B32_e32 0, implicit $exec
+ bb.0:
+ liveins: $vgpr0_vgpr1, $sgpr0_sgpr1, $scc
+ $sgpr2 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 0, 0
+ S_CBRANCH_SCC1 %bb.2, implicit $scc
+ bb.1:
+ liveins: $vgpr0_vgpr1, $sgpr2
+ $vgpr2 = GLOBAL_LOAD_DWORD $vgpr0_vgpr1, 0, 0, implicit $exec
+ bb.2:
+ liveins: $sgpr2
+ $sgpr2 = S_MOV_B32 $sgpr2
+ $vgpr0 = V_MOV_B32_e32 0, implicit $exec
+...
+
---
name: wait_loadcnt_with_outstanding_smem
tracksRegLiveness: true
diff --git a/llvm/unittests/ADT/BitTest.cpp b/llvm/unittests/ADT/BitTest.cpp
index 88ae36c..eaed4e1 100644
--- a/llvm/unittests/ADT/BitTest.cpp
+++ b/llvm/unittests/ADT/BitTest.cpp
@@ -247,6 +247,29 @@ TEST(BitTest, BitWidth) {
EXPECT_EQ(64, llvm::bit_width(uint64_t(0xffffffffffffffffull)));
}
+TEST(BitTest, BitWidthConstexpr) {
+ static_assert(llvm::bit_width_constexpr(0u) == 0);
+ static_assert(llvm::bit_width_constexpr(1u) == 1);
+ static_assert(llvm::bit_width_constexpr(2u) == 2);
+ static_assert(llvm::bit_width_constexpr(3u) == 2);
+ static_assert(llvm::bit_width_constexpr(4u) == 3);
+ static_assert(llvm::bit_width_constexpr(5u) == 3);
+ static_assert(llvm::bit_width_constexpr(6u) == 3);
+ static_assert(llvm::bit_width_constexpr(7u) == 3);
+ static_assert(llvm::bit_width_constexpr(8u) == 4);
+
+ static_assert(llvm::bit_width_constexpr(255u) == 8);
+ static_assert(llvm::bit_width_constexpr(256u) == 9);
+ static_assert(llvm::bit_width_constexpr(257u) == 9);
+
+ static_assert(
+ llvm::bit_width_constexpr(std::numeric_limits<uint16_t>::max()) == 16);
+ static_assert(
+ llvm::bit_width_constexpr(std::numeric_limits<uint32_t>::max()) == 32);
+ static_assert(
+ llvm::bit_width_constexpr(std::numeric_limits<uint64_t>::max()) == 64);
+}
+
TEST(BitTest, CountlZero) {
uint8_t Z8 = 0;
uint16_t Z16 = 0;
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index f0e2369..b4d816e 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/TableGen/CodeGenHelpers.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
@@ -30,26 +31,10 @@
using namespace llvm;
namespace {
-// Simple RAII helper for defining ifdef-undef-endif scopes.
-class IfDefScope {
-public:
- IfDefScope(StringRef Name, raw_ostream &OS) : Name(Name), OS(OS) {
- OS << "#ifdef " << Name << "\n"
- << "#undef " << Name << "\n";
- }
-
- ~IfDefScope() { OS << "\n#endif // " << Name << "\n\n"; }
-
-private:
- StringRef Name;
- raw_ostream &OS;
-};
-} // namespace
-
-namespace {
enum class Frontend { LLVM, Flang, Clang };
+} // namespace
-StringRef getFESpelling(Frontend FE) {
+static StringRef getFESpelling(Frontend FE) {
switch (FE) {
case Frontend::LLVM:
return "llvm";
@@ -60,7 +45,6 @@ StringRef getFESpelling(Frontend FE) {
}
llvm_unreachable("unknown FE kind");
}
-} // namespace
// Get the full namespace qualifier for the directive language.
static std::string getQualifier(const DirectiveLanguage &DirLang,
@@ -297,13 +281,8 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "#include <cstddef>\n"; // for size_t
OS << "#include <utility>\n"; // for std::pair
OS << "\n";
- OS << "namespace llvm {\n";
-
- // Open namespaces defined in the directive language
- SmallVector<StringRef, 2> Namespaces;
- SplitString(DirLang.getCppNamespace(), Namespaces, "::");
- for (auto Ns : Namespaces)
- OS << "namespace " << Ns << " {\n";
+ NamespaceEmitter LlvmNS(OS, "llvm");
+ NamespaceEmitter DirLangNS(OS, DirLang.getCppNamespace());
if (DirLang.hasEnableBitmaskEnumInNamespace())
OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n";
@@ -380,9 +359,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "\n";
}
- // Closing namespaces
- for (auto Ns : reverse(Namespaces))
- OS << "} // namespace " << Ns << "\n";
+ DirLangNS.close();
// These specializations need to be in ::llvm.
for (StringRef Enum : {"Association", "Category", "Directive", "Clause"}) {
@@ -392,9 +369,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << " static constexpr bool is_iterable = true;\n";
OS << "};\n";
}
-
- OS << "} // namespace llvm\n";
-
+ LlvmNS.close();
OS << "#endif // LLVM_" << Lang << "_INC\n";
}
@@ -971,11 +946,10 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
std::string IfDefName{"GEN_"};
IfDefName += getFESpelling(FE).upper();
IfDefName += "_DIRECTIVE_CLAUSE_SETS";
- IfDefScope Scope(IfDefName, OS);
+ IfDefEmitter Scope(OS, IfDefName);
StringRef Namespace =
getFESpelling(FE == Frontend::Flang ? Frontend::LLVM : FE);
- OS << "\n";
// The namespace has to be different for clang vs flang, as 2 structs with the
// same name but different layout is UB. So just put the 'clang' on in the
// clang namespace.
@@ -1016,9 +990,8 @@ static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
std::string IfDefName{"GEN_"};
IfDefName += getFESpelling(FE).upper();
IfDefName += "_DIRECTIVE_CLAUSE_MAP";
- IfDefScope Scope(IfDefName, OS);
+ IfDefEmitter Scope(OS, IfDefName);
- OS << "\n";
OS << "{\n";
// The namespace has to be different for clang vs flang, as 2 structs with the
@@ -1062,9 +1035,7 @@ static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
static void generateFlangClauseParserClass(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
- IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES", OS);
-
- OS << "\n";
+ IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_PARSER_CLASSES");
for (const Clause Clause : DirLang.getClauses()) {
if (!Clause.getFlangClass().empty()) {
@@ -1089,9 +1060,8 @@ static void generateFlangClauseParserClass(const DirectiveLanguage &DirLang,
static void generateFlangClauseParserClassList(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
- IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST", OS);
+ IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST");
- OS << "\n";
interleaveComma(DirLang.getClauses(), OS, [&](const Record *C) {
Clause Clause(C);
OS << Clause.getFormattedParserClassName() << "\n";
@@ -1102,9 +1072,8 @@ static void generateFlangClauseParserClassList(const DirectiveLanguage &DirLang,
static void generateFlangClauseDump(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
- IfDefScope Scope("GEN_FLANG_DUMP_PARSE_TREE_CLAUSES", OS);
+ IfDefEmitter Scope(OS, "GEN_FLANG_DUMP_PARSE_TREE_CLAUSES");
- OS << "\n";
for (const Clause Clause : DirLang.getClauses()) {
OS << "NODE(" << DirLang.getFlangClauseBaseClass() << ", "
<< Clause.getFormattedParserClassName() << ")\n";
@@ -1116,10 +1085,9 @@ static void generateFlangClauseDump(const DirectiveLanguage &DirLang,
static void generateFlangClauseUnparse(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
- IfDefScope Scope("GEN_FLANG_CLAUSE_UNPARSE", OS);
+ IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_UNPARSE");
StringRef Base = DirLang.getFlangClauseBaseClass();
- OS << "\n";
for (const Clause Clause : DirLang.getClauses()) {
if (Clause.skipFlangUnparser())
@@ -1172,9 +1140,8 @@ static void generateFlangClauseUnparse(const DirectiveLanguage &DirLang,
static void generateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
- IfDefScope Scope("GEN_FLANG_CLAUSE_CHECK_ENTER", OS);
+ IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_CHECK_ENTER");
- OS << "\n";
for (const Clause Clause : DirLang.getClauses()) {
OS << "void Enter(const parser::" << DirLang.getFlangClauseBaseClass()
<< "::" << Clause.getFormattedParserClassName() << " &);\n";
@@ -1186,12 +1153,11 @@ static void generateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang,
static void generateFlangClauseParserKindMap(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
- IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_KIND_MAP", OS);
+ IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_PARSER_KIND_MAP");
StringRef Prefix = DirLang.getClausePrefix();
std::string Qual = getQualifier(DirLang);
- OS << "\n";
for (const Record *R : DirLang.getClauses()) {
Clause C(R);
OS << "if constexpr (std::is_same_v<A, parser::"
@@ -1216,11 +1182,10 @@ static void generateFlangClausesParser(const DirectiveLanguage &DirLang,
llvm::sort(Names, [](const auto &A, const auto &B) {
return A.second.Name > B.second.Name;
});
- IfDefScope Scope("GEN_FLANG_CLAUSES_PARSER", OS);
+ IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSES_PARSER");
StringRef Base = DirLang.getFlangClauseBaseClass();
unsigned LastIndex = Names.size() - 1;
- OS << "\n";
OS << "TYPE_PARSER(\n";
for (auto [Index, RecSp] : llvm::enumerate(Names)) {
auto [R, S] = RecSp;
@@ -1313,10 +1278,9 @@ static void emitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
static void generateClauseClassMacro(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
// Generate macros style information for legacy code in clang
- IfDefScope Scope("GEN_CLANG_CLAUSE_CLASS", OS);
+ IfDefEmitter Scope(OS, "GEN_CLANG_CLAUSE_CLASS");
StringRef Prefix = DirLang.getClausePrefix();
- OS << "\n";
OS << "#ifndef CLAUSE\n";
OS << "#define CLAUSE(Enum, Str, Implicit)\n";
@@ -1375,12 +1339,11 @@ static void generateClauseClassMacro(const DirectiveLanguage &DirLang,
// language. This code can be included in library.
void emitDirectivesBasicImpl(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
- IfDefScope Scope("GEN_DIRECTIVES_IMPL", OS);
+ IfDefEmitter Scope(OS, "GEN_DIRECTIVES_IMPL");
StringRef DPrefix = DirLang.getDirectivePrefix();
StringRef CPrefix = DirLang.getClausePrefix();
- OS << "\n";
OS << "#include \"llvm/Frontend/Directive/Spelling.h\"\n";
OS << "#include \"llvm/Support/ErrorHandling.h\"\n";
OS << "#include <utility>\n";
diff --git a/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp
index 6b723bc..e2b5241 100644
--- a/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "TargetFeaturesEmitter.h"
+#include "llvm/TableGen/CodeGenHelpers.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/TargetParser/SubtargetFeature.h"
@@ -43,7 +44,7 @@ FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) {
PrintFatalError(
"Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
- OS << "namespace " << Target << " {\n";
+ NamespaceEmitter NS(OS, Target);
OS << "enum {\n";
@@ -58,9 +59,8 @@ FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) {
OS << " " << "NumSubtargetFeatures = " << N << "\n";
- // Close enumeration and namespace
+ // Close enumeration.
OS << "};\n";
- OS << "} // end namespace " << Target << "\n";
return FeatureMap;
}
@@ -149,25 +149,23 @@ void TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS,
void TargetFeaturesEmitter::run(raw_ostream &OS) {
OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n";
- OS << "\n#ifdef GET_SUBTARGETFEATURES_ENUM\n";
- OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n";
-
- OS << "namespace llvm {\n";
- auto FeatureMap = enumeration(OS);
- OS << "} // end namespace llvm\n\n";
- OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n";
+ FeatureMapTy FeatureMap;
+ {
+ IfDefEmitter IfDef(OS, "GET_SUBTARGETFEATURES_ENUM");
+ NamespaceEmitter NS(OS, "llvm");
+ FeatureMap = enumeration(OS);
+ }
- OS << "\n#ifdef GET_SUBTARGETFEATURES_KV\n";
- OS << "#undef GET_SUBTARGETFEATURES_KV\n\n";
+ {
+ IfDefEmitter IfDef(OS, "GET_SUBTARGETFEATURES_KV");
+ NamespaceEmitter NS(OS, "llvm");
- OS << "namespace llvm {\n";
- printFeatureKeyValues(OS, FeatureMap);
- OS << "\n";
+ printFeatureKeyValues(OS, FeatureMap);
+ OS << "\n";
- printCPUKeyValues(OS, FeatureMap);
- OS << "\n";
- OS << "} // end namespace llvm\n\n";
- OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n";
+ printCPUKeyValues(OS, FeatureMap);
+ OS << "\n";
+ }
}
static TableGen::Emitter::OptClass<TargetFeaturesEmitter>
diff --git a/llvm/utils/TableGen/CompressInstEmitter.cpp b/llvm/utils/TableGen/CompressInstEmitter.cpp
index ccf8385..d8c5ca7 100644
--- a/llvm/utils/TableGen/CompressInstEmitter.cpp
+++ b/llvm/utils/TableGen/CompressInstEmitter.cpp
@@ -167,7 +167,7 @@ bool CompressInstEmitter::validateRegister(const Record *Reg,
assert(RegClass->isSubClassOf("RegisterClass") &&
"RegClass record should be a RegisterClass");
const CodeGenRegisterClass &RC = Target.getRegisterClass(RegClass);
- const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower());
+ const CodeGenRegister *R = Target.getRegBank().getReg(Reg);
assert(R != nullptr && "Register not defined!!");
return RC.contains(R);
}
diff --git a/llvm/utils/profcheck-xfail.txt b/llvm/utils/profcheck-xfail.txt
index 13121bd7..53187c8 100644
--- a/llvm/utils/profcheck-xfail.txt
+++ b/llvm/utils/profcheck-xfail.txt
@@ -108,7 +108,6 @@ Instrumentation/AddressSanitizer/AMDGPU/global_metadata_addrspacecasts.ll
Instrumentation/AddressSanitizer/AMDGPU/instrument-stack.ll
Instrumentation/AddressSanitizer/AMDGPU/no_redzones_in_lds_globals.ll
Instrumentation/AddressSanitizer/AMDGPU/no_redzones_in_scratch_globals.ll
-Instrumentation/AddressSanitizer/RISCV/asan-rvv-intrinsics.ll
Instrumentation/AddressSanitizer/asan_address_space_attr.ll
Instrumentation/AddressSanitizer/asan-detect-invalid-pointer-pair.ll
Instrumentation/AddressSanitizer/asan-disable-sanitizer-instrumentation.ll
@@ -194,6 +193,7 @@ Instrumentation/AddressSanitizer/odr-check-ignore.ll
Instrumentation/AddressSanitizer/program-addrspace.ll
Instrumentation/AddressSanitizer/ps4.ll
Instrumentation/AddressSanitizer/remove-memory-effects.ll
+Instrumentation/AddressSanitizer/RISCV/asan-rvv-intrinsics.ll
Instrumentation/AddressSanitizer/scale-offset.ll
Instrumentation/AddressSanitizer/skip-coro.ll
Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll
@@ -781,8 +781,8 @@ Transforms/GlobalOpt/shrink-global-to-bool-check-debug.ll
Transforms/GlobalOpt/shrink-global-to-bool-opaque-ptrs.ll
Transforms/GVN/debugloc-load-select.ll
Transforms/GVN/load-through-select-dbg.ll
-Transforms/GVN/masked-load-store-no-mem-dep.ll
Transforms/GVN/masked-load-store.ll
+Transforms/GVN/masked-load-store-no-mem-dep.ll
Transforms/GVN/opaque-ptr.ll
Transforms/GVN/pr69301.ll
Transforms/GVN/pre-invalid-prof-metadata.ll
@@ -1297,9 +1297,9 @@ Transforms/OpenMP/spmdization_remarks.ll
Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll
Transforms/PGOProfile/chr-dead-pred.ll
Transforms/PGOProfile/chr-dup-threshold.ll
+Transforms/PGOProfile/chr-lifetimes.ll
Transforms/PGOProfile/chr.ll
Transforms/PGOProfile/chr-poison.ll
-Transforms/PGOProfile/chr-lifetimes.ll
Transforms/PGOProfile/comdat.ll
Transforms/PGOProfile/cspgo_profile_summary.ll
Transforms/PGOProfile/memop_profile_funclet_wasm.ll
@@ -1432,10 +1432,10 @@ Transforms/SimplifyCFG/switch-dup-bbs.ll
Transforms/SimplifyCFG/switch_mask.ll
Transforms/SimplifyCFG/switch_msan.ll
Transforms/SimplifyCFG/switch-on-const-select.ll
-Transforms/SimplifyCFG/switch-transformations-no-lut.ll
Transforms/SimplifyCFG/switchToSelect-domtree-preservation-edgecase.ll
Transforms/SimplifyCFG/switch-to-select-multiple-edge-per-block-phi.ll
Transforms/SimplifyCFG/switch-to-select-two-case.ll
+Transforms/SimplifyCFG/switch-transformations-no-lut.ll
Transforms/SimplifyCFG/wc-widen-block.ll
Transforms/SimplifyCFG/X86/disable-lookup-table.ll
Transforms/SimplifyCFG/X86/hoist-loads-stores-with-cf.ll
@@ -1530,8 +1530,8 @@ Transforms/SROA/select-load.ll
Transforms/SROA/slice-width.ll
Transforms/SROA/std-clamp.ll
Transforms/SROA/vector-conversion.ll
-Transforms/SROA/vector-promotion.ll
Transforms/SROA/vector-promotion-cannot-tree-structure-merge.ll
+Transforms/SROA/vector-promotion.ll
Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll
Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll
Transforms/StructurizeCFG/hoist-zerocost.ll
diff --git a/mlir/include/mlir/TableGen/CodeGenHelpers.h b/mlir/include/mlir/TableGen/CodeGenHelpers.h
index cf14f65..252da21 100644
--- a/mlir/include/mlir/TableGen/CodeGenHelpers.h
+++ b/mlir/include/mlir/TableGen/CodeGenHelpers.h
@@ -1,3 +1,4 @@
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -20,6 +21,8 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/TableGen/CodeGenHelpers.h"
+#include <utility>
namespace llvm {
class RecordKeeper;
@@ -36,46 +39,17 @@ std::string strfmt(const char *fmt, Parameters &&...parameters) {
return llvm::formatv(fmt, std::forward<Parameters>(parameters)...).str();
}
-// Simple RAII helper for defining ifdef-undef-endif scopes.
-class IfDefScope {
-public:
- IfDefScope(llvm::StringRef name, llvm::raw_ostream &os)
- : name(name.str()), os(os) {
- os << "#ifdef " << name << "\n"
- << "#undef " << name << "\n\n";
- }
- ~IfDefScope() { os << "\n#endif // " << name << "\n\n"; }
-
-private:
- std::string name;
- llvm::raw_ostream &os;
-};
-
-// A helper RAII class to emit nested namespaces for this op.
-class NamespaceEmitter {
+// A helper RAII class to emit nested namespaces for a dialect.
+class DialectNamespaceEmitter {
public:
- NamespaceEmitter(raw_ostream &os, const Dialect &dialect) : os(os) {
+ DialectNamespaceEmitter(raw_ostream &os, const Dialect &dialect) {
if (!dialect)
return;
- emitNamespaceStarts(os, dialect.getCppNamespace());
- }
- NamespaceEmitter(raw_ostream &os, StringRef cppNamespace) : os(os) {
- emitNamespaceStarts(os, cppNamespace);
- }
-
- ~NamespaceEmitter() {
- for (StringRef ns : llvm::reverse(namespaces))
- os << "} // namespace " << ns << "\n";
+ nsEmitter.emplace(os, dialect.getCppNamespace());
}
private:
- void emitNamespaceStarts(raw_ostream &os, StringRef cppNamespace) {
- llvm::SplitString(cppNamespace, namespaces, "::");
- for (StringRef ns : namespaces)
- os << "namespace " << ns << " {\n";
- }
- raw_ostream &os;
- SmallVector<StringRef, 2> namespaces;
+ std::optional<llvm::NamespaceEmitter> nsEmitter;
};
/// This class deduplicates shared operation verification code by emitting
diff --git a/mlir/include/mlir/TableGen/Dialect.h b/mlir/include/mlir/TableGen/Dialect.h
index ea8f405..37c6427a 100644
--- a/mlir/include/mlir/TableGen/Dialect.h
+++ b/mlir/include/mlir/TableGen/Dialect.h
@@ -107,6 +107,7 @@ public:
// Returns whether the dialect is defined.
explicit operator bool() const { return def != nullptr; }
+ bool isDefined() const { return def != nullptr; }
private:
const llvm::Record *def;
diff --git a/mlir/lib/TableGen/CodeGenHelpers.cpp b/mlir/lib/TableGen/CodeGenHelpers.cpp
index 2c119fd..cb90ef8 100644
--- a/mlir/lib/TableGen/CodeGenHelpers.cpp
+++ b/mlir/lib/TableGen/CodeGenHelpers.cpp
@@ -16,6 +16,7 @@
#include "mlir/TableGen/Pattern.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
+#include "llvm/TableGen/CodeGenHelpers.h"
#include "llvm/TableGen/Record.h"
using namespace llvm;
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
index b911565..06ef396 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
@@ -10,12 +10,12 @@
#include "CppGenUtilities.h"
#include "mlir/TableGen/AttrOrTypeDef.h"
#include "mlir/TableGen/Class.h"
-#include "mlir/TableGen/CodeGenHelpers.h"
#include "mlir/TableGen/Format.h"
#include "mlir/TableGen/GenInfo.h"
#include "mlir/TableGen/Interfaces.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/TableGen/CodeGenHelpers.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/TableGenBackend.h"
@@ -71,14 +71,14 @@ public:
void emitDecl(raw_ostream &os) const {
if (storageCls && def.genStorageClass()) {
- NamespaceEmitter ns(os, def.getStorageNamespace());
+ llvm::NamespaceEmitter ns(os, def.getStorageNamespace());
os << "struct " << def.getStorageClassName() << ";\n";
}
defCls.writeDeclTo(os);
}
void emitDef(raw_ostream &os) const {
if (storageCls && def.genStorageClass()) {
- NamespaceEmitter ns(os, def.getStorageNamespace());
+ llvm::NamespaceEmitter ns(os, def.getStorageNamespace());
storageCls->writeDeclTo(os); // everything is inline
}
defCls.writeDefTo(os);
@@ -850,7 +850,7 @@ class AsmPrinter;
bool DefGenerator::emitDecls(StringRef selectedDialect) {
emitSourceFileHeader((defType + "Def Declarations").str(), os);
- IfDefScope scope("GET_" + defType.upper() + "DEF_CLASSES", os);
+ llvm::IfDefEmitter scope(os, "GET_" + defType.upper() + "DEF_CLASSES");
// Output the common "header".
os << typeDefDeclHeader;
@@ -860,7 +860,7 @@ bool DefGenerator::emitDecls(StringRef selectedDialect) {
if (defs.empty())
return false;
{
- NamespaceEmitter nsEmitter(os, defs.front().getDialect());
+ DialectNamespaceEmitter nsEmitter(os, defs.front().getDialect());
// Declare all the def classes first (in case they reference each other).
for (const AttrOrTypeDef &def : defs) {
@@ -892,7 +892,7 @@ bool DefGenerator::emitDecls(StringRef selectedDialect) {
//===----------------------------------------------------------------------===//
void DefGenerator::emitTypeDefList(ArrayRef<AttrOrTypeDef> defs) {
- IfDefScope scope("GET_" + defType.upper() + "DEF_LIST", os);
+ llvm::IfDefEmitter scope(os, "GET_" + defType.upper() + "DEF_LIST");
auto interleaveFn = [&](const AttrOrTypeDef &def) {
os << def.getDialect().getCppNamespace() << "::" << def.getCppClassName();
};
@@ -1083,11 +1083,11 @@ bool DefGenerator::emitDefs(StringRef selectedDialect) {
return false;
emitTypeDefList(defs);
- IfDefScope scope("GET_" + defType.upper() + "DEF_CLASSES", os);
+ llvm::IfDefEmitter scope(os, "GET_" + defType.upper() + "DEF_CLASSES");
emitParsePrintDispatch(defs);
for (const AttrOrTypeDef &def : defs) {
{
- NamespaceEmitter ns(os, def.getDialect());
+ DialectNamespaceEmitter ns(os, def.getDialect());
DefGen gen(def);
gen.emitDef(os);
}
@@ -1102,7 +1102,7 @@ bool DefGenerator::emitDefs(StringRef selectedDialect) {
// Emit the default parser/printer for Attributes if the dialect asked for it.
if (isAttrGenerator && firstDialect.useDefaultAttributePrinterParser()) {
- NamespaceEmitter nsEmitter(os, firstDialect);
+ DialectNamespaceEmitter nsEmitter(os, firstDialect);
if (firstDialect.isExtensible()) {
os << llvm::formatv(dialectDefaultAttrPrinterParserDispatch,
firstDialect.getCppClassName(),
@@ -1116,7 +1116,7 @@ bool DefGenerator::emitDefs(StringRef selectedDialect) {
// Emit the default parser/printer for Types if the dialect asked for it.
if (!isAttrGenerator && firstDialect.useDefaultTypePrinterParser()) {
- NamespaceEmitter nsEmitter(os, firstDialect);
+ DialectNamespaceEmitter nsEmitter(os, firstDialect);
if (firstDialect.isExtensible()) {
os << llvm::formatv(dialectDefaultTypePrinterParserDispatch,
firstDialect.getCppClassName(),
diff --git a/mlir/tools/mlir-tblgen/DialectGen.cpp b/mlir/tools/mlir-tblgen/DialectGen.cpp
index 02941ec..2e8810d 100644
--- a/mlir/tools/mlir-tblgen/DialectGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectGen.cpp
@@ -242,7 +242,7 @@ static const char *const discardableAttrHelperDecl = R"(
static void emitDialectDecl(Dialect &dialect, raw_ostream &os) {
// Emit all nested namespaces.
{
- NamespaceEmitter nsEmitter(os, dialect);
+ DialectNamespaceEmitter nsEmitter(os, dialect);
// Emit the start of the decl.
std::string cppName = dialect.getCppClassName();
@@ -358,7 +358,7 @@ static void emitDialectDef(Dialect &dialect, const RecordKeeper &records,
<< "::" << cppClassName << ")\n";
// Emit all nested namespaces.
- NamespaceEmitter nsEmitter(os, dialect);
+ DialectNamespaceEmitter nsEmitter(os, dialect);
/// Build the list of dependent dialects.
std::string dependentDialectRegistrations;
diff --git a/mlir/tools/mlir-tblgen/OmpOpGen.cpp b/mlir/tools/mlir-tblgen/OmpOpGen.cpp
index 91bc61b..e1be11a 100644
--- a/mlir/tools/mlir-tblgen/OmpOpGen.cpp
+++ b/mlir/tools/mlir-tblgen/OmpOpGen.cpp
@@ -342,7 +342,7 @@ static bool verifyDecls(const RecordKeeper &records, raw_ostream &) {
/// structures according to the `clauses` argument of each definition deriving
/// from `OpenMP_Op`.
static bool genClauseOps(const RecordKeeper &records, raw_ostream &os) {
- mlir::tblgen::NamespaceEmitter ns(os, "mlir::omp");
+ llvm::NamespaceEmitter ns(os, "mlir::omp");
for (const Record *clause : records.getAllDerivedDefinitions("OpenMP_Clause"))
genClauseOpsStruct(clause, os);
diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
index 7e8e559..c3420d4 100644
--- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
@@ -36,6 +36,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/CodeGenHelpers.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
@@ -4855,7 +4856,7 @@ static void emitOpClassDecls(const RecordKeeper &records,
}
// Emit the op class declarations.
- IfDefScope scope("GET_OP_CLASSES", os);
+ IfDefEmitter scope(os, "GET_OP_CLASSES");
if (defs.empty())
return;
StaticVerifierFunctionEmitter staticVerifierEmitter(os, records);
@@ -4898,7 +4899,7 @@ static bool emitOpDecls(const RecordKeeper &records, raw_ostream &os) {
return false;
Dialect dialect = Operator(defs.front()).getDialect();
- NamespaceEmitter ns(os, dialect);
+ DialectNamespaceEmitter ns(os, dialect);
const char *const opRegistrationHook =
"void register{0}Operations{1}({2}::{0} *dialect);\n";
@@ -4921,7 +4922,7 @@ static void emitOpDefShard(const RecordKeeper &records,
std::string shardGuard = "GET_OP_DEFS_";
std::string indexStr = std::to_string(shardIndex);
shardGuard += indexStr;
- IfDefScope scope(shardGuard, os);
+ IfDefEmitter scope(os, shardGuard);
// Emit the op registration hook in the first shard.
const char *const opRegistrationHook =
@@ -4962,14 +4963,14 @@ static bool emitOpDefs(const RecordKeeper &records, raw_ostream &os) {
// If no shard was requested, emit the regular op list and class definitions.
if (shardedDefs.size() == 1) {
{
- IfDefScope scope("GET_OP_LIST", os);
+ IfDefEmitter scope(os, "GET_OP_LIST");
interleave(
defs, os,
[&](const Record *def) { os << Operator(def).getQualCppClassName(); },
",\n");
}
{
- IfDefScope scope("GET_OP_CLASSES", os);
+ IfDefEmitter scope(os, "GET_OP_CLASSES");
emitOpClassDefs(records, defs, os);
}
return false;
diff --git a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
index 41ffdfc..3ead2f0 100644
--- a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
+++ b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
@@ -50,7 +50,6 @@ using mlir::tblgen::EnumCase;
using mlir::tblgen::EnumInfo;
using mlir::tblgen::NamedAttribute;
using mlir::tblgen::NamedTypeConstraint;
-using mlir::tblgen::NamespaceEmitter;
using mlir::tblgen::Operator;
//===----------------------------------------------------------------------===//
@@ -261,7 +260,7 @@ static void emitInterfaceDecl(const Availability &availability,
std::string(formatv("{0}Traits", interfaceName));
StringRef cppNamespace = availability.getInterfaceClassNamespace();
- NamespaceEmitter nsEmitter(os, cppNamespace);
+ llvm::NamespaceEmitter nsEmitter(os, cppNamespace);
os << "class " << interfaceName << ";\n\n";
// Emit the traits struct containing the concept and model declarations.