Since now intrinsics can define what parameters are required to beEncode them directly as an imm argument to G_INTRINSIC*.
immediates, avoid using registers for them. This will be more
Since now intrinsics can now define what parameters are required to be
convenient to work with,immediates, avoid using registers for them. and avoids a few issues that SelectionDAGIntrinsics could
dealt with by using TargetConstantpotentially want a constant that isn't a legal register type. Intrinsics could potentially wantAlso,
a constant that isn't a legal register type. Alsosince G_CONSTANT is subject to CSE and legalization, since G_CONSTANT istransforms could
subject to CSE and legalization, transforms could potentially obscureotentially obscure the value (and create extra work for the
the value (and create extra work for the selector).selector). The register bank of a G_CONSTANT is also meaningful, so
this could throw off future folding and legalization logic for AMDGPU.
This will be much more convenient to work with than needing to call
getConstantVRegVal and checking if it may have failed for every
constant intrinsic parameter. AMDGPU has quite a lot of intrinsics wth
immarg operands, many of which need inspection during lowering. Having
to find the value in a register is going to add a lot of boilerplate
and waste compile time.
SelectionDAG has always provided TargetConstant for constants which
should not be legalized or materialized in a register. The distinction
between Constant and TargetConstant was somewhat fuzzy, and there was
no automatic way to force usage of TargetConstant for certain
intrinsic parameters. They were both ultimately ConstantSDNode, and it
was inconsistently used. It was quite easy to mis-select an
instruction requiring an immediate. For SelectionDAG, start emitting
TargetConstant for these arguments, and using timm to match them.
Most of the work here is to cleanup target handling of constants. Some
targets process intrinsics through intermediate custom nodes, which
need to preserve TargetConstant usage to match the intrinsic
expectation. Pattern inputs now need to distinguish whether a constant
is merely compatible with an operand or whether it is mandatory.
The GlobalISelEmitter needs to treat timm as a special case of a leaf
node, simlar to MachineBasicBlock operands. This should also enable
handling of patterns for some G_* instructions with immediates, like
G_FENCE or G_EXTRACT.
I haven't finished updating all of the targets yet. I handled X86
first, figuring it would be the worst to handle. Most of the remaining
work is for hexagon, but SystemZ also needs a non-trivial change.
There is one crash remaining in GlobalISelEmitter when using timm for
a standalone Pat for an ARM intrinsic.