LLVM学习笔记(62)

4.4.3.3.2. 指令处理的设置

4.4.3.3.2.1. 目标机器相关设置

除了基类以外,X86TargetLowering构造函数本身也是一个庞然大物,我们必须要分段来看。V7.0做了不小的改动,改进了代码的结构,修改了一些指令的设置。

100     X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,

101                                          const X86Subtarget &STI)

102         : TargetLowering(TM), Subtarget(&STI) {

103       bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();

104       X86ScalarSSEf64 = Subtarget->hasSSE2();

105       X86ScalarSSEf32 = Subtarget->hasSSE1();

106       MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0));

107    

108       // Set up the TargetLowering object.

109    

110       // X86 is weird. It always uses i8 for shift amounts and setcc results.

111       setBooleanContents(ZeroOrOneBooleanContent);

112       // X86-SSE is even stranger. It uses -1 or 0 for vector masks.

113       setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);

114    

115       // For 64-bit, since we have so many registers, use the ILP scheduler.

116       // For 32-bit, use the register pressure specific scheduling.

117       // For Atom, always use ILP scheduling.

118       if (Subtarget->isAtom())

119         setSchedulingPreference(Sched::ILP);

120       else if (Subtarget->is64Bit())

121         setSchedulingPreference(Sched::ILP);

122       else

123         setSchedulingPreference(Sched::RegPressure);

124       const X86RegisterInfo *RegInfo = Subtarget->getRegisterInfo();

125      setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());

126    

127       // Bypass expensive divides on Atom when compiling with O2.

128       if (TM.getOptLevel() >= CodeGenOpt::Default) {

129         if (Subtarget->hasSlowDivide32())

130           addBypassSlowDiv(32, 8);

131         if (Subtarget->hasSlowDivide64() && Subtarget->is64Bit())

132           addBypassSlowDiv(64, 32);

133       }

134    

135       if (Subtarget->isTargetKnownWindowsMSVC() ||

136           Subtarget.isTargetWindowsItanium()) {

137         // Setup Windows compiler runtime calls.

138         setLibcallName(RTLIB::SDIV_I64, "_alldiv");

139         setLibcallName(RTLIB::UDIV_I64, "_aulldiv");

140         setLibcallName(RTLIB::SREM_I64, "_allrem");

141         setLibcallName(RTLIB::UREM_I64, "_aullrem");

142         setLibcallName(RTLIB::MUL_I64, "_allmul");

143         setLibcallCallingConv(RTLIB::SDIV_I64, CallingConv::X86_StdCall);

144         setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::X86_StdCall);

145         setLibcallCallingConv(RTLIB::SREM_I64, CallingConv::X86_StdCall);

146         setLibcallCallingConv(RTLIB::UREM_I64, CallingConv::X86_StdCall);

147         setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::X86_StdCall);

148       }

149    

150       if (Subtarget->isTargetDarwin()) {

151         // Darwin should use _setjmp/_longjmp instead of setjmp/longjmp.

152         setUseUnderscoreSetJmp(false);

153         setUseUnderscoreLongJmp(false);

154       } else if (Subtarget->isTargetWindowsGNU()) {

155         // MS runtime is weird: it exports _setjmp, but longjmp!

156         setUseUnderscoreSetJmp(true);

157         setUseUnderscoreLongJmp(false);

158       } else {

159         setUseUnderscoreSetJmp(true);

160         setUseUnderscoreLongJmp(true);

161       }

162    

163       // Set up the register classes.

164       addRegisterClass(MVT::i8, &X86::GR8RegClass);

165       addRegisterClass(MVT::i16, &X86::GR16RegClass);

166       addRegisterClass(MVT::i32, &X86::GR32RegClass);

167       if (Subtarget->is64Bit())

168         addRegisterClass(MVT::i64, &X86::GR64RegClass);

111行将布尔值的表示方式更改为ZeroOrOneBooleanContent(原是UndefinedBooleanContent)。118~123行根据CPU类型更改调度模式。125行的getStackRegister()返回X86RegisterInfo的StackPtr成员(它在X86RegisterInfo构造函数里根据目标机器设置)。

基类TargetLoweringBase类型为DenseMap<unsigned int, unsigned int>的BypassSlowDivWidths的容器用于通知代码生成器绕过慢的除法或取余指令。例如,BypassSlowDivWidths[32,8]格式代码生成器在操作数为小于256的正整数时,使用8位div/rem指令绕过32位div/rem指令。上面130行为类似Atom的处理器设置这个容器项。

164行以下的GRXRegClass都是由TableGen根据.td文件描述生成在X86GenRegisterInfo.inc文件里的对象定义。为了关联这些对象与它们的类型,定义了容器AvailableRegClasses(类型std::vector< std::pair<MVT, const TargetRegisterClass*>>)与容器const TargetRegisterClass *RegClassForVT[MVT:: LAST_VALUETYPE],并通过addRegisterClass()实现关联。

4.4.3.3.2.2. 标量操作数类型的处理设置

下面根据目标X86芯片支持的指令集为各种操作设置处理活动。这是一些比较繁琐的工作。要针对每种IR操作与每种操作数类型来设置。下面Expand的含义是建议将操作数分为较小的两部分。

