Skip to content

Commit 0c50c0b

Browse files
committed
[FEnv] File with properties of constrained intrinsics
Summary In several places we need to enumerate all constrained intrinsics or IR nodes that should be represented by them. It is easy to miss some of the cases. To make working with these intrinsics more convenient and robust, this change introduces file containing definitions of all constrained intrinsics and some of their properties. This file can be included to generate constrained intrinsics processing code. Reviewers: kpn, andrew.w.kaylor, cameron.mcinally, uweigand Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D69887
1 parent f3225f2 commit 0c50c0b

12 files changed

+208
-594
lines changed

llvm/docs/AddingConstrainedIntrinsics.rst

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,52 +13,52 @@ Add the intrinsic
1313

1414
Multiple files need to be updated when adding a new constrained intrinsic.
1515

16-
Add the new intrinsic to the table of intrinsics.::
16+
Add the new intrinsic to the table of intrinsics::
1717

1818
include/llvm/IR/Intrinsics.td
1919

20-
Update class ConstrainedFPIntrinsic to know about the intrinsics.::
20+
Add SelectionDAG node types
21+
===========================
2122

22-
include/llvm/IR/IntrinsicInst.h
23+
Add the new STRICT version of the node type to the ISD::NodeType enum::
2324

24-
Functions like ConstrainedFPIntrinsic::isUnaryOp() or
25-
ConstrainedFPIntrinsic::isTernaryOp() may need to know about the new
26-
intrinsic.::
25+
include/llvm/CodeGen/ISDOpcodes.h
2726

28-
lib/IR/IntrinsicInst.cpp
27+
Strict version name must be a concatenation of prefix "STRICT_" and the name
28+
of corresponding non-strict node name. For instance, strict version of the
29+
node FADD must be STRICT_FADD.
2930

30-
Update the IR verifier::
31+
Update mappings
32+
===============
3133

32-
lib/IR/Verifier.cpp
34+
Add new record to the mapping of instructions to constrained intrinsic and
35+
DAG nodes::
3336

34-
Add SelectionDAG node types
35-
===========================
36-
37-
Add the new STRICT version of the node type to the ISD::NodeType enum.::
37+
include/llvm/IR/ConstrainedOps.def
3838

39-
include/llvm/CodeGen/ISDOpcodes.h
39+
Follow instructions provided in this file.
4040

41-
In class SDNode update isStrictFPOpcode()::
41+
Update IR components
42+
====================
4243

43-
include/llvm/CodeGen/SelectionDAGNodes.h
44+
Update the IR verifier::
4445

45-
A mapping from the STRICT SDnode type to the non-STRICT is done in
46-
TargetLoweringBase::getStrictFPOperationAction(). This allows STRICT
47-
nodes to be legalized similarly to the non-STRICT node type.::
46+
lib/IR/Verifier.cpp
4847

49-
include/llvm/CodeGen/TargetLowering.h
48+
Update Selector components
49+
==========================
5050

5151
Building the SelectionDAG
5252
-------------------------
5353

54-
The switch statement in SelectionDAGBuilder::visitIntrinsicCall() needs
55-
to be updated to call SelectionDAGBuilder::visitConstrainedFPIntrinsic().
56-
That function, in turn, needs to be updated to know how to create the
57-
SDNode for the intrinsic. The new STRICT node will eventually be converted
54+
The function SelectionDAGBuilder::visitConstrainedFPIntrinsic builds DAG nodes
55+
using mappings specified in ConstrainedOps.def. If however this default build is
56+
not sufficient, the build can be modified, see how it is implemented for
57+
STRICT_FP_ROUND. The new STRICT node will eventually be converted
5858
to the matching non-STRICT node. For this reason it should have the same
5959
operands and values as the non-STRICT version but should also use the chain.
6060
This makes subsequent sharing of code for STRICT and non-STRICT code paths
61-
easier.::
61+
easier::
6262

6363
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
6464

@@ -74,18 +74,17 @@ Be careful of the chain since STRICT nodes use it but their counterparts
7474
often don't.
7575

