Skip to content

Commit c1bb379

Browse files
authored
[NFC][SYCL] Refactor SpecConstantsPass (#10613)
To improve readability of `SpecConstantsPass::run` function, some of its content is outlined into a separate helper functions.
1 parent ea2e6e0 commit c1bb379

File tree

2 files changed

+114
-178
lines changed

2 files changed

+114
-178
lines changed

llvm/test/tools/sycl-post-link/spec-constants/composite-default-value.ll

Lines changed: 0 additions & 92 deletions
This file was deleted.

llvm/tools/sycl-post-link/SpecConstants.cpp

Lines changed: 114 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,115 @@ Instruction *emitSpecConstantRecursive(Type *Ty, Instruction *InsertBefore,
610610
DefaultValue);
611611
}
612612

613+
/// Function creates load instruction from the given Buffer by the given Offset.
614+
/// Function returns the value of load instruction.
615+
Value *createLoadFromBuffer(CallInst *InsertBefore, Value *Buffer,
616+
size_t Offset, Type *SCType) {
617+
LLVMContext &C = InsertBefore->getContext();
618+
Type *Int8Ty = Type::getInt8Ty(C);
619+
Type *Int32Ty = Type::getInt32Ty(C);
620+
GetElementPtrInst *GEP = GetElementPtrInst::Create(
621+
Int8Ty, Buffer, {ConstantInt::get(Int32Ty, Offset, false)}, "gep",
622+
InsertBefore);
623+
624+
Instruction *BitCast = nullptr;
625+
if (SCType->isIntegerTy(1)) // No bitcast to i1 before load
626+
BitCast = GEP;
627+
else
628+
BitCast =
629+
new BitCastInst(GEP, PointerType::get(SCType, GEP->getAddressSpace()),
630+
"bc", InsertBefore);
631+
632+
// When we encounter i1 spec constant, we still load the whole byte
633+
Value *Load = new LoadInst(SCType->isIntegerTy(1) ? Int8Ty : SCType, BitCast,
634+
"load", InsertBefore);
635+
if (SCType->isIntegerTy(1)) // trunc back to i1 if necessary
636+
Load = CastInst::CreateIntegerCast(Load, SCType, /* IsSigned */ false,
637+
"tobool", InsertBefore);
638+
639+
return Load;
640+
}
641+
642+
/// Function tries to dig out the initializer from the given CallInst to
643+
/// SpecConst function. ArgIndex is the expected index of the function operand
644+
/// leading to the initializer.
645+
///
646+
/// Examples:
647+
/// 1)
648+
/// %"spec_id" = type { i32 }
649+
/// @value = internal addrspace(1) constant %"spec_id" { i32 123 }, align 4
650+
/// call spir_func i32 @sycl_getScalar2020SpecConst(%1, @value, %2)
651+
///
652+
/// 2)
653+
/// %"spec_id" = type { %A }
654+
/// %A = type { i32 }
655+
/// @value = constant %"spec_id" { %A { i32 1 } }, align 4
656+
/// call spir_func void @getCompositeSpecConst(%1, %2, @value, %3)
657+
Constant *getSpecConstInitializerFromCI(CallInst *CI, unsigned ArgIndex) {
658+
auto *GV =
659+
cast<GlobalVariable>(CI->getArgOperand(ArgIndex)->stripPointerCasts());
660+
661+
// Go through global variable if the argument was not null.
662+
assert(GV->hasInitializer() && "GV is expected to have initializer");
663+
Constant *Initializer = GV->getInitializer();
664+
assert((isa<ConstantAggregate>(Initializer) || Initializer->isZeroValue()) &&
665+
"expected specialization_id instance");
666+
// specialization_id structure contains a single field which is the
667+
// default value of corresponding specialization constant.
668+
return Initializer->getAggregateElement(0u);
669+
}
670+
671+
/// Function replaces last Metadata node in the given vector with new
672+
/// node which contains given Padding.
673+
void updatePaddingInLastMDNode(LLVMContext &Ctx,
674+
MapVector<StringRef, MDNode *> &SCMetadata,
675+
unsigned Padding) {
676+
// The spec constant map can't be empty as the first offset is 0
677+
// and so it can't be misaligned.
678+
assert(!SCMetadata.empty() && "Cannot add padding to first spec constant");
679+
680+
// To communicate the padding to the runtime, update the metadata
681+
// node of the previous spec constant to append a padding node. It
682+
// can't be added in front of the current spec constant, as doing
683+
// so would require the spec constant node to have a non-zero
684+
// CompositeOffset which breaks accessing it in the runtime.
685+
auto Last = SCMetadata.back();
686+
687+
// Emulated spec constants don't use composite so should
688+
// always be formatted as (SymID, ID, Offset, Size), except when
689+
// they include padding, but since padding is added at insertion
690+
// of the next element, the last element of the map can never be
691+
// padded.
692+
assert(Last.second->getNumOperands() == 4 &&
693+
"Incorrect emulated spec constant format");
694+
695+
Type *Int32Ty = Type::getInt32Ty(Ctx);
696+
SmallVector<Metadata *, 16> MDOps;
697+
698+
// Copy the existing metadata.
699+
MDOps.push_back(Last.second->getOperand(0));
700+
MDOps.push_back(Last.second->getOperand(1));
701+
MDOps.push_back(Last.second->getOperand(2));
702+
auto &SizeOp = Last.second->getOperand(3);
703+
MDOps.push_back(SizeOp);
704+
705+
// Extract the size of the previous node to use as CompositeOffset
706+
// for the padding node.
707+
auto PrevSize = mdconst::extract<ConstantInt>(SizeOp)->getValue();
708+
709+
// The max value is a magic value used for padding that the
710+
// runtime knows to skip.
711+
MDOps.push_back(ConstantAsMetadata::get(Constant::getIntegerValue(
712+
Int32Ty, APInt(32, std::numeric_limits<unsigned>::max()))));
713+
MDOps.push_back(
714+
ConstantAsMetadata::get(Constant::getIntegerValue(Int32Ty, PrevSize)));
715+
MDOps.push_back(ConstantAsMetadata::get(
716+
Constant::getIntegerValue(Int32Ty, APInt(32, Padding))));
717+
718+
// Replace the last metadata node with the node including the padding.
719+
SCMetadata[Last.first] = MDNode::get(Ctx, MDOps);
720+
}
721+
613722
} // namespace
614723