X86TargetLowering::X86TargetLowering(续)

170       for (MVT VT : MVT::integer_valuetypes())

171         setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);

172    

173       // We don't accept any truncstore of integer registers.

174       setTruncStoreAction(MVT::i64, MVT::i32, Expand);

175       setTruncStoreAction(MVT::i64, MVT::i16, Expand);

176       setTruncStoreAction(MVT::i64, MVT::i8 , Expand);

177       setTruncStoreAction(MVT::i32, MVT::i16, Expand);

178       setTruncStoreAction(MVT::i32, MVT::i8 , Expand);

179       setTruncStoreAction(MVT::i16, MVT::i8,  Expand);

180    

181       setTruncStoreAction(MVT::f64, MVT::f32, Expand);

182    

183       // SETOEQ and SETUNE require checking two conditions.

184       setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand);

185       setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand);

186       setCondCodeAction(ISD::SETOEQ, MVT::f80, Expand);

187       setCondCodeAction(ISD::SETUNE, MVT::f32, Expand);

188       setCondCodeAction(ISD::SETUNE, MVT::f64, Expand);

189       setCondCodeAction(ISD::SETUNE, MVT::f80, Expand);

190    

191       // Integer absolute.

192       if (Subtarget.hasCMov()) {

193         setOperationAction(ISD::ABS , MVT::i16  , Custom);

194         setOperationAction(ISD::ABS, MVT::i32  , Custom);

195         if (Subtarget.is64Bit())

196           setOperationAction(ISD::ABS, MVT::i64  , Custom);

197       }

198    

199       // Promote all UINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have this

200       // operation.

201       setOperationAction(ISD::UINT_TO_FP       , MVT::i1   , Promote);

202       setOperationAction(ISD::UINT_TO_FP       , MVT::i8   , Promote);

203       setOperationAction(ISD::UINT_TO_FP       , MVT::i16  , Promote);

204    

205       if (Subtarget.is64Bit()) {

206         if (!Subtarget.useSoftFloat() && Subtarget.hasAVX512())

207           // f32/f64 are legal, f80 is custom.

208           setOperationAction(ISD::UINT_TO_FP   , MVT::i32  , Custom);

209         else

210           setOperationAction(ISD::UINT_TO_FP   , MVT::i32  , Promote);

211           setOperationAction(ISD::UINT_TO_FP     , MVT::i64  , Custom);

212       } else if (!Subtarget.useSoftFloat()) {

213         // We have an algorithm for SSE2->double, and we turn this into a

214         // 64-bit FILD followed by conditional FADD for other targets.

215         setOperationAction(ISD::UINT_TO_FP     , MVT::i64  , Custom);

216         // We have an algorithm for SSE2, and we turn this into a 64-bit

217         // FILD or VCVTUSI2SS/SD for other targets.

218         setOperationAction(ISD::UINT_TO_FP     , MVT::i32  , Custom);

219       } else {

220         setOperationAction(ISD::UINT_TO_FP     , MVT::i32  , Expand);

221       }

222    

223       // Promote i1/i8 SINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have

224       // this operation.

225       setOperationAction(ISD::SINT_TO_FP       , MVT::i1   , Promote);

226       setOperationAction(ISD::SINT_TO_FP       , MVT::i8   , Promote);

227    

228       if (!Subtarget->useSoftFloat()) {

229         // SSE has no i16 to fp conversion, only i32

230         if (X86ScalarSSEf32) {

231           setOperationAction(ISD::SINT_TO_FP     , MVT::i16  , Promote);

232           // f32 and f64 cases are Legal, f80 case is not

233           setOperationAction(ISD::SINT_TO_FP     , MVT::i32  , Custom);

234         } else {

235           setOperationAction(ISD::SINT_TO_FP     , MVT::i16  , Custom);

236           setOperationAction(ISD::SINT_TO_FP     , MVT::i32  , Custom);

237         }

238       } else {

239         setOperationAction(ISD::SINT_TO_FP     , MVT::i16  , Promote);

240         setOperationAction(ISD::SINT_TO_FP     , MVT::i32  , Promote Expand);

241       }

242    

243       // Promote i1/i8 FP_TO_SINT to larger FP_TO_SINTS's, as X86 doesn't have

244       // this operation.

245       setOperationAction(ISD::FP_TO_SINT       , MVT::i1   , Promote);

246       setOperationAction(ISD::FP_TO_SINT       , MVT::i8   , Promote);

247    

