diff --git a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp index 76a46c7a2b760..6d7647f9abb56 100644 --- a/llvm/lib/Target/DirectX/DXILLegalizePass.cpp +++ b/llvm/lib/Target/DirectX/DXILLegalizePass.cpp @@ -98,9 +98,9 @@ static void fixI8UseChain(Instruction &I, ElementType = AI->getAllocatedType(); if (auto *GEP = dyn_cast(NewOperands[0])) { ElementType = GEP->getSourceElementType(); - if (ElementType->isArrayTy()) - ElementType = ElementType->getArrayElementType(); } + if (ElementType->isArrayTy()) + ElementType = ElementType->getArrayElementType(); LoadInst *NewLoad = Builder.CreateLoad(ElementType, NewOperands[0]); ReplacedValues[Load] = NewLoad; ToRemove.push_back(Load); @@ -562,6 +562,45 @@ legalizeGetHighLowi64Bytes(Instruction &I, } } +static void +legalizeLoadStoreOnArrayAllocas(Instruction &I, + SmallVectorImpl &ToRemove, + DenseMap &) { + + Value *PtrOp; + unsigned PtrOpIndex; + [[maybe_unused]] Type *LoadStoreTy; + if (auto *LI = dyn_cast(&I)) { + PtrOp = LI->getPointerOperand(); + PtrOpIndex = LI->getPointerOperandIndex(); + LoadStoreTy = LI->getType(); + } else if (auto *SI = dyn_cast(&I)) { + PtrOp = SI->getPointerOperand(); + PtrOpIndex = SI->getPointerOperandIndex(); + LoadStoreTy = SI->getValueOperand()->getType(); + } else + return; + + assert(LoadStoreTy->isSingleValueType() && + "Expected load/store type to be a single-valued type"); + + auto *AllocaPtrOp = dyn_cast(PtrOp); + if (!AllocaPtrOp) + return; + + Type *Ty = AllocaPtrOp->getAllocatedType(); + if (!isa(Ty)) + return; + assert(!isa(Ty->getArrayElementType()) && + "Expected allocated type of AllocaInst to be a flat ArrayType"); + + IRBuilder<> Builder(&I); + Value *Zero = Builder.getInt32(0); + Value *GEP = Builder.CreateGEP(Ty, AllocaPtrOp, {Zero, Zero}, "", + GEPNoWrapFlags::all()); + I.setOperand(PtrOpIndex, GEP); +} + namespace { class DXILLegalizationPipeline { @@ -612,6 +651,7 @@ class DXILLegalizationPipeline { // downcastI64toI32InsertExtractElements needs to handle. LegalizationPipeline[Stage2].push_back( downcastI64toI32InsertExtractElements); + LegalizationPipeline[Stage2].push_back(legalizeLoadStoreOnArrayAllocas); } }; diff --git a/llvm/test/CodeGen/DirectX/legalize-i8.ll b/llvm/test/CodeGen/DirectX/legalize-i8.ll index f8aa2c5ecd932..7eb47ba661f4c 100644 --- a/llvm/test/CodeGen/DirectX/legalize-i8.ll +++ b/llvm/test/CodeGen/DirectX/legalize-i8.ll @@ -127,10 +127,9 @@ define i32 @i8_geps_index0() { ; CHECK: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4 ; CHECK-NEXT: ret i32 [[LOAD]] %1 = alloca [2 x i32], align 8 - %2 = getelementptr inbounds nuw i8, ptr %1, i32 0 - %3 = load i8, ptr %2 - %4 = sext i8 %3 to i32 - ret i32 %4 + %2 = load i8, ptr %1 + %3 = sext i8 %2 to i32 + ret i32 %3 } define i32 @i8_geps_index1() { @@ -149,11 +148,14 @@ define i32 @i8_geps_index1() { define i32 @i8_gep_store() { ; CHECK-LABEL: define i32 @i8_gep_store( ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [2 x i32], align 8 + ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw [2 x i32], ptr [[ALLOCA]], i32 0, i32 0 + ; CHECK-NEXT: store i32 0, ptr [[GEP]], align 4 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw [2 x i32], ptr [[ALLOCA]], i32 0, i32 1 ; CHECK-NEXT: store i32 1, ptr [[GEP]], align 4 ; CHECK: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4 ; CHECK-NEXT: ret i32 [[LOAD]] %1 = alloca [2 x i32], align 8 + store i8 0, ptr %1 %2 = getelementptr inbounds nuw i8, ptr %1, i32 4 store i8 1, ptr %2 %3 = load i8, ptr %2 diff --git a/llvm/test/CodeGen/DirectX/legalize-load-store-array-alloca.ll b/llvm/test/CodeGen/DirectX/legalize-load-store-array-alloca.ll new file mode 100644 index 0000000000000..b25b3de901d91 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/legalize-load-store-array-alloca.ll @@ -0,0 +1,23 @@ +; RUN: opt -S -passes='dxil-legalize' -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s + +define float @load() { +; CHECK-LABEL: define float @load +; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [2 x float], align 4 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw [2 x float], ptr [[ALLOCA]], i32 0, i32 0 +; CHECK-NEXT: [[LOAD:%.*]] = load float, ptr [[GEP]], align 4 +; CHECK-NEXT: ret float [[LOAD]] + %a = alloca [2 x float], align 4 + %b = load float, ptr %a, align 4 + ret float %b +} + +define void @store() { +; CHECK-LABEL: define void @store +; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [3 x i32], align 4 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw [3 x i32], ptr [[ALLOCA]], i32 0, i32 0 +; CHECK-NEXT: store i32 0, ptr [[GEP]], align 4 +; CHECK-NEXT: ret void + %a = alloca [3 x i32], align 4 + store i32 0, ptr %a, align 4 + ret void +}