[RFC] Don't use llvm.experimental intrinsics

We currently have a convention where new intrinsics are sometimes (but not always) added with a name like llvm.experimental.foo. I’d like to propose that we stop doing that, and instead add an appropriate warning box in LangRef that indicates the intrinsic is experimental.

The problem I have with “experimental” intrinsics, is that most of them are immediately or very quickly used in the default production pipeline, produced either by Clang or LLVM. As such, they need to be held to essentially the same standard as non-experimental intrinsics, which includes auto-upgrade support for any changes to their design.

The signature of intrinsics can always be changed as long as auto-upgrade is implemented for the change. This is also true for non-experimental intrinsics, including heavily used ones.

To me it seems like having the llvm.experimental prefix just results in intrinsics remaining “experimental” a lot longer than is really sensible, because nobody wants to deal with the necessary churn of performing the rename.

I do think it would be good to indicate the status of intrinsics somehow, but I think just adding a LangRef warning would be sufficient for that. Especially as this allows us to add more useful information than a single bit:

This intrinsic is experimental, because full optimization support is not implemented yet. Prefer using the IR expansion for now.

This intrinsic is experimental, because it’s not supported across all targets yet.

This intrinsic is experimental, because there are still some open questions around its design.

10 Likes

Sounds good to me! Looks like there are quite a few that would need updating though:

llvm/include/llvm/IR/Intrinsics.td
908:// 'llvm.experimental.noalias.scope.decl' intrinsic: Inserted at the location of
914:def int_experimental_noalias_scope_decl
1025:def int_experimental_memset_pattern
1173:  def int_experimental_constrained_fadd : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1178:  def int_experimental_constrained_fsub : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1183:  def int_experimental_constrained_fmul : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1188:  def int_experimental_constrained_fdiv : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1193:  def int_experimental_constrained_frem : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1199:  def int_experimental_constrained_fma : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1206:  def int_experimental_constrained_fmuladd : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1213:  def int_experimental_constrained_fptosi : DefaultAttrsIntrinsic<[ llvm_anyint_ty ],
1217:  def int_experimental_constrained_fptoui : DefaultAttrsIntrinsic<[ llvm_anyint_ty ],
1221:  def int_experimental_constrained_sitofp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1226:  def int_experimental_constrained_uitofp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1231:  def int_experimental_constrained_fptrunc : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1236:  def int_experimental_constrained_fpext : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1244:  def int_experimental_constrained_sqrt : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1248:  def int_experimental_constrained_powi : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1253:  def int_experimental_constrained_ldexp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1258:  def int_experimental_constrained_asin  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1262:  def int_experimental_constrained_acos  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1266:  def int_experimental_constrained_atan  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1270:  def int_experimental_constrained_atan2 : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1275:  def int_experimental_constrained_sin  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1279:  def int_experimental_constrained_cos  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1283:  def int_experimental_constrained_tan  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1287:  def int_experimental_constrained_sinh  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1291:  def int_experimental_constrained_cosh  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1295:  def int_experimental_constrained_tanh  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1299:  def int_experimental_constrained_pow  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1304:  def int_experimental_constrained_log  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1308:  def int_experimental_constrained_log10: DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1312:  def int_experimental_constrained_log2 : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1316:  def int_experimental_constrained_exp  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1320:  def int_experimental_constrained_exp2 : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1324:  def int_experimental_constrained_rint  : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1328:  def int_experimental_constrained_nearbyint : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1332:  def int_experimental_constrained_lrint : DefaultAttrsIntrinsic<[ llvm_anyint_ty ],
1336:  def int_experimental_constrained_llrint : DefaultAttrsIntrinsic<[ llvm_anyint_ty ],
1340:  def int_experimental_constrained_maxnum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1344:  def int_experimental_constrained_minnum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1348:  def int_experimental_constrained_maximum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1352:  def int_experimental_constrained_minimum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1356:  def int_experimental_constrained_ceil : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1359:  def int_experimental_constrained_floor : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1362:  def int_experimental_constrained_lround : DefaultAttrsIntrinsic<[ llvm_anyint_ty ],
1365:  def int_experimental_constrained_llround : DefaultAttrsIntrinsic<[ llvm_anyint_ty ],
1368:  def int_experimental_constrained_round : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1371:  def int_experimental_constrained_roundeven : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1374:  def int_experimental_constrained_trunc : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ],
1380:  def int_experimental_constrained_fcmp
1384:  def int_experimental_constrained_fcmps
1662:// Note that it is still experimental, which means that its semantics
1675:def int_experimental_stackmap : DefaultAttrsIntrinsic<[],
1678:def int_experimental_patchpoint_void : Intrinsic<[],
1685:def int_experimental_patchpoint : Intrinsic<[llvm_any_ty],
1697:def int_experimental_gc_statepoint : Intrinsic<[llvm_token_ty],
1705:def int_experimental_gc_result : DefaultAttrsIntrinsic<
1708:def int_experimental_gc_relocate : DefaultAttrsIntrinsic<
1712:def int_experimental_gc_get_pointer_base : DefaultAttrsIntrinsic<
1716:def int_experimental_gc_get_pointer_offset : DefaultAttrsIntrinsic<
1836:def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty],
1840:def int_experimental_guard : Intrinsic<[], [llvm_i1_ty, llvm_vararg_ty],
1844:def int_experimental_widenable_condition : DefaultAttrsIntrinsic<[llvm_i1_ty], [],
1932:def int_experimental_vp_strided_store : DefaultAttrsIntrinsic<[],
1940:def int_experimental_vp_strided_load  : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
1948:def int_experimental_vector_histogram_add : DefaultAttrsIntrinsic<[],
1955:def int_experimental_vector_match : DefaultAttrsIntrinsic<
1963:def int_experimental_vector_extract_last_active:
2391:def int_experimental_get_vector_length:
2397:def int_experimental_cttz_elts:
2402:def int_experimental_vp_splice:
2411:def int_experimental_vp_reverse:
2418:def int_experimental_vp_splat:
2474:def int_experimental_vector_compress:
2801:def int_experimental_vector_partial_reduce_add : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
2860:def int_experimental_convergence_entry
2862:def int_experimental_convergence_anchor
2864:def int_experimental_convergence_loop

For the purposes of this RFC, I’m mainly interested in “stop adding more llvm.experimental intrinsics” as the outcome.

I don’t think there is a need to rename all the existing ones right now. I hope they will naturally either get renamed over time or go away (e.g. all the constrained FP intrinsics would go away if we switch to operand bundles).

I’m in favor of this proposal.