248       if (!Subtarget.useSoftFloat()) {

249         // In 32-bit mode these are custom lowered.  In 64-bit mode F32 and F64

250         // are Legal, f80 is custom lowered.

251         setOperationAction(ISD::FP_TO_SINT     , MVT::i64  , Custom);

252         setOperationAction(ISD::SINT_TO_FP     , MVT::i64  , Custom);

253    

254         if (X86ScalarSSEf32) {

255           setOperationAction(ISD::FP_TO_SINT     , MVT::i16  , Promote);

256           // f32 and f64 cases are Legal, f80 case is not

257           setOperationAction(ISD::FP_TO_SINT     , MVT::i32  , Custom);

258         } else {

259           setOperationAction(ISD::FP_TO_SINT     , MVT::i16  , Custom);

260           setOperationAction(ISD::FP_TO_SINT     , MVT::i32  , Custom);

261         }

262       } else {

263         setOperationAction(ISD::FP_TO_SINT     , MVT::i16  , Promote);

264         setOperationAction(ISD::FP_TO_SINT     , MVT::i32  , Expand);

265         setOperationAction(ISD::FP_TO_SINT     , MVT::i64  , Expand);

266       }

267    

268       // Handle FP_TO_UINT by promoting the destination to a larger signed

269       // conversion.

270       setOperationAction(ISD::FP_TO_UINT       , MVT::i1   , Promote);

271       setOperationAction(ISD::FP_TO_UINT       , MVT::i8   , Promote);

272       setOperationAction(ISD::FP_TO_UINT       , MVT::i16  , Promote);

273    

274       if (Subtarget.is64Bit()) {

275         if (!Subtarget.useSoftFloat() && Subtarget.hasAVX512()) {

276           // FP_TO_UINT-i32/i64 is legal for f32/f64, but custom for f80.

277           setOperationAction(ISD::FP_TO_UINT   , MVT::i32  , Custom);

278           setOperationAction(ISD::FP_TO_UINT   , MVT::i64  , Custom);

279         } else {

280           setOperationAction(ISD::FP_TO_UINT   , MVT::i32  , Promote);

281           setOperationAction(ISD::FP_TO_UINT   , MVT::i64  , Expand);

282         }

283       } else if (!Subtarget.useSoftFloat()) {

284         // Since AVX is a superset of SSE3, only check for SSE here.

285         if (Subtarget.hasSSE1() && !Subtarget.hasSSE3())

286           // Expand FP_TO_UINT into a select.

287           // FIXME: We would like to use a Custom expander here eventually to do

288           // the optimal thing for SSE vs. the default expansion in the legalizer.

289           setOperationAction(ISD::FP_TO_UINT   , MVT::i32  , Expand);

290         else

291           // With AVX512 we can use vcvts[ds]2usi for f32/f64->i32, f80 is custom.

292           // With SSE3 we can use fisttpll to convert to a signed i64; without

293           // SSE, we're stuck with a fistpll.

294           setOperationAction(ISD::FP_TO_UINT   , MVT::i32  , Custom);

295    

296         setOperationAction(ISD::FP_TO_UINT     , MVT::i64  , Custom);

297       }

298    

299       // TODO: when we have SSE, these could be more efficient, by using movd/movq.

300       if (!X86ScalarSSEf64) {

301         setOperationAction(ISD::BITCAST        , MVT::f32  , Expand);

302         setOperationAction(ISD::BITCAST        , MVT::i32  , Expand);

303         if (Subtarget->is64Bit()) {

304           setOperationAction(ISD::BITCAST      , MVT::f64  , Expand);

305           // Without SSE, i64->f64 goes through memory.

306           setOperationAction(ISD::BITCAST      , MVT::i64  , Expand);

307         }

308       } else if (!Subtarget.is64Bit())

309         setOperationAction(ISD::BITCAST      , MVT::i64  , Custom);

310    

311       // Scalar integer divide and remainder are lowered to use operations that

312       // produce two results, to match the available instructions. This exposes

313       // the two-result form to trivial CSE, which is able to combine x/y and x%y

314       // into a single instruction.

315       //

316       // Scalar integer multiply-high is also lowered to use two-result

317       // operations, to match the available instructions. However, plain multiply

318       // (low) operations are left as Legal, as there are single-result

319       // instructions for this in x86. Using the two-result multiply instructions

320       // when both high and low results are needed must be arranged by dagcombine.

321       for (auto VT : { MVT::i8, MVT::i16, MVT::i32, MVT::i64 }) {

322         setOperationAction(ISD::MULHS, VT, Expand);

323         setOperationAction(ISD::MULHU, VT, Expand);

324         setOperationAction(ISD::SDIV, VT, Expand);

325         setOperationAction(ISD::UDIV, VT, Expand);

326         setOperationAction(ISD::SREM, VT, Expand);

327         setOperationAction(ISD::UREM, VT, Expand);

328       }

329    

330       setOperationAction(ISD::BR_JT            , MVT::Other, Expand);

331       setOperationAction(ISD::BRCOND           , MVT::Other, Custom);

332       for (auto VT : { MVT::f32, MVT::f64, MVT::f80, MVT::f128,

333                        MVT::i8,  MVT::i16, MVT::i32, MVT::i64 }) {

334         setOperationAction(ISD::BR_CC,     VT, Expand);

335         setOperationAction(ISD::SELECT_CC, VT, Expand);

336       }

337       if (Subtarget->is64Bit())

338         setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Legal);

339       setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16  , Legal);

340       setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8   , Legal);

341       setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1   , Expand);

342       setOperationAction(ISD::FP_ROUND_INREG   , MVT::f32  , Expand);

343    

