Skip to content

Commit 1415d66

Browse files
[X86][GlobalISel] - Legalize And Select of G_FPTOSI/G_SITOFP in X87 mode
1 parent a0aa5f8 commit 1415d66

File tree

11 files changed

+866
-192
lines changed

11 files changed

+866
-192
lines changed

llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class X86InstructionSelector : public InstructionSelector {
7777
unsigned getPtrLoadStoreOp(const LLT &Ty, const RegisterBank &RB,
7878
unsigned Opc) const;
7979

80+
bool checkMemoryOpSize(const MachineInstr &MI, unsigned NumBytes) const;
81+
8082
bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
8183
MachineFunction &MF) const;
8284
bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
@@ -355,6 +357,15 @@ bool X86InstructionSelector::selectCopy(MachineInstr &I,
355357
return true;
356358
}
357359

360+
bool X86InstructionSelector::checkMemoryOpSize(const MachineInstr &MI,
361+
unsigned NumBytes) const {
362+
if (!MI.mayLoadOrStore())
363+
return false;
364+
assert(MI.hasOneMemOperand() &&
365+
"Expected load/store to have only one mem op!");
366+
return (*MI.memoperands_begin())->getSize() == NumBytes;
367+
}
368+
358369
bool X86InstructionSelector::select(MachineInstr &I) {
359370
assert(I.getParent() && "Instruction should be in a basic block!");
360371
assert(I.getParent()->getParent() && "Instruction should be in a function!");
@@ -364,7 +375,7 @@ bool X86InstructionSelector::select(MachineInstr &I) {
364375
MachineRegisterInfo &MRI = MF.getRegInfo();
365376

366377
unsigned Opcode = I.getOpcode();
367-
if (!isPreISelGenericOpcode(Opcode)) {
378+
if (!isPreISelGenericOpcode(Opcode) && !I.isPreISelOpcode()) {
368379
// Certain non-generic instructions also need some special handling.
369380

370381
if (Opcode == TargetOpcode::LOAD_STACK_GUARD)

llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
1818
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
1919
#include "llvm/CodeGen/MachineConstantPool.h"
20+
#include "llvm/CodeGen/MachineFrameInfo.h"
2021
#include "llvm/CodeGen/TargetOpcodes.h"
2122
#include "llvm/CodeGen/ValueTypes.h"
2223
#include "llvm/IR/DerivedTypes.h"
@@ -498,7 +499,16 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
498499
(typePairInSet(0, 1, {{s64, s32}})(Query) ||
499500
(Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));
500501
})
501-
.clampScalar(1, s32, sMaxScalar)
502+
.customIf([=](const LegalityQuery &Query) -> bool {
503+
if (!UseX87)
504+
return false;
505+
if ((typeIs(0, s32)(Query) && HasSSE1) ||
506+
(typeIs(0, s64)(Query) && HasSSE2))
507+
return false;
508+
return typeInSet(0, {s32, s64, s80})(Query) &&
509+
typeInSet(1, {s16, s32, s64})(Query);
510+
})
511+
.clampScalar(1, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar)
502512
.widenScalarToNextPow2(1)
503513
.clampScalar(0, s32, HasSSE2 ? s64 : s32)
504514
.widenScalarToNextPow2(0);
@@ -512,9 +522,18 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
512522
(typePairInSet(0, 1, {{s32, s64}})(Query) ||
513523
(Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));
514524
})
515-
.clampScalar(1, s32, HasSSE2 ? s64 : s32)
525+
.customIf([=](const LegalityQuery &Query) -> bool {
526+
if (!UseX87)
527+
return false;
528+
if ((typeIs(1, s32)(Query) && HasSSE1) ||
529+
(typeIs(1, s64)(Query) && HasSSE2))
530+
return false;
531+
return typeInSet(0, {s16, s32, s64})(Query) &&
532+
typeInSet(1, {s32, s64, s80})(Query);
533+
})
534+
.clampScalar(0, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar)
516535
.widenScalarToNextPow2(0)
517-
.clampScalar(0, s32, sMaxScalar)
536+
.clampScalar(1, s32, HasSSE2 ? s64 : s32)
518537
.widenScalarToNextPow2(1);
519538

