Skip to content

Commit ff32516

Browse files
mshelegoigcbot
authored andcommitted
Move float control management to a separate pass
Functions with CMFloatControl attribute have to save float controls on entry and restore before return. To do it we need a register, so cr0 read/writes need to be created before regalloc
1 parent 67059bc commit ff32516

13 files changed

+287
-119
lines changed

IGC/VectorCompiler/lib/GenXCodeGen/CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#=========================== begin_copyright_notice ============================
22
#
3-
# Copyright (C) 2017-2023 Intel Corporation
3+
# Copyright (C) 2017-2024 Intel Corporation
44
#
55
# SPDX-License-Identifier: MIT
66
#
@@ -43,6 +43,7 @@ set(CODEGEN_SOURCES
4343
GenXEmulate.cpp
4444
GenXExtractVectorizer.cpp
4545
GenXFixInvalidFuncName.cpp
46+
GenXFloatControl.cpp
4647
GenXLegalizeGVLoadUses.cpp
4748
GenXGASCastAnalyzer.cpp
4849
GenXGASDynamicResolution.cpp

IGC/VectorCompiler/lib/GenXCodeGen/GenX.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2017-2023 Intel Corporation
3+
Copyright (C) 2017-2024 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66
@@ -156,6 +156,7 @@ FunctionPass *createGenXGlobalUniformAnalysisPass();
156156
ModulePass *createGenXBuiltinFunctionsPass(BuiltinFunctionKind Kind);
157157
FunctionPass *createGenXLegacyToLscTranslatorPass();
158158
ModulePass *createGenXSLMResolution();
159+
ModulePass *createGenXFloatControlWrapperPass();
159160

160161
namespace genx {
161162

IGC/VectorCompiler/lib/GenXCodeGen/GenXCisaBuilder.cpp

-89
Original file line numberDiff line numberDiff line change
@@ -386,22 +386,6 @@ class GenXKernelBuilder {
386386
std::map<Function *, VISA_GenVar *> FPMap;
387387
SmallVector<InsertValueInst *, 10> RetvInserts;
388388

389-
// The default float control from kernel attribute. Each subroutine may
390-
// overrride this control mask, but it should revert back to the default float
391-
// control mask before exiting from the subroutine.
392-
uint32_t DefaultFloatControl = 0;
393-
394-
enum CRBits {
395-
SinglePrecisionMode = 1,
396-
RoundingMode = 3 << 4,
397-
DoublePrecisionDenorm = 1 << 6,
398-
SinglePrecisionDenorm = 1 << 7,
399-
HalfPrecisionDenorm = 1 << 10,
400-
SystolicDenorm = 1 << 30,
401-
};
402-
403-
uint32_t CRMask = 0;
404-
405389
// normally false, set to true if there is any SIMD CF in the func or this is
406390
// (indirectly) called inside any SIMD CF.
407391
bool NoMask = false;
@@ -434,7 +418,6 @@ class GenXKernelBuilder {
434418
bool buildInstruction(Instruction *Inst);
435419
bool buildMainInst(Instruction *Inst, genx::BaleInfo BI, unsigned Mod,
436420
const DstOpndDesc &DstDesc);
437-
void buildControlRegUpdate(unsigned Mask, bool Clear);
438421
void buildJoin(CallInst *Join, BranchInst *Branch);
439422
bool buildBranch(BranchInst *Branch);
440423
void buildIndirectBr(IndirectBrInst *Br);
@@ -1126,12 +1109,6 @@ bool GenXKernelBuilder::run() {
11261109
GrfByteSize = Subtarget->getGRFByteSize();
11271110
StackSurf = Subtarget->stackSurface();
11281111

1129-
CRMask = CRBits::RoundingMode | CRBits::DoublePrecisionDenorm |
1130-
CRBits::SinglePrecisionDenorm | CRBits::HalfPrecisionDenorm;
1131-
1132-
if (Subtarget->hasSystolicDenormControl())
1133-
CRMask |= CRBits::SystolicDenorm;
1134-
11351112
StackCallExecSize =
11361113
getExecSizeFromValue(BackendConfig->getInteropSubgroupSize());
11371114

@@ -1324,28 +1301,6 @@ void GenXKernelBuilder::buildInstructions() {
13241301
beginFunctionLight(Func);
13251302
CurrentPadding = 0;
13261303

1327-
// If a float control is specified, emit code to make that happen.
1328-
// Float control contains rounding mode, denorm behaviour and single
1329-
// precision float mode (ALT or IEEE) Relevant bits are already set as
1330-
// defined for VISA control reg in header definition on enums
1331-
if (Func->hasFnAttribute(genx::FunctionMD::CMFloatControl)) {
1332-
uint32_t FloatControl = 0;
1333-
Func->getFnAttribute(genx::FunctionMD::CMFloatControl)
1334-
.getValueAsString()
1335-
.getAsInteger(0, FloatControl);
1336-
1337-
// Clear current float control bits to known zero state
1338-
buildControlRegUpdate(CRMask, true);
1339-
1340-
// Set rounding mode to required state if that isn't zero
1341-
FloatControl &= CRMask;
1342-
if (FloatControl) {
1343-
if (FG->getHead() == Func)
1344-
DefaultFloatControl = FloatControl;
1345-
buildControlRegUpdate(FloatControl, false);
1346-
}
1347-
}
1348-
13491304
// Only output a label for the initial basic block if it is used from
13501305
// somewhere else.
13511306
bool NeedsLabel = !Func->front().use_empty();
@@ -4015,39 +3970,6 @@ void GenXKernelBuilder::buildIntrinsic(CallInst *CI, unsigned IntrinID,
40153970
#include "GenXIntrinsicsBuildMap.inc"
40163971
}
40173972

4018-
/**************************************************************************************************
4019-
* buildControlRegUpdate : generate an instruction to apply a mask to
4020-
* the control register (V14).
4021-
*
4022-
* Enter: Mask = the mask to apply
4023-
* Clear = false if bits set in Mask should be set in V14,
4024-
* true if bits set in Mask should be cleared in V14.
4025-
*/
4026-
void GenXKernelBuilder::buildControlRegUpdate(unsigned Mask, bool Clear) {
4027-
ISA_Opcode Opcode;
4028-
// write opcode
4029-
if (Clear) {
4030-
Opcode = ISA_AND;
4031-
Mask = ~Mask;
4032-
} else
4033-
Opcode = ISA_OR;
4034-
4035-
Region Single = Region(1, 4);
4036-
4037-
VISA_GenVar *Decl = nullptr;
4038-
CISA_CALL(Kernel->GetPredefinedVar(Decl, PREDEFINED_CR0));
4039-
VISA_VectorOpnd *dst =
4040-
createRegionOperand(&Single, Decl, DONTCARESIGNED, 0, true);
4041-
VISA_VectorOpnd *src0 =
4042-
createRegionOperand(&Single, Decl, DONTCARESIGNED, 0, false);
4043-
4044-
VISA_VectorOpnd *src1 = nullptr;
4045-
CISA_CALL(Kernel->CreateVISAImmediate(src1, &Mask, ISA_TYPE_UD));
4046-
4047-
appendVISALogicOrShiftInst(Opcode, nullptr, false, vISA_EMASK_M1, EXEC_SIZE_1,
4048-
dst, src0, src1);
4049-
}
4050-
40513973
/***********************************************************************
40523974
* buildBranch : build a conditional or unconditional branch
40533975
*
@@ -5447,17 +5369,6 @@ void GenXKernelBuilder::buildCall(CallInst *CI, const DstOpndDesc &DstDesc) {
54475369
}
54485370

54495371
void GenXKernelBuilder::buildRet(ReturnInst *RI) {
5450-
uint32_t FloatControl = 0;
5451-
auto F = RI->getFunction();
5452-
F->getFnAttribute(genx::FunctionMD::CMFloatControl)
5453-
.getValueAsString()
5454-
.getAsInteger(0, FloatControl);
5455-
FloatControl &= CRMask;
5456-
if (FloatControl != DefaultFloatControl) {
5457-
buildControlRegUpdate(CRMask, true);
5458-
if (DefaultFloatControl)
5459-
buildControlRegUpdate(DefaultFloatControl, false);
5460-
}
54615372
if (vc::requiresStackCall(Func)) {
54625373
appendVISACFFunctionRetInst(nullptr, vISA_EMASK_M1, StackCallExecSize);
54635374
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*========================== begin_copyright_notice ============================
2+
3+
Copyright (C) 2024 Intel Corporation
4+
5+
SPDX-License-Identifier: MIT
6+
7+
============================= end_copyright_notice ===========================*/
8+
9+
#include "FunctionGroup.h"
10+
#include "GenX.h"
11+
#include "GenXTargetMachine.h"
12+
#include "GenXUtil.h"
13+
14+
#include "llvm/CodeGen/TargetPassConfig.h"
15+
#include "llvm/InitializePasses.h"
16+
17+
#define DEBUG_TYPE "GENX_FLOAT_CONTROL"
18+
19+
namespace llvm {
20+
21+
class GenXFloatControl : public FGPassImplInterface, IDMixin<GenXFloatControl> {
22+
23+
// Must be up to date with CR0 layout
24+
enum Bits {
25+
SinglePrecisionMode = 1,
26+
RoundingMode = 3 << 4,
27+
DoublePrecisionDenorm = 1 << 6,
28+
SinglePrecisionDenorm = 1 << 7,
29+
HalfPrecisionDenorm = 1 << 10,
30+
FPToIntRoundingMode = 1 << 12,
31+
SystolicDenorm = 1 << 30,
32+
};
33+
34+
uint32_t DefaultFloatControl = 0;
35+
uint32_t Mask = 0;
36+
37+
bool getFloatControl(Function *F, uint32_t *Val);
38+
39+
Value *buildCr0Update(Value* V, Instruction *InsertBefore);
40+
41+
public:
42+
void releaseMemory() {}
43+
void print(raw_ostream &OS, const FunctionGroup *FG) const {}
44+
bool runOnFunctionGroup(FunctionGroup &FG);
45+
void verifyAnalysis() const {}
46+
47+
static void getAnalysisUsage(AnalysisUsage &AU) {
48+
AU.addRequired<TargetPassConfig>();
49+
AU.setPreservesAll();
50+
}
51+
static StringRef getPassName() { return "GenXFloatControl"; }
52+
};
53+
54+
void initializeGenXFloatControlWrapperPass(PassRegistry &);
55+
56+
using GenXFloatControlWrapper = FunctionGroupWrapperPass<GenXFloatControl>;
57+
58+
} // namespace llvm
59+
60+
using namespace llvm;
61+
using namespace genx;
62+
63+
INITIALIZE_PASS_BEGIN(GenXFloatControlWrapper, "GenXFloatControlWrapper",
64+
"GenXFloatControlWrapper", false, false)
65+
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
66+
INITIALIZE_PASS_END(GenXFloatControlWrapper, "GenXFloatControlWrapper",
67+
"GenXFloatControlWrapper", false, false)
68+
69+
ModulePass *llvm::createGenXFloatControlWrapperPass() {
70+
initializeGenXFloatControlWrapperPass(*PassRegistry::getPassRegistry());
71+
return new GenXFloatControlWrapper();
72+
}
73+
74+
bool GenXFloatControl::runOnFunctionGroup(FunctionGroup &FG) {
75+
// By default allow to specify with the attribute only rounding and denorm
76+
// modes
77+
Mask = Bits::RoundingMode | Bits::DoublePrecisionDenorm |
78+
Bits::SinglePrecisionDenorm | Bits::HalfPrecisionDenorm;
79+
const auto *Subtarget = &getAnalysis<TargetPassConfig>()
80+
.getTM<GenXTargetMachine>()
81+
.getGenXSubtarget();
82+
if (Subtarget->hasSystolicDenormControl()) {
83+
Mask |= Bits::SystolicDenorm;
84+
}
85+
86+
for (auto It = FG.begin(); It != FG.end(); It++) {
87+
Function *F = *It;
88+
uint32_t FloatControl = DefaultFloatControl;
89+
if (!getFloatControl(F, &FloatControl) && !fg::isHead(*F))
90+
continue;
91+
// Kernels, stackcalls and subroutines with attribute set float control on
92+
// entry - provided by the attribute or the default one
93+
auto *V = ConstantInt::get(Type::getInt32Ty(F->getContext()), FloatControl);
94+
auto *OldV = buildCr0Update(V, F->getEntryBlock().getFirstNonPHI());
95+
if (fg::isGroupHead(*F))
96+
continue;
97+
// Stackcalls and subroutines with attribute must save caller's float
98+
// control on entry and restore it before return
99+
for (auto &BB : *F)
100+
if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
101+
buildCr0Update(OldV, RI);
102+
}
103+
104+
return true;
105+
}
106+
107+
bool GenXFloatControl::getFloatControl(Function *F, uint32_t *Val) {
108+
if (!F->hasFnAttribute(FunctionMD::CMFloatControl))
109+
return false;
110+
F->getFnAttribute(FunctionMD::CMFloatControl)
111+
.getValueAsString()
112+
.getAsInteger(0, *Val);
113+
return true;
114+
}
115+
116+
Value *GenXFloatControl::buildCr0Update(Value *V, Instruction *InsertBefore) {
117+
IRBuilder<> B(InsertBefore);
118+
auto &DL = InsertBefore->getDebugLoc();
119+
auto *M = InsertBefore->getModule();
120+
121+
auto *Ty = B.getInt32Ty();
122+
auto *VTy = IGCLLVM::FixedVectorType::get(Ty, 4);
123+
auto *Id = B.getInt32(PreDefined_Vars::PREDEFINED_CR0);
124+
125+
auto *Cr0 = B.CreateCall(
126+
vc::getAnyDeclaration(M, GenXIntrinsic::genx_read_predef_reg, {VTy, VTy}),
127+
{Id, UndefValue::get(VTy)});
128+
129+
Region R(Ty);
130+
131+
auto *RdR = R.createRdRegion(Cr0, "cr0.0", InsertBefore, DL, true);
132+
auto *AndOld = B.CreateAnd(RdR, ~Mask);
133+
auto *AndNew = B.CreateAnd(V, Mask);
134+
auto *Or = B.CreateOr(AndOld, AndNew);
135+
auto *WrR = R.createWrRegion(Cr0, Or, "cr0.0.updated", InsertBefore, DL);
136+
137+
B.CreateCall(
138+
vc::getAnyDeclaration(M, GenXIntrinsic::genx_write_predef_reg, {VTy, VTy}),
139+
{Id, WrR});
140+
141+
return RdR;
142+
}

IGC/VectorCompiler/lib/GenXCodeGen/GenXTargetMachine.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ void initializeGenXPasses(PassRegistry &registry) {
191191
initializeGenXLegacyToLscTranslatorPass(registry);
192192
initializeGenXSLMResolutionPass(registry);
193193
initializeGenXTypeLegalizationPass(registry);
194+
initializeGenXFloatControlWrapperPass(registry);
194195
// WRITE HERE MORE PASSES IF IT'S NEEDED;
195196
}
196197

@@ -709,6 +710,7 @@ bool GenXTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
709710
vc::addPass(PM, createGlobalDCEPass());
710711
/// .. include:: GenXModule.h
711712
vc::addPass(PM, createGenXModulePass());
713+
vc::addPass(PM, createGenXFloatControlWrapperPass());
712714
/// .. include:: GenXLiveness.h
713715
vc::addPass(PM, createGenXGroupBalingWrapperPass(BalingKind::BK_Analysis,
714716
&Subtarget));

IGC/VectorCompiler/lib/GenXCodeGen/GenXTargetMachine.h

+2
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ void initializeGenXInitBiFConstantsPass(PassRegistry &);
271271
void initializeGenXFinalizerPass(PassRegistry &);
272272
void initializeGenXBuiltinFunctionsPass(PassRegistry &);
273273
void initializeGenXSLMResolutionPass(PassRegistry &);
274+
void initializeGenXFloatControlWrapperPass(PassRegistry &);
275+
274276
} // End llvm namespace
275277

276278
#endif

IGC/VectorCompiler/lib/GenXCodeGen/GenXVisaRegAlloc.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2017-2023 Intel Corporation
3+
Copyright (C) 2017-2024 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66

IGC/VectorCompiler/lib/GenXCodeGen/GenXVisaRegAlloc.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2017-2023 Intel Corporation
3+
Copyright (C) 2017-2024 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66

IGC/VectorCompiler/test/CisaBuilder/debugtrap.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
;=========================== begin_copyright_notice ============================
22
;
3-
; Copyright (C) 2023 Intel Corporation
3+
; Copyright (C) 2023-2024 Intel Corporation
44
;
55
; SPDX-License-Identifier: MIT
66
;

IGC/VectorCompiler/test/DebugInfo/basic_var_locs.ll

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
;=========================== begin_copyright_notice ============================
22
;
3-
; Copyright (C) 2020-2021 Intel Corporation
3+
; Copyright (C) 2020-2024 Intel Corporation
44
;
55
; SPDX-License-Identifier: MIT
66
;
@@ -112,8 +112,6 @@ attributes #1 = { nounwind readnone speculatable willreturn }
112112
attributes #2 = { nounwind readnone }
113113
attributes #3 = { nounwind readonly }
114114
attributes #4 = { nounwind }
115-
attributes #5 = { noinline nounwind "CMFloatControl"="0" }
116-
attributes #6 = { noinline nounwind "CMFloatControl"="48" }
117115

118116
!llvm.module.flags = !{!0, !1}
119117
!llvm.dbg.cu = !{!2}

0 commit comments

Comments
 (0)