344       setOperationAction(ISD::FREM             , MVT::f32  , Expand);

345       setOperationAction(ISD::FREM             , MVT::f64  , Expand);

346       setOperationAction(ISD::FREM             , MVT::f80  , Expand);

347       setOperationAction(ISD::FLT_ROUNDS_      , MVT::i32  , Custom);

348    

349       // Promote the i8 variants and force them on up to i32 which has a shorter

350      // encoding.

351       setOperationPromotedToType(ISD::CTTZ           , MVT::i8   , MVT::i32);

352       setOperationPromotedToType(ISD::CTTZ_ZERO_UNDEF, MVT::i8   , MVT::i32);

353       if (Subtarget->hasBMI()) {

354         setOperationAction(ISD::CTTZ           , MVT::i16  , Custom);

355         setOperationAction(ISD::CTTZ           , MVT::i32  , Custom);

356         setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i16  , Legal);

357         setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32  , Legal);

358         if (Subtarget->is64Bit()) {

359           setOperationAction(ISD::CTTZ         , MVT::i64  , Custom);

360           setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);

361        }

362      }

363    

364       if (Subtarget->hasLZCNT()) {

365         // When promoting the i8 variants, force them to i32 for a shorter

366         // encoding.

367         setOperationPromotedToType(ISD::CTLZ           , MVT::i8   , MVT::i32);

368         setOperationPromotedToType(ISD::CTLZ_ZERO_UNDEF, MVT::i8   , MVT::i32);

369       } else {

370         setOperationAction(ISD::CTLZ           , MVT::i8   , Custom);

371         setOperationAction(ISD::CTLZ           , MVT::i16  , Custom);

372         setOperationAction(ISD::CTLZ           , MVT::i32  , Custom);

373         setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i8   , Custom);

374         setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i16  , Custom);

375         setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32  , Custom);

376         if (Subtarget->is64Bit()) {

377           setOperationAction(ISD::CTLZ         , MVT::i64  , Custom);

378           setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Custom);

379         }

380       }

381    

382       // Special handling for half-precision floating point conversions.

383       // If we don't have F16C support, then lower half float conversions

384       // into library calls.

385       if (Subtarget->useSoftFloat() || !Subtarget->hasF16C()) {

386         setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand);

387         setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand);

388       }

389    

390       // There's never any support for operations beyond MVT::f32.

391       setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);

392       setOperationAction(ISD::FP16_TO_FP, MVT::f80, Expand);

393       setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand);

394       setOperationAction(ISD::FP_TO_FP16, MVT::f80, Expand);

395    

396       setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);

397       setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);

398       setLoadExtAction(ISD::EXTLOAD, MVT::f80, MVT::f16, Expand);

399       setTruncStoreAction(MVT::f32, MVT::f16, Expand);

400       setTruncStoreAction(MVT::f64, MVT::f16, Expand);

401       setTruncStoreAction(MVT::f80, MVT::f16, Expand);

402    

403       if (Subtarget->hasPOPCNT()) {

404         setOperationPromotedToType(ISD::CTPOP, MVT::i8, MVT::i32);

405       } else {

406         setOperationAction(ISD::CTPOP          , MVT::i8   , Expand);

407         setOperationAction(ISD::CTPOP          , MVT::i16  , Expand);

408         setOperationAction(ISD::CTPOP          , MVT::i32  , Expand);

409         if (Subtarget->is64Bit())

410           setOperationAction(ISD::CTPOP        , MVT::i64  , Expand);

411       }

412    

413       setOperationAction(ISD::READCYCLECOUNTER , MVT::i64  , Custom);

414    

415       if (!Subtarget->hasMOVBE())

416         setOperationAction(ISD::BSWAP          , MVT::i16  , Expand);

417    

418       // These should be promoted to a larger select which is supported.

419       setOperationAction(ISD::SELECT          , MVT::i1   , Promote);

420       // X86 wants to expand cmov itself.

421       for (auto VT : { MVT::f32, MVT::f64, MVT::f80, MVT::f128 }) {

422         setOperationAction(ISD::SELECT, VT, Custom);

423         setOperationAction(ISD::SETCC, VT, Custom);

424       }

425       for (auto VT : { MVT::i8, MVT::i16, MVT::i32, MVT::i64 }) {

426         if (VT == MVT::i64 && !Subtarget.is64Bit())

427           continue;

428         setOperationAction(ISD::SELECT, VT, Custom);

429         setOperationAction(ISD::SETCC,  VT, Custom);

430       }

431    

432      // Custom action for SELECT MMX and expand action for SELECT_CC MMX

433       setOperationAction(ISD::SELECT, MVT::x86mmx, Custom);

434       setOperationAction(ISD::SELECT_CC, MVT::x86mmx, Expand);

435    

436       setOperationAction(ISD::EH_RETURN       , MVT::Other, Custom);

437       // NOTE: EH_SJLJ_SETJMP/_LONGJMP are not recommended, since

438       // LLVM/Clang supports zero-cost DWARF and SEH exception handling.

439       setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom);

440       setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);

