1 //===- MipsLegalizerInfo.cpp ------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 /// This file implements the targeting of the Machinelegalizer class for Mips.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
13 #include "MipsLegalizerInfo.h"
14 #include "MipsTargetMachine.h"
15 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
19 MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget
&ST
) {
20 using namespace TargetOpcode
;
22 const LLT s1
= LLT::scalar(1);
23 const LLT s32
= LLT::scalar(32);
24 const LLT s64
= LLT::scalar(64);
25 const LLT p0
= LLT::pointer(0, 32);
27 getActionDefinitionsBuilder({G_ADD
, G_SUB
, G_MUL
})
29 .clampScalar(0, s32
, s32
);
31 getActionDefinitionsBuilder({G_UADDO
, G_UADDE
, G_USUBO
, G_USUBE
, G_UMULO
})
32 .lowerFor({{s32
, s1
}});
34 getActionDefinitionsBuilder(G_UMULH
)
38 getActionDefinitionsBuilder({G_LOAD
, G_STORE
})
39 .legalForTypesWithMemDesc({{s32
, p0
, 8, 8},
46 getActionDefinitionsBuilder(G_IMPLICIT_DEF
)
47 .legalFor({s32
, s64
});
49 getActionDefinitionsBuilder(G_UNMERGE_VALUES
)
50 .legalFor({{s32
, s64
}});
52 getActionDefinitionsBuilder(G_MERGE_VALUES
)
53 .legalFor({{s64
, s32
}});
55 getActionDefinitionsBuilder({G_ZEXTLOAD
, G_SEXTLOAD
})
56 .legalForTypesWithMemDesc({{s32
, p0
, 8, 8},
58 .clampScalar(0, s32
, s32
);
60 getActionDefinitionsBuilder({G_ZEXT
, G_SEXT
})
61 .legalIf([](const LegalityQuery
&Query
) { return false; })
64 getActionDefinitionsBuilder(G_TRUNC
)
65 .legalIf([](const LegalityQuery
&Query
) { return false; })
68 getActionDefinitionsBuilder(G_SELECT
)
69 .legalForCartesianProduct({p0
, s32
, s64
}, {s32
})
73 getActionDefinitionsBuilder(G_BRCOND
)
77 getActionDefinitionsBuilder(G_BRJT
)
78 .legalFor({{p0
, s32
}});
80 getActionDefinitionsBuilder(G_BRINDIRECT
)
83 getActionDefinitionsBuilder(G_PHI
)
84 .legalFor({p0
, s32
, s64
})
87 getActionDefinitionsBuilder({G_AND
, G_OR
, G_XOR
})
89 .clampScalar(0, s32
, s32
);
91 getActionDefinitionsBuilder({G_SDIV
, G_SREM
, G_UREM
, G_UDIV
})
96 getActionDefinitionsBuilder({G_SHL
, G_ASHR
, G_LSHR
})
97 .legalFor({{s32
, s32
}})
98 .clampScalar(1, s32
, s32
)
99 .clampScalar(0, s32
, s32
);
101 getActionDefinitionsBuilder(G_ICMP
)
102 .legalForCartesianProduct({s32
}, {s32
, p0
})
103 .clampScalar(1, s32
, s32
)
106 getActionDefinitionsBuilder(G_CONSTANT
)
108 .clampScalar(0, s32
, s32
);
110 getActionDefinitionsBuilder({G_GEP
, G_INTTOPTR
})
111 .legalFor({{p0
, s32
}});
113 getActionDefinitionsBuilder(G_PTRTOINT
)
114 .legalFor({{s32
, p0
}});
116 getActionDefinitionsBuilder(G_FRAME_INDEX
)
119 getActionDefinitionsBuilder({G_GLOBAL_VALUE
, G_JUMP_TABLE
})
122 getActionDefinitionsBuilder(G_DYN_STACKALLOC
)
123 .lowerFor({{p0
, s32
}});
126 getActionDefinitionsBuilder(G_FCONSTANT
)
127 .legalFor({s32
, s64
});
129 getActionDefinitionsBuilder({G_FADD
, G_FSUB
, G_FMUL
, G_FDIV
, G_FABS
, G_FSQRT
})
130 .legalFor({s32
, s64
});
132 getActionDefinitionsBuilder(G_FCMP
)
133 .legalFor({{s32
, s32
}, {s32
, s64
}})
136 getActionDefinitionsBuilder({G_FCEIL
, G_FFLOOR
})
137 .libcallFor({s32
, s64
});
139 getActionDefinitionsBuilder(G_FPEXT
)
140 .legalFor({{s64
, s32
}});
142 getActionDefinitionsBuilder(G_FPTRUNC
)
143 .legalFor({{s32
, s64
}});
145 // FP to int conversion instructions
146 getActionDefinitionsBuilder(G_FPTOSI
)
147 .legalForCartesianProduct({s32
}, {s64
, s32
})
148 .libcallForCartesianProduct({s64
}, {s64
, s32
})
151 getActionDefinitionsBuilder(G_FPTOUI
)
152 .libcallForCartesianProduct({s64
}, {s64
, s32
})
153 .lowerForCartesianProduct({s32
}, {s64
, s32
})
156 // Int to FP conversion instructions
157 getActionDefinitionsBuilder(G_SITOFP
)
158 .legalForCartesianProduct({s64
, s32
}, {s32
})
159 .libcallForCartesianProduct({s64
, s32
}, {s64
})
162 getActionDefinitionsBuilder(G_UITOFP
)
163 .libcallForCartesianProduct({s64
, s32
}, {s64
})
164 .customForCartesianProduct({s64
, s32
}, {s32
})
167 getActionDefinitionsBuilder(G_SEXT_INREG
).lower();
170 verify(*ST
.getInstrInfo());
173 bool MipsLegalizerInfo::legalizeCustom(MachineInstr
&MI
,
174 MachineRegisterInfo
&MRI
,
175 MachineIRBuilder
&MIRBuilder
,
176 GISelChangeObserver
&Observer
) const {
178 using namespace TargetOpcode
;
180 MIRBuilder
.setInstr(MI
);
181 const MipsSubtarget
&STI
=
182 static_cast<const MipsSubtarget
&>(MIRBuilder
.getMF().getSubtarget());
183 const LLT s32
= LLT::scalar(32);
184 const LLT s64
= LLT::scalar(64);
186 switch (MI
.getOpcode()) {
188 Register Dst
= MI
.getOperand(0).getReg();
189 Register Src
= MI
.getOperand(1).getReg();
190 LLT DstTy
= MRI
.getType(Dst
);
191 LLT SrcTy
= MRI
.getType(Src
);
195 if (DstTy
!= s32
&& DstTy
!= s64
)
198 // Let 0xABCDEFGH be given unsigned in MI.getOperand(1). First let's convert
199 // unsigned to double. Mantissa has 52 bits so we use following trick:
200 // First make floating point bit mask 0x43300000ABCDEFGH.
201 // Mask represents 2^52 * 0x1.00000ABCDEFGH i.e. 0x100000ABCDEFGH.0 .
202 // Next, subtract 2^52 * 0x1.0000000000000 i.e. 0x10000000000000.0 from it.
203 // Done. Trunc double to float if needed.
205 MachineInstrBuilder Bitcast
= MIRBuilder
.buildInstr(
206 STI
.isFP64bit() ? Mips::BuildPairF64_64
: Mips::BuildPairF64
, {s64
},
207 {Src
, MIRBuilder
.buildConstant(s32
, UINT32_C(0x43300000))});
208 Bitcast
.constrainAllUses(MIRBuilder
.getTII(), *STI
.getRegisterInfo(),
209 *STI
.getRegBankInfo());
211 MachineInstrBuilder TwoP52FP
= MIRBuilder
.buildFConstant(
212 s64
, BitsToDouble(UINT64_C(0x4330000000000000)));
215 MIRBuilder
.buildFSub(Dst
, Bitcast
, TwoP52FP
);
217 MachineInstrBuilder ResF64
= MIRBuilder
.buildFSub(s64
, Bitcast
, TwoP52FP
);
218 MIRBuilder
.buildFPTrunc(Dst
, ResF64
);
221 MI
.eraseFromParent();
231 bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr
&MI
,
232 MachineRegisterInfo
&MRI
,
233 MachineIRBuilder
&MIRBuilder
) const {
234 const MipsSubtarget
&ST
=
235 static_cast<const MipsSubtarget
&>(MI
.getMF()->getSubtarget());
236 const MipsInstrInfo
&TII
= *ST
.getInstrInfo();
237 const MipsRegisterInfo
&TRI
= *ST
.getRegisterInfo();
238 const RegisterBankInfo
&RBI
= *ST
.getRegBankInfo();
239 MIRBuilder
.setInstr(MI
);
241 switch (MI
.getIntrinsicID()) {
242 case Intrinsic::memcpy
:
243 case Intrinsic::memset
:
244 case Intrinsic::memmove
:
245 if (createMemLibcall(MIRBuilder
, MRI
, MI
) ==
246 LegalizerHelper::UnableToLegalize
)
248 MI
.eraseFromParent();
250 case Intrinsic::trap
: {
251 MachineInstr
*Trap
= MIRBuilder
.buildInstr(Mips::TRAP
);
252 MI
.eraseFromParent();
253 return constrainSelectedInstRegOperands(*Trap
, TII
, TRI
, RBI
);