Also make sure we generate type checks for the controlling type variable in legalization patterns. This is not needed for encodings since the encoding tables are already keyed on the controlling type variable.
102 lines
2.8 KiB
Python
102 lines
2.8 KiB
Python
"""
|
|
Custom legalization patterns for Intel.
|
|
"""
|
|
from __future__ import absolute_import
|
|
from cdsl.ast import Var
|
|
from cdsl.xform import Rtl, XFormGroup
|
|
from base.immediates import imm64, floatcc
|
|
from base.types import i32, i64
|
|
from base import legalize as shared
|
|
from base import instructions as insts
|
|
from . import instructions as x86
|
|
from .defs import ISA
|
|
|
|
intel_expand = XFormGroup(
|
|
'intel_expand',
|
|
"""
|
|
Legalize instructions by expansion.
|
|
|
|
Use Intel-specific instructions if needed.
|
|
""",
|
|
isa=ISA, chain=shared.expand)
|
|
|
|
a = Var('a')
|
|
dead = Var('dead')
|
|
x = Var('x')
|
|
xhi = Var('xhi')
|
|
y = Var('y')
|
|
a1 = Var('a1')
|
|
a2 = Var('a2')
|
|
|
|
#
|
|
# Division and remainder.
|
|
#
|
|
intel_expand.legalize(
|
|
a << insts.udiv(x, y),
|
|
Rtl(
|
|
xhi << insts.iconst(imm64(0)),
|
|
(a, dead) << x86.udivmodx(x, xhi, y)
|
|
))
|
|
|
|
intel_expand.legalize(
|
|
a << insts.urem(x, y),
|
|
Rtl(
|
|
xhi << insts.iconst(imm64(0)),
|
|
(dead, a) << x86.udivmodx(x, xhi, y)
|
|
))
|
|
|
|
for ty in [i32, i64]:
|
|
intel_expand.legalize(
|
|
a << insts.sdiv.bind(ty)(x, y),
|
|
Rtl(
|
|
xhi << insts.sshr_imm(x, imm64(ty.lane_bits() - 1)),
|
|
(a, dead) << x86.sdivmodx(x, xhi, y)
|
|
))
|
|
intel_expand.legalize(
|
|
a << insts.srem.bind(ty)(x, y),
|
|
Rtl(
|
|
xhi << insts.sshr_imm(x, imm64(ty.lane_bits() - 1)),
|
|
(dead, a) << x86.sdivmodx(x, xhi, y)
|
|
))
|
|
|
|
# Floating point condition codes.
|
|
#
|
|
# The 8 condition codes in `supported_floatccs` are directly supported by a
|
|
# `ucomiss` or `ucomisd` instruction. The remaining codes need legalization
|
|
# patterns.
|
|
|
|
# Equality needs an explicit `ord` test which checks the parity bit.
|
|
intel_expand.legalize(
|
|
a << insts.fcmp(floatcc.eq, x, y),
|
|
Rtl(
|
|
a1 << insts.fcmp(floatcc.ord, x, y),
|
|
a2 << insts.fcmp(floatcc.ueq, x, y),
|
|
a << insts.band(a1, a2)
|
|
))
|
|
intel_expand.legalize(
|
|
a << insts.fcmp(floatcc.ne, x, y),
|
|
Rtl(
|
|
a1 << insts.fcmp(floatcc.uno, x, y),
|
|
a2 << insts.fcmp(floatcc.one, x, y),
|
|
a << insts.bor(a1, a2)
|
|
))
|
|
|
|
# Inequalities that need to be reversed.
|
|
for cc, rev_cc in [
|
|
(floatcc.lt, floatcc.gt),
|
|
(floatcc.le, floatcc.ge),
|
|
(floatcc.ugt, floatcc.ult),
|
|
(floatcc.uge, floatcc.ule)]:
|
|
intel_expand.legalize(
|
|
a << insts.fcmp(cc, x, y),
|
|
Rtl(
|
|
a << insts.fcmp(rev_cc, y, x)
|
|
))
|
|
|
|
# We need to modify the CFG for min/max legalization.
|
|
intel_expand.custom_legalize(insts.fmin, 'expand_minmax')
|
|
intel_expand.custom_legalize(insts.fmax, 'expand_minmax')
|
|
|
|
# Conversions from unsigned need special handling.
|
|
intel_expand.custom_legalize(insts.fcvt_from_uint, 'expand_fcvt_from_uint')
|