441       setOperationAction(ISD::EH_SJLJ_SETUP_DISPATCH, MVT::Other, Custom);

442       if (TM.Options.ExceptionModel == ExceptionHandling::SjLj)

443         setLibcallName(RTLIB::UNWIND_RESUME, "_Unwind_SjLj_Resume");

444    

445       // Darwin ABI issue.

446       for (auto VT : { MVT::i32, MVT::i64 }) {

447         if (VT == MVT::i64 && !Subtarget.is64Bit())

448           continue;

449         setOperationAction(ISD::ConstantPool    , VT, Custom);

450         setOperationAction(ISD::JumpTable       , VT, Custom);

451         setOperationAction(ISD::GlobalAddress   , VT, Custom);

452         setOperationAction(ISD::GlobalTLSAddress, VT, Custom);

453         setOperationAction(ISD::ExternalSymbol  , VT, Custom);

454         setOperationAction(ISD::BlockAddress    , VT, Custom);

455       }

456    

457       // 64-bit shl, sar, srl (iff 32-bit x86)

458       for (auto VT : { MVT::i32, MVT::i64 }) {

459         if (VT == MVT::i64 && !Subtarget.is64Bit())

460           continue;

461         setOperationAction(ISD::SHL_PARTS, VT, Custom);

462         setOperationAction(ISD::SRA_PARTS, VT, Custom);

463         setOperationAction(ISD::SRL_PARTS, VT, Custom);

464       }

465    

466       if (Subtarget.hasSSEPrefetch() || Subtarget.has3DNow())

467         setOperationAction(ISD::PREFETCH      , MVT::Other, Legal);

468    

469       setOperationAction(ISD::ATOMIC_FENCE  , MVT::Other, Custom);

470    

471       // Expand certain atomics

472       for (auto VT : { MVT::i8, MVT::i16, MVT::i32, MVT::i64 }) {

473        setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, VT, Custom);

474         setOperationAction(ISD::ATOMIC_LOAD_SUB, VT, Custom);

475         setOperationAction(ISD::ATOMIC_LOAD_ADD, VT, Custom);

476         setOperationAction(ISD::ATOMIC_LOAD_OR, VT, Custom);

477         setOperationAction(ISD::ATOMIC_LOAD_XOR, VT, Custom);

478         setOperationAction(ISD::ATOMIC_LOAD_AND, VT, Custom);

479         setOperationAction(ISD::ATOMIC_STORE, VT, Custom);

480       }

481    

482       if (Subtarget->hasCmpxchg16b()) {

483         setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, MVT::i128, Custom);

484       }

485    

486       // FIXME - use subtarget debug flags

487       if (!Subtarget->isTargetDarwin() && !Subtarget->isTargetELF() &&

488           !Subtarget->isTargetCygMing() && !Subtarget->isTargetWin64() &&

489           TM.Options.ExceptionModel != ExceptionHandling::SjLj) {

490         setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);

491       }

492    

493       setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);

494       setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i64, Custom);

495    

496       setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom);

497       setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom);

498    

499       setOperationAction(ISD::TRAP, MVT::Other, Legal);

500       setOperationAction(ISD::DEBUGTRAP, MVT::Other, Legal);

501    

502       // VASTART needs to be custom lowered to use the VarArgsFrameIndex

503       setOperationAction(ISD::VASTART           , MVT::Other, Custom);

504       setOperationAction(ISD::VAEND             , MVT::Other, Expand);

505       bool Is64Bit = Subtarget.is64Bit();

506       setOperationAction(ISD::VAARG,  MVT::Other, Is64Bit ? Custom : Expand);

507       setOperationAction(ISD::VACOPY, MVT::Other, Is64Bit ? Custom : Expand);

508    

509       setOperationAction(ISD::STACKSAVE,          MVT::Other, Expand);

510       setOperationAction(ISD::STACKRESTORE,       MVT::Other, Expand);

511    

512       setOperationAction(ISD::DYNAMIC_STACKALLOC, getPointerTy(*TD) PtrVT, Custom);

513    

514       // GC_TRANSITION_START and GC_TRANSITION_END need custom lowering.

515       setOperationAction(ISD::GC_TRANSITION_START, MVT::Other, Custom);

516       setOperationAction(ISD::GC_TRANSITION_END, MVT::Other, Custom);

X86TargetLowering构造函数非常冗长,但不算太复杂。上面所调用的AddPromotedToType()是将指定的操作,指定的操作数类型,与提升类型关联。维持这个关联关系的容器是PromoteToType(类型std::map<std::pair<unsigned, MVT::SimpleValueType>, MVT::SimpleValueType>,其中std::pair记录操作与操作数原始类型)。

V7.0进行了一些代码结构上的改良,例如将setOperationAction()AddPromotedToType()组合为setOperationPromotedToType(),并修改了一些指令与指定类型操作数的处理。

518行的useSoftFloat()如果返回true,表示目标机器使用软件方法实现浮点操作。不过X86处理器族都使用硬件实现浮点操作。那么下面开始处理浮点操作。

X86TargetLowering::X86TargetLowering(续)

