Skip to content

Commit 1a28a89

Browse files
author
Johannes Doerfert
committedOct 5, 2014
Introduce the ScopArrayInfo class.
This class allows to store information about the arrays in the SCoP. For each base pointer in the SCoP one object is created storing the type and dimension sizes of the array. The objects can be obtained via the SCoP, a MemoryAccess or the isl_id associated with the output dimension of a MemoryAccess (the description of what is accessed). So far we use the information in the IslExprBuilder to create the right base type before indexing into the base array. This fixes the bug http://llvm.org/bugs/show_bug.cgi?id=21113 (both test cases are included). On top of that we can now build runtime alias checks for delinearized arrays as the dimension sizes are also part of the ScopArrayInfo objects. Differential Revision: http://reviews.llvm.org/D5613 llvm-svn: 219077
1 parent a00381f commit 1a28a89

12 files changed

+287
-46
lines changed
 

‎polly/include/polly/ScopInfo.h

+82-5
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,70 @@ class TempScop;
5959
class SCEVAffFunc;
6060
class Comparison;
6161

62-
//===----------------------------------------------------------------------===//
62+
/// @brief A class to store information about arrays in the SCoP.
63+
///
64+
/// Objects are accessible via the ScoP, MemoryAccess or the id associated with
65+
/// the MemoryAccess access function.
66+
///
67+
class ScopArrayInfo {
68+
public:
69+
/// @brief Construct a ScopArrayInfo object.
70+
///
71+
/// @param BasePtr The array base pointer.
72+
/// @param AccessType The type used to access this array.
73+
/// @param IslCtx The isl context used to create the base pointer id.
74+
/// @param DimensionSizes A vector containing the size of each dimension.
75+
ScopArrayInfo(Value *BasePtr, Type *AccessType, isl_ctx *IslCtx,
76+
const SmallVector<const SCEV *, 4> &DimensionSizes);
77+
78+
/// @brief Destructor to free the isl id of the base pointer.
79+
~ScopArrayInfo();
80+
81+
/// @brief Return the base pointer.
82+
Value *getBasePtr() const { return BasePtr; }
83+
84+
/// @brief Return the number of dimensions.
85+
unsigned getNumberOfDimensions() const { return DimensionSizes.size(); }
86+
87+
/// @brief Return the size of dimension @p dim.
88+
const SCEV *getDimensionSize(unsigned dim) const {
89+
assert(dim < getNumberOfDimensions() && "Invalid dimension");
90+
return DimensionSizes[dim];
91+
}
92+
93+
/// @brief Return the type used to access this array in the SCoP.
94+
Type *getType() const { return AccessType; }
95+
96+
/// @brief Return the isl id for the base pointer.
97+
__isl_give isl_id *getBasePtrId() const;
98+
99+
/// @brief Dump a readable representation to stderr.
100+
void dump() const;
101+
102+
/// @brief Print a readable representation to @p OS.
103+
void print(raw_ostream &OS) const;
104+
105+
/// @brief Access the ScopArrayInfo associated with an access function.
106+
static const ScopArrayInfo *
107+
getFromAccessFunction(__isl_keep isl_pw_multi_aff *PMA);
108+
109+
/// @brief Access the ScopArrayInfo associated with an isl Id.
110+
static const ScopArrayInfo *getFromId(__isl_take isl_id *Id);
111+
112+
private:
113+
/// @brief The base pointer.
114+
Value *BasePtr;
115+
116+
/// @brief The type used to access this array.
117+
Type *AccessType;
118+
119+
/// @brief The isl id for the base pointer.
120+
isl_id *Id;
121+
122+
/// @brief The sizes of each dimension.
123+
SmallVector<const SCEV *, 4> DimensionSizes;
124+
};
125+
63126
/// @brief Represent memory accesses in statements.
64127
class MemoryAccess {
65128
public:
@@ -148,11 +211,12 @@ class MemoryAccess {
148211
public:
149212
/// @brief Create a memory access from an access in LLVM-IR.
150213
///
151-
/// @param Access The memory access.
152-
/// @param Statement The statement that contains the access.
153-
/// @param SE The ScalarEvolution analysis.
214+
/// @param Access The memory access.
215+
/// @param AccInst The access instruction.
216+
/// @param Statement The statement that contains the access.
217+
/// @param SAI The ScopArrayInfo object for this base pointer.
154218
MemoryAccess(const IRAccess &Access, Instruction *AccInst,
155-
ScopStmt *Statement);
219+
ScopStmt *Statement, const ScopArrayInfo *SAI);
156220

157221
~MemoryAccess();
158222

@@ -188,6 +252,9 @@ class MemoryAccess {
188252
/// @brief Get the base array isl_id for this access.
189253
__isl_give isl_id *getArrayId() const;
190254

255+
/// @brief Get the ScopArrayInfo object for the base address.
256+
const ScopArrayInfo *getScopArrayInfo() const;
257+
191258
/// @brief Return a string representation of the accesse's reduction type.
192259
const std::string getReductionOperatorStr() const;
193260

@@ -534,6 +601,9 @@ class Scop {
534601
/// Constraints on parameters.
535602
isl_set *Context;
536603

604+
/// @brief A map to remember ScopArrayInfo objects for all base pointers.
605+
DenseMap<const Value *, const ScopArrayInfo *> ScopArrayInfoMap;
606+
537607
/// @brief The assumptions under which this scop was built.
538608
///
539609
/// When constructing a scop sometimes the exact representation of a statement
@@ -728,6 +798,13 @@ class Scop {
728798
const_reverse_iterator rend() const { return Stmts.rend(); }
729799
//@}
730800

801+
/// @brief Return the (possibly new) ScopArrayInfo object for @p Access.
802+
const ScopArrayInfo *getOrCreateScopArrayInfo(const IRAccess &Access,
803+
Instruction *AccessInst);
804+
805+
/// @brief Return the cached ScopArrayInfo object for @p BasePtr.
806+
const ScopArrayInfo *getScopArrayInfo(Value *BasePtr);
807+
731808
void setContext(isl_set *NewContext);
732809

733810
/// @brief Align the parameters in the statement to the scop context

‎polly/lib/Analysis/ScopInfo.cpp

+82-7
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,43 @@ int SCEVAffinator::getLoopDepth(const Loop *L) {
278278
return L->getLoopDepth() - outerLoop->getLoopDepth();
279279
}
280280

281+
ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *AccessType, isl_ctx *Ctx,
282+
const SmallVector<const SCEV *, 4> &DimensionSizes)
283+
: BasePtr(BasePtr), AccessType(AccessType), DimensionSizes(DimensionSizes) {
284+
const std::string BasePtrName = getIslCompatibleName("MemRef_", BasePtr, "");
285+
Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this);
286+
}
287+
288+
ScopArrayInfo::~ScopArrayInfo() { isl_id_free(Id); }
289+
290+
isl_id *ScopArrayInfo::getBasePtrId() const { return isl_id_copy(Id); }
291+
292+
void ScopArrayInfo::dump() const { print(errs()); }
293+
294+
void ScopArrayInfo::print(raw_ostream &OS) const {
295+
OS << "ScopArrayInfo:\n";
296+
OS << " Base: " << *getBasePtr() << "\n";
297+
OS << " Type: " << *getType() << "\n";
298+
OS << " Dimension Sizes:\n";
299+
for (unsigned u = 0; u < getNumberOfDimensions(); u++)
300+
OS << " " << u << ") " << *DimensionSizes[u] << "\n";
301+
OS << "\n";
302+
}
303+
304+
const ScopArrayInfo *
305+
ScopArrayInfo::getFromAccessFunction(__isl_keep isl_pw_multi_aff *PMA) {
306+
isl_id *Id = isl_pw_multi_aff_get_tuple_id(PMA, isl_dim_out);
307+
assert(Id && "Output dimension didn't have an ID");
308+
return getFromId(Id);
309+
}
310+
311+
const ScopArrayInfo *ScopArrayInfo::getFromId(isl_id *Id) {
312+
void *User = isl_id_get_user(Id);
313+
const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
314+
isl_id_free(Id);
315+
return SAI;
316+
}
317+
281318
const std::string
282319
MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) {
283320
switch (RT) {
@@ -348,6 +385,14 @@ static MemoryAccess::AccessType getMemoryAccessType(const IRAccess &Access) {
348385
llvm_unreachable("Unknown IRAccess type!");
349386
}
350387

388+
const ScopArrayInfo *MemoryAccess::getScopArrayInfo() const {
389+
isl_id *ArrayId = getArrayId();
390+
void *User = isl_id_get_user(ArrayId);
391+
const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
392+
isl_id_free(ArrayId);
393+
return SAI;
394+
}
395+
351396
isl_id *MemoryAccess::getArrayId() const {
352397
return isl_map_get_tuple_id(AccessRelation, isl_dim_out);
353398
}
@@ -433,14 +478,15 @@ void MemoryAccess::assumeNoOutOfBound(const IRAccess &Access) {
433478
}
434479

435480
MemoryAccess::MemoryAccess(const IRAccess &Access, Instruction *AccInst,
436-
ScopStmt *Statement)
481+
ScopStmt *Statement, const ScopArrayInfo *SAI)
437482
: Type(getMemoryAccessType(Access)), Statement(Statement), Inst(AccInst),
438483
newAccessRelation(nullptr) {
439484

440485
isl_ctx *Ctx = Statement->getIslCtx();
441486
BaseAddr = Access.getBase();
442487
BaseName = getIslCompatibleName("MemRef_", getBaseAddr(), "");
443-
isl_id *BaseAddrId = isl_id_alloc(Ctx, getBaseName().c_str(), nullptr);
488+
489+
isl_id *BaseAddrId = SAI->getBasePtrId();
444490

445491
if (!Access.isAffine()) {
446492
// We overapproximate non-affine accesses with a possible access to the
@@ -666,18 +712,23 @@ void ScopStmt::buildScattering(SmallVectorImpl<unsigned> &Scatter) {
666712
}
667713

668714
void ScopStmt::buildAccesses(TempScop &tempScop, const Region &CurRegion) {
669-
for (auto &&Access : *tempScop.getAccessFunctions(BB)) {
670-
MemAccs.push_back(new MemoryAccess(Access.first, Access.second, this));
715+
for (const auto &AccessPair : *tempScop.getAccessFunctions(BB)) {
716+
const IRAccess &Access = AccessPair.first;
717+
Instruction *AccessInst = AccessPair.second;
718+
719+
const ScopArrayInfo *SAI =
720+
getParent()->getOrCreateScopArrayInfo(Access, AccessInst);
721+
MemAccs.push_back(new MemoryAccess(Access, AccessInst, this, SAI));
671722

672723
// We do not track locations for scalar memory accesses at the moment.
673724
//
674725
// We do not have a use for this information at the moment. If we need this
675726
// at some point, the "instruction -> access" mapping needs to be enhanced
676727
// as a single instruction could then possibly perform multiple accesses.
677-
if (!Access.first.isScalar()) {
678-
assert(!InstructionToAccess.count(Access.second) &&
728+
if (!Access.isScalar()) {
729+
assert(!InstructionToAccess.count(AccessInst) &&
679730
"Unexpected 1-to-N mapping on instruction to access map!");
680-
InstructionToAccess[Access.second] = MemAccs.back();
731+
InstructionToAccess[AccessInst] = MemAccs.back();
681732
}
682733
}
683734
}
@@ -1373,6 +1424,10 @@ Scop::~Scop() {
13731424
for (ScopStmt *Stmt : *this)
13741425
delete Stmt;
13751426

1427+
// Free the ScopArrayInfo objects.
1428+
for (auto &ScopArrayInfoPair : ScopArrayInfoMap)
1429+
delete ScopArrayInfoPair.second;
1430+
13761431
// Free the alias groups
13771432
for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) {
13781433
for (MinMaxAccessTy &MMA : *MinMaxAccesses) {
@@ -1383,6 +1438,26 @@ Scop::~Scop() {
13831438
}
13841439
}
13851440

1441+
const ScopArrayInfo *Scop::getOrCreateScopArrayInfo(const IRAccess &Access,
1442+
Instruction *AccessInst) {
1443+
Value *BasePtr = Access.getBase();
1444+
const ScopArrayInfo *&SAI = ScopArrayInfoMap[BasePtr];
1445+
if (!SAI) {
1446+
Type *AccessType = getPointerOperand(*AccessInst)->getType();
1447+
SAI = new ScopArrayInfo(BasePtr, AccessType, getIslCtx(), Access.Sizes);
1448+
}
1449+
return SAI;
1450+
}
1451+
1452+
const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr) {
1453+
const SCEV *PtrSCEV = SE->getSCEV(BasePtr);
1454+
const SCEVUnknown *PtrBaseSCEV =
1455+
cast<SCEVUnknown>(SE->getPointerBase(PtrSCEV));
1456+
const ScopArrayInfo *SAI = ScopArrayInfoMap[PtrBaseSCEV->getValue()];
1457+
assert(SAI && "No ScopArrayInfo available for this base pointer");
1458+
return SAI;
1459+
}
1460+
13861461
std::string Scop::getContextStr() const { return stringFromIslObj(Context); }
13871462
std::string Scop::getAssumedContextStr() const {
13881463
return stringFromIslObj(AssumedContext);

‎polly/lib/CodeGen/IslCodeGeneration.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include "polly/CodeGen/BlockGenerators.h"
2424
#include "polly/CodeGen/CodeGeneration.h"
2525
#include "polly/CodeGen/IslAst.h"
26-
#include "polly/CodeGen/IslExprBuilder.h"
2726
#include "polly/CodeGen/LoopGenerators.h"
2827
#include "polly/CodeGen/Utils.h"
2928
#include "polly/Dependences.h"

‎polly/lib/CodeGen/IslExprBuilder.cpp

+16-26
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "polly/CodeGen/IslExprBuilder.h"
1313

14+
#include "polly/ScopInfo.h"
1415
#include "polly/Support/GICHelper.h"
1516

1617
#include "llvm/Support/Debug.h"
@@ -103,39 +104,28 @@ Value *IslExprBuilder::createAccessAddress(isl_ast_expr *Expr) {
103104
assert(isl_ast_expr_get_op_n_arg(Expr) == 2 &&
104105
"Multidimensional access functions are not supported yet");
105106

106-
Value *Base, *IndexOp, *Zero, *Access;
107-
SmallVector<Value *, 4> Indices;
108-
Type *PtrElTy;
107+
Value *Base, *IndexOp, *Access;
108+
isl_ast_expr *BaseExpr;
109+
isl_id *BaseId;
109110

110-
Base = create(isl_ast_expr_get_op_arg(Expr, 0));
111+
BaseExpr = isl_ast_expr_get_op_arg(Expr, 0);
112+
BaseId = isl_ast_expr_get_id(BaseExpr);
113+
isl_ast_expr_free(BaseExpr);
114+
115+
const ScopArrayInfo *SAI = ScopArrayInfo::getFromId(BaseId);
116+
Base = SAI->getBasePtr();
111117
assert(Base->getType()->isPointerTy() && "Access base should be a pointer");
118+
const Twine &BaseName = Base->getName();
119+
120+
if (Base->getType() != SAI->getType())
121+
Base = Builder.CreateBitCast(Base, SAI->getType(),
122+
"polly.access.cast." + BaseName);
112123

113124
IndexOp = create(isl_ast_expr_get_op_arg(Expr, 1));
114125
assert(IndexOp->getType()->isIntegerTy() &&
115126
"Access index should be an integer");
116-
Zero = ConstantInt::getNullValue(IndexOp->getType());
117-
118-
// If base is a array type like,
119-
// int A[N][M][K];
120-
// we have to adjust the GEP. The easiest way is to transform accesses like,
121-
// A[i][j][k]
122-
// into equivalent ones like,
123-
// A[0][0][ i*N*M + j*M + k]
124-
// because SCEV already folded the "peudo dimensions" into one. Thus our index
125-
// operand will be 'i*N*M + j*M + k' anyway.
126-
PtrElTy = Base->getType()->getPointerElementType();
127-
while (PtrElTy->isArrayTy()) {
128-
Indices.push_back(Zero);
129-
PtrElTy = PtrElTy->getArrayElementType();
130-
}
131-
132-
Indices.push_back(IndexOp);
133-
assert((PtrElTy->isIntOrIntVectorTy() || PtrElTy->isFPOrFPVectorTy() ||
134-
PtrElTy->isPtrOrPtrVectorTy()) &&
135-
"We do not yet change the type of the access base during code "
136-
"generation.");
137127

138-
Access = Builder.CreateGEP(Base, Indices, "polly.access." + Base->getName());
128+
Access = Builder.CreateGEP(Base, IndexOp, "polly.access." + BaseName);
139129

140130
isl_ast_expr_free(Expr);
141131
return Access;

‎polly/lib/Exchange/JSONExporter.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ bool JSONImporter::runOnScop(Scop &scop) {
277277
return false;
278278
}
279279

280+
isl_id *OutId = isl_map_get_tuple_id(currentAccessMap, isl_dim_out);
281+
newAccessMap = isl_map_set_tuple_id(newAccessMap, isl_dim_out, OutId);
282+
280283
// We keep the old alignment, thus we cannot allow accesses to memory
281284
// locations that were not accessed before.
282285
isl_set *newAccessSet = isl_map_range(isl_map_copy(newAccessMap));

‎polly/test/Isl/CodeGen/MemAccess/codegen_constant_offset.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ for.inc: ; preds = %for.body
4040
for.end: ; preds = %for.cond
4141
ret i32 0
4242
}
43-
; CHECK: load i32* getelementptr inbounds ([100 x i32]* @A, i64 0, i64 10)
43+
; CHECK: load i32* getelementptr inbounds ([100 x i32]* @A, i{{(32|64)}} 0, i{{(32|64)}} 10)

‎polly/test/Isl/CodeGen/MemAccess/codegen_simple.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ for.inc: ; preds = %for.body
4040
for.end: ; preds = %for.cond
4141
ret i32 0
4242
}
43-
; CHECK: load i32* getelementptr inbounds ([100 x i32]* @A, i64 0, i64 0)
43+
; CHECK: load i32* getelementptr inbounds ([100 x i32]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0)

‎polly/test/Isl/CodeGen/MemAccess/codegen_simple_float.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ for.inc: ; preds = %for.body
3838
for.end: ; preds = %for.cond
3939
ret i32 0
4040
}
41-
; CHECK: load float* getelementptr inbounds ([100 x float]* @A, i64 0, i64 0)
41+
; CHECK: load float* getelementptr inbounds ([100 x float]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0)

‎polly/test/Isl/CodeGen/MemAccess/codegen_simple_md.ll

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ for.end6: ; preds = %for.cond
6363
; WITHCONST: %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
6464
; WITHCONST: %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
6565
; WITHCONST: %[[SUM2:[._a-zA-Z0-9]+]] = add nsw i64 %[[SUM1]], 5
66-
; WITHCONST: %[[ACC:[._a-zA-Z0-9]*]] = getelementptr [1040 x i32]* @A, i64 0, i64 %[[SUM2]]
66+
; WITHCONST: %[[ACC:[._a-zA-Z0-9]*]] = getelementptr i32* getelementptr inbounds ([1040 x i32]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0), i64 %[[SUM2]]
6767
; WITHCONST: store i32 100, i32* %[[ACC]]
6868

6969
; WITHOUTCONST: %[[IVOut:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
7070
; WITHOUTCONST: %[[IVIn:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
7171
; WITHOUTCONST: %[[MUL1:[._a-zA-Z0-9]+]] = mul nsw i64 16, %[[IVOut]]
7272
; WITHOUTCONST: %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
7373
; WITHOUTCONST: %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
74-
; WITHOUTCONST: %[[ACC:[._a-zA-Z0-9]*]] = getelementptr [1040 x i32]* @A, i64 0, i64 %[[SUM1]]
74+
; WITHOUTCONST: %[[ACC:[._a-zA-Z0-9]*]] = getelementptr i32* getelementptr inbounds ([1040 x i32]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0), i64 %[[SUM1]]
7575
; WITHOUTCONST: store i32 100, i32* %[[ACC]]

‎polly/test/Isl/CodeGen/MemAccess/codegen_simple_md_float.ll

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ for.end6: ; preds = %for.cond
5959
; WITHCONST: %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
6060
; WITHCONST: %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
6161
; WITHCONST: %[[SUM2:[._a-zA-Z0-9]+]] = add nsw i64 %[[SUM1]], 5
62-
; WITHCONST: %[[ACC:[._a-zA-Z0-9]*]] = getelementptr [1040 x float]* @A, i64 0, i64 %[[SUM2]]
62+
; WITHCONST: %[[ACC:[._a-zA-Z0-9]*]] = getelementptr float* getelementptr inbounds ([1040 x float]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0), i64 %[[SUM2]]
6363
; WITHCONST: store float 1.000000e+02, float* %[[ACC]]
6464

6565
; WITHOUTCONST: %[[IVOut:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
6666
; WITHOUTCONST: %[[IVIn:polly.indvar[0-9]*]] = phi i64 [ 0, %polly.loop_preheader{{[0-9]*}} ], [ %polly.indvar_next{{[0-9]*}}, %polly.{{[._a-zA-Z0-9]*}} ]
6767
; WITHOUTCONST: %[[MUL1:[._a-zA-Z0-9]+]] = mul nsw i64 16, %[[IVOut]]
6868
; WITHOUTCONST: %[[MUL2:[._a-zA-Z0-9]+]] = mul nsw i64 2, %[[IVIn]]
6969
; WITHOUTCONST: %[[SUM1:[._a-zA-Z0-9]+]] = add nsw i64 %[[MUL1]], %[[MUL2]]
70-
; WITHOUTCONST: %[[ACC:[._a-zA-Z0-9]*]] = getelementptr [1040 x float]* @A, i64 0, i64 %[[SUM1]]
70+
; WITHOUTCONST: %[[ACC:[._a-zA-Z0-9]*]] = getelementptr float* getelementptr inbounds ([1040 x float]* @A, i{{(32|64)}} 0, i{{(32|64)}} 0), i64 %[[SUM1]]
7171
; WITHOUTCONST: store float 1.000000e+02, float* %[[ACC]]

0 commit comments

Comments
 (0)
Please sign in to comment.