llvm.org GIT mirror llvm / 29165da
[MSP430] Generate EABI-compliant libcalls Updates the MSP430 target to generate EABI-compatible libcall names. As a byproduct, adjusts the hardware multiplier options available in the MSP430 target, adds support for promotion of the ISD::MUL operation for 8-bit integers, and correctly marks R11 as used by call instructions. Patch by Andrew Wygle. Differential Revision: https://reviews.llvm.org/D32676 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302820 91177308-0d34-0410-b5e6-96231b3b80d8 Vadzim Dambrouski 3 years ago
12 changed file(s) with 989 addition(s) and 62 deletion(s). Raw diff Collapse all Expand all
200200 /// shaders)
201201 AMDGPU_HS = 93,
202202
203 /// Calling convention used for special MSP430 rtlib functions
204 /// which have an "optimized" convention using additional registers.
205 MSP430_BUILTIN = 94,
206
203207 /// The highest possible calling convention ID. Must be some 2^k - 1.
204208 MaxID = 1023
205209 };
41864186 ReplacedNode(Node);
41874187 break;
41884188 }
4189 case ISD::MUL:
41894190 case ISD::SDIV:
41904191 case ISD::SREM:
41914192 case ISD::UDIV:
3939
4040 typedef enum {
4141 NoHWMult,
42 HWMultIntr,
43 HWMultNoIntr
42 HWMult16,
43 HWMult32,
44 HWMultF5
4445 } HWMultUseMode;
4546
4647 static cl::opt
47 HWMultMode("msp430-hwmult-mode", cl::Hidden,
48 HWMultMode("mhwmult", cl::Hidden,
4849 cl::desc("Hardware multiplier use mode"),
49 cl::init(HWMultNoIntr),
50 cl::init(NoHWMult),
5051 cl::values(
51 clEnumValN(NoHWMult, "no",
52 clEnumValN(NoHWMult, "none",
5253 "Do not use hardware multiplier"),
53 clEnumValN(HWMultIntr, "interrupts",
54 "Assume hardware multiplier can be used inside interrupts"),
55 clEnumValN(HWMultNoIntr, "use",
56 "Assume hardware multiplier cannot be used inside interrupts")));
54 clEnumValN(HWMult16, "16bit",
55 "Use 16-bit hardware multiplier"),
56 clEnumValN(HWMult32, "32bit",
57 "Use 32-bit hardware multiplier"),
58 clEnumValN(HWMultF5, "f5series",
59 "Use F5 series hardware multiplier")));
5760
5861 MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM,
5962 const MSP430Subtarget &STI)
130133 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
131134
132135 // FIXME: Implement efficiently multiplication by a constant
133 setOperationAction(ISD::MUL, MVT::i8, Expand);
134 setOperationAction(ISD::MULHS, MVT::i8, Expand);
135 setOperationAction(ISD::MULHU, MVT::i8, Expand);
136 setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand);
137 setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand);
138 setOperationAction(ISD::MUL, MVT::i16, Expand);
136 setOperationAction(ISD::MUL, MVT::i8, Promote);
137 setOperationAction(ISD::MULHS, MVT::i8, Promote);
138 setOperationAction(ISD::MULHU, MVT::i8, Promote);
139 setOperationAction(ISD::SMUL_LOHI, MVT::i8, Promote);
140 setOperationAction(ISD::UMUL_LOHI, MVT::i8, Promote);
141 setOperationAction(ISD::MUL, MVT::i16, LibCall);
139142 setOperationAction(ISD::MULHS, MVT::i16, Expand);
140143 setOperationAction(ISD::MULHU, MVT::i16, Expand);
141144 setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand);
142145 setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand);
143146
144 setOperationAction(ISD::UDIV, MVT::i8, Expand);
145 setOperationAction(ISD::UDIVREM, MVT::i8, Expand);
146 setOperationAction(ISD::UREM, MVT::i8, Expand);
147 setOperationAction(ISD::SDIV, MVT::i8, Expand);
148 setOperationAction(ISD::SDIVREM, MVT::i8, Expand);
149 setOperationAction(ISD::SREM, MVT::i8, Expand);
150 setOperationAction(ISD::UDIV, MVT::i16, Expand);
147 setOperationAction(ISD::UDIV, MVT::i8, Promote);
148 setOperationAction(ISD::UDIVREM, MVT::i8, Promote);
149 setOperationAction(ISD::UREM, MVT::i8, Promote);
150 setOperationAction(ISD::SDIV, MVT::i8, Promote);
151 setOperationAction(ISD::SDIVREM, MVT::i8, Promote);
152 setOperationAction(ISD::SREM, MVT::i8, Promote);
153 setOperationAction(ISD::UDIV, MVT::i16, LibCall);
151154 setOperationAction(ISD::UDIVREM, MVT::i16, Expand);
152 setOperationAction(ISD::UREM, MVT::i16, Expand);
153 setOperationAction(ISD::SDIV, MVT::i16, Expand);
155 setOperationAction(ISD::UREM, MVT::i16, LibCall);
156 setOperationAction(ISD::SDIV, MVT::i16, LibCall);
154157 setOperationAction(ISD::SDIVREM, MVT::i16, Expand);
155 setOperationAction(ISD::SREM, MVT::i16, Expand);
158 setOperationAction(ISD::SREM, MVT::i16, LibCall);
156159
157160 // varargs support
158161 setOperationAction(ISD::VASTART, MVT::Other, Custom);
161164 setOperationAction(ISD::VACOPY, MVT::Other, Expand);
162165 setOperationAction(ISD::JumpTable, MVT::i16, Custom);
163166
164 // Libcalls names.
165 if (HWMultMode == HWMultIntr) {
166 setLibcallName(RTLIB::MUL_I8, "__mulqi3hw");
167 setLibcallName(RTLIB::MUL_I16, "__mulhi3hw");
168 } else if (HWMultMode == HWMultNoIntr) {
169 setLibcallName(RTLIB::MUL_I8, "__mulqi3hw_noint");
170 setLibcallName(RTLIB::MUL_I16, "__mulhi3hw_noint");
171 }
167 // EABI Libcalls - EABI Section 6.2
168 const struct {
169 const RTLIB::Libcall Op;
170 const char * const Name;
171 const ISD::CondCode Cond;
172 } LibraryCalls[] = {
173 // Floating point conversions - EABI Table 6
174 { RTLIB::FPROUND_F64_F32, "__mspabi_cvtdf", ISD::SETCC_INVALID },
175 { RTLIB::FPEXT_F32_F64, "__mspabi_cvtfd", ISD::SETCC_INVALID },
176 // The following is NOT implemented in libgcc
177 //{ RTLIB::FPTOSINT_F64_I16, "__mspabi_fixdi", ISD::SETCC_INVALID },
178 { RTLIB::FPTOSINT_F64_I32, "__mspabi_fixdli", ISD::SETCC_INVALID },
179 { RTLIB::FPTOSINT_F64_I64, "__mspabi_fixdlli", ISD::SETCC_INVALID },
180 // The following is NOT implemented in libgcc
181 //{ RTLIB::FPTOUINT_F64_I16, "__mspabi_fixdu", ISD::SETCC_INVALID },
182 { RTLIB::FPTOUINT_F64_I32, "__mspabi_fixdul", ISD::SETCC_INVALID },
183 { RTLIB::FPTOUINT_F64_I64, "__mspabi_fixdull", ISD::SETCC_INVALID },
184 // The following is NOT implemented in libgcc
185 //{ RTLIB::FPTOSINT_F32_I16, "__mspabi_fixfi", ISD::SETCC_INVALID },
186 { RTLIB::FPTOSINT_F32_I32, "__mspabi_fixfli", ISD::SETCC_INVALID },
187 { RTLIB::FPTOSINT_F32_I64, "__mspabi_fixflli", ISD::SETCC_INVALID },
188 // The following is NOT implemented in libgcc
189 //{ RTLIB::FPTOUINT_F32_I16, "__mspabi_fixfu", ISD::SETCC_INVALID },
190 { RTLIB::FPTOUINT_F32_I32, "__mspabi_fixful", ISD::SETCC_INVALID },
191 { RTLIB::FPTOUINT_F32_I64, "__mspabi_fixfull", ISD::SETCC_INVALID },
192 // TODO The following IS implemented in libgcc
193 //{ RTLIB::SINTTOFP_I16_F64, "__mspabi_fltid", ISD::SETCC_INVALID },
194 { RTLIB::SINTTOFP_I32_F64, "__mspabi_fltlid", ISD::SETCC_INVALID },
195 // TODO The following IS implemented in libgcc but is not in the EABI
196 { RTLIB::SINTTOFP_I64_F64, "__mspabi_fltllid", ISD::SETCC_INVALID },
197 // TODO The following IS implemented in libgcc
198 //{ RTLIB::UINTTOFP_I16_F64, "__mspabi_fltud", ISD::SETCC_INVALID },
199 { RTLIB::UINTTOFP_I32_F64, "__mspabi_fltuld", ISD::SETCC_INVALID },
200 // The following IS implemented in libgcc but is not in the EABI
201 { RTLIB::UINTTOFP_I64_F64, "__mspabi_fltulld", ISD::SETCC_INVALID },
202 // TODO The following IS implemented in libgcc
203 //{ RTLIB::SINTTOFP_I16_F32, "__mspabi_fltif", ISD::SETCC_INVALID },
204 { RTLIB::SINTTOFP_I32_F32, "__mspabi_fltlif", ISD::SETCC_INVALID },
205 // TODO The following IS implemented in libgcc but is not in the EABI
206 { RTLIB::SINTTOFP_I64_F32, "__mspabi_fltllif", ISD::SETCC_INVALID },
207 // TODO The following IS implemented in libgcc
208 //{ RTLIB::UINTTOFP_I16_F32, "__mspabi_fltuf", ISD::SETCC_INVALID },
209 { RTLIB::UINTTOFP_I32_F32, "__mspabi_fltulf", ISD::SETCC_INVALID },
210 // The following IS implemented in libgcc but is not in the EABI
211 { RTLIB::UINTTOFP_I64_F32, "__mspabi_fltullf", ISD::SETCC_INVALID },
212
213 // Floating point comparisons - EABI Table 7
214 { RTLIB::OEQ_F64, "__mspabi_cmpd", ISD::SETEQ },
215 { RTLIB::UNE_F64, "__mspabi_cmpd", ISD::SETNE },
216 { RTLIB::OGE_F64, "__mspabi_cmpd", ISD::SETGE },
217 { RTLIB::OLT_F64, "__mspabi_cmpd", ISD::SETLT },
218 { RTLIB::OLE_F64, "__mspabi_cmpd", ISD::SETLE },
219 { RTLIB::OGT_F64, "__mspabi_cmpd", ISD::SETGT },
220 { RTLIB::OEQ_F32, "__mspabi_cmpf", ISD::SETEQ },
221 { RTLIB::UNE_F32, "__mspabi_cmpf", ISD::SETNE },
222 { RTLIB::OGE_F32, "__mspabi_cmpf", ISD::SETGE },
223 { RTLIB::OLT_F32, "__mspabi_cmpf", ISD::SETLT },
224 { RTLIB::OLE_F32, "__mspabi_cmpf", ISD::SETLE },
225 { RTLIB::OGT_F32, "__mspabi_cmpf", ISD::SETGT },
226
227 // Floating point arithmetic - EABI Table 8
228 { RTLIB::ADD_F64, "__mspabi_addd", ISD::SETCC_INVALID },
229 { RTLIB::ADD_F32, "__mspabi_addf", ISD::SETCC_INVALID },
230 { RTLIB::DIV_F64, "__mspabi_divd", ISD::SETCC_INVALID },
231 { RTLIB::DIV_F32, "__mspabi_divf", ISD::SETCC_INVALID },
232 { RTLIB::MUL_F64, "__mspabi_mpyd", ISD::SETCC_INVALID },
233 { RTLIB::MUL_F32, "__mspabi_mpyf", ISD::SETCC_INVALID },
234 { RTLIB::SUB_F64, "__mspabi_subd", ISD::SETCC_INVALID },
235 { RTLIB::SUB_F32, "__mspabi_subf", ISD::SETCC_INVALID },
236 // The following are NOT implemented in libgcc
237 // { RTLIB::NEG_F64, "__mspabi_negd", ISD::SETCC_INVALID },
238 // { RTLIB::NEG_F32, "__mspabi_negf", ISD::SETCC_INVALID },
239
240 // TODO: SLL/SRA/SRL are in libgcc, RLL isn't
241
242 // Universal Integer Operations - EABI Table 9
243 { RTLIB::SDIV_I16, "__mspabi_divi", ISD::SETCC_INVALID },
244 { RTLIB::SDIV_I32, "__mspabi_divli", ISD::SETCC_INVALID },
245 { RTLIB::SDIV_I64, "__mspabi_divlli", ISD::SETCC_INVALID },
246 { RTLIB::UDIV_I16, "__mspabi_divu", ISD::SETCC_INVALID },
247 { RTLIB::UDIV_I32, "__mspabi_divul", ISD::SETCC_INVALID },
248 { RTLIB::UDIV_I64, "__mspabi_divull", ISD::SETCC_INVALID },
249 { RTLIB::SREM_I16, "__mspabi_remi", ISD::SETCC_INVALID },
250 { RTLIB::SREM_I32, "__mspabi_remli", ISD::SETCC_INVALID },
251 { RTLIB::SREM_I64, "__mspabi_remlli", ISD::SETCC_INVALID },
252 { RTLIB::UREM_I16, "__mspabi_remu", ISD::SETCC_INVALID },
253 { RTLIB::UREM_I32, "__mspabi_remul", ISD::SETCC_INVALID },
254 { RTLIB::UREM_I64, "__mspabi_remull", ISD::SETCC_INVALID },
255
256 };
257
258 for (const auto &LC : LibraryCalls) {
259 setLibcallName(LC.Op, LC.Name);
260 if (LC.Cond != ISD::SETCC_INVALID)
261 setCmpLibcallCC(LC.Op, LC.Cond);
262 }
263
264 if (HWMultMode == HWMult16) {
265 const struct {
266 const RTLIB::Libcall Op;
267 const char * const Name;
268 } LibraryCalls[] = {
269 // Integer Multiply - EABI Table 9
270 { RTLIB::MUL_I16, "__mspabi_mpyi_hw" },
271 { RTLIB::MUL_I32, "__mspabi_mpyl_hw" },
272 { RTLIB::MUL_I64, "__mspabi_mpyll_hw" },
273 // TODO The __mspabi_mpysl*_hw functions ARE implemented in libgcc
274 // TODO The __mspabi_mpyul*_hw functions ARE implemented in libgcc
275 };
276 for (const auto &LC : LibraryCalls) {
277 setLibcallName(LC.Op, LC.Name);
278 }
279 } else if (HWMultMode == HWMult32) {
280 const struct {
281 const RTLIB::Libcall Op;
282 const char * const Name;
283 } LibraryCalls[] = {
284 // Integer Multiply - EABI Table 9
285 { RTLIB::MUL_I16, "__mspabi_mpyi_hw" },
286 { RTLIB::MUL_I32, "__mspabi_mpyl_hw32" },
287 { RTLIB::MUL_I64, "__mspabi_mpyll_hw32" },
288 // TODO The __mspabi_mpysl*_hw32 functions ARE implemented in libgcc
289 // TODO The __mspabi_mpyul*_hw32 functions ARE implemented in libgcc
290 };
291 for (const auto &LC : LibraryCalls) {
292 setLibcallName(LC.Op, LC.Name);
293 }
294 } else if (HWMultMode == HWMultF5) {
295 const struct {
296 const RTLIB::Libcall Op;
297 const char * const Name;
298 } LibraryCalls[] = {
299 // Integer Multiply - EABI Table 9
300 { RTLIB::MUL_I16, "__mspabi_mpyi_f5hw" },
301 { RTLIB::MUL_I32, "__mspabi_mpyl_f5hw" },
302 { RTLIB::MUL_I64, "__mspabi_mpyll_f5hw" },
303 // TODO The __mspabi_mpysl*_f5hw functions ARE implemented in libgcc
304 // TODO The __mspabi_mpyul*_f5hw functions ARE implemented in libgcc
305 };
306 for (const auto &LC : LibraryCalls) {
307 setLibcallName(LC.Op, LC.Name);
308 }
309 } else { // NoHWMult
310 const struct {
311 const RTLIB::Libcall Op;
312 const char * const Name;
313 } LibraryCalls[] = {
314 // Integer Multiply - EABI Table 9
315 { RTLIB::MUL_I16, "__mspabi_mpyi" },
316 { RTLIB::MUL_I32, "__mspabi_mpyl" },
317 { RTLIB::MUL_I64, "__mspabi_mpyll" },
318 // The __mspabi_mpysl* functions are NOT implemented in libgcc
319 // The __mspabi_mpyul* functions are NOT implemented in libgcc
320 };
321 for (const auto &LC : LibraryCalls) {
322 setLibcallName(LC.Op, LC.Name);
323 }
324 setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::MSP430_BUILTIN);
325 }
326
327 // Several of the runtime library functions use a special calling conv
328 setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::MSP430_BUILTIN);
329 setLibcallCallingConv(RTLIB::UREM_I64, CallingConv::MSP430_BUILTIN);
330 setLibcallCallingConv(RTLIB::SDIV_I64, CallingConv::MSP430_BUILTIN);
331 setLibcallCallingConv(RTLIB::SREM_I64, CallingConv::MSP430_BUILTIN);
332 setLibcallCallingConv(RTLIB::ADD_F64, CallingConv::MSP430_BUILTIN);
333 setLibcallCallingConv(RTLIB::SUB_F64, CallingConv::MSP430_BUILTIN);
334 setLibcallCallingConv(RTLIB::MUL_F64, CallingConv::MSP430_BUILTIN);
335 setLibcallCallingConv(RTLIB::DIV_F64, CallingConv::MSP430_BUILTIN);
336 setLibcallCallingConv(RTLIB::OEQ_F64, CallingConv::MSP430_BUILTIN);
337 setLibcallCallingConv(RTLIB::UNE_F64, CallingConv::MSP430_BUILTIN);
338 setLibcallCallingConv(RTLIB::OGE_F64, CallingConv::MSP430_BUILTIN);
339 setLibcallCallingConv(RTLIB::OLT_F64, CallingConv::MSP430_BUILTIN);
340 setLibcallCallingConv(RTLIB::OLE_F64, CallingConv::MSP430_BUILTIN);
341 setLibcallCallingConv(RTLIB::OGT_F64, CallingConv::MSP430_BUILTIN);
342 // TODO: __mspabi_srall, __mspabi_srlll, __mspabi_sllll
172343
173344 setMinFunctionAlignment(1);
174345 setPrefFunctionAlignment(2);
280451 static void AnalyzeArguments(CCState &State,
281452 SmallVectorImpl &ArgLocs,
282453 const SmallVectorImpl &Args) {
283 static const MCPhysReg RegList[] = {
454 static const MCPhysReg CRegList[] = {
284455 MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15
285456 };
286 static const unsigned NbRegs = array_lengthof(RegList);
457 static const unsigned CNbRegs = array_lengthof(CRegList);
458 static const MCPhysReg BuiltinRegList[] = {
459 MSP430::R8, MSP430::R9, MSP430::R10, MSP430::R11,
460 MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15
461 };
462 static const unsigned BuiltinNbRegs = array_lengthof(BuiltinRegList);
463
464 ArrayRef RegList;
465 unsigned NbRegs;
466
467 bool Builtin = (State.getCallingConv() == CallingConv::MSP430_BUILTIN);
468 if (Builtin) {
469 RegList = BuiltinRegList;
470 NbRegs = BuiltinNbRegs;
471 } else {
472 RegList = CRegList;
473 NbRegs = CNbRegs;
474 }
287475
288476 if (State.isVarArg()) {
289477 AnalyzeVarArgs(State, Args);
292480
293481 SmallVector ArgsParts;
294482 ParseFunctionArgs(Args, ArgsParts);
483
484 if (Builtin) {
485 assert(ArgsParts.size() == 2 &&
486 "Builtin calling convention requires two arguments");
487 }
295488
296489 unsigned RegsLeft = NbRegs;
297490 bool UsedStack = false;
321514 }
322515
323516 unsigned Parts = ArgsParts[i];
517
518 if (Builtin) {
519 assert(Parts == 4 &&
520 "Builtin calling convention requires 64-bit arguments");
521 }
324522
325523 if (!UsedStack && Parts == 2 && RegsLeft == 1) {
326524 // Special case for 32-bit register split, see EABI section 3.3.3
399597 switch (CallConv) {
400598 default:
401599 llvm_unreachable("Unsupported calling convention");
600 case CallingConv::MSP430_BUILTIN:
402601 case CallingConv::Fast:
403602 case CallingConv::C:
404603 return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
597796
598797 /// LowerCCCCallTo - functions arguments are copied from virtual regs to
599798 /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
600 // TODO: sret.
601799 SDValue MSP430TargetLowering::LowerCCCCallTo(
602800 SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg,
603801 bool isTailCall, const SmallVectorImpl &Outs,
209209 // a use to prevent stack-pointer assignments that appear immediately
210210 // before calls from potentially appearing dead. Uses for argument
211211 // registers are added manually.
212 let Defs = [R12, R13, R14, R15, SR],
212 let Defs = [R11, R12, R13, R14, R15, SR],
213213 Uses = [SP] in {
214214 def CALLi : II16i<0x0,
215215 (outs), (ins i16imm:$dst),
4040 const Function* F = MF->getFunction();
4141 static const MCPhysReg CalleeSavedRegs[] = {
4242 MSP430::FP, MSP430::R5, MSP430::R6, MSP430::R7,
43 MSP430::R8, MSP430::R9, MSP430::R10, MSP430::R11,
43 MSP430::R8, MSP430::R9, MSP430::R10,
4444 0
4545 };
4646 static const MCPhysReg CalleeSavedRegsFP[] = {
4747 MSP430::R5, MSP430::R6, MSP430::R7,
48 MSP430::R8, MSP430::R9, MSP430::R10, MSP430::R11,
48 MSP430::R8, MSP430::R9, MSP430::R10,
4949 0
5050 };
5151 static const MCPhysReg CalleeSavedRegsIntr[] = {
+0
-22
test/CodeGen/MSP430/2009-11-05-8BitLibcalls.ll less more
None ; RUN: llc < %s | FileCheck %s
1
2 target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"
3 target triple = "msp430-elf"
4
5 @g_29 = common global i8 0, align 1 ; [#uses=0]
6
7 define signext i8 @foo(i8 signext %_si1, i8 signext %_si2) nounwind readnone {
8 entry:
9 ; CHECK-LABEL: foo:
10 ; CHECK: call #__mulqi3
11 %mul = mul i8 %_si2, %_si1 ; [#uses=1]
12 ret i8 %mul
13 }
14
15 define void @uint81(i16* nocapture %p_32) nounwind {
16 entry:
17 %call = tail call i16 @bar(i8* bitcast (i8 (i8, i8)* @foo to i8*)) nounwind ; [#uses=0]
18 ret void
19 }
20
21 declare i16 @bar(i8*)
0 ; RUN: llc -O0 -mhwmult=16bit < %s | FileCheck %s
1
2 target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16-a0:16:16"
3 target triple = "msp430---elf"
4
5 @g_i32 = global i32 123, align 8
6 @g_i64 = global i64 456, align 8
7 @g_i16 = global i16 789, align 8
8
9 define i16 @mpyi() #0 {
10 entry:
11 ; CHECK: mpyi:
12
13 ; CHECK: call #__mspabi_mpyi_hw
14 %0 = load volatile i16, i16* @g_i16, align 8
15 %1 = mul i16 %0, %0
16
17 ret i16 %1
18 }
19
20 define i32 @mpyli() #0 {
21 entry:
22 ; CHECK: mpyli:
23
24 ; CHECK: call #__mspabi_mpyl_hw
25 %0 = load volatile i32, i32* @g_i32, align 8
26 %1 = mul i32 %0, %0
27
28 ret i32 %1
29 }
30
31 define i64 @mpylli() #0 {
32 entry:
33 ; CHECK: mpylli:
34
35 ; CHECK: call #__mspabi_mpyll_hw
36 %0 = load volatile i64, i64* @g_i64, align 8
37 %1 = mul i64 %0, %0
38
39 ret i64 %1
40 }
41
42 attributes #0 = { nounwind }
0 ; RUN: llc -O0 -mhwmult=32bit < %s | FileCheck %s
1
2 target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16-a0:16:16"
3 target triple = "msp430---elf"
4
5 @g_i32 = global i32 123, align 8
6 @g_i64 = global i64 456, align 8
7 @g_i16 = global i16 789, align 8
8
9 define i16 @mpyi() #0 {
10 entry:
11 ; CHECK: mpyi:
12
13 ; CHECK: call #__mspabi_mpyi_hw
14 %0 = load volatile i16, i16* @g_i16, align 8
15 %1 = mul i16 %0, %0
16
17 ret i16 %1
18 }
19
20 define i32 @mpyli() #0 {
21 entry:
22 ; CHECK: mpyli:
23
24 ; CHECK: call #__mspabi_mpyl_hw32
25 %0 = load volatile i32, i32* @g_i32, align 8
26 %1 = mul i32 %0, %0
27
28 ret i32 %1
29 }
30
31 define i64 @mpylli() #0 {
32 entry:
33 ; CHECK: mpylli:
34
35 ; CHECK: call #__mspabi_mpyll_hw32
36 %0 = load volatile i64, i64* @g_i64, align 8
37 %1 = mul i64 %0, %0
38
39 ret i64 %1
40 }
41
42 attributes #0 = { nounwind }
0 ; RUN: llc -O0 -mhwmult=f5series < %s | FileCheck %s
1
2 target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16-a0:16:16"
3 target triple = "msp430---elf"
4
5 @g_i32 = global i32 123, align 8
6 @g_i64 = global i64 456, align 8
7 @g_i16 = global i16 789, align 8
8
9 define i16 @mpyi() #0 {
10 entry:
11 ; CHECK: mpyi:
12
13 ; CHECK: call #__mspabi_mpyi_f5hw
14 %0 = load volatile i16, i16* @g_i16, align 8
15 %1 = mul i16 %0, %0
16
17 ret i16 %1
18 }
19
20 define i32 @mpyli() #0 {
21 entry:
22 ; CHECK: mpyli:
23
24 ; CHECK: call #__mspabi_mpyl_f5hw
25 %0 = load volatile i32, i32* @g_i32, align 8
26 %1 = mul i32 %0, %0
27
28 ret i32 %1
29 }
30
31 define i64 @mpylli() #0 {
32 entry:
33 ; CHECK: mpylli:
34
35 ; CHECK: call #__mspabi_mpyll_f5hw
36 %0 = load volatile i64, i64* @g_i64, align 8
37 %1 = mul i64 %0, %0
38
39 ret i64 %1
40 }
41
42 attributes #0 = { nounwind }
1111 store i16 %i, i16* %i.addr, align 2
1212 %0 = load i16, i16* %i.addr, align 2
1313 ; CHECK: mov.w #2, r13
14 ; CHECK: call #__mulhi3hw_noint
14 ; CHECK: call #__mspabi_mpyi
1515 ; CHECK: br .LJTI0_0(r12)
1616 switch i16 %0, label %sw.default [
1717 i16 0, label %sw.bb
0 ; RUN: llc -O0 < %s | FileCheck %s
1
2 target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16-a0:16:16"
3 target triple = "msp430---elf"
4
5 @g_double = global double 123.0, align 8
6 @g_float = global float 123.0, align 8
7 @g_i32 = global i32 123, align 8
8 @g_i64 = global i64 456, align 8
9 @g_i16 = global i16 789, align 8
10
11 define float @d2f() #0 {
12 entry:
13 ; CHECK: d2f:
14
15 ; CHECK: call #__mspabi_cvtdf
16 %0 = load volatile double, double* @g_double, align 8
17 %1 = fptrunc double %0 to float
18
19 ret float %1
20 }
21
22 define double @f2d() #0 {
23 entry:
24 ; CHECK: f2d:
25
26 ; CHECK: call #__mspabi_cvtfd
27 %0 = load volatile float, float* @g_float, align 8
28 %1 = fpext float %0 to double
29
30 ret double %1
31 }
32
33 define i32 @d2l() #0 {
34 entry:
35 ; CHECK: d2l:
36
37 ; CHECK: call #__mspabi_fixdli
38 %0 = load volatile double, double* @g_double, align 8
39 %1 = fptosi double %0 to i32
40
41 ret i32 %1
42 }
43
44 define i64 @d2ll() #0 {
45 entry:
46 ; CHECK: d2ll:
47
48 ; CHECK: call #__mspabi_fixdlli
49 %0 = load volatile double, double* @g_double, align 8
50 %1 = fptosi double %0 to i64
51
52 ret i64 %1
53 }
54
55 define i32 @d2ul() #0 {
56 entry:
57 ; CHECK: d2ul:
58
59 ; CHECK: call #__mspabi_fixdul
60 %0 = load volatile double, double* @g_double, align 8
61 %1 = fptoui double %0 to i32
62
63 ret i32 %1
64 }
65
66 define i64 @d2ull() #0 {
67 entry:
68 ; CHECK: d2ull:
69
70 ; CHECK: call #__mspabi_fixdull
71 %0 = load volatile double, double* @g_double, align 8
72 %1 = fptoui double %0 to i64
73
74 ret i64 %1
75 }
76
77 define i32 @f2l() #0 {
78 entry:
79 ; CHECK: f2l:
80
81 ; CHECK: call #__mspabi_fixfli
82 %0 = load volatile float, float* @g_float, align 8
83 %1 = fptosi float %0 to i32
84
85 ret i32 %1
86 }
87
88 define i64 @f2ll() #0 {
89 entry:
90 ; CHECK: f2ll:
91
92 ; CHECK: call #__mspabi_fixflli
93 %0 = load volatile float, float* @g_float, align 8
94 %1 = fptosi float %0 to i64
95
96 ret i64 %1
97 }
98
99 define i32 @f2ul() #0 {
100 entry:
101 ; CHECK: f2ul:
102
103 ; CHECK: call #__mspabi_fixful
104 %0 = load volatile float, float* @g_float, align 8
105 %1 = fptoui float %0 to i32
106
107 ret i32 %1
108 }
109
110 define i64 @f2ull() #0 {
111 entry:
112 ; CHECK: f2ull:
113
114 ; CHECK: call #__mspabi_fixfull
115 %0 = load volatile float, float* @g_float, align 8
116 %1 = fptoui float %0 to i64
117
118 ret i64 %1
119 }
120
121 define double @l2d() #0 {
122 entry:
123 ; CHECK: l2d:
124
125 ; CHECK: call #__mspabi_fltlid
126 %0 = load volatile i32, i32* @g_i32, align 8
127 %1 = sitofp i32 %0 to double
128
129 ret double %1
130 }
131
132 define double @ll2d() #0 {
133 entry:
134 ; CHECK: ll2d:
135
136 ; CHECK: call #__mspabi_fltllid
137 %0 = load volatile i64, i64* @g_i64, align 8
138 %1 = sitofp i64 %0 to double
139
140 ret double %1
141 }
142
143 define double @ul2d() #0 {
144 entry:
145 ; CHECK: ul2d:
146
147 ; CHECK: call #__mspabi_fltuld
148 %0 = load volatile i32, i32* @g_i32, align 8
149 %1 = uitofp i32 %0 to double
150
151 ret double %1
152 }
153
154 define double @ull2d() #0 {
155 entry:
156 ; CHECK: ull2d:
157
158 ; CHECK: call #__mspabi_fltulld
159 %0 = load volatile i64, i64* @g_i64, align 8
160 %1 = uitofp i64 %0 to double
161
162 ret double %1
163 }
164
165 define float @l2f() #0 {
166 entry:
167 ; CHECK: l2f:
168
169 ; CHECK: call #__mspabi_fltlif
170 %0 = load volatile i32, i32* @g_i32, align 8
171 %1 = sitofp i32 %0 to float
172
173 ret float %1
174 }
175
176 define float @ll2f() #0 {
177 entry:
178 ; CHECK: ll2f:
179
180 ; CHECK: call #__mspabi_fltllif
181 %0 = load volatile i64, i64* @g_i64, align 8
182 %1 = sitofp i64 %0 to float
183
184 ret float %1
185 }
186
187 define float @ul2f() #0 {
188 entry:
189 ; CHECK: ul2f:
190
191 ; CHECK: call #__mspabi_fltulf
192 %0 = load volatile i32, i32* @g_i32, align 8
193 %1 = uitofp i32 %0 to float
194
195 ret float %1
196 }
197
198 define float @ull2f() #0 {
199 entry:
200 ; CHECK: ull2f:
201
202 ; CHECK: call #__mspabi_fltullf
203 %0 = load volatile i64, i64* @g_i64, align 8
204 %1 = uitofp i64 %0 to float
205
206 ret float %1
207 }
208
209 define i1 @cmpd_oeq() #0 {
210 entry:
211 ; CHECK: cmpd_oeq:
212
213 ; CHECK: call #__mspabi_cmpd
214 %0 = load volatile double, double* @g_double, align 8
215 %1 = fcmp oeq double %0, 123.0
216
217 ret i1 %1
218 }
219
220 define i1 @cmpd_une() #0 {
221 entry:
222 ; CHECK: cmpd_une:
223
224 ; CHECK: call #__mspabi_cmpd
225 %0 = load volatile double, double* @g_double, align 8
226 %1 = fcmp une double %0, 123.0
227
228 ret i1 %1
229 }
230
231 define i1 @cmpd_oge() #0 {
232 entry:
233 ; CHECK: cmpd_oge:
234
235 ; CHECK: call #__mspabi_cmpd
236 %0 = load volatile double, double* @g_double, align 8
237 %1 = fcmp oge double %0, 123.0
238
239 ret i1 %1
240 }
241
242 define i1 @cmpd_olt() #0 {
243 entry:
244 ; CHECK: cmpd_olt:
245
246 ; CHECK: call #__mspabi_cmpd
247 %0 = load volatile double, double* @g_double, align 8
248 %1 = fcmp olt double %0, 123.0
249
250 ret i1 %1
251 }
252
253 define i1 @cmpd_ole() #0 {
254 entry:
255 ; CHECK: cmpd_ole:
256
257 ; CHECK: call #__mspabi_cmpd
258 %0 = load volatile double, double* @g_double, align 8
259 %1 = fcmp ole double %0, 123.0
260
261 ret i1 %1
262 }
263
264 define i1 @cmpd_ogt() #0 {
265 entry:
266 ; CHECK: cmpd_ogt:
267
268 ; CHECK: call #__mspabi_cmpd
269 %0 = load volatile double, double* @g_double, align 8
270 %1 = fcmp ogt double %0, 123.0
271
272 ret i1 %1
273 }
274
275 define i1 @cmpf_oeq() #0 {
276 entry:
277 ; CHECK: cmpf_oeq:
278
279 ; CHECK: call #__mspabi_cmpf
280 %0 = load volatile float, float* @g_float, align 8
281 %1 = fcmp oeq float %0, 123.0
282
283 ret i1 %1
284 }
285
286 define i1 @cmpf_une() #0 {
287 entry:
288 ; CHECK: cmpf_une:
289
290 ; CHECK: call #__mspabi_cmpf
291 %0 = load volatile float, float* @g_float, align 8
292 %1 = fcmp une float %0, 123.0
293
294 ret i1 %1
295 }
296
297 define i1 @cmpf_oge() #0 {
298 entry:
299 ; CHECK: cmpf_oge:
300
301 ; CHECK: call #__mspabi_cmpf
302 %0 = load volatile float, float* @g_float, align 8
303 %1 = fcmp oge float %0, 123.0
304
305 ret i1 %1
306 }
307
308 define i1 @cmpf_olt() #0 {
309 entry:
310 ; CHECK: cmpf_olt:
311
312 ; CHECK: call #__mspabi_cmpf
313 %0 = load volatile float, float* @g_float, align 8
314 %1 = fcmp olt float %0, 123.0
315
316 ret i1 %1
317 }
318
319 define i1 @cmpf_ole() #0 {
320 entry:
321 ; CHECK: cmpf_ole:
322
323 ; CHECK: call #__mspabi_cmpf
324 %0 = load volatile float, float* @g_float, align 8
325 %1 = fcmp ole float %0, 123.0
326
327 ret i1 %1
328 }
329
330 define i1 @cmpf_ogt() #0 {
331 entry:
332 ; CHECK: cmpf_ogt:
333
334 ; CHECK: call #__mspabi_cmpf
335 %0 = load volatile float, float* @g_float, align 8
336 %1 = fcmp ogt float %0, 123.0
337
338 ret i1 %1
339 }
340
341 define double @addd() #0 {
342 entry:
343 ; CHECK: addd:
344
345 ; CHECK: call #__mspabi_addd
346 %0 = load volatile double, double* @g_double, align 8
347 %1 = fadd double %0, 123.0
348
349 ret double %1
350 }
351
352 define float @addf() #0 {
353 entry:
354 ; CHECK: addf:
355
356 ; CHECK: call #__mspabi_addf
357 %0 = load volatile float, float* @g_float, align 8
358 %1 = fadd float %0, 123.0
359
360 ret float %1
361 }
362
363 define double @divd() #0 {
364 entry:
365 ; CHECK: divd:
366
367 ; CHECK: call #__mspabi_divd
368 %0 = load volatile double, double* @g_double, align 8
369 %1 = fdiv double %0, 123.0
370
371 ret double %1
372 }
373
374 define float @divf() #0 {
375 entry:
376 ; CHECK: divf:
377
378 ; CHECK: call #__mspabi_divf
379 %0 = load volatile float, float* @g_float, align 8
380 %1 = fdiv float %0, 123.0
381
382 ret float %1
383 }
384
385 define double @mpyd() #0 {
386 entry:
387 ; CHECK: mpyd:
388
389 ; CHECK: call #__mspabi_mpyd
390 %0 = load volatile double, double* @g_double, align 8
391 %1 = fmul double %0, 123.0
392
393 ret double %1
394 }
395
396 define float @mpyf() #0 {
397 entry:
398 ; CHECK: mpyf:
399
400 ; CHECK: call #__mspabi_mpyf
401 %0 = load volatile float, float* @g_float, align 8
402 %1 = fmul float %0, 123.0
403
404 ret float %1
405 }
406
407 define double @subd() #0 {
408 entry:
409 ; CHECK: subd:
410
411 ; CHECK: call #__mspabi_subd
412 %0 = load volatile double, double* @g_double, align 8
413 %1 = fsub double %0, %0
414
415 ret double %1
416 }
417
418 define float @subf() #0 {
419 entry:
420 ; CHECK: subf:
421
422 ; CHECK: call #__mspabi_subf
423 %0 = load volatile float, float* @g_float, align 8
424 %1 = fsub float %0, %0
425
426 ret float %1
427 }
428
429 define i16 @divi() #0 {
430 entry:
431 ; CHECK: divi:
432
433 ; CHECK: call #__mspabi_divi
434 %0 = load volatile i16, i16* @g_i16, align 8
435 %1 = sdiv i16 %0, %0
436
437 ret i16 %1
438 }
439
440 define i32 @divli() #0 {
441 entry:
442 ; CHECK: divli:
443
444 ; CHECK: call #__mspabi_divli
445 %0 = load volatile i32, i32* @g_i32, align 8
446 %1 = sdiv i32 %0, %0
447
448 ret i32 %1
449 }
450
451 define i64 @divlli() #0 {
452 entry:
453 ; CHECK: divlli:
454
455 ; CHECK: call #__mspabi_divlli
456 %0 = load volatile i64, i64* @g_i64, align 8
457 %1 = sdiv i64 %0, %0
458
459 ret i64 %1
460 }
461
462 define i16 @divu() #0 {
463 entry:
464 ; CHECK: divu:
465
466 ; CHECK: call #__mspabi_divu
467 %0 = load volatile i16, i16* @g_i16, align 8
468 %1 = udiv i16 %0, %0
469
470 ret i16 %1
471 }
472
473 define i32 @divul() #0 {
474 entry:
475 ; CHECK: divul:
476
477 ; CHECK: call #__mspabi_divul
478 %0 = load volatile i32, i32* @g_i32, align 8
479 %1 = udiv i32 %0, %0
480
481 ret i32 %1
482 }
483
484 define i64 @divull() #0 {
485 entry:
486 ; CHECK: divull:
487
488 ; CHECK: call #__mspabi_divull
489 %0 = load volatile i64, i64* @g_i64, align 8
490 %1 = udiv i64 %0, %0
491
492 ret i64 %1
493 }
494
495 define i16 @remi() #0 {
496 entry:
497 ; CHECK: remi:
498
499 ; CHECK: call #__mspabi_remi
500 %0 = load volatile i16, i16* @g_i16, align 8
501 %1 = srem i16 %0, %0
502
503 ret i16 %1
504 }
505
506 define i32 @remli() #0 {
507 entry:
508 ; CHECK: remli:
509
510 ; CHECK: call #__mspabi_remli
511 %0 = load volatile i32, i32* @g_i32, align 8
512 %1 = srem i32 %0, %0
513
514 ret i32 %1
515 }
516
517 define i64 @remlli() #0 {
518 entry:
519 ; CHECK: remlli:
520
521 ; CHECK: call #__mspabi_remlli
522 %0 = load volatile i64, i64* @g_i64, align 8
523 %1 = srem i64 %0, %0
524
525 ret i64 %1
526 }
527
528 define i16 @remu() #0 {
529 entry:
530 ; CHECK: remu:
531
532 ; CHECK: call #__mspabi_remu
533 %0 = load volatile i16, i16* @g_i16, align 8
534 %1 = urem i16 %0, %0
535
536 ret i16 %1
537 }
538
539 define i32 @remul() #0 {
540 entry:
541 ; CHECK: remul:
542
543 ; CHECK: call #__mspabi_remul
544 %0 = load volatile i32, i32* @g_i32, align 8
545 %1 = urem i32 %0, %0
546
547 ret i32 %1
548 }
549
550 define i64 @remull() #0 {
551 entry:
552 ; CHECK: remull:
553
554 ; CHECK: call #__mspabi_remull
555 %0 = load volatile i64, i64* @g_i64, align 8
556 %1 = urem i64 %0, %0
557
558 ret i64 %1
559 }
560
561 define i16 @mpyi() #0 {
562 entry:
563 ; CHECK: mpyi:
564
565 ; CHECK: call #__mspabi_mpyi
566 %0 = load volatile i16, i16* @g_i16, align 8
567 %1 = mul i16 %0, %0
568
569 ret i16 %1
570 }
571
572 define i32 @mpyli() #0 {
573 entry:
574 ; CHECK: mpyli:
575
576 ; CHECK: call #__mspabi_mpyl
577 %0 = load volatile i32, i32* @g_i32, align 8
578 %1 = mul i32 %0, %0
579
580 ret i32 %1
581 }
582
583 define i64 @mpylli() #0 {
584 entry:
585 ; CHECK: mpylli:
586
587 ; CHECK: call #__mspabi_mpyll
588 %0 = load volatile i64, i64* @g_i64, align 8
589 %1 = mul i64 %0, %0
590
591 ret i64 %1
592 }
593
594 attributes #0 = { nounwind }
0 ; RUN: llc < %s | FileCheck %s
1
2 target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"
3 target triple = "msp430-elf"
4
5 @g_29 = common global i8 0, align 1 ; [#uses=0]
6
7 define signext i8 @foo(i8 signext %_si1, i8 signext %_si2) nounwind readnone {
8 entry:
9 ; CHECK-LABEL: foo:
10 ; CHECK: call #__mspabi_mpyi
11 %mul = mul i8 %_si2, %_si1 ; [#uses=1]
12 ret i8 %mul
13 }
14
15 define void @uint81(i16* nocapture %p_32) nounwind {
16 entry:
17 %call = tail call i16 @bar(i8* bitcast (i8 (i8, i8)* @foo to i8*)) nounwind ; [#uses=0]
18 ret void
19 }
20
21 declare i16 @bar(i8*)