518       if (!Subtarget->useSoftFloat() && X86ScalarSSEf64) {

519         // f32 and f64 use SSE.

520         // Set up the FP register classes.

521         addRegisterClass(MVT::f32, Subtarget.hasAVX512() ? &X86::FR32XRegClass

522                                                          : &X86::FR32RegClass);

523         addRegisterClass(MVT::f64, Subtarget.hasAVX512() ? &X86::FR64XRegClass

524                                                          : &X86::FR64RegClass);

525    

526         for (auto VT : { MVT::f32, MVT::f64 }) {

527           // Use ANDPD to simulate FABS.

528           setOperationAction(ISD::FABS, VT, Custom);

529    

530           // Use XORP to simulate FNEG.

531           setOperationAction(ISD::FNEG, VT, Custom);

532    

533           // Use ANDPD and ORPD to simulate FCOPYSIGN.

534           setOperationAction(ISD::FCOPYSIGN, VT, Custom);

535    

536           // We don't support sin/cos/fmod

537           setOperationAction(ISD::FSIN   , VT, Expand);

538           setOperationAction(ISD::FCOS   , VT, Expand);

539           setOperationAction(ISD::FSINCOS, VT, Expand);

540         }

541    

542         // Lower this to MOVMSK plus an AND.

543         setOperationAction(ISD::FGETSIGN, MVT::i64, Custom);

544         setOperationAction(ISD::FGETSIGN, MVT::i32, Custom);

545    

546         // Expand FP immediates into loads from the stack, except for the special

547         // cases we handle.

548         addLegalFPImmediate(APFloat(+0.0)); // xorpd

549         addLegalFPImmediate(APFloat(+0.0f)); // xorps

550       } else if (UseX87 && X86ScalarSSEf32) {

551         // Use SSE for f32, x87 for f64.

552         // Set up the FP register classes.

553         addRegisterClass(MVT::f32, &X86::FR32RegClass);

554         addRegisterClass(MVT::f64, &X86::RFP64RegClass);

555    

556         // Use ANDPS to simulate FABS.

557         setOperationAction(ISD::FABS , MVT::f32, Custom);

558    

559         // Use XORP to simulate FNEG.

560         setOperationAction(ISD::FNEG , MVT::f32, Custom);

561    

562         setOperationAction(ISD::UNDEF,     MVT::f64, Expand);

563    

564         // Use ANDPS and ORPS to simulate FCOPYSIGN.

565         setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);

566         setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom);

567    

568         // We don't support sin/cos/fmod

569         setOperationAction(ISD::FSIN   , MVT::f32, Expand);

570         setOperationAction(ISD::FCOS   , MVT::f32, Expand);

571         setOperationAction(ISD::FSINCOS, MVT::f32, Expand);

572    

573         // Special cases we handle for FP constants.

574         addLegalFPImmediate(APFloat(+0.0f)); // xorps

575         addLegalFPImmediate(APFloat(+0.0)); // FLD0

576         addLegalFPImmediate(APFloat(+1.0)); // FLD1

577         addLegalFPImmediate(APFloat(-0.0)); // FLD0/FCHS

578         addLegalFPImmediate(APFloat(-1.0)); // FLD1/FCHS

579    

580         // Always expand sin/cos functions even though x87 has an instruction.

581         setOperationAction(ISD::FSIN   , MVT::f64, Expand);

582         setOperationAction(ISD::FCOS   , MVT::f64, Expand);

583         setOperationAction(ISD::FSINCOS, MVT::f64, Expand);

584       } else if (UseX87) {

585         // f32 and f64 in x87.

586         // Set up the FP register classes.

587         addRegisterClass(MVT::f64, &X86::RFP64RegClass);

588         addRegisterClass(MVT::f32, &X86::RFP32RegClass);

589    

590         for (auto VT : { MVT::f32, MVT::f64 }) {

591           setOperationAction(ISD::UNDEF,     VT, Expand);

592           setOperationAction(ISD::FCOPYSIGN, VT, Expand);

593    

594           // Always expand sin/cos functions even though x87 has an instruction.

595           setOperationAction(ISD::FSIN   , VT, Expand);

596           setOperationAction(ISD::FCOS   , VT, Expand);

597           setOperationAction(ISD::FSINCOS, VT, Expand);

598        }

599         addLegalFPImmediate(APFloat(+0.0)); // FLD0

600         addLegalFPImmediate(APFloat(+1.0)); // FLD1

601         addLegalFPImmediate(APFloat(-0.0)); // FLD0/FCHS

602         addLegalFPImmediate(APFloat(-1.0)); // FLD1/FCHS

603         addLegalFPImmediate(APFloat(+0.0f)); // FLD0

604         addLegalFPImmediate(APFloat(+1.0f)); // FLD1

605         addLegalFPImmediate(APFloat(-0.0f)); // FLD0/FCHS

606         addLegalFPImmediate(APFloat(-1.0f)); // FLD1/FCHS

607       }

608    

609       // We don't support FMA.

610       setOperationAction(ISD::FMA, MVT::f64, Expand);

611       setOperationAction(ISD::FMA, MVT::f32, Expand);

612    

613       // Long double always uses X87.

