Skip to content

Commit a4b9e82

Browse files
[X86][GlobalISel] - Legalize And Select G_FPTOSI/G_SITOFP in X87 mode (llvm#137377)
Support legalization and selection of G_FPTOSI/G_SITOFP generic opcodes in x87 mode.
1 parent 5b8031a commit a4b9e82

File tree

12 files changed

+729
-160
lines changed

12 files changed

+729
-160
lines changed

llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,16 @@ class LegalizeRuleSet {
935935
Types2);
936936
}
937937

938+
/// The instruction is custom when the predicate is true and type indexes 0
939+
/// and 1 are all in their respective lists.
940+
LegalizeRuleSet &
941+
customForCartesianProduct(bool Pred, std::initializer_list<LLT> Types0,
942+
std::initializer_list<LLT> Types1) {
943+
if (!Pred)
944+
return *this;
945+
return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1);
946+
}
947+
938948
/// Unconditionally custom lower.
939949
LegalizeRuleSet &custom() {
940950
return customIf(always);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ bool X86InstructionSelector::select(MachineInstr &I) {
364364
MachineRegisterInfo &MRI = MF.getRegInfo();
365365

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

370370
if (Opcode == TargetOpcode::LOAD_STACK_GUARD)

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

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -490,31 +490,25 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
490490
});
491491

492492
getActionDefinitionsBuilder(G_SITOFP)
493-
.legalIf([=](const LegalityQuery &Query) {
494-
return (HasSSE1 &&
495-
(typePairInSet(0, 1, {{s32, s32}})(Query) ||
496-
(Is64Bit && typePairInSet(0, 1, {{s32, s64}})(Query)))) ||
497-
(HasSSE2 &&
498-
(typePairInSet(0, 1, {{s64, s32}})(Query) ||
499-
(Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));
500-
})
501-
.clampScalar(1, s32, sMaxScalar)
493+
.legalFor(HasSSE1, {{s32, s32}})
494+
.legalFor(HasSSE1 && Is64Bit, {{s32, s64}})
495+
.legalFor(HasSSE2, {{s64, s32}})
496+
.legalFor(HasSSE2 && Is64Bit, {{s64, s64}})
497+
.clampScalar(1, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar)
502498
.widenScalarToNextPow2(1)
499+
.customForCartesianProduct(UseX87, {s32, s64, s80}, {s16, s32, s64})
503500
.clampScalar(0, s32, HasSSE2 ? s64 : s32)
504501
.widenScalarToNextPow2(0);
505502

506503
getActionDefinitionsBuilder(G_FPTOSI)
507-
.legalIf([=](const LegalityQuery &Query) {
508-
return (HasSSE1 &&
509-
(typePairInSet(0, 1, {{s32, s32}})(Query) ||
510-
(Is64Bit && typePairInSet(0, 1, {{s64, s32}})(Query)))) ||
511-
(HasSSE2 &&
512-
(typePairInSet(0, 1, {{s32, s64}})(Query) ||
513-
(Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query))));
514-
})
515-
.clampScalar(1, s32, HasSSE2 ? s64 : s32)
504+
.legalFor(HasSSE1, {{s32, s32}})
505+
.legalFor(HasSSE1 && Is64Bit, {{s64, s32}})
506+
.legalFor(HasSSE2, {{s32, s64}})
507+
.legalFor(HasSSE2 && Is64Bit, {{s64, s64}})
508+
.clampScalar(0, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar)
516509
.widenScalarToNextPow2(0)
517-
.clampScalar(0, s32, sMaxScalar)
510+
.customForCartesianProduct(UseX87, {s16, s32, s64}, {s32, s64, s80})
511+
.clampScalar(1, s32, HasSSE2 ? s64 : s32)
518512
.widenScalarToNextPow2(1);
519513

520514
// For G_UITOFP and G_FPTOUI without AVX512, we have to custom legalize types
@@ -671,10 +665,70 @@ bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
671665
return legalizeUITOFP(MI, MRI, Helper);
672666
case TargetOpcode::G_STORE:
673667
return legalizeNarrowingStore(MI, MRI, Helper);
668+
case TargetOpcode::G_SITOFP:
669+
return legalizeSITOFP(MI, MRI, Helper);
670+
case TargetOpcode::G_FPTOSI:
671+
return legalizeFPTOSI(MI, MRI, Helper);
674672
}
675673
llvm_unreachable("expected switch to return");
676674
}
677675