7676
The code to do the conversion or mutation of the STRICT node to a non-STRICT
77-
version of the node happens in SelectionDAG::mutateStrictFPToFP(). Be
77+
version of the node happens in SelectionDAG::mutateStrictFPToFP(). In most cases
78+
the function can do the conversion using information from ConstrainedOps.def. Be
7879
careful updating this function since some nodes have the same return type
7980
as their input operand, but some are different. Both of these cases must
80-
be properly handled.::
81+
be properly handled::
8182

8283
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
8384

84-
However, the mutation may not happen if the new node has not been registered
85-
in TargetLoweringBase::initActions(). If the corresponding non-STRICT node
86-
is Legal but a target does not know about STRICT nodes then the STRICT
87-
node will default to Legal and mutation will be bypassed with a "Cannot
88-
select" error. Register the new STRICT node as Expand to avoid this bug.::
85+
Whether the mutation may happens or not, depends on how the new node has been
86+
registered in TargetLoweringBase::initActions(). By default all strict nodes are
87+
registered with Expand action::
8988

9089
lib/CodeGen/TargetLoweringBase.cpp
9190

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -690,38 +690,9 @@ END_TWO_BYTE_PACK()
690690
switch (NodeType) {
691691
default:
692692
return false;
693-
case ISD::STRICT_FADD:
694-
case ISD::STRICT_FSUB:
695-
case ISD::STRICT_FMUL:
696-
case ISD::STRICT_FDIV:
697-
case ISD::STRICT_FREM:
698-
case ISD::STRICT_FMA:
699-
case ISD::STRICT_FSQRT:
700-
case ISD::STRICT_FPOW:
701-
case ISD::STRICT_FPOWI:
702-
case ISD::STRICT_FSIN:
703-
case ISD::STRICT_FCOS:
704-
case ISD::STRICT_FEXP:
705-
case ISD::STRICT_FEXP2:
706-
case ISD::STRICT_FLOG:
707-
case ISD::STRICT_FLOG10:
708-
case ISD::STRICT_FLOG2:
709-
case ISD::STRICT_LRINT:
710-
case ISD::STRICT_LLRINT:
711-
case ISD::STRICT_FRINT:
712-
case ISD::STRICT_FNEARBYINT:
713-
case ISD::STRICT_FMAXNUM:
714-
case ISD::STRICT_FMINNUM:
715-
case ISD::STRICT_FCEIL:
716-
case ISD::STRICT_FFLOOR:
717-
case ISD::STRICT_LROUND:
718-
case ISD::STRICT_LLROUND:
719-
case ISD::STRICT_FROUND:
720-
case ISD::STRICT_FTRUNC:
721-
case ISD::STRICT_FP_TO_SINT:
722-
case ISD::STRICT_FP_TO_UINT:
723-
case ISD::STRICT_FP_ROUND:
724-
case ISD::STRICT_FP_EXTEND:
693+
#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
694+
case ISD::STRICT_##DAGN:
695+
#include "llvm/IR/ConstrainedOps.def"
725696
return true;
726697
}
727698
}

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -944,38 +944,9 @@ class TargetLoweringBase {
944944
unsigned EqOpc;
945945
switch (Op) {
946946
default: llvm_unreachable("Unexpected FP pseudo-opcode");
947-
case ISD::STRICT_FADD: EqOpc = ISD::FADD; break;
948-
case ISD::STRICT_FSUB: EqOpc = ISD::FSUB; break;
949-
case ISD::STRICT_FMUL: EqOpc = ISD::FMUL; break;
950-
case ISD::STRICT_FDIV: EqOpc = ISD::FDIV; break;
951-
case ISD::STRICT_FREM: EqOpc = ISD::FREM; break;
952-
case ISD::STRICT_FSQRT: EqOpc = ISD::FSQRT; break;
953-
case ISD::STRICT_FPOW: EqOpc = ISD::FPOW; break;
954-
case ISD::STRICT_FPOWI: EqOpc = ISD::FPOWI; break;
955-
case ISD::STRICT_FMA: EqOpc = ISD::FMA; break;
956-
case ISD::STRICT_FSIN: EqOpc = ISD::FSIN; break;
957-
case ISD::STRICT_FCOS: EqOpc = ISD::FCOS; break;
958-
case ISD::STRICT_FEXP: EqOpc = ISD::FEXP; break;
959-
case ISD::STRICT_FEXP2: EqOpc = ISD::FEXP2; break;
960-
case ISD::STRICT_FLOG: EqOpc = ISD::FLOG; break;
961-
case ISD::STRICT_FLOG10: EqOpc = ISD::FLOG10; break;
962-
case ISD::STRICT_FLOG2: EqOpc = ISD::FLOG2; break;
963-
case ISD::STRICT_LRINT: EqOpc = ISD::LRINT; break;
964-
case ISD::STRICT_LLRINT: EqOpc = ISD::LLRINT; break;
965-
case ISD::STRICT_FRINT: EqOpc = ISD::FRINT; break;
966-
case ISD::STRICT_FNEARBYINT: EqOpc = ISD::FNEARBYINT; break;
967-
case ISD::STRICT_FMAXNUM: EqOpc = ISD::FMAXNUM; break;
968-
case ISD::STRICT_FMINNUM: EqOpc = ISD::FMINNUM; break;
969-
case ISD::STRICT_FCEIL: EqOpc = ISD::FCEIL; break;
970-
case ISD::STRICT_FFLOOR: EqOpc = ISD::FFLOOR; break;
971-
case ISD::STRICT_LROUND: EqOpc = ISD::LROUND; break;
972-
case ISD::STRICT_LLROUND: EqOpc = ISD::LLROUND; break;
973-
case ISD::STRICT_FROUND: EqOpc = ISD::FROUND; break;
974-
case ISD::STRICT_FTRUNC: EqOpc = ISD::FTRUNC; break;
975-
case ISD::STRICT_FP_TO_SINT: EqOpc = ISD::FP_TO_SINT; break;
976-
case ISD::STRICT_FP_TO_UINT: EqOpc = ISD::FP_TO_UINT; break;
977-
case ISD::STRICT_FP_ROUND: EqOpc = ISD::FP_ROUND; break;
978-
case ISD::STRICT_FP_EXTEND: EqOpc = ISD::FP_EXTEND; break;
947+
#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
948+
case ISD::STRICT_##DAGN: EqOpc = ISD::DAGN; break;
949+
#include "llvm/IR/ConstrainedOps.def"
979950
}
980951

981952
return getOperationAction(EqOpc, VT);
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===- llvm/IR/ConstrainedOps.def - Constrained intrinsics ------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Defines properties of constrained intrinsics, in particular corresponding
10+
// floating point operations and DAG nodes.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef INSTRUCTION
15+
#define INSTRUCTION(N,A,R,I,D)
16+
#endif
17+
18+
// In most cases intrinsic function is handled similar to instruction.
19+
#ifndef FUNCTION
20+
#define FUNCTION INSTRUCTION
21+
#endif
22+
23+
// Arguments of the entries are:
24+
// - instruction or intrinsic function name.
25+
// - Number of original instruction/intrinsic arguments.
26+
// - 1 if the corresponding constrained intrinsic has rounding mode argument.
27+
// - name of the constrained intrinsic to represent this instruction/function.
28+
// - DAG node corresponding to the constrained intrinsic without prefix STRICT_.
29+
30+
// These are definitions for instructions, that are converted into constrained
31+
// intrinsics.
32+
//
33+
INSTRUCTION(FAdd, 2, 1, experimental_constrained_fadd, FADD)
34+
INSTRUCTION(FSub, 2, 1, experimental_constrained_fsub, FSUB)
35+
INSTRUCTION(FMul, 2, 1, experimental_constrained_fmul, FMUL)
36+
INSTRUCTION(FDiv, 2, 1, experimental_constrained_fdiv, FDIV)
37+
INSTRUCTION(FRem, 2, 1, experimental_constrained_frem, FREM)
38+
INSTRUCTION(FPExt, 1, 0, experimental_constrained_fpext, FP_EXTEND)
39+
INSTRUCTION(FPToSI, 1, 0, experimental_constrained_fptosi, FP_TO_SINT)
40+
INSTRUCTION(FPToUI, 1, 0, experimental_constrained_fptoui, FP_TO_UINT)
41+
INSTRUCTION(FPTrunc, 1, 1, experimental_constrained_fptrunc, FP_ROUND)
42+
43+
// Theses are definitions for intrinsic functions, that are converted into
44+
// constrained intrinsics.
45+
//
46+
FUNCTION(ceil, 1, 1, experimental_constrained_ceil, FCEIL)
47+
FUNCTION(cos, 1, 1, experimental_constrained_cos, FCOS)
48+
FUNCTION(exp, 1, 1, experimental_constrained_exp, FEXP)
49+
FUNCTION(exp2, 1, 1, experimental_constrained_exp2, FEXP2)
50+
FUNCTION(floor, 1, 1, experimental_constrained_floor, FFLOOR)
51+
FUNCTION(fma, 3, 1, experimental_constrained_fma, FMA)
52+
FUNCTION(log, 1, 1, experimental_constrained_log, FLOG)
53+
FUNCTION(log10, 1, 1, experimental_constrained_log10, FLOG10)
54+
FUNCTION(log2, 1, 1, experimental_constrained_log2, FLOG2)
55+
FUNCTION(lrint, 1, 1, experimental_constrained_lrint, LRINT)
56+
FUNCTION(llrint, 1, 1, experimental_constrained_llrint, LLRINT)
57+
FUNCTION(lround, 1, 0, experimental_constrained_lround, LROUND)
58+
FUNCTION(llround, 1, 0, experimental_constrained_llround, LLROUND)
59+
FUNCTION(maxnum, 2, 1, experimental_constrained_maxnum, FMAXNUM)
60+
FUNCTION(minnum, 2, 1, experimental_constrained_minnum, FMINNUM)
61+
FUNCTION(nearbyint, 1, 1, experimental_constrained_nearbyint, FNEARBYINT)
62+
FUNCTION(pow, 2, 1, experimental_constrained_pow, FPOW)
63+
FUNCTION(powi, 2, 1, experimental_constrained_powi, FPOWI)
64+
FUNCTION(rint, 1, 1, experimental_constrained_rint, FRINT)
65+
FUNCTION(round, 1, 1, experimental_constrained_round, FROUND)
66+
FUNCTION(sin, 1, 1, experimental_constrained_sin, FSIN)
67+
FUNCTION(sqrt, 1, 1, experimental_constrained_sqrt, FSQRT)
68+
FUNCTION(trunc, 1, 1, experimental_constrained_trunc, FTRUNC)
69+
70+
#undef INSTRUCTION
71+
#undef FUNCTION

llvm/include/llvm/IR/IntrinsicInst.h

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -251,44 +251,7 @@ namespace llvm {
251251
static Optional<StringRef> ExceptionBehaviorToStr(ExceptionBehavior);
252252

253253
// Methods for support type inquiry through isa, cast, and dyn_cast:
254-
static bool classof(const IntrinsicInst *I) {
255-
switch (I->getIntrinsicID()) {
256-
case Intrinsic::experimental_constrained_fadd:
257-
case Intrinsic::experimental_constrained_fsub:
258-
case Intrinsic::experimental_constrained_fmul:
259-
case Intrinsic::experimental_constrained_fdiv:
260-
case Intrinsic::experimental_constrained_frem:
261-
case Intrinsic::experimental_constrained_fma:
262-
case Intrinsic::experimental_constrained_fptosi:
263-
case Intrinsic::experimental_constrained_fptoui:
264-
case Intrinsic::experimental_constrained_fptrunc:
265-
case Intrinsic::experimental_constrained_fpext:
266-
case Intrinsic::experimental_constrained_sqrt:
267-
case Intrinsic::experimental_constrained_pow:
268-
case Intrinsic::experimental_constrained_powi:
269-
case Intrinsic::experimental_constrained_sin:
270-
case Intrinsic::experimental_constrained_cos:
271-
case Intrinsic::experimental_constrained_exp:
272-
case Intrinsic::experimental_constrained_exp2:
273-
case Intrinsic::experimental_constrained_log:
274-
case Intrinsic::experimental_constrained_log10:
275-
case Intrinsic::experimental_constrained_log2:
276-
case Intrinsic::experimental_constrained_lrint:
277-
case Intrinsic::experimental_constrained_llrint:
278-
case Intrinsic::experimental_constrained_rint:
279-
case Intrinsic::experimental_constrained_nearbyint:
280-
case Intrinsic::experimental_constrained_maxnum:
281-
case Intrinsic::experimental_constrained_minnum:
282-
case Intrinsic::experimental_constrained_ceil:
283-
case Intrinsic::experimental_constrained_floor:
284-
case Intrinsic::experimental_constrained_lround:
285-
case Intrinsic::experimental_constrained_llround:
286-
case Intrinsic::experimental_constrained_round:
287-
case Intrinsic::experimental_constrained_trunc:
288-
return true;
289-
default: return false;
290-
}
291-
}
254+
static bool classof(const IntrinsicInst *I);
292255
static bool classof(const Value *V) {
293256
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
294257
}

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -310,34 +310,9 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
310310
switch (Op.getOpcode()) {
311311
default:
312312
return TranslateLegalizeResults(Op, Result);
313-
case ISD::STRICT_FADD:
314-
case ISD::STRICT_FSUB:
315-
case ISD::STRICT_FMUL:
316-
case ISD::STRICT_FDIV:
317-
case ISD::STRICT_FREM:
318-
case ISD::STRICT_FSQRT:
319-
case ISD::STRICT_FMA:
320-
case ISD::STRICT_FPOW:
321-
case ISD::STRICT_FPOWI:
322-
case ISD::STRICT_FSIN:
323-
case ISD::STRICT_FCOS:
324-
case ISD::STRICT_FEXP:
325-
case ISD::STRICT_FEXP2:
326-
case ISD::STRICT_FLOG:
327-
case ISD::STRICT_FLOG10:
328-
case ISD::STRICT_FLOG2:
329-
case ISD::STRICT_FRINT:
330-
case ISD::STRICT_FNEARBYINT:
331-
case ISD::STRICT_FMAXNUM:
332-
case ISD::STRICT_FMINNUM:
333-
case ISD::STRICT_FCEIL:
334-
case ISD::STRICT_FFLOOR:
335-
case ISD::STRICT_FROUND:
336-
case ISD::STRICT_FTRUNC:
337-
case ISD::STRICT_FP_TO_SINT:
338-
case ISD::STRICT_FP_TO_UINT:
339-
case ISD::STRICT_FP_ROUND:
340-
case ISD::STRICT_FP_EXTEND:
313+
#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
314+
case ISD::STRICT_##DAGN:
315+
#include "llvm/IR/ConstrainedOps.def"
341316
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
342317
// If we're asked to expand a strict vector floating-point operation,
343318
// by default we're going to simply unroll it. That is usually the
@@ -838,32 +813,9 @@ SDValue VectorLegalizer::Expand(SDValue Op) {
838813
// targets? This should probably be investigated. And if we still prefer to
839814
// unroll an explanation could be helpful.
840815
return DAG.UnrollVectorOp(Op.getNode());
841-
case ISD::STRICT_FADD:
842-
case ISD::STRICT_FSUB:
843-
case ISD::STRICT_FMUL:
844-
case ISD::STRICT_FDIV:
845-
case ISD::STRICT_FREM:
846-
case ISD::STRICT_FSQRT:
847-
case ISD::STRICT_FMA:
848-
case ISD::STRICT_FPOW:
849-
case ISD::STRICT_FPOWI:
850-
case ISD::STRICT_FSIN:
851-
case ISD::STRICT_FCOS:
852-
case ISD::STRICT_FEXP:
853-
case ISD::STRICT_FEXP2:
854-
case ISD::STRICT_FLOG:
855-
case ISD::STRICT_FLOG10:
856-
case ISD::STRICT_FLOG2:
857-
case ISD::STRICT_FRINT:
858-
case ISD::STRICT_FNEARBYINT:
859-
case ISD::STRICT_FMAXNUM:
860-
case ISD::STRICT_FMINNUM:
861-
case ISD::STRICT_FCEIL:
862-
case ISD::STRICT_FFLOOR:
863-
case ISD::STRICT_FROUND:
864-
case ISD::STRICT_FTRUNC:
865-
case ISD::STRICT_FP_TO_SINT:
866-
case ISD::STRICT_FP_TO_UINT:
816+
#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
817+
case ISD::STRICT_##DAGN:
818+
#include "llvm/IR/ConstrainedOps.def"
867819
return ExpandStrictFPOp(Op);
868820
case ISD::VECREDUCE_ADD:
869821
case ISD::VECREDUCE_MUL:

0 commit comments

Comments
 (0)