614       if (UseX87) {

615         if (Subtarget.is64Bit() && Subtarget.hasMMX()) {

616           addRegisterClass(MVT::f128, &X86::VR128RegClass);

617           ValueTypeActions.setTypeAction(MVT::f128, TypeSoftenFloat);

618           setOperationAction(ISD::FABS , MVT::f128, Custom);

619           setOperationAction(ISD::FNEG , MVT::f128, Custom);

620           setOperationAction(ISD::FCOPYSIGN, MVT::f128, Custom);

621         }

622    

623         addRegisterClass(MVT::f80, &X86::RFP80RegClass);

624         setOperationAction(ISD::UNDEF,     MVT::f80, Expand);

625         setOperationAction(ISD::FCOPYSIGN, MVT::f80, Expand);

626         {

627           APFloat TmpFlt = APFloat::getZero(APFloat::x87DoubleExtended);

628           addLegalFPImmediate(TmpFlt);  // FLD0

629           TmpFlt.changeSign();

630           addLegalFPImmediate(TmpFlt);  // FLD0/FCHS

631    

632           bool ignored;

633           APFloat TmpFlt2(+1.0);

634           TmpFlt2.convert(APFloat::x87DoubleExtended, APFloat::rmNearestTiesToEven,

635                           &ignored);

636           addLegalFPImmediate(TmpFlt2);  // FLD1

637           TmpFlt2.changeSign();

638           addLegalFPImmediate(TmpFlt2);  // FLD1/FCHS

639         }

640    

641         // Always expand sin/cos functions even though x87 has an instruction.

642         setOperationAction(ISD::FSIN   , MVT::f80, Expand);

643         setOperationAction(ISD::FCOS   , MVT::f80, Expand);

644         setOperationAction(ISD::FSINCOS, MVT::f80, Expand);

645    

646         setOperationAction(ISD::FFLOOR, MVT::f80, Expand);

647         setOperationAction(ISD::FCEIL,  MVT::f80, Expand);

648         setOperationAction(ISD::FTRUNC, MVT::f80, Expand);

649         setOperationAction(ISD::FRINT,  MVT::f80, Expand);

650         setOperationAction(ISD::FNEARBYINT, MVT::f80, Expand);

651         setOperationAction(ISD::FMA, MVT::f80, Expand);

652       }

653    

654       // Always use a library call for pow.

655       setOperationAction(ISD::FPOW             , MVT::f32  , Expand);

656       setOperationAction(ISD::FPOW             , MVT::f64  , Expand);

657       setOperationAction(ISD::FPOW             , MVT::f80  , Expand);

658    

659       setOperationAction(ISD::FLOG, MVT::f80, Expand);

660       setOperationAction(ISD::FLOG2, MVT::f80, Expand);

661       setOperationAction(ISD::FLOG10, MVT::f80, Expand);

662       setOperationAction(ISD::FEXP, MVT::f80, Expand);

663       setOperationAction(ISD::FEXP2, MVT::f80, Expand);

664       setOperationAction(ISD::FMINNUM, MVT::f80, Expand);

665       setOperationAction(ISD::FMAXNUM, MVT::f80, Expand);

上面的addLegalFPImmediate()向容器LegalFPImmediates(类型std::vector<APFloat>)记录指令选择能合法用于浮点指令的浮点立即数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/162255.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

加班做报表被嘲低效!快用大数据分析工具

做数据分析报表很耗时间&#xff0c;因为不仅要解决多业务系统数据质量标准不一问题&#xff0c;还需要进行大量的公式计算、报表设计与制作。但那是以前&#xff0c;在大数据分析工具强势崛起的当下&#xff0c;这些工作都能交给大数据分析工具来做了。以前是花90%的时间做报表…

9.Docker的虚悬镜像-Dangling Image

1.虚悬镜像的概念 虚悬镜像 (Dangling Image) 指的是仓库名 (镜像名) 和标签 TAG 都是 的镜像。 2.构建本地虚悬镜像 这里我以unbuntu为例来说明。 2.1 编写Dockerfile文件 FROM ubuntu:22.042.2 根据Dockerfile文件构建虚悬镜像 docker build .上面这段命令&#xff0c…

选择ERP系统的关键指标

在制造业工厂中&#xff0c;选择一个合适的ERP系统能够显著提升生产效率、优化资源管理、增强决策支持。然而&#xff0c;如何从众多ERP系统中选择一个适合自己企业的系统&#xff0c;是许多负责人在面临的问题。本文将详细介绍选择ERP系统的关键指标&#xff0c;帮助制造业工厂…

python查看目录属性

os.chown(path, uid, gid)

[MySQL-基础]SQL语句

目录 hello! 这里是欧_aita的频道。 今日语录: 只有放弃才是真正的失败。 祝福语&#xff1a;愿你的代码生活充满注释&#xff0c;逻辑清晰&#xff0c;debug之路畅通无阻。 大家可以在评论区畅所欲言&#xff0c;可以指出我的错误&#xff0c;在交流中共同进步。 欢迎关注我的…

基于51单片机的病床呼叫系统设计

