[Clang] Track alloca element types to avoid getAllocatedType() calls (#181740)

Store alloca element types alongside alloca pointers in Clang's CodeGen,
eliminating the need to query getAllocatedType() later.

Changes:
- CodeGenFunction.h: Modified DominatingLLVMValue::saved_type to track
type Uses Type==nullptr as sentinel for "not saved" instead of separate
bool. Fixes a bug where it previously tried to use the addrspacecasted
value constructor and later cast it to an alloca.
- CGHLSLRuntime.cpp: Changed OutputSemantic map to store (Value*, Type*)
pairs to trivially remove getAllocatedType calls.

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jameson Nash 2026-03-09 21:34:57 -04:00 committed by GitHub
parent eebc390eb0
commit 29cb6f0147
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 18 deletions

View File

@ -951,7 +951,8 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
OB.emplace_back("convergencectrl", bundleArgs);
}
llvm::DenseMap<const DeclaratorDecl *, llvm::Value *> OutputSemantic;
llvm::DenseMap<const DeclaratorDecl *, std::pair<llvm::Value *, llvm::Type *>>
OutputSemantic;
unsigned SRetOffset = 0;
for (const auto &Param : Fn->args()) {
@ -959,7 +960,7 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
SRetOffset = 1;
llvm::Type *VarType = Param.getParamStructRetType();
llvm::Value *Var = B.CreateAlloca(VarType);
OutputSemantic.try_emplace(FD, Var);
OutputSemantic.try_emplace(FD, std::make_pair(Var, VarType));
Args.push_back(Var);
continue;
}
@ -995,12 +996,14 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
CI->setCallingConv(Fn->getCallingConv());
if (Fn->getReturnType() != CGM.VoidTy)
OutputSemantic.try_emplace(FD, CI);
// Element type is unused, so set to dummy value (NULL).
OutputSemantic.try_emplace(FD, std::make_pair(CI, nullptr));
for (auto &[Decl, Source] : OutputSemantic) {
for (auto &[Decl, SourcePair] : OutputSemantic) {
llvm::Value *Source = SourcePair.first;
llvm::Type *ElementType = SourcePair.second;
AllocaInst *AI = dyn_cast<AllocaInst>(Source);
llvm::Value *SourceValue =
AI ? B.CreateLoad(AI->getAllocatedType(), Source) : Source;
llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
auto AttrBegin = Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
auto AttrEnd = Decl->specific_attr_end<HLSLAppliedSemanticAttr>();

View File

@ -119,7 +119,17 @@ enum TypeEvaluationKind {
/// Helper class with most of the code for saving a value for a
/// conditional expression cleanup.
struct DominatingLLVMValue {
typedef llvm::PointerIntPair<llvm::Value *, 1, bool> saved_type;
struct saved_type {
llvm::Value *Value; // Original value if not saved, alloca if saved
llvm::Type *Type; // nullptr if not saved, element type if saved
saved_type() : Value(nullptr), Type(nullptr) {}
saved_type(llvm::Value *V) : Value(V), Type(nullptr) {}
saved_type(llvm::AllocaInst *Alloca, llvm::Type *Ty)
: Value(Alloca), Type(Ty) {}
bool isSaved() const { return Type != nullptr; }
};
/// Answer whether the given value needs extra work to be saved.
static bool needsSaving(llvm::Value *value) {
@ -5600,28 +5610,29 @@ private:
inline DominatingLLVMValue::saved_type
DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) {
if (!needsSaving(value))
return saved_type(value, false);
return saved_type(value);
// Otherwise, we need an alloca.
auto align = CharUnits::fromQuantity(
CGF.CGM.getDataLayout().getPrefTypeAlign(value->getType()));
Address alloca =
CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save");
CGF.Builder.CreateStore(value, alloca);
CGF.CGM.getDataLayout().getPrefTypeAlign(value->getType()))
.getAsAlign();
llvm::AllocaInst *AI =
CGF.CreateTempAlloca(value->getType(), "cond-cleanup.save");
AI->setAlignment(align);
CGF.Builder.CreateAlignedStore(value, AI, align);
return saved_type(alloca.emitRawPointer(CGF), true);
return saved_type(AI, value->getType());
}
inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF,
saved_type value) {
// If the value says it wasn't saved, trust that it's still dominating.
if (!value.getInt())
return value.getPointer();
if (!value.isSaved())
return value.Value;
// Otherwise, it should be an alloca instruction, as set up in save().
auto alloca = cast<llvm::AllocaInst>(value.getPointer());
return CGF.Builder.CreateAlignedLoad(alloca->getAllocatedType(), alloca,
alloca->getAlign());
auto Alloca = cast<llvm::AllocaInst>(value.Value);
return CGF.Builder.CreateAlignedLoad(value.Type, Alloca, Alloca->getAlign());
}
} // end namespace CodeGen