<div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial"><div style="margin: 0;">Thanks, Tim.</div><div style="margin: 0;"><br></div><div style="margin: 0;">Actually, I am implementing a new backend. The hardware support vector of 512 bits. But vector type should be aligned to 1024 bits in memory. So I added "v512:1024" to datalayout for both clang and llvm. </div><div style="margin: 0;">Unfortunately Clang will crash for some cases. The reason is that, when calculating the size of an array of vector, llvm will consider the alignment of the element of an array, but clang will not. When calculating the size of type [10 x <16 x i32>], llvm considers each element's store size which aligns each element's size to its alignment.  </div><div style="margin: 0;">After adding "v512:1024" to datalayout, llvm considers the size of [10 x <16 x i32>] to be 10240 bits.</div><div style="margin: 0;">But Clang still considers its size to be 5120 bits. So when this array is in a struct, Clang crashes in CGRecordLowering::clipTailPadding().</div><div style="margin: 0;"><div style="margin: 0px;">--------------------------------------------------------------------------------------------------------------------------</div><div style="margin: 0px;"><div style="margin: 0px;"><div style="margin: 0px;">/// getConstantArrayInfoInChars - Performing the computation in CharUnits</div><div style="margin: 0px;">/// instead of in bits prevents overflowing the uint64_t for some large arrays.</div><div style="margin: 0px;">std::pair<CharUnits, CharUnits></div><div style="margin: 0px;">static getConstantArrayInfoInChars(const ASTContext &Context,</div><div style="margin: 0px;">                                   const ConstantArrayType *CAT) {</div><div style="margin: 0px;">  std::pair<CharUnits, CharUnits> EltInfo =</div><div style="margin: 0px;">      Context.getTypeInfoInChars(CAT->getElementType());</div><div style="margin: 0px;">  uint64_t Size = CAT->getSize().getZExtValue();</div><div style="margin: 0px;">  assert((Size == 0 || static_cast<uint64_t>(EltInfo.first.getQuantity()) <=</div><div style="margin: 0px;">              (uint64_t)(-1)/Size) &&</div><div style="margin: 0px;">         "Overflow in array type char size evaluation");</div><div style="margin: 0px;">  uint64_t Width = EltInfo.first.getQuantity() * Size;                  // I make modification here</div><div style="margin: 0px;">  unsigned Align = EltInfo.second.getQuantity();</div><div style="margin: 0px;">  if (!Context.getTargetInfo().getCXXABI().isMicrosoft() ||</div><div style="margin: 0px;">      Context.getTargetInfo().getPointerWidth(0) == 64)</div><div style="margin: 0px;">    Width = llvm::alignTo(Width, Align);</div><div style="margin: 0px;">  return std::make_pair(CharUnits::fromQuantity(Width),</div><div style="margin: 0px;">                        CharUnits::fromQuantity(Align));</div><div style="margin: 0px;">}</div></div><div style="margin: 0px;">--------------------------------------------------------------------------------------------------------------------------</div></div></div><div style="margin: 0;">So I make modification where Width is calculated. </div><div style="margin: 0;">--------------------------------------------------------------------------------------------------------------------------</div><div style="margin: 0;">uint64_t Width = EltInfo.first.getQuantity() * Size;                               // before modification</div><div style="margin: 0;">uint64_t Width = llvm::alignTo(EltInfo.first.getQuantity(), EltInfo.second.getQuantity())* Size; // after modification</div><div style="margin: 0;">----------------------------------------------------------------------------------------------------------------------------</div><div style="margin: 0;">But I am worried that my modification would make test cases for other target fail.</div><div style="margin: 0;">How could I know if my modification would make tests for other target like x86/Arm fail? </div><div style="margin: 0;">How could I test it? I have read the reference,<a href="https://llvm.org/docs/TestingGuide.html">LLVM Testing Infrastructure Guide ¡ª LLVM 12 documentation</a>.</div><div style="margin: 0;">But I don't have a clear idea.</div><div style="margin: 0;"><br></div><div style="margin: 0;">Best Regards,</div><div style="margin: 0;">Jerry</div><p style="margin: 0;"><br></p><p style="margin: 0;"><br></p><div style="position:relative;zoom:1"></div><div id="divNeteaseMailCard"></div><p style="margin: 0;"><br></p><div id="isForwardContent">-------- Forwarding messages --------<br>From: "ÁÖÕþ×Ú" <jackie_linzz@126.com><br>Date: 2020-12-08 20:15:31<br>To:  "llvm-dev@lists.llvm.org" <llvm-dev@lists.llvm.org>,"cfe-dev@lists.llvm.org" <cfe-dev@lists.llvm.org><br>Subject: about element size/alignment in an array<br><div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial"><div style="margin:0;">Hi, there.</div><div style="margin:0;"><br></div><div style="margin:0;">I met a problem about element size/alignment in an array. I defined the following vector type.</div><div style="margin:0;">-------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;">typedef int __attribute__((__vector_size__(64), aligned(128))) v16i32;</div><div style="margin:0;">struct container {</div><div style="margin:0;">    v16i32 arr[10];</div><div style="margin:0;">    v16i32 val;</div><div style="margin:0;">} stu;</div><div style="margin:0;">-------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;">Its size is 512bits. And alignment is 1024bits.</div><div style="margin:0;">I also defined the datalayout in clang and llvm, "v512:1024". I need vector of 512bits to be aligned to 1024bits no matter whether it is in an array or not. </div><div style="margin:0;"><br></div><div style="margin:0;">but I saw the code as below in clang/lib/AST/ASTContext.cpp. line 1749</div><div style="margin:0;">--------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;"><div style="margin:0;"><div style="margin:0;">/// getConstantArrayInfoInChars - Performing the computation in CharUnits</div><div style="margin:0;">/// instead of in bits prevents overflowing the uint64_t for some large arrays.</div><div style="margin:0;">std::pair<CharUnits, CharUnits></div><div style="margin:0;">static getConstantArrayInfoInChars(const ASTContext &Context,</div><div style="margin:0;">                                   const ConstantArrayType *CAT) {</div><div style="margin:0;">  std::pair<CharUnits, CharUnits> EltInfo =</div><div style="margin:0;">      Context.getTypeInfoInChars(CAT->getElementType());</div><div style="margin:0;">  uint64_t Size = CAT->getSize().getZExtValue();</div><div style="margin:0;">  assert((Size == 0 || static_cast<uint64_t>(EltInfo.first.getQuantity()) <=</div><div style="margin:0;">              (uint64_t)(-1)/Size) &&</div><div style="margin:0;">         "Overflow in array type char size evaluation");</div><div style="margin:0;">  uint64_t Width = EltInfo.first.getQuantity() * Size;                  //here</div><div style="margin:0;">  unsigned Align = EltInfo.second.getQuantity();</div><div style="margin:0;">  if (!Context.getTargetInfo().getCXXABI().isMicrosoft() ||</div><div style="margin:0;">      Context.getTargetInfo().getPointerWidth(0) == 64)</div><div style="margin:0;">    Width = llvm::alignTo(Width, Align);</div><div style="margin:0;">  return std::make_pair(CharUnits::fromQuantity(Width),</div><div style="margin:0;">                        CharUnits::fromQuantity(Align));</div><div style="margin:0;">}</div></div><div style="margin:0;">--------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;">when caculating the size of an array, the alignment of element is not considered. Thus the width of the array "arr" in struct container is 512x10bits, not 1024x10bits.</div><div style="margin:0;">And the offset of "val" in struct container is 512x10bits. That's 640bytes.</div><div style="margin:0;">but it is not the way in which size of "arr" is caculated in CGRecordLowering::clipTailPadding(), line 586 of clang/lib/CodeGen/CGRecordLayoutBuilder.cpp</div><div style="margin:0;">--------------------------------------------------------------------------------------------------------------------------</div><div style="margin:0;"><div style="margin:0;">void CGRecordLowering::clipTailPadding() {</div><div style="margin:0;">  std::vector<MemberInfo>::iterator Prior = Members.begin();</div><div style="margin:0;">  CharUnits Tail = getSize(Prior->Data);   //here</div><div style="margin:0;">  for (std::vector<MemberInfo>::iterator Member = Prior + 1,</div><div style="margin:0;">                                         MemberEnd = Members.end();</div><div style="margin:0;">       Member != MemberEnd; ++Member) {</div><div style="margin:0;">    // Only members with data and the scissor can cut into tail padding.</div><div style="margin:0;">    if (!Member->Data && Member->Kind != MemberInfo::Scissor)</div><div style="margin:0;">      continue;</div><div style="margin:0;">    if (Member->Offset < Tail) {               // and here</div><div style="margin:0;">      assert(Prior->Kind == MemberInfo::Field &&</div><div style="margin:0;">             "Only storage fields have tail padding!");</div><div style="margin:0;">      if (!Prior->FD || Prior->FD->isBitField())</div><div style="margin:0;">        Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(</div><div style="margin:0;">            cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8)));</div><div style="margin:0;">      else {</div><div style="margin:0;">        assert(Prior->FD->hasAttr<NoUniqueAddressAttr>() &&</div><div style="margin:0;">               "should not have reused this field's tail padding");     // doesn't meet this assert</div><div style="margin:0;">        Prior->Data = getByteArrayType(</div><div style="margin:0;">            Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).first);</div><div style="margin:0;">      }</div><div style="margin:0;">    }</div><div style="margin:0;">    if (Member->Data)</div><div style="margin:0;">      Prior = Member;</div><div style="margin:0;">    Tail = Prior->Offset + getSize(Prior->Data);</div><div style="margin:0;">  }</div><div style="margin:0;">}</div><div style="margin:0;">--------------------------------------------------------------------------------------------------------------------------</div><div>the "getSize(Prior->Data)" function will consider the alignment of element. When "Prior" points to the first field "arr" of struct container, "Tail" is 1024x10/8 = 1280 bytes. That's the size of type [10 x <16 x i32>] considering alignment.</div><div>At the first iteration of for loop, "Member" points to the second field "val" of struct container. "Member->Offset" is 640bytes.</div><div>"if (Member->Offset < Tail)" is true, and the execution goes in. And later "else" branch is executed. </div><div>The "assert" in else clause will fail, and clang will crash.</div><div><br></div><div>I think when caculating the size of an array, the alignment of element should also be considered. But it is not the case in code.</div><div>I am not sure whether it is a bug in clang or there is something I don't know.</div><div>Could anyone help me? Thanks in advance!</div><div><br></div><div><br></div><div>Best Regards,</div><div>Jerry</div></div><div style="margin:0;"><br></div><div><br></div></div><div style="margin:0;"><br></div></div><br><br><span title="neteasefooter"><p> </p></span></div></div><br><br><span title="neteasefooter"><p> </p></span>