**单片机设计介绍&#xff0c; 基于51单片机的病床呼叫系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的病床呼叫系统是一种用于医疗机构的设备&#xff0c;旨在提供快速、可靠的病人呼叫和监控功能。以下是…

HDFS元数据管理/磁盘清理维护

元数据管理 1.元数据管理概述 > HDFS分类-类型分包括以下几部分 文件、目录自身的属性信息&#xff0c;例如文件名&#xff0c;目录名&#xff0c;修改信息等 文件记录的信息的存储相关的信息&#xff0c;例如存储块信息&#xff0c;分块情况&#xff0c;副本个数等 记录…

03_使用API_系统与数学工具

数学工具 Math 代表数学&#xff0c;是一个工具类&#xff0c;里面提供的都是对数据进行操作的一些静态方法 public class Test {public static void main(String[] args) {// 1. Math.abs() : 取绝对值System.out.println(Math.abs(-3.14)); // >>> 3.14// 2. Ma…

Centos7使用rpm安装mysql 5.7.43

Centos7使用rpm安装mysql 5.7.43 1、下载rpm包 wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.43-1.el7.x86_64.rpm-bundle.tar2、解压并安装 tar xf mysql-5.7.43-1.el7.x86_64.rpm-bundle.tar yum -y install mysql-*3、按需修改mysql配置 #注意&a…

Django框架环境的搭建(图文详解)

目录 day01 Web框架和Django基础 1.web框架底层 1.1 网络通信​编辑 1.2 常见软件架构 1.3 手撸web框架 2.web框架 2.1 wsgiref 2.2 werkzeug 2.3 各框架的区别 3.快速上手django框架 3.1 安装 3.2 命令行 3.3 Pycharm 4.虚拟环境 4.1 创建虚拟环境 - 命令行 4…

7.华为OD技术面手撕代码实录:判断ip地址

判断ip地址 编写一个函数来验证输入的字符串是否是有效的 Pv4Q 或IPv6 地址。IPv4 地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为 0-255,用(“.”)分割。比如,172.16.254.1: 同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。IPv6…

页面添加水印效果实现

页面效果&#xff1a; 源代码&#xff1a; <div id"water-wrapper"></div> <div><div>111111111111111111111111111111111111111111111111111111111111111111111111111111111111</div><div>1111111111111111111111111111111111…

电线电缆行业生产管理怎么数字化?

行业介绍 随着市场环境的变化和现代生产管理理念的不断更新&#xff0c;电缆的生产模式也在发生转变&#xff0c;批量小&#xff0c;规格多&#xff0c;交期短的新型制造需求逐年上升&#xff0c;所以企业车间管理的重要性越发凸显&#xff0c;作为企业良性运营的关键&#xf…

Python学习:常用数据结构

Python DataStructure 一、数组(array)二、双向链表(linkedlist)三、栈(stack)四、队列(queue)五、Python中的可变与不可变类型 一、数组(array) class array:def __init__(self, capacity: int):self._data []self._capacity capacitydef __getitem__(self, position: int)…

2023 年 亚太赛 APMCM (A题)国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 完整内容可以在文章末尾领取&#xff01; 问题1 图像处理&am…

硬核神作|2w字带你拿下Sentinal

目录 Sentinel概述 基本介绍 Sentinel 基本核心概念 Sentinel安装 简单安装启动 启动配置项 SpringCloud简单整合 实战架构 父工程pom文件 teacher-service服务 student-service服务 测试 整合Sentinel SpringCloud微服务保护方案解读 服务雪崩定义 问题的产生 …

AIGC重塑教育:AI大模型驱动的教育变革与实践

这次&#xff0c;狼真的来了。 AI正迅猛地改变着我们的生活。 根据高盛发布的一份报告&#xff0c;AI有可能取代3亿个全职工作岗位&#xff0c;影响全球18%的工作岗位。在欧美&#xff0c;或许四分之一的工作可以用AI完成。另一份Statista的报告预测&#xff0c;仅2023年&#…

字节码指令分类

字节码指令大致分为九类&#xff1a; 一&#xff1a;加载和存储指令用于将数据在栈帧中的局部变量表和操作数栈之间来回传输 二&#xff1a;算术指令用于对两个操作数栈上的值进行某种特定运算&#xff0c;并把结果重新存入到操作栈顶。运算指令可以分为两种&#xff1a;对整…

VivadoAndTcl: eval

用于拼接执行多个命令。后面可以接一个或者多个参数&#xff0c;如果是一个参数&#xff0c;则把这个参数当做命令来执行&#xff0c;如果是多个参数&#xff0c;则将多个参数用concat命令连接起来后再执行。 举例如下&#xff1a; # 一个参数的情况 set do {set var0 {hello…

【Linux】make/Makefile 进度条小程序

目录 一&#xff0c;认识 make/makefile 二&#xff0c;实例代码 1&#xff0c;依赖关系 2&#xff0c;原理 3&#xff0c;项目清理 4&#xff0c;测试讲解 三&#xff0c;Linux第一个小程序&#xff0d;进度条 game.h game.c test.c 程序详解 一&#xff0c;认识 m…