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
}});
125 getActionDefinitionsBuilder(G_VASTART
)
129 getActionDefinitionsBuilder(G_FCONSTANT
)
130 .legalFor({s32
, s64
});
132 getActionDefinitionsBuilder({G_FADD
, G_FSUB
, G_FMUL
, G_FDIV
, G_FABS
, G_FSQRT
})
133 .legalFor({s32
, s64
});
135 getActionDefinitionsBuilder(G_FCMP
)
136 .legalFor({{s32
, s32
}, {s32
, s64
}})
139 getActionDefinitionsBuilder({G_FCEIL
, G_FFLOOR
})
140 .libcallFor({s32
, s64
});
142 getActionDefinitionsBuilder(G_FPEXT
)
143 .legalFor({{s64
, s32
}});
145 getActionDefinitionsBuilder(G_FPTRUNC
)
146 .legalFor({{s32
, s64
}});
148 // FP to int conversion instructions
149 getActionDefinitionsBuilder(G_FPTOSI
)
150 .legalForCartesianProduct({s32
}, {s64
, s32
})
151 .libcallForCartesianProduct({s64
}, {s64
, s32
})
154 getActionDefinitionsBuilder(G_FPTOUI
)
155 .libcallForCartesianProduct({s64
}, {s64
, s32
})
156 .lowerForCartesianProduct({s32
}, {s64
, s32
})
159 // Int to FP conversion instructions
160 getActionDefinitionsBuilder(G_SITOFP
)
161 .legalForCartesianProduct({s64
, s32
}, {s32
})
162 .libcallForCartesianProduct({s64
, s32
}, {s64
})
165 getActionDefinitionsBuilder(G_UITOFP
)
166 .libcallForCartesianProduct({s64
, s32
}, {s64
})
167 .customForCartesianProduct({s64
, s32
}, {s32
})
170 getActionDefinitionsBuilder(G_SEXT_INREG
).lower();
173 verify(*ST
.getInstrInfo());
176 bool MipsLegalizerInfo::legalizeCustom(MachineInstr
&MI
,
177 MachineRegisterInfo
&MRI
,
178 MachineIRBuilder
&MIRBuilder
,
179 GISelChangeObserver
&Observer
) const {
181 using namespace TargetOpcode
;
183 MIRBuilder
.setInstr(MI
);
184 const MipsSubtarget
&STI
=
185 static_cast<const MipsSubtarget
&>(MIRBuilder
.getMF().getSubtarget());
186 const LLT s32
= LLT::scalar(32);
187 const LLT s64
= LLT::scalar(64);
189 switch (MI
.getOpcode()) {
191 Register Dst
= MI
.getOperand(0).getReg();
192 Register Src
= MI
.getOperand(1).getReg();
193 LLT DstTy
= MRI
.getType(Dst
);
194 LLT SrcTy
= MRI
.getType(Src
);
198 if (DstTy
!= s32
&& DstTy
!= s64
)
201 // Let 0xABCDEFGH be given unsigned in MI.getOperand(1). First let's convert
202 // unsigned to double. Mantissa has 52 bits so we use following trick:
203 // First make floating point bit mask 0x43300000ABCDEFGH.
204 // Mask represents 2^52 * 0x1.00000ABCDEFGH i.e. 0x100000ABCDEFGH.0 .
205 // Next, subtract 2^52 * 0x1.0000000000000 i.e. 0x10000000000000.0 from it.
206 // Done. Trunc double to float if needed.
208 MachineInstrBuilder Bitcast
= MIRBuilder
.buildInstr(
209 STI
.isFP64bit() ? Mips::BuildPairF64_64
: Mips::BuildPairF64
, {s64
},
210 {Src
, MIRBuilder
.buildConstant(s32
, UINT32_C(0x43300000))});
211 Bitcast
.constrainAllUses(MIRBuilder
.getTII(), *STI
.getRegisterInfo(),
212 *STI
.getRegBankInfo());
214 MachineInstrBuilder TwoP52FP
= MIRBuilder
.buildFConstant(
215 s64
, BitsToDouble(UINT64_C(0x4330000000000000)));
218 MIRBuilder
.buildFSub(Dst
, Bitcast
, TwoP52FP
);
220 MachineInstrBuilder ResF64
= MIRBuilder
.buildFSub(s64
, Bitcast
, TwoP52FP
);
221 MIRBuilder
.buildFPTrunc(Dst
, ResF64
);
224 MI
.eraseFromParent();
234 bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr
&MI
,
235 MachineRegisterInfo
&MRI
,
236 MachineIRBuilder
&MIRBuilder
) const {
237 const MipsSubtarget
&ST
=
238 static_cast<const MipsSubtarget
&>(MI
.getMF()->getSubtarget());
239 const MipsInstrInfo
&TII
= *ST
.getInstrInfo();
240 const MipsRegisterInfo
&TRI
= *ST
.getRegisterInfo();
241 const RegisterBankInfo
&RBI
= *ST
.getRegBankInfo();
242 MIRBuilder
.setInstr(MI
);
244 switch (MI
.getIntrinsicID()) {
245 case Intrinsic::memcpy
:
246 case Intrinsic::memset
:
247 case Intrinsic::memmove
:
248 if (createMemLibcall(MIRBuilder
, MRI
, MI
) ==
249 LegalizerHelper::UnableToLegalize
)
251 MI
.eraseFromParent();
253 case Intrinsic::trap
: {
254 MachineInstr
*Trap
= MIRBuilder
.buildInstr(Mips::TRAP
);
255 MI
.eraseFromParent();
256 return constrainSelectedInstRegOperands(*Trap
, TII
, TRI
, RBI
);
258 case Intrinsic::vacopy
: {
259 Register Tmp
= MRI
.createGenericVirtualRegister(LLT::pointer(0, 32));
260 MachinePointerInfo MPO
;
261 MIRBuilder
.buildLoad(Tmp
, MI
.getOperand(2),
262 *MI
.getMF()->getMachineMemOperand(
263 MPO
, MachineMemOperand::MOLoad
, 4, 4));
264 MIRBuilder
.buildStore(Tmp
, MI
.getOperand(1),
265 *MI
.getMF()->getMachineMemOperand(
266 MPO
, MachineMemOperand::MOStore
, 4, 4));
267 MI
.eraseFromParent();