520539
// For G_UITOFP and G_FPTOUI without AVX512, we have to custom legalize types
@@ -671,10 +690,77 @@ bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
671690
return legalizeUITOFP(MI, MRI, Helper);
672691
case TargetOpcode::G_STORE:
673692
return legalizeNarrowingStore(MI, MRI, Helper);
693+
case TargetOpcode::G_SITOFP:
694+
return legalizeSITOFP(MI, MRI, Helper);
695+
case TargetOpcode::G_FPTOSI:
696+
return legalizeFPTOSI(MI, MRI, Helper);
674697
}
675698
llvm_unreachable("expected switch to return");
676699
}
677700

701+
bool X86LegalizerInfo::legalizeSITOFP(MachineInstr &MI,
702+
MachineRegisterInfo &MRI,
703+
LegalizerHelper &Helper) const {
704+
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
705+
MachineFunction &MF = *MI.getMF();
706+
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
707+
708+
assert((SrcTy.getSizeInBits() == 16 || SrcTy.getSizeInBits() == 32 ||
709+
SrcTy.getSizeInBits() == 64) &&
710+
"Unexpected source type for SITOFP in X87 mode.");
711+
712+
const LLT p0 = LLT::pointer(0, MF.getTarget().getPointerSizeInBits(0));
713+
int MemSize = SrcTy.getSizeInBytes();
714+
int StackSlot =
715+
MF.getFrameInfo().CreateStackObject(MemSize, Align(MemSize), false);
716+
717+
auto SlotPointer = MIRBuilder.buildFrameIndex(p0, StackSlot);
718+
MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, StackSlot);
719+
MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
720+
PtrInfo, MachineMemOperand::MOStore, MemSize, Align(MemSize));
721+
722+
// Store the integer value on the FPU stack.
723+
MIRBuilder.buildStore(Src, SlotPointer, *StoreMMO);
724+
725+
MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
726+
PtrInfo, MachineMemOperand::MOLoad, MemSize, Align(MemSize));
727+
MIRBuilder.buildInstr(X86::G_FILD)
728+
.addDef(Dst)
729+
.addUse(SlotPointer.getReg(0))
730+
.addMemOperand(LoadMMO);
731+
732+
MI.eraseFromParent();
733+
return true;
734+
}
735+
736+
bool X86LegalizerInfo::legalizeFPTOSI(MachineInstr &MI,
737+
MachineRegisterInfo &MRI,
738+
LegalizerHelper &Helper) const {
739+
MachineFunction &MF = *MI.getMF();
740+
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
741+
const LLT p0 = LLT::pointer(0, MF.getTarget().getPointerSizeInBits(0));
742+
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
743+
744+
unsigned MemSize = DstTy.getSizeInBytes();
745+
int StackSlot =
746+
MF.getFrameInfo().CreateStackObject(MemSize, Align(MemSize), false);
747+
748+
auto SlotPointer = MIRBuilder.buildFrameIndex(p0, StackSlot);
749+
750+
MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, StackSlot);
751+
MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
752+
PtrInfo, MachineMemOperand::MOStore, MemSize, Align(MemSize));
753+
754+
MIRBuilder.buildInstr(X86::G_FIST)
755+
.addUse(Src)
756+
.addUse(SlotPointer.getReg(0))
757+
.addMemOperand(StoreMMO);
758+
759+
MIRBuilder.buildLoad(Dst, SlotPointer, PtrInfo, Align(MemSize));
760+
MI.eraseFromParent();
761+
return true;
762+
}
763+
678764
bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI,
679765
MachineRegisterInfo &MRI,
680766
LegalizerHelper &Helper) const {

llvm/lib/Target/X86/GISel/X86LegalizerInfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ class X86LegalizerInfo : public LegalizerInfo {
4848

4949
bool legalizeNarrowingStore(MachineInstr &MI, MachineRegisterInfo &MRI,
5050
LegalizerHelper &Helper) const;
51+
52+
bool legalizeSITOFP(MachineInstr &MI, MachineRegisterInfo &MRI,
53+
LegalizerHelper &Helper) const;
54+
55+
bool legalizeFPTOSI(MachineInstr &MI, MachineRegisterInfo &MRI,
56+
LegalizerHelper &Helper) const;
5157
};
5258
} // namespace llvm
5359
#endif

llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ bool X86RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
111111
case TargetOpcode::G_FPTOSI:
112112
case TargetOpcode::G_FPTOUI:
113113
case TargetOpcode::G_FCMP:
114+
case X86::G_FIST:
114115
case TargetOpcode::G_LROUND:
115116
case TargetOpcode::G_LLROUND:
116117
case TargetOpcode::G_INTRINSIC_TRUNC:
@@ -129,6 +130,7 @@ bool X86RegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
129130
switch (MI.getOpcode()) {
130131
case TargetOpcode::G_SITOFP:
131132
case TargetOpcode::G_UITOFP:
133+
case X86::G_FILD:
132134
return true;
133135
default:
134136
break;
@@ -296,6 +298,16 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
296298
// VECRReg)
297299
getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
298300
break;
301+
case X86::G_FIST:
302+
case X86::G_FILD: {
303+
auto &Op0 = MI.getOperand(0);
304+
auto &Op1 = MI.getOperand(1);
305+
const LLT Ty0 = MRI.getType(Op0.getReg());
306+
const LLT Ty1 = MRI.getType(Op1.getReg());
307+
OpRegBankIdx[0] = getPartialMappingIdx(MI, Ty0, /* isFP= */ true);
308+
OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ false);
309+
break;
310+
}
299311
case TargetOpcode::G_SITOFP:
300312
case TargetOpcode::G_FPTOSI:
301313
case TargetOpcode::G_UITOFP:

llvm/lib/Target/X86/X86InstrFragments.td

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -841,13 +841,21 @@ def X86fldf80 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{
841841

842842
def X86fild16 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{
843843
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
844-
}]>;
844+
}]> {
845+
let GISelPredicateCode = [{ return checkMemoryOpSize(MI, 2); }];
846+
}
847+
845848
def X86fild32 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{
846849
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
847-
}]>;
850+
}]> {
851+
let GISelPredicateCode = [{ return checkMemoryOpSize(MI, 4); }];
852+
}
853+
848854
def X86fild64 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{
849855
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
850-
}]>;
856+
}]> {
857+
let GISelPredicateCode = [{ return checkMemoryOpSize(MI, 8); }];
858+
}
851859

852860
def X86fist32 : PatFrag<(ops node:$val, node:$ptr),
853861
(X86fist node:$val, node:$ptr), [{
@@ -862,15 +870,23 @@ def X86fist64 : PatFrag<(ops node:$val, node:$ptr),
862870
def X86fp_to_i16mem : PatFrag<(ops node:$val, node:$ptr),
863871
(X86fp_to_mem node:$val, node:$ptr), [{
864872
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
865-
}]>;
873+
}]> {
874+
let GISelPredicateCode = [{ return checkMemoryOpSize(MI, 2); }];
875+
}
876+
866877
def X86fp_to_i32mem : PatFrag<(ops node:$val, node:$ptr),
867878
(X86fp_to_mem node:$val, node:$ptr), [{
868879
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
869-
}]>;
880+
}]> {
881+
let GISelPredicateCode = [{ return checkMemoryOpSize(MI, 4); }];
882+
}
883+
870884
def X86fp_to_i64mem : PatFrag<(ops node:$val, node:$ptr),
871885
(X86fp_to_mem node:$val, node:$ptr), [{
872886
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
873-
}]>;
887+
}]> {
888+
let GISelPredicateCode = [{ return checkMemoryOpSize(MI, 8); }];
889+
}
874890

875891
//===----------------------------------------------------------------------===//
876892
// FPStack pattern fragments
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===- X86InstrGISel.td - X86 GISel target specific opcodes -*- tablegen -*===//
2+
//
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
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// X86 GlobalISel target pseudo instruction definitions. This is kept
10+
// separately from the other tablegen files for organizational purposes, but
11+
// share the same infrastructure.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
class X86GenericInstruction : GenericInstruction { let Namespace = "X86"; }
16+
17+
def G_FILD : X86GenericInstruction {
18+
let OutOperandList = (outs type0:$dst);
19+
let InOperandList = (ins ptype1:$src);
20+
let hasSideEffects = false;
21+
let mayLoad = true;
22+
}
23+
def G_FIST : X86GenericInstruction {
24+
let OutOperandList = (outs);
25+
let InOperandList = (ins type0:$src1, ptype1:$src2);
26+
let hasSideEffects = false;
27+
let mayStore = true;
28+
}
29+
30+
def : GINodeEquiv<G_FILD, X86fild>;
31+
def : GINodeEquiv<G_FIST, X86fp_to_mem>;

llvm/lib/Target/X86/X86InstrInfo.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ include "X86InstrFormats.td"
3737
//
3838
include "X86InstrUtils.td"
3939

40+
//===----------------------------------------------------------------------===//
41+
// Global ISel
42+
//
43+
include "X86InstrGISel.td"
44+
4045
//===----------------------------------------------------------------------===//
4146
// Subsystems.
4247
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)