Skip to content

Commit 8109f29

Browse files
ashermancinellivar-const
authored andcommitted
[flang] Handle volatility in lowering and codegen (llvm#135311)
* Enable lowering and conversion patterns to pass volatility information from higher level operations to lower level ones. * Enable codegen to pass volatility to LLVM dialect ops by setting an attribute on loads, stores, and memory intrinsics. * Add utilities for passing along the volatility from an input type to an output type. To introduce volatile types into the IR, entities with the volatile attribute will be given a volatile type in the bridge; this is not enabled in this patch. User code should not result in IR with volatile types yet, so this patch contains no tests with Fortran source, only IR that already contains volatile types. Part 3 of llvm#132486.
1 parent 14cd832 commit 8109f29

File tree

18 files changed

+674
-67
lines changed

18 files changed

+674
-67
lines changed

flang/include/flang/Optimizer/Builder/BoxValue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ class AbstractIrBox : public AbstractBox, public AbstractArrayBox {
236236
auto ty = getBoxTy().getEleTy();
237237
if (fir::isa_ref_type(ty))
238238
return ty;
239-
return fir::ReferenceType::get(ty);
239+
return fir::ReferenceType::get(ty, fir::isa_volatile_type(ty));
240240
}
241241

242242
/// Get the scalar type related to the described entity

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,10 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
402402
mlir::Value createConvertWithVolatileCast(mlir::Location loc, mlir::Type toTy,
403403
mlir::Value val);
404404

405+
/// Cast \p value to have \p isVolatile volatility.
406+
mlir::Value createVolatileCast(mlir::Location loc, bool isVolatile,
407+
mlir::Value value);
408+
405409
/// Create a fir.store of \p val into \p addr. A lazy conversion
406410
/// of \p val to the element type of \p addr is created if needed.
407411
void createStoreWithConvert(mlir::Location loc, mlir::Value val,

flang/lib/Lower/ConvertCall.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,6 @@ Fortran::lower::genCallOpAndResult(
327327
charFuncPointerLength = charBox->getLen();
328328
}
329329
}
330-
331330
const bool isExprCall =
332331
converter.getLoweringOptions().getLowerToHighLevelFIR() &&
333332
callSiteType.getNumResults() == 1 &&
@@ -519,7 +518,9 @@ Fortran::lower::genCallOpAndResult(
519518
// Do not attempt any reboxing here that could break this.
520519
bool legacyLowering =
521520
!converter.getLoweringOptions().getLowerToHighLevelFIR();
522-
cast = builder.convertWithSemantics(loc, snd, fst,
521+
bool isVolatile = fir::isa_volatile_type(snd);
522+
cast = builder.createVolatileCast(loc, isVolatile, fst);
523+
cast = builder.convertWithSemantics(loc, snd, cast,
523524
callingImplicitInterface,
524525
/*allowRebox=*/legacyLowering);
525526
}
@@ -1415,6 +1416,11 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
14151416
addr = hlfir::genVariableRawAddress(loc, builder, entity);
14161417
}
14171418

1419+
// If the volatility of the input type does not match the dummy type,
1420+
// we need to cast the argument.
1421+
const bool isToTypeVolatile = fir::isa_volatile_type(dummyTypeWithActualRank);
1422+
addr = builder.createVolatileCast(loc, isToTypeVolatile, addr);
1423+
14181424
// For ranked actual passed to assumed-rank dummy, the cast to assumed-rank
14191425
// box is inserted when building the fir.call op. Inserting it here would
14201426
// cause the fir.if results to be assumed-rank in case of OPTIONAL dummy,

flang/lib/Lower/ConvertExprToHLFIR.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,19 +212,25 @@ class HlfirDesignatorBuilder {
212212
auto charType = mlir::dyn_cast<fir::CharacterType>(resultValueType);
213213
if (charType && charType.hasDynamicLen())
214214
return fir::BoxCharType::get(charType.getContext(), charType.getFKind());
215+
216+
// When volatile is enabled, enable volatility on the designatory type.
217+
const bool isVolatile = false;
218+
215219
// Arrays with non default lower bounds or dynamic length or dynamic extent
216220
// need a fir.box to hold the dynamic or lower bound information.
217221
if (fir::hasDynamicSize(resultValueType) ||
218222
mayHaveNonDefaultLowerBounds(partInfo))
219-
return fir::BoxType::get(resultValueType);
223+
return fir::BoxType::get(resultValueType, isVolatile);
224+
220225
// Non simply contiguous ref require a fir.box to carry the byte stride.
221226
if (mlir::isa<fir::SequenceType>(resultValueType) &&
222227
!Fortran::evaluate::IsSimplyContiguous(
223228
designatorNode, getConverter().getFoldingContext(),
224229
/*namedConstantSectionsAreAlwaysContiguous=*/false))
225-
return fir::BoxType::get(resultValueType);
230+
return fir::BoxType::get(resultValueType, isVolatile);
231+
226232
// Other designators can be handled as raw addresses.
227-
return fir::ReferenceType::get(resultValueType);
233+
return fir::ReferenceType::get(resultValueType, isVolatile);
228234
}
229235

230236
template <typename T>
@@ -1824,7 +1830,10 @@ class HlfirBuilder {
18241830
assert(compType && "failed to retrieve component type");
18251831
mlir::Value compShape =
18261832
designatorBuilder.genComponentShape(sym, compType);
1827-
mlir::Type designatorType = builder.getRefType(compType);
1833+
const bool isDesignatorVolatile =
1834+
fir::isa_volatile_type(baseOp.getType());
1835+
mlir::Type designatorType =
1836+
builder.getRefType(compType, isDesignatorVolatile);
18281837

18291838
mlir::Type fieldElemType = hlfir::getFortranElementType(compType);
18301839
llvm::SmallVector<mlir::Value, 1> typeParams;

flang/lib/Lower/HostAssociations.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ class CapturedProcedure : public CapturedSymbols<CapturedProcedure> {
194194
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
195195
mlir::Type typeInTuple = fir::dyn_cast_ptrEleTy(args.addrInTuple.getType());
196196
assert(typeInTuple && "addrInTuple must be an address");
197-
mlir::Value castBox = builder.createConvert(args.loc, typeInTuple,
198-
fir::getBase(args.hostValue));
197+
mlir::Value castBox = builder.createConvertWithVolatileCast(
198+
args.loc, typeInTuple, fir::getBase(args.hostValue));
199199
builder.create<fir::StoreOp>(args.loc, castBox, args.addrInTuple);
200200
}
201201

@@ -265,8 +265,8 @@ class CapturedPolymorphicScalar
265265
mlir::Location loc = args.loc;
266266
mlir::Type typeInTuple = fir::dyn_cast_ptrEleTy(args.addrInTuple.getType());
267267
assert(typeInTuple && "addrInTuple must be an address");
268-
mlir::Value castBox = builder.createConvert(args.loc, typeInTuple,
269-
fir::getBase(args.hostValue));
268+
mlir::Value castBox = builder.createConvertWithVolatileCast(
269+
args.loc, typeInTuple, fir::getBase(args.hostValue));
270270
if (Fortran::semantics::IsOptional(sym)) {
271271
auto isPresent =
272272
builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), castBox);
@@ -329,8 +329,8 @@ class CapturedAllocatableAndPointer
329329
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
330330
mlir::Type typeInTuple = fir::dyn_cast_ptrEleTy(args.addrInTuple.getType());
331331
assert(typeInTuple && "addrInTuple must be an address");
332-
mlir::Value castBox = builder.createConvert(args.loc, typeInTuple,
333-
fir::getBase(args.hostValue));
332+
mlir::Value castBox = builder.createConvertWithVolatileCast(
333+
args.loc, typeInTuple, fir::getBase(args.hostValue));
334334
builder.create<fir::StoreOp>(args.loc, castBox, args.addrInTuple);
335335
}
336336
static void getFromTuple(const GetFromTuple &args,

flang/lib/Lower/IO.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,8 @@ static void genOutputItemList(
720720
fir::factory::CharacterExprHelper helper{builder, loc};
721721
if (mlir::isa<fir::BoxType>(argType)) {
722722
mlir::Value box = fir::getBase(converter.genExprBox(loc, *expr, stmtCtx));
723-
outputFuncArgs.push_back(builder.createConvert(loc, argType, box));
723+
outputFuncArgs.push_back(
724+
builder.createConvertWithVolatileCast(loc, argType, box));
724725
if (containsDerivedType(itemTy))
725726
outputFuncArgs.push_back(getNonTbpDefinedIoTableAddr(converter));
726727
} else if (helper.isCharacterScalar(itemTy)) {
@@ -730,9 +731,9 @@ static void genOutputItemList(
730731
if (!exv.getCharBox())
731732
llvm::report_fatal_error(
732733
"internal error: scalar character not in CharBox");
733-
outputFuncArgs.push_back(builder.createConvert(
734+
outputFuncArgs.push_back(builder.createConvertWithVolatileCast(
734735
loc, outputFunc.getFunctionType().getInput(1), fir::getBase(exv)));
735-
outputFuncArgs.push_back(builder.createConvert(
736+
outputFuncArgs.push_back(builder.createConvertWithVolatileCast(
736737
loc, outputFunc.getFunctionType().getInput(2), fir::getLen(exv)));
737738
} else {
738739
fir::ExtendedValue itemBox = converter.genExprValue(loc, expr, stmtCtx);
@@ -743,7 +744,8 @@ static void genOutputItemList(
743744
outputFuncArgs.push_back(parts.first);
744745
outputFuncArgs.push_back(parts.second);
745746
} else {
746-
itemValue = builder.createConvert(loc, argType, itemValue);
747+
itemValue =
748+
builder.createConvertWithVolatileCast(loc, argType, itemValue);
747749
outputFuncArgs.push_back(itemValue);
748750
}
749751
}
@@ -827,7 +829,8 @@ createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter,
827829
mlir::Value box = fir::getBase(item);
828830
auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(box.getType());
829831
assert(boxTy && "must be previously emboxed");
830-
inputFuncArgs.push_back(builder.createConvert(loc, argType, box));
832+
auto casted = builder.createConvertWithVolatileCast(loc, argType, box);
833+
inputFuncArgs.push_back(casted);
831834
if (containsDerivedType(boxTy))
832835
inputFuncArgs.push_back(getNonTbpDefinedIoTableAddr(converter));
833836
} else {

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -577,14 +577,20 @@ mlir::Value fir::FirOpBuilder::convertWithSemantics(
577577
return createConvert(loc, toTy, val);
578578
}
579579

580+
mlir::Value fir::FirOpBuilder::createVolatileCast(mlir::Location loc,
581+
bool isVolatile,
582+
mlir::Value val) {
583+
mlir::Type volatileAdjustedType =
584+
fir::updateTypeWithVolatility(val.getType(), isVolatile);
585+
if (volatileAdjustedType == val.getType())
586+
return val;
587+
return create<fir::VolatileCastOp>(loc, volatileAdjustedType, val);
588+
}
589+
580590
mlir::Value fir::FirOpBuilder::createConvertWithVolatileCast(mlir::Location loc,
581591
mlir::Type toTy,
582592
mlir::Value val) {
583-
if (fir::isa_volatile_type(val.getType()) != fir::isa_volatile_type(toTy)) {
584-
mlir::Type volatileAdjustedType = fir::updateTypeWithVolatility(
585-
val.getType(), fir::isa_volatile_type(toTy));
586-
val = create<fir::VolatileCastOp>(loc, volatileAdjustedType, val);
587-
}
593+
val = createVolatileCast(loc, fir::isa_volatile_type(toTy), val);
588594
return createConvert(loc, toTy, val);
589595
}
590596

flang/lib/Optimizer/Builder/HLFIRTools.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,9 @@ hlfir::Entity hlfir::genVariableBox(mlir::Location loc,
382382
mlir::Value addr = var.getBase();
383383
if (mlir::isa<fir::BoxCharType>(var.getType()))
384384
addr = genVariableRawAddress(loc, builder, var);
385-
mlir::Type boxType = fir::BoxType::get(var.getElementOrSequenceType());
385+
const bool isVolatile = fir::isa_volatile_type(var.getType());
386+
mlir::Type boxType =
387+
fir::BoxType::get(var.getElementOrSequenceType(), isVolatile);
386388
if (forceBoxType) {
387389
boxType = forceBoxType;
388390
mlir::Type baseType =
@@ -793,15 +795,16 @@ mlir::Type hlfir::getVariableElementType(hlfir::Entity variable) {
793795
if (variable.isScalar())
794796
return variable.getType();
795797
mlir::Type eleTy = variable.getFortranElementType();
798+
const bool isVolatile = fir::isa_volatile_type(variable.getType());
796799
if (variable.isPolymorphic())
797-
return fir::ClassType::get(eleTy);
800+
return fir::ClassType::get(eleTy, isVolatile);
798801
if (auto charType = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
799802
if (charType.hasDynamicLen())
800803
return fir::BoxCharType::get(charType.getContext(), charType.getFKind());
801804
} else if (fir::isRecordWithTypeParameters(eleTy)) {
802-
return fir::BoxType::get(eleTy);
805+
return fir::BoxType::get(eleTy, isVolatile);
803806
}
804-
return fir::ReferenceType::get(eleTy);
807+
return fir::ReferenceType::get(eleTy, isVolatile);
805808
}
806809

807810
mlir::Type hlfir::getEntityElementType(hlfir::Entity entity) {

flang/lib/Optimizer/Builder/MutableBox.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ createNewFirBox(fir::FirOpBuilder &builder, mlir::Location loc,
7676
cleanedLengths = lengths;
7777
}
7878
mlir::Value emptySlice;
79-
return builder.create<fir::EmboxOp>(loc, box.getBoxTy(), cleanedAddr, shape,
79+
auto boxType = fir::updateTypeWithVolatility(
80+
box.getBoxTy(), fir::isa_volatile_type(cleanedAddr.getType()));
81+
return builder.create<fir::EmboxOp>(loc, boxType, cleanedAddr, shape,
8082
emptySlice, cleanedLengths, tdesc);
8183
}
8284

@@ -281,6 +283,9 @@ class MutablePropertyWriter {
281283
unsigned allocator = kDefaultAllocator) {
282284
mlir::Value irBox = createNewFirBox(builder, loc, box, addr, lbounds,
283285
extents, lengths, tdesc);
286+
const bool valueTypeIsVolatile =
287+
fir::isa_volatile_type(fir::unwrapRefType(box.getAddr().getType()));
288+
irBox = builder.createVolatileCast(loc, valueTypeIsVolatile, irBox);
284289
builder.create<fir::StoreOp>(loc, irBox, box.getAddr());
285290
}
286291

@@ -346,7 +351,8 @@ mlir::Value fir::factory::createUnallocatedBox(
346351
baseBoxType = baseBoxType.getBoxTypeWithNewShape(/*rank=*/0);
347352
auto baseAddrType = baseBoxType.getEleTy();
348353
if (!fir::isa_ref_type(baseAddrType))
349-
baseAddrType = builder.getRefType(baseAddrType);
354+
baseAddrType =
355+
builder.getRefType(baseAddrType, fir::isa_volatile_type(baseBoxType));
350356
auto type = fir::unwrapRefType(baseAddrType);
351357
auto eleTy = fir::unwrapSequenceType(type);
352358
if (auto recTy = mlir::dyn_cast<fir::RecordType>(eleTy))
@@ -516,7 +522,7 @@ void fir::factory::associateMutableBox(fir::FirOpBuilder &builder,
516522
source.match(
517523
[&](const fir::PolymorphicValue &p) {
518524
mlir::Value sourceBox;
519-
if (auto polyBox = source.getBoxOf<fir::PolymorphicValue>())
525+
if (auto *polyBox = source.getBoxOf<fir::PolymorphicValue>())
520526
sourceBox = polyBox->getSourceBox();
521527
writer.updateMutableBox(p.getAddr(), /*lbounds=*/std::nullopt,
522528
/*extents=*/std::nullopt,

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,20 @@ struct CmpcOpConversion : public fir::FIROpConversion<fir::CmpcOp> {
689689
}
690690
};
691691

692+
/// fir.volatile_cast is only useful at the fir level. Once we lower to LLVM,
693+
/// volatility is described by setting volatile attributes on the LLVM ops.
694+
struct VolatileCastOpConversion
695+
: public fir::FIROpConversion<fir::VolatileCastOp> {
696+
using FIROpConversion::FIROpConversion;
697+
698+
llvm::LogicalResult
699+
matchAndRewrite(fir::VolatileCastOp volatileCast, OpAdaptor adaptor,
700+
mlir::ConversionPatternRewriter &rewriter) const override {
701+
rewriter.replaceOp(volatileCast, adaptor.getOperands()[0]);
702+
return mlir::success();
703+
}
704+
};
705+
692706
/// convert value of from-type to value of to-type
693707
struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
694708
using FIROpConversion::FIROpConversion;
@@ -3224,6 +3238,7 @@ struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> {
32243238
mlir::ConversionPatternRewriter &rewriter) const override {
32253239

32263240
mlir::Type llvmLoadTy = convertObjectType(load.getType());
3241+
const bool isVolatile = fir::isa_volatile_type(load.getMemref().getType());
32273242
if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(load.getType())) {
32283243
// fir.box is a special case because it is considered an ssa value in
32293244
// fir, but it is lowered as a pointer to a descriptor. So
@@ -3253,16 +3268,17 @@ struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> {
32533268
mlir::Value boxSize =
32543269
computeBoxSize(loc, boxTypePair, inputBoxStorage, rewriter);
32553270
auto memcpy = rewriter.create<mlir::LLVM::MemcpyOp>(
3256-
loc, newBoxStorage, inputBoxStorage, boxSize, /*isVolatile=*/false);
3271+
loc, newBoxStorage, inputBoxStorage, boxSize, isVolatile);
32573272

32583273
if (std::optional<mlir::ArrayAttr> optionalTag = load.getTbaa())
32593274
memcpy.setTBAATags(*optionalTag);
32603275
else
32613276
attachTBAATag(memcpy, boxTy, boxTy, nullptr);
32623277
rewriter.replaceOp(load, newBoxStorage);
32633278
} else {
3264-
auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(
3279+
mlir::LLVM::LoadOp loadOp = rewriter.create<mlir::LLVM::LoadOp>(
32653280
load.getLoc(), llvmLoadTy, adaptor.getOperands(), load->getAttrs());
3281+
loadOp.setVolatile_(isVolatile);
32663282
if (std::optional<mlir::ArrayAttr> optionalTag = load.getTbaa())
32673283
loadOp.setTBAATags(*optionalTag);
32683284
else
@@ -3540,17 +3556,22 @@ struct StoreOpConversion : public fir::FIROpConversion<fir::StoreOp> {
35403556
mlir::Value llvmValue = adaptor.getValue();
35413557
mlir::Value llvmMemref = adaptor.getMemref();
35423558
mlir::LLVM::AliasAnalysisOpInterface newOp;
3559+
const bool isVolatile = fir::isa_volatile_type(store.getMemref().getType());
35433560
if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(storeTy)) {
35443561
mlir::Type llvmBoxTy = lowerTy().convertBoxTypeAsStruct(boxTy);
35453562
// Always use memcpy because LLVM is not as effective at optimizing
35463563
// aggregate loads/stores as it is optimizing memcpy.
35473564
TypePair boxTypePair{boxTy, llvmBoxTy};
35483565
mlir::Value boxSize =
35493566
computeBoxSize(loc, boxTypePair, llvmValue, rewriter);
3550-
newOp = rewriter.create<mlir::LLVM::MemcpyOp>(
3551-
loc, llvmMemref, llvmValue, boxSize, /*isVolatile=*/false);
3567+
newOp = rewriter.create<mlir::LLVM::MemcpyOp>(loc, llvmMemref, llvmValue,
3568+
boxSize, isVolatile);
35523569
} else {
3553-
newOp = rewriter.create<mlir::LLVM::StoreOp>(loc, llvmValue, llvmMemref);
3570+
mlir::LLVM::StoreOp storeOp =
3571+
rewriter.create<mlir::LLVM::StoreOp>(loc, llvmValue, llvmMemref);
3572+
if (isVolatile)
3573+
storeOp.setVolatile_(true);
3574+
newOp = storeOp;
35543575
}
35553576
if (std::optional<mlir::ArrayAttr> optionalTag = store.getTbaa())
35563577
newOp.setTBAATags(*optionalTag);
@@ -4193,21 +4214,22 @@ void fir::populateFIRToLLVMConversionPatterns(
41934214
BoxIsAllocOpConversion, BoxIsArrayOpConversion, BoxIsPtrOpConversion,
41944215
BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion,
41954216
BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion,
4196-
CmpcOpConversion, ConvertOpConversion, CoordinateOpConversion,
4197-
CopyOpConversion, DTEntryOpConversion, DeclareOpConversion,
4198-
DivcOpConversion, EmboxOpConversion, EmboxCharOpConversion,
4199-
EmboxProcOpConversion, ExtractValueOpConversion, FieldIndexOpConversion,
4200-
FirEndOpConversion, FreeMemOpConversion, GlobalLenOpConversion,
4201-
GlobalOpConversion, InsertOnRangeOpConversion, IsPresentOpConversion,
4202-
LenParamIndexOpConversion, LoadOpConversion, MulcOpConversion,
4203-
NegcOpConversion, NoReassocOpConversion, SelectCaseOpConversion,
4204-
SelectOpConversion, SelectRankOpConversion, SelectTypeOpConversion,
4205-
ShapeOpConversion, ShapeShiftOpConversion, ShiftOpConversion,
4206-
SliceOpConversion, StoreOpConversion, StringLitOpConversion,
4207-
SubcOpConversion, TypeDescOpConversion, TypeInfoOpConversion,
4208-
UnboxCharOpConversion, UnboxProcOpConversion, UndefOpConversion,
4209-
UnreachableOpConversion, XArrayCoorOpConversion, XEmboxOpConversion,
4210-
XReboxOpConversion, ZeroOpConversion>(converter, options);
4217+
CmpcOpConversion, VolatileCastOpConversion, ConvertOpConversion,
4218+
CoordinateOpConversion, CopyOpConversion, DTEntryOpConversion,
4219+
DeclareOpConversion, DivcOpConversion, EmboxOpConversion,
4220+
EmboxCharOpConversion, EmboxProcOpConversion, ExtractValueOpConversion,
4221+
FieldIndexOpConversion, FirEndOpConversion, FreeMemOpConversion,
4222+
GlobalLenOpConversion, GlobalOpConversion, InsertOnRangeOpConversion,
4223+
IsPresentOpConversion, LenParamIndexOpConversion, LoadOpConversion,
4224+
MulcOpConversion, NegcOpConversion, NoReassocOpConversion,
4225+
SelectCaseOpConversion, SelectOpConversion, SelectRankOpConversion,
4226+
SelectTypeOpConversion, ShapeOpConversion, ShapeShiftOpConversion,
4227+
ShiftOpConversion, SliceOpConversion, StoreOpConversion,
4228+
StringLitOpConversion, SubcOpConversion, TypeDescOpConversion,
4229+
TypeInfoOpConversion, UnboxCharOpConversion, UnboxProcOpConversion,
4230+
UndefOpConversion, UnreachableOpConversion, XArrayCoorOpConversion,
4231+
XEmboxOpConversion, XReboxOpConversion, ZeroOpConversion>(converter,
4232+
options);
42114233

42124234
// Patterns that are populated without a type converter do not trigger
42134235
// target materializations for the operands of the root op.

0 commit comments

Comments
 (0)