Skip to content

Commit 5cfefc7

Browse files
authored
Fix CB vector to scalar array translation generating invalid IR (microsoft#6777)
In the special code to handle the memcpy pattern where a constant buffer contains a vector array that initializes a local (or static global) scalar array for use by the shader, an invalid assumption was made that if the memcpy dest was global, that the src is global as well. This was not the case, and when expecting to generate constant expressions to index the src, these generated orphaned instructions instead, leading to invalid IR. This fixes the issue by leveraging ReplaceConstantWithInst, and setting the insertion point for the Builder. Now, replacement *could* fail, if src instructions don't dominate replacement uses, so bool for replaced all is returned from replaceScalarArrayWithVectorArray. Another issue was that it would replace the dest for the original memcpy with src along the way. Now, if we don't replace all uses, this turns the memcpy into a no-op and any remaining uses are no longer coming from src, but an undef dest instead. This was also fixed to skip this replacement, then clean up this use if all other uses have been successfully replaced. Fixes microsoft#6510
1 parent 759e9e1 commit 5cfefc7

File tree

4 files changed

+447
-15
lines changed

4 files changed

+447
-15
lines changed

lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3427,7 +3427,7 @@ static void updateLifetimeForReplacement(Value *From, Value *To) {
34273427
static bool DominateAllUsers(Instruction *I, Value *V, DominatorTree *DT);
34283428

34293429
namespace {
3430-
void replaceScalarArrayGEPWithVectorArrayGEP(User *GEP, Value *VectorArray,
3430+
bool replaceScalarArrayGEPWithVectorArrayGEP(User *GEP, Value *VectorArray,
34313431
IRBuilder<> &Builder,
34323432
unsigned sizeInDwords) {
34333433
gep_type_iterator GEPIt = gep_type_begin(GEP), E = gep_type_end(GEP);
@@ -3461,11 +3461,30 @@ void replaceScalarArrayGEPWithVectorArrayGEP(User *GEP, Value *VectorArray,
34613461
Value *CompIdx = Builder.CreateAnd(ArrayIdx, mask);
34623462
Value *NewGEP = Builder.CreateGEP(
34633463
VecPtr, {ConstantInt::get(CompIdx->getType(), 0), CompIdx});
3464-
GEP->replaceAllUsesWith(NewGEP);
3464+
3465+
if (isa<ConstantExpr>(GEP) && isa<Instruction>(NewGEP)) {
3466+
if (!ReplaceConstantWithInst(cast<Constant>(GEP), NewGEP, Builder)) {
3467+
// If new instructions unable to be used, clean them up.
3468+
if (NewGEP->user_empty())
3469+
cast<Instruction>(NewGEP)->eraseFromParent();
3470+
if (isa<Instruction>(VecPtr) && VecPtr->user_empty())
3471+
cast<Instruction>(VecPtr)->eraseFromParent();
3472+
if (isa<Instruction>(CompIdx) && CompIdx->user_empty())
3473+
cast<Instruction>(CompIdx)->eraseFromParent();
3474+
if (isa<Instruction>(VecIdx) && VecIdx->user_empty())
3475+
cast<Instruction>(VecIdx)->eraseFromParent();
3476+
return false;
3477+
}
3478+
return true;
3479+
} else {
3480+
GEP->replaceAllUsesWith(NewGEP);
3481+
}
3482+
return true;
34653483
}
34663484

3467-
void replaceScalarArrayWithVectorArray(Value *ScalarArray, Value *VectorArray,
3485+
bool replaceScalarArrayWithVectorArray(Value *ScalarArray, Value *VectorArray,
34683486
MemCpyInst *MC, unsigned sizeInDwords) {
3487+
bool bReplacedAll = true;
34693488
LLVMContext &Context = ScalarArray->getContext();
34703489
// All users should be element type.
34713490
// Replace users of AI or GV.
@@ -3474,38 +3493,52 @@ void replaceScalarArrayWithVectorArray(Value *ScalarArray, Value *VectorArray,
34743493
if (U->user_empty())
34753494
continue;
34763495
if (BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
3477-
BCI->setOperand(0, VectorArray);
3496+
// Avoid replacing the dest of the memcpy to support partial replacement.
3497+
if (MC->getArgOperand(0) != BCI)
3498+
BCI->setOperand(0, VectorArray);
34783499
continue;
34793500
}
34803501

34813502
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
34823503
IRBuilder<> Builder(Context);
3504+
// If we need to replace the constant with an instruction, start at the
3505+
// memcpy, so we replace only users dominated by it.
3506+
if (isa<Instruction>(VectorArray))
3507+
Builder.SetInsertPoint(MC);
3508+
34833509
if (GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
3484-
// NewGEP must be GEPOperator too.
3485-
// No instruction will be build.
3486-
replaceScalarArrayGEPWithVectorArrayGEP(U, VectorArray, Builder,
3487-
sizeInDwords);
3510+
if (!replaceScalarArrayGEPWithVectorArrayGEP(U, VectorArray, Builder,
3511+
sizeInDwords))
3512+
bReplacedAll = false;
34883513
} else if (CE->getOpcode() == Instruction::AddrSpaceCast) {
34893514
Value *NewAddrSpaceCast = Builder.CreateAddrSpaceCast(
34903515
VectorArray,
34913516
PointerType::get(VectorArray->getType()->getPointerElementType(),
34923517
CE->getType()->getPointerAddressSpace()));
3493-
replaceScalarArrayWithVectorArray(CE, NewAddrSpaceCast, MC,
3494-
sizeInDwords);
3518+
if (!replaceScalarArrayWithVectorArray(CE, NewAddrSpaceCast, MC,
3519+
sizeInDwords)) {
3520+
bReplacedAll = false;
3521+
if (Instruction *NewInst = dyn_cast<Instruction>(NewAddrSpaceCast))
3522+
if (NewInst->user_empty())
3523+
NewInst->eraseFromParent();
3524+
}
34953525
} else if (CE->hasOneUse() && CE->user_back() == MC) {
34963526
continue;
34973527
} else {
34983528
DXASSERT(0, "not implemented");
34993529
}
35003530
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
35013531
IRBuilder<> Builder(GEP);
3502-
replaceScalarArrayGEPWithVectorArrayGEP(U, VectorArray, Builder,
3503-
sizeInDwords);
3504-
GEP->eraseFromParent();
3532+
if (!replaceScalarArrayGEPWithVectorArrayGEP(U, VectorArray, Builder,
3533+
sizeInDwords))
3534+
bReplacedAll = false;
3535+
else
3536+
GEP->eraseFromParent();
35053537
} else {
35063538
DXASSERT(0, "not implemented");
35073539
}
35083540
}
3541+
return bReplacedAll;
35093542
}
35103543

35113544
// For pattern like
@@ -3521,8 +3554,25 @@ bool tryToReplaceCBVec4ArrayToScalarArray(Value *V, Type *TyV, Value *Src,
35213554
Type *EltTy = AT->getElementType();
35223555
unsigned sizeInBits = DL.getTypeSizeInBits(EltTy);
35233556
// Convert array of float4 to array of float.
3524-
replaceScalarArrayWithVectorArray(V, Src, MC, sizeInBits >> 5);
3525-
return true;
3557+
if (replaceScalarArrayWithVectorArray(V, Src, MC, sizeInBits >> 5)) {
3558+
Value *DstBC = MC->getArgOperand(0);
3559+
MC->setArgOperand(0, UndefValue::get(MC->getArgOperand(0)->getType()));
3560+
if (DstBC->user_empty()) {
3561+
// Replacement won't include the memcpy dest. Now remove that use.
3562+
if (BitCastInst *BCI = dyn_cast<BitCastInst>(DstBC)) {
3563+
Value *Dst = BCI->getOperand(0);
3564+
Type *DstTy = Dst->getType();
3565+
if (Dst == V)
3566+
BCI->setOperand(0, UndefValue::get(DstTy));
3567+
else
3568+
llvm_unreachable("Unexpected dest of memcpy.");
3569+
}
3570+
} else {
3571+
llvm_unreachable("Unexpected users of memcpy bitcast.");
3572+
}
3573+
return true;
3574+
}
3575+
return false;
35263576
}
35273577

35283578
} // namespace
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
; RUN: %opt %s -hlsl-passes-resume -scalarrepl-param-hlsl -S | FileCheck %s
2+
3+
; This case should fail to do memcpy replacement because init block does not
4+
; dominate init.end block.
5+
; However, it should not produce invalid IR, as it would have with #6510 due
6+
; to attempting to replace constant dest with instruction source, while
7+
; assuming the source was not constant.
8+
9+
; This makes sure memcpy was split and elements are properly copied to the
10+
; scalar array, then that the scalar array is used for the result.
11+
12+
; Generated using:
13+
; ExtractIRForPassTest.py -p scalarrepl-param-hlsl -o array-to-cbvec-1.ll array-to-cbvec-1.hlsl -- -T vs_6_0
14+
; uint4 VectorArray[2];
15+
;
16+
; uint2 main(int i : IN) : OUT {
17+
; static const uint ScalarArray[8] = (uint[8])VectorArray;
18+
; return uint2(ScalarArray[1], ScalarArray[6]);
19+
; }
20+
21+
; CHECK-NOT: badref
22+
; CHECK-NOT: store <4 x float> zeroinitializer
23+
24+
; Copy array elements from constant to scalar array
25+
; CHECK: %[[VectorArray:.*]] = getelementptr inbounds %"$Globals", %"$Globals"* %{{.*}}, i32 0, i32 0
26+
; CHECK: %[[gep_VA0:.*]] = getelementptr [2 x <4 x i32>], [2 x <4 x i32>]* %[[VectorArray]], i32 0, i32 0
27+
; CHECK: %[[ld_VA0:.*]] = load <4 x i32>, <4 x i32>* %[[gep_VA0]]
28+
; CHECK: %[[ea_VA0_1:.*]] = extractelement <4 x i32> %[[ld_VA0]], i64 1
29+
; CHECK: store i32 %[[ea_VA0_1]], i32* getelementptr inbounds ([8 x i32], [8 x i32]* @"\01?ScalarArray@?1??main@@YA?AV?$vector@I$01@@H@Z@4QBIB", i32 0, i32 1)
30+
; CHECK: %[[gep_VA1:.*]] = getelementptr [2 x <4 x i32>], [2 x <4 x i32>]* %[[VectorArray]], i32 0, i32 1
31+
; CHECK: %[[ld_VA1:.*]] = load <4 x i32>, <4 x i32>* %[[gep_VA1]]
32+
; CHECK: %[[ea_VA1_2:.*]] = extractelement <4 x i32> %[[ld_VA1]], i64 2
33+
; CHECK: store i32 %[[ea_VA1_2]], i32* getelementptr inbounds ([8 x i32], [8 x i32]* @"\01?ScalarArray@?1??main@@YA?AV?$vector@I$01@@H@Z@4QBIB", i32 0, i32 6)
34+
35+
; Load from scalar array and return it
36+
; CHECK: %[[ld_SA1:.*]] = load i32, i32* getelementptr inbounds ([8 x i32], [8 x i32]* @"\01?ScalarArray@?1??main@@YA?AV?$vector@I$01@@H@Z@4QBIB", i32 0, i32 1), align 4
37+
; CHECK: %[[ld_SA6:.*]] = load i32, i32* getelementptr inbounds ([8 x i32], [8 x i32]* @"\01?ScalarArray@?1??main@@YA?AV?$vector@I$01@@H@Z@4QBIB", i32 0, i32 6), align 4
38+
; CHECK: %[[ie_SA1:.*]] = insertelement <2 x i32> undef, i32 %[[ld_SA1]], i64 0
39+
; CHECK: %[[ie_SA6:.*]] = insertelement <2 x i32> %[[ie_SA1]], i32 %[[ld_SA6]], i64 1
40+
; CHECK: store <2 x i32> %[[ie_SA6]], <2 x i32>* %0
41+
42+
target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
43+
target triple = "dxil-ms-dx"
44+
45+
%"$Globals" = type { [2 x <4 x i32>] }
46+
%dx.types.Handle = type { i8* }
47+
%dx.types.ResourceProperties = type { i32, i32 }
48+
49+
@"\01?VectorArray@@3QBV?$vector@I$03@@B" = external constant [2 x <4 x i32>], align 4
50+
@"\01?ScalarArray@?1??main@@YA?AV?$vector@I$01@@H@Z@4QBIB" = internal global [8 x i32] zeroinitializer, align 4
51+
@"$Globals" = external constant %"$Globals"
52+
53+
; Function Attrs: nounwind
54+
define <2 x i32> @main(i32 %i) #0 {
55+
entry:
56+
%0 = alloca i32
57+
store i32 0, i32* %0
58+
%1 = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %\22$Globals\22*, i32)"(i32 0, %"$Globals"* @"$Globals", i32 0)
59+
%2 = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %\22$Globals\22)"(i32 14, %dx.types.Handle %1, %dx.types.ResourceProperties { i32 13, i32 32 }, %"$Globals" undef)
60+
%3 = call %"$Globals"* @"dx.hl.subscript.cb.rn.%\22$Globals\22* (i32, %dx.types.Handle, i32)"(i32 6, %dx.types.Handle %2, i32 0)
61+
%4 = getelementptr inbounds %"$Globals", %"$Globals"* %3, i32 0, i32 0
62+
%i.addr = alloca i32, align 4, !dx.temp !13
63+
store i32 %i, i32* %i.addr, align 4, !tbaa !23
64+
%5 = load i32, i32* %0, !dbg !27 ; line:4 col:5
65+
%6 = and i32 %5, 1, !dbg !27 ; line:4 col:5
66+
%7 = icmp ne i32 %6, 0, !dbg !27 ; line:4 col:5
67+
br i1 %7, label %init.end, label %init, !dbg !27 ; line:4 col:5
68+
69+
init: ; preds = %entry
70+
%8 = or i32 %5, 1, !dbg !27 ; line:4 col:5
71+
store i32 %8, i32* %0, !dbg !27 ; line:4 col:5
72+
%9 = bitcast [8 x i32]* @"\01?ScalarArray@?1??main@@YA?AV?$vector@I$01@@H@Z@4QBIB" to i8*, !dbg !31 ; line:4 col:49
73+
%10 = bitcast [2 x <4 x i32>]* %4 to i8*, !dbg !31 ; line:4 col:49
74+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %9, i8* %10, i64 32, i32 1, i1 false), !dbg !31 ; line:4 col:49
75+
br label %init.end, !dbg !27 ; line:4 col:5
76+
77+
init.end: ; preds = %init, %entry
78+
%11 = load i32, i32* getelementptr inbounds ([8 x i32], [8 x i32]* @"\01?ScalarArray@?1??main@@YA?AV?$vector@I$01@@H@Z@4QBIB", i32 0, i32 1), align 4, !dbg !32, !tbaa !23 ; line:5 col:18
79+
%12 = load i32, i32* getelementptr inbounds ([8 x i32], [8 x i32]* @"\01?ScalarArray@?1??main@@YA?AV?$vector@I$01@@H@Z@4QBIB", i32 0, i32 6), align 4, !dbg !33, !tbaa !23 ; line:5 col:34
80+
%13 = insertelement <2 x i32> undef, i32 %11, i64 0, !dbg !34 ; line:5 col:17
81+
%14 = insertelement <2 x i32> %13, i32 %12, i64 1, !dbg !34 ; line:5 col:17
82+
ret <2 x i32> %14, !dbg !35 ; line:5 col:5
83+
}
84+
85+
; Function Attrs: nounwind
86+
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0
87+
88+
; Function Attrs: nounwind readnone
89+
declare %"$Globals"* @"dx.hl.subscript.cb.rn.%\22$Globals\22* (i32, %dx.types.Handle, i32)"(i32, %dx.types.Handle, i32) #1
90+
91+
; Function Attrs: nounwind readnone
92+
declare %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %\22$Globals\22*, i32)"(i32, %"$Globals"*, i32) #1
93+
94+
; Function Attrs: nounwind readnone
95+
declare %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %\22$Globals\22)"(i32, %dx.types.Handle, %dx.types.ResourceProperties, %"$Globals") #1
96+
97+
attributes #0 = { nounwind }
98+
attributes #1 = { nounwind readnone }
99+
100+
!llvm.module.flags = !{!0}
101+
!pauseresume = !{!1}
102+
!llvm.ident = !{!2}
103+
!dx.version = !{!3}
104+
!dx.valver = !{!4}
105+
!dx.shaderModel = !{!5}
106+
!dx.typeAnnotations = !{!6, !9}
107+
!dx.entryPoints = !{!16}
108+
!dx.fnprops = !{!20}
109+
!dx.options = !{!21, !22}
110+
111+
!0 = !{i32 2, !"Debug Info Version", i32 3}
112+
!1 = !{!"hlsl-hlemit", !"hlsl-hlensure"}
113+
!2 = !{!"dxc(private) 1.8.0.14508 (main, 263a77335-dirty)"}
114+
!3 = !{i32 1, i32 0}
115+
!4 = !{i32 1, i32 7}
116+
!5 = !{!"vs", i32 6, i32 0}
117+
!6 = !{i32 0, %"$Globals" undef, !7}
118+
!7 = !{i32 32, !8}
119+
!8 = !{i32 6, !"VectorArray", i32 3, i32 0, i32 7, i32 5}
120+
!9 = !{i32 1, <2 x i32> (i32)* @main, !10}
121+
!10 = !{!11, !14}
122+
!11 = !{i32 1, !12, !13}
123+
!12 = !{i32 4, !"OUT", i32 7, i32 5}
124+
!13 = !{}
125+
!14 = !{i32 0, !15, !13}
126+
!15 = !{i32 4, !"IN", i32 7, i32 4}
127+
!16 = !{<2 x i32> (i32)* @main, !"main", null, !17, null}
128+
!17 = !{null, null, !18, null}
129+
!18 = !{!19}
130+
!19 = !{i32 0, %"$Globals"* @"$Globals", !"$Globals", i32 0, i32 -1, i32 1, i32 32, null}
131+
!20 = !{<2 x i32> (i32)* @main, i32 1}
132+
!21 = !{i32 -2147483584}
133+
!22 = !{i32 -1}
134+
!23 = !{!24, !24, i64 0}
135+
!24 = !{!"int", !25, i64 0}
136+
!25 = !{!"omnipotent char", !26, i64 0}
137+
!26 = !{!"Simple C/C++ TBAA"}
138+
!27 = !DILocation(line: 4, column: 5, scope: !28)
139+
!28 = !DISubprogram(name: "main", scope: !29, file: !29, line: 3, type: !30, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, function: <2 x i32> (i32)* @main)
140+
!29 = !DIFile(filename: "t:\5Carray-mapping.hlsl", directory: "")
141+
!30 = !DISubroutineType(types: !13)
142+
!31 = !DILocation(line: 4, column: 49, scope: !28)
143+
!32 = !DILocation(line: 5, column: 18, scope: !28)
144+
!33 = !DILocation(line: 5, column: 34, scope: !28)
145+
!34 = !DILocation(line: 5, column: 17, scope: !28)
146+
!35 = !DILocation(line: 5, column: 5, scope: !28)
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
; RUN: %opt %s -hlsl-passes-resume -scalarrepl-param-hlsl -S | FileCheck %s
2+
3+
; Local ScalarArray copy should be eliminated in favor of directly accessing
4+
; VectorArray from cbuffer.
5+
6+
; Generated using:
7+
; ExtractIRForPassTest.py -p scalarrepl-param-hlsl -o array-to-cbvec-2.ll array-to-cbvec-2.hlsl -- -T vs_6_0
8+
; uint4 VectorArray[2];
9+
; static const uint ScalarArray[8] = (uint[8])VectorArray;
10+
;
11+
; uint2 main(int i : IN) : OUT {
12+
; return uint2(ScalarArray[1], ScalarArray[6]);
13+
; }
14+
15+
; replace memcpy path works in this case
16+
; CHECK: %[[VectorArray:.*]] = getelementptr inbounds %"$Globals", %"$Globals"* %{{.*}}, i32 0, i32 0
17+
; CHECK: %[[gep_VA1:.*]] = getelementptr [2 x <4 x i32>], [2 x <4 x i32>]* %[[VectorArray]], i32 0, i32 1
18+
; CHECK: %[[gep_VA1_2:.*]] = getelementptr <4 x i32>, <4 x i32>* %[[gep_VA1]], i32 0, i32 2
19+
; CHECK: %[[gep_VA0:.*]] = getelementptr [2 x <4 x i32>], [2 x <4 x i32>]* %[[VectorArray]], i32 0, i32 0
20+
; CHECK: %[[gep_VA0_1:.*]] = getelementptr <4 x i32>, <4 x i32>* %[[gep_VA0]], i32 0, i32 1
21+
; CHECK: %[[ld_VA0_1:.*]] = load i32, i32* %[[gep_VA0_1]], align 4
22+
; CHECK: %[[ld_VA1_2:.*]] = load i32, i32* %[[gep_VA1_2]], align 4
23+
; CHECK: %[[ie_VA0_1:.*]] = insertelement <2 x i32> undef, i32 %[[ld_VA0_1]], i64 0
24+
; CHECK: %[[ie_VA1_2:.*]] = insertelement <2 x i32> %[[ie_VA0_1]], i32 %[[ld_VA1_2]], i64 1
25+
; CHECK: store <2 x i32> %[[ie_VA1_2]], <2 x i32>* %0
26+
27+
target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
28+
target triple = "dxil-ms-dx"
29+
30+
%"$Globals" = type { [2 x <4 x i32>] }
31+
%dx.types.Handle = type { i8* }
32+
%dx.types.ResourceProperties = type { i32, i32 }
33+
34+
@"\01?VectorArray@@3QBV?$vector@I$03@@B" = external constant [2 x <4 x i32>], align 4
35+
@ScalarArray = internal global [8 x i32] undef, align 4
36+
@"$Globals" = external constant %"$Globals"
37+
38+
; Function Attrs: nounwind
39+
define <2 x i32> @main(i32 %i) #0 {
40+
entry:
41+
%0 = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %\22$Globals\22*, i32)"(i32 0, %"$Globals"* @"$Globals", i32 0) #0, !dbg !23 ; line:2 col:45
42+
%1 = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %\22$Globals\22)"(i32 14, %dx.types.Handle %0, %dx.types.ResourceProperties { i32 13, i32 32 }, %"$Globals" undef) #0, !dbg !23 ; line:2 col:45
43+
%2 = call %"$Globals"* @"dx.hl.subscript.cb.rn.%\22$Globals\22* (i32, %dx.types.Handle, i32)"(i32 6, %dx.types.Handle %1, i32 0) #0, !dbg !23 ; line:2 col:45
44+
%3 = getelementptr inbounds %"$Globals", %"$Globals"* %2, i32 0, i32 0, !dbg !23 ; line:2 col:45
45+
%4 = bitcast [2 x <4 x i32>]* %3 to i8*, !dbg !23 ; line:2 col:45
46+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([8 x i32]* @ScalarArray to i8*), i8* %4, i64 32, i32 1, i1 false) #0, !dbg !23 ; line:2 col:45
47+
%i.addr = alloca i32, align 4, !dx.temp !13
48+
store i32 %i, i32* %i.addr, align 4, !tbaa !29
49+
%5 = load i32, i32* getelementptr inbounds ([8 x i32], [8 x i32]* @ScalarArray, i32 0, i32 1), align 4, !dbg !33, !tbaa !29 ; line:5 col:18
50+
%6 = load i32, i32* getelementptr inbounds ([8 x i32], [8 x i32]* @ScalarArray, i32 0, i32 6), align 4, !dbg !34, !tbaa !29 ; line:5 col:34
51+
%7 = insertelement <2 x i32> undef, i32 %5, i64 0, !dbg !35 ; line:5 col:17
52+
%8 = insertelement <2 x i32> %7, i32 %6, i64 1, !dbg !35 ; line:5 col:17
53+
ret <2 x i32> %8, !dbg !36 ; line:5 col:5
54+
}
55+
56+
; Function Attrs: nounwind
57+
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0
58+
59+
; Function Attrs: nounwind readnone
60+
declare %"$Globals"* @"dx.hl.subscript.cb.rn.%\22$Globals\22* (i32, %dx.types.Handle, i32)"(i32, %dx.types.Handle, i32) #1
61+
62+
; Function Attrs: nounwind readnone
63+
declare %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %\22$Globals\22*, i32)"(i32, %"$Globals"*, i32) #1
64+
65+
; Function Attrs: nounwind readnone
66+
declare %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %\22$Globals\22)"(i32, %dx.types.Handle, %dx.types.ResourceProperties, %"$Globals") #1
67+
68+
attributes #0 = { nounwind }
69+
attributes #1 = { nounwind readnone }
70+
71+
!llvm.module.flags = !{!0}
72+
!pauseresume = !{!1}
73+
!llvm.ident = !{!2}
74+
!dx.version = !{!3}
75+
!dx.valver = !{!4}
76+
!dx.shaderModel = !{!5}
77+
!dx.typeAnnotations = !{!6, !9}
78+
!dx.entryPoints = !{!16}
79+
!dx.fnprops = !{!20}
80+
!dx.options = !{!21, !22}
81+
82+
!0 = !{i32 2, !"Debug Info Version", i32 3}
83+
!1 = !{!"hlsl-hlemit", !"hlsl-hlensure"}
84+
!2 = !{!"dxc(private) 1.8.0.14508 (main, 263a77335-dirty)"}
85+
!3 = !{i32 1, i32 0}
86+
!4 = !{i32 1, i32 7}
87+
!5 = !{!"vs", i32 6, i32 0}
88+
!6 = !{i32 0, %"$Globals" undef, !7}
89+
!7 = !{i32 32, !8}
90+
!8 = !{i32 6, !"VectorArray", i32 3, i32 0, i32 7, i32 5}
91+
!9 = !{i32 1, <2 x i32> (i32)* @main, !10}
92+
!10 = !{!11, !14}
93+
!11 = !{i32 1, !12, !13}
94+
!12 = !{i32 4, !"OUT", i32 7, i32 5}
95+
!13 = !{}
96+
!14 = !{i32 0, !15, !13}
97+
!15 = !{i32 4, !"IN", i32 7, i32 4}
98+
!16 = !{<2 x i32> (i32)* @main, !"main", null, !17, null}
99+
!17 = !{null, null, !18, null}
100+
!18 = !{!19}
101+
!19 = !{i32 0, %"$Globals"* @"$Globals", !"$Globals", i32 0, i32 -1, i32 1, i32 32, null}
102+
!20 = !{<2 x i32> (i32)* @main, i32 1}
103+
!21 = !{i32 -2147483584}
104+
!22 = !{i32 -1}
105+
!23 = !DILocation(line: 2, column: 45, scope: !24, inlinedAt: !27)
106+
!24 = !DISubprogram(name: "??__EScalarArray@@YAXXZ", scope: !25, file: !25, line: 2, type: !26, isLocal: true, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false)
107+
!25 = !DIFile(filename: "t:\5Carray-mapping.hlsl", directory: "")
108+
!26 = !DISubroutineType(types: !13)
109+
!27 = distinct !DILocation(line: 4, scope: !28)
110+
!28 = !DISubprogram(name: "main", scope: !25, file: !25, line: 4, type: !26, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, function: <2 x i32> (i32)* @main)
111+
!29 = !{!30, !30, i64 0}
112+
!30 = !{!"int", !31, i64 0}
113+
!31 = !{!"omnipotent char", !32, i64 0}
114+
!32 = !{!"Simple C/C++ TBAA"}
115+
!33 = !DILocation(line: 5, column: 18, scope: !28)
116+
!34 = !DILocation(line: 5, column: 34, scope: !28)
117+
!35 = !DILocation(line: 5, column: 17, scope: !28)
118+
!36 = !DILocation(line: 5, column: 5, scope: !28)

0 commit comments

Comments
 (0)