Skip to content

Commit 61c7c64

Browse files
committed
[NFC][SYCL] Refactor SpecConstPass. Part 1
1 parent 7bf1f57 commit 61c7c64

File tree

1 file changed

+117
-85
lines changed

1 file changed

+117
-85
lines changed

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

Lines changed: 117 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,118 @@ Instruction *emitSpecConstantRecursive(Type *Ty, Instruction *InsertBefore,
612612

613613
} // namespace
614614

615+
/// Function creates load instruction from the given Buffer by the given Offset.
616+
/// Function returns the value of load instruction.
617+
static Value *createLoadFromBuffer(CallInst *CI, Value *Buffer, size_t Offset,
618+
Type *SCType) {
619+
LLVMContext &C = CI->getContext();
620+
Type *Int8Ty = Type::getInt8Ty(C);
621+
Type *Int32Ty = Type::getInt32Ty(C);
622+
GetElementPtrInst *GEP = GetElementPtrInst::Create(
623+
Int8Ty, Buffer, {ConstantInt::get(Int32Ty, Offset, false)}, "gep", CI);
624+
625+
Instruction *BitCast = nullptr;
626+
if (SCType->isIntegerTy(1)) // No bitcast to i1 before load
627+
BitCast = GEP;
628+
else
629+
BitCast = new BitCastInst(
630+
GEP, PointerType::get(SCType, GEP->getAddressSpace()), "bc", CI);
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", CI);
635+
if (SCType->isIntegerTy(1)) // trunc back to i1 if necessary
636+
Load = CastInst::CreateIntegerCast(Load, SCType, /* IsSigned */ false,
637+
"tobool", CI);
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+
static Constant *tryGetSpecConstInitializerFromCI(CallInst *CI,
658+
unsigned ArgIndex) {
659+
assert(CI->getNumOperands() > ArgIndex && "ArgIndex is out of boundary");
660+
auto *GV = dyn_cast<GlobalVariable>(
661+
CI->getArgOperand(ArgIndex)->stripPointerCasts());
662+
if (!GV)
663+
return nullptr;
664+
665+
// Go through global variable if the argument was not null.
666+
assert(GV->hasInitializer() && "GV is expected to have initializer");
667+
Constant *Initializer = GV->getInitializer();
668+
assert((isa<ConstantAggregate>(Initializer) || Initializer->isZeroValue()) &&
669+
"expected specialization_id instance");
670+
// specialization_id structure contains a single field which is the
671+
// default value of corresponding specialization constant.
672+
return Initializer->getAggregateElement(0u);
673+
}
674+
675+
/// Function replaces last Metadata node in the given vector with new
676+
/// node which contains given Padding.
677+
static void
678+
updatePaddingInLastMDNode(LLVMContext &Ctx,
679+
MapVector<StringRef, MDNode *> &SCMetadata,
680+
unsigned Padding) {
681+
// The spec constant map can't be empty as the first offset is 0
682+
// and so it can't be misaligned.
683+
assert(!SCMetadata.empty() && "Cannot add padding to first spec constant");
684+
685+
// To communicate the padding to the runtime, update the metadata
686+
// node of the previous spec constant to append a padding node. It
687+
// can't be added in front of the current spec constant, as doing
688+
// so would require the spec constant node to have a non-zero
689+
// CompositeOffset which breaks accessing it in the runtime.
690+
auto Last = SCMetadata.back();
691+
692+
// Emulated spec constants don't use composite so should
693+
// always be formatted as (SymID, ID, Offset, Size), except when
694+
// they include padding, but since padding is added at insertion
695+
// of the next element, the last element of the map can never be
696+
// padded.
697+
assert(Last.second->getNumOperands() == 4 &&
698+
"Incorrect emulated spec constant format");
699+
700+
Type *Int32Ty = Type::getInt32Ty(Ctx);
701+
SmallVector<Metadata *, 16> MDOps;
702+
703+
// Copy the existing metadata.
704+
MDOps.push_back(Last.second->getOperand(0));
705+
MDOps.push_back(Last.second->getOperand(1));
706+
MDOps.push_back(Last.second->getOperand(2));
707+
auto &SizeOp = Last.second->getOperand(3);
708+
MDOps.push_back(SizeOp);
709+
710+
// Extract the size of the previous node to use as CompositeOffset
711+
// for the padding node.
712+
auto PrevSize = mdconst::extract<ConstantInt>(SizeOp)->getValue();
713+
714+
// The max value is a magic value used for padding that the
715+
// runtime knows to skip.
716+
MDOps.push_back(ConstantAsMetadata::get(Constant::getIntegerValue(
717+
Int32Ty, APInt(32, std::numeric_limits<unsigned>::max()))));
718+
MDOps.push_back(
719+
ConstantAsMetadata::get(Constant::getIntegerValue(Int32Ty, PrevSize)));
720+
MDOps.push_back(ConstantAsMetadata::get(
721+
Constant::getIntegerValue(Int32Ty, APInt(32, Padding))));
722+
723+
// Replace the last metadata node with the node including the padding.
724+
SCMetadata[Last.first] = MDNode::get(Ctx, MDOps);
725+
}
726+
615727
PreservedAnalyses SpecConstantsPass::run(Module &M,
616728
ModuleAnalysisManager &MAM) {
617729
ID NextID = {0, false};
@@ -627,6 +739,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
627739
// setting (see below).
628740
bool IRModified = false;
629741

742+
LLVMContext &Ctx = M.getContext();
630743
for (Function &F : M) {
631744
if (!F.isDeclaration())
632745
continue;
@@ -665,23 +778,8 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
665778
StringRef SymID = getStringLiteralArg(CI, NameArgNo, DelInsts);
666779
Value *Replacement = nullptr;
667780

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-
}
781+
Constant *DefaultValue =
782+
tryGetSpecConstInitializerFromCI(CI, NameArgNo + 1);
685783

686784
bool IsNewSpecConstant = false;
687785
unsigned Padding = 0;
@@ -743,54 +841,7 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
743841
OffsetMap[SymID] = NextOffset;
744842

745843
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);
844+
updatePaddingInLastMDNode(Ctx, SCMetadata, Padding);
794845
}
795846

796847
SCMetadata[SymID] = generateSpecConstantMetadata(
@@ -800,31 +851,12 @@ PreservedAnalyses SpecConstantsPass::run(Module &M,
800851
NextOffset += Size;
801852
}
802853

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);
854+
Replacement = createLoadFromBuffer(CI, RTBuffer, CurrentOffset, SCTy);
822855
}
823856

824857
if (IsNewSpecConstant && DefaultValue) {
825858
if (Padding != 0) {
826859
// Initialize the padding with null data
827-
LLVMContext &Ctx = DefaultValue->getContext();
828860
auto PadTy = ArrayType::get(Type::getInt8Ty(Ctx), Padding);
829861
DefaultsMetadata.push_back(MDNode::get(
830862
Ctx,

0 commit comments

Comments
 (0)