615724
PreservedAnalyses SpecConstantsPass::run(Module &M,
@@ -627,6 +736,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
627736
// setting (see below).
628737
bool IRModified = false;
629738

739+
LLVMContext &Ctx = M.getContext();
630740
for (Function &F : M) {
631741
if (!F.isDeclaration())
632742
continue;
@@ -665,23 +775,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
665775
StringRef SymID = getStringLiteralArg(CI, NameArgNo, DelInsts);
666776
Value *Replacement = nullptr;
667777

668-
Constant *DefaultValue = nullptr;
669-
// There is a mechanism to specify the default value in SYCL 2020.
670-
// It is stored as an initializer of a global variable referenced by
671-
// the second argument of the intrinsic.
672-
auto *GV = dyn_cast<GlobalVariable>(
673-
CI->getArgOperand(NameArgNo + 1)->stripPointerCasts());
674-
// Go through global variable if the second argument was not null.
675-
if (GV) {
676-
assert(GV->hasInitializer() && "expected initializer");
677-
auto *Initializer = GV->getInitializer();
678-
assert((isa<ConstantAggregate>(Initializer) ||
679-
Initializer->isZeroValue()) &&
680-
"expected specialization_id instance");
681-
// specialization_id structure contains a single field which is the
682-
// default value of corresponding specialization constant.
683-
DefaultValue = Initializer->getAggregateElement(0u);
684-
}
778+
Constant *DefaultValue = getSpecConstInitializerFromCI(CI, NameArgNo + 1);
685779

686780
bool IsNewSpecConstant = false;
687781
unsigned Padding = 0;
@@ -743,54 +837,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
743837
OffsetMap[SymID] = NextOffset;
744838

745839
assert(CurrentOffset % Align == 0 && "Alignment calculation error");
746-
747-
// The spec constant map can't be empty as the first offset is 0
748-
// and so it can't be misaligned.
749-
assert(!SCMetadata.empty() &&
750-
"Cannot add padding to first spec constant");
751-
752-
// To communicate the padding to the runtime, update the metadata
753-
// node of the previous spec constant to append a padding node. It
754-
// can't be added in front of the current spec constant, as doing
755-
// so would require the spec constant node to have a non-zero
756-
// CompositeOffset which breaks accessing it in the runtime.
757-
auto Prev = SCMetadata.back();
758-
759-
// Emulated spec constants don't use composite so should
760-
// always be formatted as (SymID, ID, Offset, Size), except when
761-
// they include padding, but since padding is added at insertion
762-
// of the next element, the last element of the map can never be
763-
// padded.
764-
assert(Prev.second->getNumOperands() == 4 &&
765-
"Incorrect emulated spec constant format");
766-
767-
LLVMContext &Ctx = M.getContext();
768-
auto *Int32Ty = Type::getInt32Ty(Ctx);
769-
SmallVector<Metadata *, 16> MDOps;
770-
771-
// Copy the existing metadata.
772-
MDOps.push_back(Prev.second->getOperand(0));
773-
MDOps.push_back(Prev.second->getOperand(1));
774-
MDOps.push_back(Prev.second->getOperand(2));
775-
auto &SizeOp = Prev.second->getOperand(3);
776-
MDOps.push_back(SizeOp);
777-
778-
// Extract the size of the previous node to use as CompositeOffset
779-
// for the padding node.
780-
auto PrevSize = mdconst::extract<ConstantInt>(SizeOp)->getValue();
781-
782-
// The max value is a magic value used for padding that the
783-
// runtime knows to skip.
784-
MDOps.push_back(ConstantAsMetadata::get(Constant::getIntegerValue(
785-
Int32Ty, APInt(32, std::numeric_limits<unsigned>::max()))));
786-
MDOps.push_back(ConstantAsMetadata::get(
787-
Constant::getIntegerValue(Int32Ty, PrevSize)));
788-
MDOps.push_back(ConstantAsMetadata::get(
789-
Constant::getIntegerValue(Int32Ty, APInt(32, Padding))));
790-
791-
// Replace previous metadata node with the node including the
792-
// padding.
793-
SCMetadata[Prev.first] = MDNode::get(Ctx, MDOps);
840+
updatePaddingInLastMDNode(Ctx, SCMetadata, Padding);
794841
}
795842

796843
SCMetadata[SymID] = generateSpecConstantMetadata(
@@ -800,31 +847,12 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
800847
NextOffset += Size;
801848
}
802849

803-
Type *Int8Ty = Type::getInt8Ty(CI->getContext());
804-
Type *Int32Ty = Type::getInt32Ty(CI->getContext());
805-
GetElementPtrInst *GEP = GetElementPtrInst::Create(
806-
Int8Ty, RTBuffer, {ConstantInt::get(Int32Ty, CurrentOffset, false)},
807-
"gep", CI);
808-
809-
Instruction *BitCast = nullptr;
810-
if (SCTy->isIntegerTy(1)) // No bitcast to i1 before load
811-
BitCast = GEP;
812-
else
813-
BitCast = new BitCastInst(
814-
GEP, PointerType::get(SCTy, GEP->getAddressSpace()), "bc", CI);
815-
816-
// When we encounter i1 spec constant, we still load the whole byte
817-
Replacement = new LoadInst(SCTy->isIntegerTy(1) ? Int8Ty : SCTy,
818-
BitCast, "load", CI);
819-
if (SCTy->isIntegerTy(1)) // trunc back to i1 if necessary
820-
Replacement = CastInst::CreateIntegerCast(
821-
Replacement, SCTy, /* IsSigned */ false, "tobool", CI);
850+
Replacement = createLoadFromBuffer(CI, RTBuffer, CurrentOffset, SCTy);
822851
}
823852

824-
if (IsNewSpecConstant && DefaultValue) {
853+
if (IsNewSpecConstant) {
825854
if (Padding != 0) {
826855
// Initialize the padding with null data
827-
LLVMContext &Ctx = DefaultValue->getContext();
828856
auto PadTy = ArrayType::get(Type::getInt8Ty(Ctx), Padding);
829857
DefaultsMetadata.push_back(MDNode::get(
830858
Ctx,

0 commit comments

Comments
 (0)