676+
bool X86LegalizerInfo::legalizeSITOFP(MachineInstr &MI,
677+
MachineRegisterInfo &MRI,
678+
LegalizerHelper &Helper) const {
679+
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
680+
MachineFunction &MF = *MI.getMF();
681+
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
682+
683+
assert((SrcTy.getSizeInBits() == 16 || SrcTy.getSizeInBits() == 32 ||
684+
SrcTy.getSizeInBits() == 64) &&
685+
"Unexpected source type for SITOFP in X87 mode.");
686+
687+
TypeSize MemSize = SrcTy.getSizeInBytes();
688+
MachinePointerInfo PtrInfo;
689+
Align Alignmt = Helper.getStackTemporaryAlignment(SrcTy);
690+
auto SlotPointer = Helper.createStackTemporary(MemSize, Alignmt, PtrInfo);
691+
MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
692+
PtrInfo, MachineMemOperand::MOStore, MemSize, Align(MemSize));
693+
694+
// Store the integer value on the FPU stack.
695+
MIRBuilder.buildStore(Src, SlotPointer, *StoreMMO);
696+
697+
MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
698+
PtrInfo, MachineMemOperand::MOLoad, MemSize, Align(MemSize));
699+
MIRBuilder.buildInstr(X86::G_FILD)
700+
.addDef(Dst)
701+
.addUse(SlotPointer.getReg(0))
702+
.addMemOperand(LoadMMO);
703+
704+
MI.eraseFromParent();
705+
return true;
706+
}
707+
708+
bool X86LegalizerInfo::legalizeFPTOSI(MachineInstr &MI,
709+
MachineRegisterInfo &MRI,
710+
LegalizerHelper &Helper) const {
711+
MachineFunction &MF = *MI.getMF();
712+
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
713+
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
714+
715+
TypeSize MemSize = DstTy.getSizeInBytes();
716+
MachinePointerInfo PtrInfo;
717+
Align Alignmt = Helper.getStackTemporaryAlignment(DstTy);
718+
auto SlotPointer = Helper.createStackTemporary(MemSize, Alignmt, PtrInfo);
719+
MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
720+
PtrInfo, MachineMemOperand::MOStore, MemSize, Align(MemSize));
721+
722+
MIRBuilder.buildInstr(X86::G_FIST)
723+
.addUse(Src)
724+
.addUse(SlotPointer.getReg(0))
725+
.addMemOperand(StoreMMO);
726+
727+
MIRBuilder.buildLoad(Dst, SlotPointer, PtrInfo, Align(MemSize));
728+
MI.eraseFromParent();
729+
return true;
730+
}
731+
678732
bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI,
679733
MachineRegisterInfo &MRI,
680734
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: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -844,13 +844,24 @@ def X86fldf80 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{
844844

845845
def X86fild16 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{
846846
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
847-
}]>;
847+
}]> {
848+
let IsLoad = true;
849+
let MemoryVT = i16;
850+
}
851+
848852
def X86fild32 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{
849853
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
850-
}]>;
854+
}]> {
855+
let IsLoad = true;
856+
let MemoryVT = i32;
857+
}
858+
851859
def X86fild64 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{
852860
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
853-
}]>;
861+
}]> {
862+
let IsLoad = true;
863+
let MemoryVT = i64;
864+
}
854865

855866
def X86fist32 : PatFrag<(ops node:$val, node:$ptr),
856867
(X86fist node:$val, node:$ptr), [{
@@ -865,15 +876,26 @@ def X86fist64 : PatFrag<(ops node:$val, node:$ptr),
865876
def X86fp_to_i16mem : PatFrag<(ops node:$val, node:$ptr),
866877
(X86fp_to_mem node:$val, node:$ptr), [{
867878
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16;
868-
}]>;
879+
}]> {
880+
let IsStore = true;
881+
let MemoryVT = i16;
882+
}
883+
869884
def X86fp_to_i32mem : PatFrag<(ops node:$val, node:$ptr),
870885
(X86fp_to_mem node:$val, node:$ptr), [{
871886
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32;
872-
}]>;
887+
}]> {
888+
let IsStore = true;
889+
let MemoryVT = i32;
890+
}
891+
873892
def X86fp_to_i64mem : PatFrag<(ops node:$val, node:$ptr),
874893
(X86fp_to_mem node:$val, node:$ptr), [{
875894
return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64;
876-
}]>;
895+
}]> {
896+
let IsStore = true;
897+
let MemoryVT = i64;
898+
}
877899

878900
//===----------------------------------------------------------------------===//
879901
// FPStack pattern fragments

llvm/lib/Target/X86/X86InstrGISel.td

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)