[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:
parent
eebc390eb0
commit
29cb6f0147
@ -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>();
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user