<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>Looks like I forgot to add -F :[</div><div>I am outside having a late lunch.</div><div>Will handle it when I get back.</div><div><br></div><div>Thanks</div><div>Manman</div><div><br>On Apr 4, 2013, at 1:29 PM, Jim Grosbach <<a href="mailto:grosbach@apple.com">grosbach@apple.com</a>> wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=us-ascii">Hi Manman,<div><br></div><div>Was this an inadvertent early commit or something? Normally, I would expect a fairly lengthy commit message explaining a patch like this.</div><div><br></div><div>-Jim</div><div><br><div><div>On Apr 4, 2013, at 1:14 PM, Manman Ren <<a href="mailto:mren@apple.com">mren@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Author: mren<br>Date: Thu Apr  4 15:14:17 2013<br>New Revision: 178784<br><br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project?rev=178784&view=rev">http://llvm.org/viewvc/llvm-project?rev=178784&view=rev</a><br>Log:<br>Index: include/clang/Driver/CC1Options.td<br>===================================================================<br>--- include/clang/Driver/CC1Options.td<span class="Apple-tab-span" style="white-space: pre;">       </span>(revision 178718)<br>+++ include/clang/Driver/CC1Options.td<span class="Apple-tab-span" style="white-space: pre;"> </span>(working copy)<br>@@ -161,6 +161,8 @@<br>  HelpText<"Use register sized accesses to bit-fields, when possible.">;<br>def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">,<br>  HelpText<"Turn off Type Based Alias Analysis">;<br>+def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">,<br>+  HelpText<"Turn on struct-path aware Type Based Alias Analysis">;<br>def masm_verbose : Flag<["-"], "masm-verbose">,<br>  HelpText<"Generate verbose assembly output">;<br>def mcode_model : Separate<["-"], "mcode-model">,<br>Index: include/clang/Driver/Options.td<br>===================================================================<br>--- include/clang/Driver/Options.td<span class="Apple-tab-span" style="white-space: pre;">        </span>(revision 178718)<br>+++ include/clang/Driver/Options.td<span class="Apple-tab-span" style="white-space: pre;">    </span>(working copy)<br>@@ -587,6 +587,7 @@<br>  Flags<[CC1Option]>, HelpText<"Disable spell-checking">;<br>def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>;<br>def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>;<br>+def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>;<br>def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>;<br>def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>;<br>def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>,<br>Index: include/clang/Frontend/CodeGenOptions.def<br>===================================================================<br>--- include/clang/Frontend/CodeGenOptions.def<span class="Apple-tab-span" style="white-space: pre;">       </span>(revision 178718)<br>+++ include/clang/Frontend/CodeGenOptions.def<span class="Apple-tab-span" style="white-space: pre;">  </span>(working copy)<br>@@ -85,6 +85,7 @@<br>VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.<br>CODEGENOPT(RelaxAll          , 1, 0) ///< Relax all machine code instructions.<br>CODEGENOPT(RelaxedAliasing   , 1, 0) ///< Set when -fno-strict-aliasing is enabled.<br>+CODEGENOPT(StructPathTBAA    , 1, 0) ///< Whether or not to use struct-path TBAA.<br>CODEGENOPT(SaveTempLabels    , 1, 0) ///< Save temporary labels.<br>CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero<br>                                                 ///< offset in AddressSanitizer.<br>Index: lib/CodeGen/CGExpr.cpp<br>===================================================================<br>--- lib/CodeGen/CGExpr.cpp<span class="Apple-tab-span" style="white-space: pre;">        </span>(revision 178718)<br>+++ lib/CodeGen/CGExpr.cpp<span class="Apple-tab-span" style="white-space: pre;">     </span>(working copy)<br>@@ -1044,7 +1044,8 @@<br>llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue) {<br>  return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),<br>                          lvalue.getAlignment().getQuantity(),<br>-                          lvalue.getType(), lvalue.getTBAAInfo());<br>+                          lvalue.getType(), lvalue.getTBAAInfo(),<br>+                          lvalue.getTBAABaseType(), lvalue.getTBAAOffset());<br>}<br><br>static bool hasBooleanRepresentation(QualType Ty) {<br>@@ -1106,7 +1107,9 @@<br><br>llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,<br>                                              unsigned Alignment, QualType Ty,<br>-                                              llvm::MDNode *TBAAInfo) {<br>+                                              llvm::MDNode *TBAAInfo,<br>+                                              QualType TBAABaseType,<br>+                                              uint64_t TBAAOffset) {<br>  // For better performance, handle vector loads differently.<br>  if (Ty->isVectorType()) {<br>    llvm::Value *V;<br>@@ -1158,8 +1161,11 @@<br>    Load->setVolatile(true);<br>  if (Alignment)<br>    Load->setAlignment(Alignment);<br>-  if (TBAAInfo)<br>-    CGM.DecorateInstruction(Load, TBAAInfo);<br>+  if (TBAAInfo) {<br>+    llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,<br>+                                                      TBAAOffset);<br>+    CGM.DecorateInstruction(Load, TBAAPath);<br>+  }<br><br>  if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) ||<br>      (SanOpts->Enum && Ty->getAs<EnumType>())) {<br>@@ -1217,7 +1223,8 @@<br>                                        bool Volatile, unsigned Alignment,<br>                                        QualType Ty,<br>                                        llvm::MDNode *TBAAInfo,<br>-                                        bool isInit) {<br>+                                        bool isInit, QualType TBAABaseType,<br>+                                        uint64_t TBAAOffset) {<br><br>  // Handle vectors differently to get better performance.<br>  if (Ty->isVectorType()) {<br>@@ -1268,15 +1275,19 @@<br>  llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile);<br>  if (Alignment)<br>    Store->setAlignment(Alignment);<br>-  if (TBAAInfo)<br>-    CGM.DecorateInstruction(Store, TBAAInfo);<br>+  if (TBAAInfo) {<br>+    llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,<br>+                                                      TBAAOffset);<br>+    CGM.DecorateInstruction(Store, TBAAPath);<br>+  }<br>}<br><br>void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,<br>                                        bool isInit) {<br>  EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),<br>                    lvalue.getAlignment().getQuantity(), lvalue.getType(),<br>-                    lvalue.getTBAAInfo(), isInit);<br>+                    lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(),<br>+                    lvalue.getTBAAOffset());<br>}<br><br>/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this<br>@@ -2494,9 +2505,12 @@<br><br>  llvm::Value *addr = base.getAddress();<br>  unsigned cvr = base.getVRQualifiers();<br>+  bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA;<br>  if (rec->isUnion()) {<br>    // For unions, there is no pointer adjustment.<br>    assert(!type->isReferenceType() && "union has reference member");<br>+    // TODO: handle path-aware TBAA for union.<br>+    TBAAPath = false;<br>  } else {<br>    // For structs, we GEP to the field that the record layout suggests.<br>    unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);<br>@@ -2508,6 +2522,8 @@<br>      if (cvr & Qualifiers::Volatile) load->setVolatile(true);<br>      load->setAlignment(alignment.getQuantity());<br><br>+      // Loading the reference will disable path-aware TBAA.<br>+      TBAAPath = false;<br>      if (CGM.shouldUseTBAA()) {<br>        llvm::MDNode *tbaa;<br>        if (mayAlias)<br>@@ -2541,6 +2557,16 @@<br><br>  LValue LV = MakeAddrLValue(addr, type, alignment);<br>  LV.getQuals().addCVRQualifiers(cvr);<br>+  if (TBAAPath) {<br>+    const ASTRecordLayout &Layout =<br>+        getContext().getASTRecordLayout(field->getParent());<br>+    // Set the base type to be the base type of the base LValue and<br>+    // update offset to be relative to the base type.<br>+    LV.setTBAABaseType(base.getTBAABaseType());<br>+    LV.setTBAAOffset(base.getTBAAOffset() +<br>+                     Layout.getFieldOffset(field->getFieldIndex()) /<br>+                                           getContext().getCharWidth());<br>+  }<br><br>  // __weak attribute on a field is ignored.<br>  if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)<br>Index: lib/CodeGen/CGValue.h<br>===================================================================<br>--- lib/CodeGen/CGValue.h<span class="Apple-tab-span" style="white-space: pre;">        </span>(revision 178718)<br>+++ lib/CodeGen/CGValue.h<span class="Apple-tab-span" style="white-space: pre;">      </span>(working copy)<br>@@ -157,6 +157,11 @@<br><br>  Expr *BaseIvarExp;<br><br>+  /// Used by struct-path-aware TBAA.<br>+  QualType TBAABaseType;<br>+  /// Offset relative to the base type.<br>+  uint64_t TBAAOffset;<br>+<br>  /// TBAAInfo - TBAA information to attach to dereferences of this LValue.<br>  llvm::MDNode *TBAAInfo;<br><br>@@ -175,6 +180,10 @@<br>    this->ImpreciseLifetime = false;<br>    this->ThreadLocalRef = false;<br>    this->BaseIvarExp = 0;<br>+<br>+    // Initialize fields for TBAA.<br>+    this->TBAABaseType = Type;<br>+    this->TBAAOffset = 0;<br>    this->TBAAInfo = TBAAInfo;<br>  }<br><br>@@ -232,6 +241,12 @@<br>  Expr *getBaseIvarExp() const { return BaseIvarExp; }<br>  void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }<br><br>+  QualType getTBAABaseType() const { return TBAABaseType; }<br>+  void setTBAABaseType(QualType T) { TBAABaseType = T; }<br>+<br>+  uint64_t getTBAAOffset() const { return TBAAOffset; }<br>+  void setTBAAOffset(uint64_t O) { TBAAOffset = O; }<br>+<br>  llvm::MDNode *getTBAAInfo() const { return TBAAInfo; }<br>  void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; }<br><br>Index: lib/CodeGen/CodeGenFunction.h<br>===================================================================<br>--- lib/CodeGen/CodeGenFunction.h<span class="Apple-tab-span" style="white-space: pre;">     </span>(revision 178718)<br>+++ lib/CodeGen/CodeGenFunction.h<span class="Apple-tab-span" style="white-space: pre;">      </span>(working copy)<br>@@ -2211,7 +2211,9 @@<br>  /// the LLVM value representation.<br>  llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,<br>                                unsigned Alignment, QualType Ty,<br>-                                llvm::MDNode *TBAAInfo = 0);<br>+                                llvm::MDNode *TBAAInfo = 0,<br>+                                QualType TBAABaseTy = QualType(),<br>+                                uint64_t TBAAOffset = 0);<br><br>  /// EmitLoadOfScalar - Load a scalar value from an address, taking<br>  /// care to appropriately convert from the memory representation to<br>@@ -2224,7 +2226,9 @@<br>  /// the LLVM value representation.<br>  void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,<br>                         bool Volatile, unsigned Alignment, QualType Ty,<br>-                         llvm::MDNode *TBAAInfo = 0, bool isInit=false);<br>+                         llvm::MDNode *TBAAInfo = 0, bool isInit = false,<br>+                         QualType TBAABaseTy = QualType(),<br>+                         uint64_t TBAAOffset = 0);<br><br>  /// EmitStoreOfScalar - Store a scalar value to an address, taking<br>  /// care to appropriately convert from the memory representation to<br>Index: lib/CodeGen/CodeGenModule.cpp<br>===================================================================<br>--- lib/CodeGen/CodeGenModule.cpp<span class="Apple-tab-span" style="white-space: pre;">       </span>(revision 178718)<br>+++ lib/CodeGen/CodeGenModule.cpp<span class="Apple-tab-span" style="white-space: pre;">      </span>(working copy)<br>@@ -227,6 +227,20 @@<br>  return TBAA->getTBAAStructInfo(QTy);<br>}<br><br>+llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) {<br>+  if (!TBAA)<br>+    return 0;<br>+  return TBAA->getTBAAStructTypeInfo(QTy);<br>+}<br>+<br>+llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy,<br>+                                                  llvm::MDNode *AccessN,<br>+                                                  uint64_t O) {<br>+  if (!TBAA)<br>+    return 0;<br>+  return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O);<br>+}<br>+<br>void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst,<br>                                        llvm::MDNode *TBAAInfo) {<br>  Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo);<br>Index: lib/CodeGen/CodeGenModule.h<br>===================================================================<br>--- lib/CodeGen/CodeGenModule.h<span class="Apple-tab-span" style="white-space: pre;">       </span>(revision 178718)<br>+++ lib/CodeGen/CodeGenModule.h<span class="Apple-tab-span" style="white-space: pre;">        </span>(working copy)<br>@@ -501,6 +501,11 @@<br>  llvm::MDNode *getTBAAInfo(QualType QTy);<br>  llvm::MDNode *getTBAAInfoForVTablePtr();<br>  llvm::MDNode *getTBAAStructInfo(QualType QTy);<br>+  /// Return the MDNode in the type DAG for the given struct type.<br>+  llvm::MDNode *getTBAAStructTypeInfo(QualType QTy);<br>+  /// Return the path-aware tag for given base type, access node and offset.<br>+  llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN,<br>+                                     uint64_t O);<br><br>  bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor);<br><br>Index: lib/CodeGen/CodeGenTBAA.cpp<br>===================================================================<br>--- lib/CodeGen/CodeGenTBAA.cpp<span class="Apple-tab-span" style="white-space: pre;">    </span>(revision 178718)<br>+++ lib/CodeGen/CodeGenTBAA.cpp<span class="Apple-tab-span" style="white-space: pre;">        </span>(working copy)<br>@@ -21,6 +21,7 @@<br>#include "clang/AST/Mangle.h"<br>#include "clang/AST/RecordLayout.h"<br>#include "clang/Frontend/CodeGenOptions.h"<br>+#include "llvm/ADT/SmallSet.h"<br>#include "llvm/IR/Constants.h"<br>#include "llvm/IR/LLVMContext.h"<br>#include "llvm/IR/Metadata.h"<br>@@ -225,3 +226,87 @@<br>  // For now, handle any other kind of type conservatively.<br>  return StructMetadataCache[Ty] = NULL;<br>}<br>+<br>+/// Check if the given type can be handled by path-aware TBAA.<br>+static bool isTBAAPathStruct(QualType QTy) {<br>+  if (const RecordType *TTy = QTy->getAs<RecordType>()) {<br>+    const RecordDecl *RD = TTy->getDecl()->getDefinition();<br>+    // RD can be struct, union, class, interface or enum.<br>+    // For now, we only handle struct.<br>+    if (RD->isStruct() && !RD->hasFlexibleArrayMember())<br>+      return true;<br>+  }<br>+  return false;<br>+}<br>+<br>+llvm::MDNode *<br>+CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {<br>+  const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();<br>+  assert(isTBAAPathStruct(QTy));<br>+<br>+  if (llvm::MDNode *N = StructTypeMetadataCache[Ty])<br>+    return N;<br>+<br>+  if (const RecordType *TTy = QTy->getAs<RecordType>()) {<br>+    const RecordDecl *RD = TTy->getDecl()->getDefinition();<br>+<br>+    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);<br>+    SmallVector <std::pair<uint64_t, llvm::MDNode*>, 4> Fields;<br>+    // To reduce the size of MDNode for a given struct type, we only output<br>+    // once for all the fields with the same scalar types.<br>+    // Offsets for scalar fields in the type DAG are not used.<br>+    llvm::SmallSet <llvm::MDNode*, 4> ScalarFieldTypes;<br>+    unsigned idx = 0;<br>+    for (RecordDecl::field_iterator i = RD->field_begin(),<br>+         e = RD->field_end(); i != e; ++i, ++idx) {<br>+      QualType FieldQTy = i->getType();<br>+      llvm::MDNode *FieldNode;<br>+      if (isTBAAPathStruct(FieldQTy))<br>+        FieldNode = getTBAAStructTypeInfo(FieldQTy);<br>+      else {<br>+        FieldNode = getTBAAInfo(FieldQTy);<br>+        // Ignore this field if the type already exists.<br>+        if (ScalarFieldTypes.count(FieldNode))<br>+          continue;<br>+        ScalarFieldTypes.insert(FieldNode);<br>+       }<br>+      if (!FieldNode)<br>+        return StructTypeMetadataCache[Ty] = NULL;<br>+      Fields.push_back(std::make_pair(<br>+          Layout.getFieldOffset(idx) / Context.getCharWidth(), FieldNode));<br>+    }<br>+<br>+    // TODO: This is using the RTTI name. Is there a better way to get<br>+    // a unique string for a type?<br>+    SmallString<256> OutName;<br>+    llvm::raw_svector_ostream Out(OutName);<br>+    MContext.mangleCXXRTTIName(QualType(Ty, 0), Out);<br>+    Out.flush();<br>+    // Create the struct type node with a vector of pairs (offset, type).<br>+    return StructTypeMetadataCache[Ty] =<br>+      MDHelper.createTBAAStructTypeNode(OutName, Fields);<br>+  }<br>+<br>+  return StructMetadataCache[Ty] = NULL;<br>+}<br>+<br>+llvm::MDNode *<br>+CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode,<br>+                                  uint64_t Offset) {<br>+  if (!CodeGenOpts.StructPathTBAA)<br>+    return AccessNode;<br>+<br>+  const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr();<br>+  TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset);<br>+  if (llvm::MDNode *N = StructTagMetadataCache[PathTag])<br>+    return N;<br>+<br>+  llvm::MDNode *BNode = 0;<br>+  if (isTBAAPathStruct(BaseQTy))<br>+    BNode  = getTBAAStructTypeInfo(BaseQTy);<br>+  if (!BNode)<br>+    return StructTagMetadataCache[PathTag] = AccessNode;<br>+<br>+  return StructTagMetadataCache[PathTag] =<br>+    MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset);<br>+}<br>Index: lib/CodeGen/CodeGenTBAA.h<br>===================================================================<br>--- lib/CodeGen/CodeGenTBAA.h<span class="Apple-tab-span" style="white-space: pre;">        </span>(revision 178718)<br>+++ lib/CodeGen/CodeGenTBAA.h<span class="Apple-tab-span" style="white-space: pre;">  </span>(working copy)<br>@@ -35,6 +35,14 @@<br>namespace CodeGen {<br>  class CGRecordLayout;<br><br>+  struct TBAAPathTag {<br>+    TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O)<br>+      : BaseT(B), AccessN(A), Offset(O) {}<br>+    const Type *BaseT;<br>+    const llvm::MDNode *AccessN;<br>+    uint64_t Offset;<br>+  };<br>+<br>/// CodeGenTBAA - This class organizes the cross-module state that is used<br>/// while lowering AST types to LLVM types.<br>class CodeGenTBAA {<br>@@ -46,8 +54,13 @@<br>  // MDHelper - Helper for creating metadata.<br>  llvm::MDBuilder MDHelper;<br><br>-  /// MetadataCache - This maps clang::Types to llvm::MDNodes describing them.<br>+  /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing<br>+  /// them.<br>  llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;<br>+  /// This maps clang::Types to a struct node in the type DAG.<br>+  llvm::DenseMap<const Type *, llvm::MDNode *> StructTypeMetadataCache;<br>+  /// This maps TBAAPathTags to a tag node.<br>+  llvm::DenseMap<TBAAPathTag, llvm::MDNode *> StructTagMetadataCache;<br><br>  /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing<br>  /// them for struct assignments.<br>@@ -89,9 +102,49 @@<br>  /// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of<br>  /// the given type.<br>  llvm::MDNode *getTBAAStructInfo(QualType QTy);<br>+<br>+  /// Get the MDNode in the type DAG for given struct type QType.<br>+  llvm::MDNode *getTBAAStructTypeInfo(QualType QType);<br>+  /// Get the tag MDNode for a given base type, the actual sclar access MDNode<br>+  /// and offset into the base type.<br>+  llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType,<br>+                                     llvm::MDNode *AccessNode, uint64_t Offset);<br>};<br><br>}  // end namespace CodeGen<br>}  // end namespace clang<br><br>+namespace llvm {<br>+<br>+template<> struct DenseMapInfo<clang::CodeGen::TBAAPathTag> {<br>+  static clang::CodeGen::TBAAPathTag getEmptyKey() {<br>+    return clang::CodeGen::TBAAPathTag(<br>+      DenseMapInfo<const clang::Type *>::getEmptyKey(),<br>+      DenseMapInfo<const MDNode *>::getEmptyKey(),<br>+      DenseMapInfo<uint64_t>::getEmptyKey());<br>+  }<br>+<br>+  static clang::CodeGen::TBAAPathTag getTombstoneKey() {<br>+    return clang::CodeGen::TBAAPathTag(<br>+      DenseMapInfo<const clang::Type *>::getTombstoneKey(),<br>+      DenseMapInfo<const MDNode *>::getTombstoneKey(),<br>+      DenseMapInfo<uint64_t>::getTombstoneKey());<br>+  }<br>+<br>+  static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) {<br>+    return DenseMapInfo<const clang::Type *>::getHashValue(Val.BaseT) ^<br>+           DenseMapInfo<const MDNode *>::getHashValue(Val.AccessN) ^<br>+           DenseMapInfo<uint64_t>::getHashValue(Val.Offset);<br>+  }<br>+<br>+  static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS,<br>+                      const clang::CodeGen::TBAAPathTag &RHS) {<br>+    return LHS.BaseT == RHS.BaseT &&<br>+           LHS.AccessN == RHS.AccessN &&<br>+           LHS.Offset == RHS.Offset;<br>+  }<br>+};<br>+<br>+}  // end namespace llvm<br>+<br>#endif<br>Index: lib/Driver/Tools.cpp<br>===================================================================<br>--- lib/Driver/Tools.cpp<span class="Apple-tab-span" style="white-space: pre;">    </span>(revision 178718)<br>+++ lib/Driver/Tools.cpp<span class="Apple-tab-span" style="white-space: pre;">       </span>(working copy)<br>@@ -2105,6 +2105,8 @@<br>                    options::OPT_fno_strict_aliasing,<br>                    getToolChain().IsStrictAliasingDefault()))<br>    CmdArgs.push_back("-relaxed-aliasing");<br>+  if (Args.hasArg(options::OPT_fstruct_path_tbaa))<br>+    CmdArgs.push_back("-struct-path-tbaa");<br>  if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,<br>                   false))<br>    CmdArgs.push_back("-fstrict-enums");<br>Index: lib/Frontend/CompilerInvocation.cpp<br>===================================================================<br>--- lib/Frontend/CompilerInvocation.cpp<span class="Apple-tab-span" style="white-space: pre;">    </span>(revision 178718)<br>+++ lib/Frontend/CompilerInvocation.cpp<span class="Apple-tab-span" style="white-space: pre;">        </span>(working copy)<br>@@ -324,6 +324,7 @@<br>  Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(<br>    OPT_fuse_register_sized_bitfield_access);<br>  Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing);<br>+  Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa);<br>  Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);<br>  Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);<br>  Opts.NoCommon = Args.hasArg(OPT_fno_common);<br>Index: test/CodeGen/tbaa.cpp<br>===================================================================<br>--- test/CodeGen/tbaa.cpp<span class="Apple-tab-span" style="white-space: pre;"> </span>(revision 0)<br>+++ test/CodeGen/tbaa.cpp<span class="Apple-tab-span" style="white-space: pre;">   </span>(working copy)<br>@@ -0,0 +1,217 @@<br>+// RUN: %clang_cc1 -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s<br>+// RUN: %clang_cc1 -O1 -struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH<br>+// Test TBAA metadata generated by front-end.<br>+<br>+#include <stdint.h><br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   uint32_t f32;<br>+   uint16_t f16_2;<br>+   uint32_t f32_2;<br>+} StructA;<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   StructA a;<br>+   uint32_t f32;<br>+} StructB;<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   StructB b;<br>+   uint32_t f32;<br>+} StructC;<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   StructB b;<br>+   uint32_t f32;<br>+   uint8_t f8;<br>+} StructD;<br>+<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   uint32_t f32;<br>+} StructS;<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   uint32_t f32;<br>+} StructS2;<br>+<br>+uint32_t g(uint32_t *s, StructA *A, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !5<br>+  *s = 1;<br>+  A->f32 = 4;<br>+  return *s;<br>+}<br>+<br>+uint32_t g2(uint32_t *s, StructA *A, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !8<br>+  *s = 1;<br>+  A->f16 = 4;<br>+  return *s;<br>+}<br>+<br>+uint32_t g3(StructA *A, StructB *B, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9<br>+  A->f32 = 1;<br>+  B->a.f32 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g4(StructA *A, StructB *B, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !11<br>+  A->f32 = 1;<br>+  B->a.f16 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g5(StructA *A, StructB *B, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !12<br>+  A->f32 = 1;<br>+  B->f32 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g6(StructA *A, StructB *B, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !13<br>+  A->f32 = 1;<br>+  B->a.f32_2 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g7(StructA *A, StructS *S, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !14<br>+  A->f32 = 1;<br>+  S->f32 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g8(StructA *A, StructS *S, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !16<br>+  A->f32 = 1;<br>+  S->f16 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !17<br>+  S->f32 = 1;<br>+  S2->f32 = 4;<br>+  return S->f32;<br>+}<br>+<br>+uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14<br>+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !19<br>+  S->f32 = 1;<br>+  S2->f16 = 4;<br>+  return S->f32;<br>+}<br>+<br>+uint32_t g11(StructC *C, StructD *D, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !20<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !22<br>+  C->b.a.f32 = 1;<br>+  D->b.a.f32 = 4;<br>+  return C->b.a.f32;<br>+}<br>+<br>+uint32_t g12(StructC *C, StructD *D, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// TODO: differentiate the two accesses.<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !9<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9<br>+  StructB *b1 = &(C->b);<br>+  StructB *b2 = &(D->b);<br>+  // b1, b2 have different context.<br>+  b1->a.f32 = 1;<br>+  b2->a.f32 = 4;<br>+  return b1->a.f32;<br>+}<br>+<br>+// CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2}<br>+// CHECK: !2 = metadata !{metadata !"Simple C/C++ TBAA"}<br>+// CHECK: !4 = metadata !{metadata !"int", metadata !1}<br>+// CHECK: !5 = metadata !{metadata !"short", metadata !1}<br>+<br>+// PATH: !1 = metadata !{metadata !"omnipotent char", metadata !2}<br>+// PATH: !4 = metadata !{metadata !"int", metadata !1}<br>+// PATH: !5 = metadata !{metadata !6, metadata !4, i64 4}<br>+// PATH: !6 = metadata !{metadata !"_ZTS7StructA", i64 0, metadata !7, i64 4, metadata !4}<br>+// PATH: !7 = metadata !{metadata !"short", metadata !1}<br>+// PATH: !8 = metadata !{metadata !6, metadata !7, i64 0}<br>+// PATH: !9 = metadata !{metadata !10, metadata !4, i64 8}<br>+// PATH: !10 = metadata !{metadata !"_ZTS7StructB", i64 0, metadata !7, i64 4, metadata !6, i64 20, metadata !4}<br>+// PATH: !11 = metadata !{metadata !10, metadata !7, i64 4}<br>+// PATH: !12 = metadata !{metadata !10, metadata !4, i64 20}<br>+// PATH: !13 = metadata !{metadata !10, metadata !4, i64 16}<br>+// PATH: !14 = metadata !{metadata !15, metadata !4, i64 4}<br>+// PATH: !15 = metadata !{metadata !"_ZTS7StructS", i64 0, metadata !7, i64 4, metadata !4}<br>+// PATH: !16 = metadata !{metadata !15, metadata !7, i64 0}<br>+// PATH: !17 = metadata !{metadata !18, metadata !4, i64 4}<br>+// PATH: !18 = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata !7, i64 4, metadata !4}<br>+// PATH: !19 = metadata !{metadata !18, metadata !7, i64 0}<br>+// PATH: !20 = metadata !{metadata !21, metadata !4, i64 12}<br>+// PATH: !21 = metadata !{metadata !"_ZTS7StructC", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4}<br>+// PATH: !22 = metadata !{metadata !23, metadata !4, i64 12}<br>+// PATH: !23 = metadata !{metadata !"_ZTS7StructD", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4, i64 32, metadata !1}<br><br>Added:<br>   cfe/trunk/test/CodeGen/tbaa.cpp<br>Modified:<br>   cfe/trunk/include/clang/Driver/CC1Options.td<br>   cfe/trunk/include/clang/Driver/Options.td<br>   cfe/trunk/include/clang/Frontend/CodeGenOptions.def<br>   cfe/trunk/lib/CodeGen/CGExpr.cpp<br>   cfe/trunk/lib/CodeGen/CGValue.h<br>   cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>   cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>   cfe/trunk/lib/CodeGen/CodeGenModule.h<br>   cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp<br>   cfe/trunk/lib/CodeGen/CodeGenTBAA.h<br>   cfe/trunk/lib/Driver/Tools.cpp<br>   cfe/trunk/lib/Frontend/CompilerInvocation.cpp<br><br>Modified: cfe/trunk/include/clang/Driver/CC1Options.td<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Driver/CC1Options.td (original)<br>+++ cfe/trunk/include/clang/Driver/CC1Options.td Thu Apr  4 15:14:17 2013<br>@@ -161,6 +161,8 @@ def fuse_register_sized_bitfield_access:<br>  HelpText<"Use register sized accesses to bit-fields, when possible.">;<br>def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">,<br>  HelpText<"Turn off Type Based Alias Analysis">;<br>+def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">,<br>+  HelpText<"Turn on struct-path aware Type Based Alias Analysis">;<br>def masm_verbose : Flag<["-"], "masm-verbose">,<br>  HelpText<"Generate verbose assembly output">;<br>def mcode_model : Separate<["-"], "mcode-model">,<br><br>Modified: cfe/trunk/include/clang/Driver/Options.td<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Driver/Options.td (original)<br>+++ cfe/trunk/include/clang/Driver/Options.td Thu Apr  4 15:14:17 2013<br>@@ -587,6 +587,7 @@ def fno_spell_checking : Flag<["-"], "fn<br>  Flags<[CC1Option]>, HelpText<"Disable spell-checking">;<br>def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>;<br>def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>;<br>+def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>;<br>def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>;<br>def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>;<br>def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>,<br><br>Modified: cfe/trunk/include/clang/Frontend/CodeGenOptions.def<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CodeGenOptions.def?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CodeGenOptions.def?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Frontend/CodeGenOptions.def (original)<br>+++ cfe/trunk/include/clang/Frontend/CodeGenOptions.def Thu Apr  4 15:14:17 2013<br>@@ -86,6 +86,7 @@ VALUE_CODEGENOPT(OptimizationLevel, 3, 0<br>VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.<br>CODEGENOPT(RelaxAll          , 1, 0) ///< Relax all machine code instructions.<br>CODEGENOPT(RelaxedAliasing   , 1, 0) ///< Set when -fno-strict-aliasing is enabled.<br>+CODEGENOPT(StructPathTBAA    , 1, 0) ///< Whether or not to use struct-path TBAA.<br>CODEGENOPT(SaveTempLabels    , 1, 0) ///< Save temporary labels.<br>CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero<br>                                                 ///< offset in AddressSanitizer.<br><br>Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Apr  4 15:14:17 2013<br>@@ -1044,7 +1044,8 @@ CodeGenFunction::tryEmitAsConstant(DeclR<br>llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue) {<br>  return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),<br>                          lvalue.getAlignment().getQuantity(),<br>-                          lvalue.getType(), lvalue.getTBAAInfo());<br>+                          lvalue.getType(), lvalue.getTBAAInfo(),<br>+                          lvalue.getTBAABaseType(), lvalue.getTBAAOffset());<br>}<br><br>static bool hasBooleanRepresentation(QualType Ty) {<br>@@ -1106,7 +1107,9 @@ llvm::MDNode *CodeGenFunction::getRangeF<br><br>llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,<br>                                              unsigned Alignment, QualType Ty,<br>-                                              llvm::MDNode *TBAAInfo) {<br>+                                              llvm::MDNode *TBAAInfo,<br>+                                              QualType TBAABaseType,<br>+                                              uint64_t TBAAOffset) {<br>  // For better performance, handle vector loads differently.<br>  if (Ty->isVectorType()) {<br>    llvm::Value *V;<br>@@ -1158,8 +1161,11 @@ llvm::Value *CodeGenFunction::EmitLoadOf<br>    Load->setVolatile(true);<br>  if (Alignment)<br>    Load->setAlignment(Alignment);<br>-  if (TBAAInfo)<br>-    CGM.DecorateInstruction(Load, TBAAInfo);<br>+  if (TBAAInfo) {<br>+    llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,<br>+                                                      TBAAOffset);<br>+    CGM.DecorateInstruction(Load, TBAAPath);<br>+  }<br><br>  if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) ||<br>      (SanOpts->Enum && Ty->getAs<EnumType>())) {<br>@@ -1217,7 +1223,8 @@ void CodeGenFunction::EmitStoreOfScalar(<br>                                        bool Volatile, unsigned Alignment,<br>                                        QualType Ty,<br>                                        llvm::MDNode *TBAAInfo,<br>-                                        bool isInit) {<br>+                                        bool isInit, QualType TBAABaseType,<br>+                                        uint64_t TBAAOffset) {<br><br>  // Handle vectors differently to get better performance.<br>  if (Ty->isVectorType()) {<br>@@ -1268,15 +1275,19 @@ void CodeGenFunction::EmitStoreOfScalar(<br>  llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile);<br>  if (Alignment)<br>    Store->setAlignment(Alignment);<br>-  if (TBAAInfo)<br>-    CGM.DecorateInstruction(Store, TBAAInfo);<br>+  if (TBAAInfo) {<br>+    llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,<br>+                                                      TBAAOffset);<br>+    CGM.DecorateInstruction(Store, TBAAPath);<br>+  }<br>}<br><br>void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,<br>                                        bool isInit) {<br>  EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),<br>                    lvalue.getAlignment().getQuantity(), lvalue.getType(),<br>-                    lvalue.getTBAAInfo(), isInit);<br>+                    lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(),<br>+                    lvalue.getTBAAOffset());<br>}<br><br>/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this<br>@@ -2494,9 +2505,12 @@ LValue CodeGenFunction::EmitLValueForFie<br><br>  llvm::Value *addr = base.getAddress();<br>  unsigned cvr = base.getVRQualifiers();<br>+  bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA;<br>  if (rec->isUnion()) {<br>    // For unions, there is no pointer adjustment.<br>    assert(!type->isReferenceType() && "union has reference member");<br>+    // TODO: handle path-aware TBAA for union.<br>+    TBAAPath = false;<br>  } else {<br>    // For structs, we GEP to the field that the record layout suggests.<br>    unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);<br>@@ -2508,6 +2522,8 @@ LValue CodeGenFunction::EmitLValueForFie<br>      if (cvr & Qualifiers::Volatile) load->setVolatile(true);<br>      load->setAlignment(alignment.getQuantity());<br><br>+      // Loading the reference will disable path-aware TBAA.<br>+      TBAAPath = false;<br>      if (CGM.shouldUseTBAA()) {<br>        llvm::MDNode *tbaa;<br>        if (mayAlias)<br>@@ -2541,6 +2557,16 @@ LValue CodeGenFunction::EmitLValueForFie<br><br>  LValue LV = MakeAddrLValue(addr, type, alignment);<br>  LV.getQuals().addCVRQualifiers(cvr);<br>+  if (TBAAPath) {<br>+    const ASTRecordLayout &Layout =<br>+        getContext().getASTRecordLayout(field->getParent());<br>+    // Set the base type to be the base type of the base LValue and<br>+    // update offset to be relative to the base type.<br>+    LV.setTBAABaseType(base.getTBAABaseType());<br>+    LV.setTBAAOffset(base.getTBAAOffset() +<br>+                     Layout.getFieldOffset(field->getFieldIndex()) /<br>+                                           getContext().getCharWidth());<br>+  }<br><br>  // __weak attribute on a field is ignored.<br>  if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)<br><br>Modified: cfe/trunk/lib/CodeGen/CGValue.h<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGValue.h?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGValue.h?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGValue.h (original)<br>+++ cfe/trunk/lib/CodeGen/CGValue.h Thu Apr  4 15:14:17 2013<br>@@ -157,6 +157,11 @@ class LValue {<br><br>  Expr *BaseIvarExp;<br><br>+  /// Used by struct-path-aware TBAA.<br>+  QualType TBAABaseType;<br>+  /// Offset relative to the base type.<br>+  uint64_t TBAAOffset;<br>+<br>  /// TBAAInfo - TBAA information to attach to dereferences of this LValue.<br>  llvm::MDNode *TBAAInfo;<br><br>@@ -175,6 +180,10 @@ private:<br>    this->ImpreciseLifetime = false;<br>    this->ThreadLocalRef = false;<br>    this->BaseIvarExp = 0;<br>+<br>+    // Initialize fields for TBAA.<br>+    this->TBAABaseType = Type;<br>+    this->TBAAOffset = 0;<br>    this->TBAAInfo = TBAAInfo;<br>  }<br><br>@@ -232,6 +241,12 @@ public:<br>  Expr *getBaseIvarExp() const { return BaseIvarExp; }<br>  void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }<br><br>+  QualType getTBAABaseType() const { return TBAABaseType; }<br>+  void setTBAABaseType(QualType T) { TBAABaseType = T; }<br>+<br>+  uint64_t getTBAAOffset() const { return TBAAOffset; }<br>+  void setTBAAOffset(uint64_t O) { TBAAOffset = O; }<br>+<br>  llvm::MDNode *getTBAAInfo() const { return TBAAInfo; }<br>  void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; }<br><br><br>Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)<br>+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Apr  4 15:14:17 2013<br>@@ -2211,7 +2211,9 @@ public:<br>  /// the LLVM value representation.<br>  llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,<br>                                unsigned Alignment, QualType Ty,<br>-                                llvm::MDNode *TBAAInfo = 0);<br>+                                llvm::MDNode *TBAAInfo = 0,<br>+                                QualType TBAABaseTy = QualType(),<br>+                                uint64_t TBAAOffset = 0);<br><br>  /// EmitLoadOfScalar - Load a scalar value from an address, taking<br>  /// care to appropriately convert from the memory representation to<br>@@ -2224,7 +2226,9 @@ public:<br>  /// the LLVM value representation.<br>  void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,<br>                         bool Volatile, unsigned Alignment, QualType Ty,<br>-                         llvm::MDNode *TBAAInfo = 0, bool isInit=false);<br>+                         llvm::MDNode *TBAAInfo = 0, bool isInit = false,<br>+                         QualType TBAABaseTy = QualType(),<br>+                         uint64_t TBAAOffset = 0);<br><br>  /// EmitStoreOfScalar - Store a scalar value to an address, taking<br>  /// care to appropriately convert from the memory representation to<br><br>Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Apr  4 15:14:17 2013<br>@@ -227,6 +227,20 @@ llvm::MDNode *CodeGenModule::getTBAAStru<br>  return TBAA->getTBAAStructInfo(QTy);<br>}<br><br>+llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) {<br>+  if (!TBAA)<br>+    return 0;<br>+  return TBAA->getTBAAStructTypeInfo(QTy);<br>+}<br>+<br>+llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy,<br>+                                                  llvm::MDNode *AccessN,<br>+                                                  uint64_t O) {<br>+  if (!TBAA)<br>+    return 0;<br>+  return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O);<br>+}<br>+<br>void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst,<br>                                        llvm::MDNode *TBAAInfo) {<br>  Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo);<br><br>Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)<br>+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Apr  4 15:14:17 2013<br>@@ -501,6 +501,11 @@ public:<br>  llvm::MDNode *getTBAAInfo(QualType QTy);<br>  llvm::MDNode *getTBAAInfoForVTablePtr();<br>  llvm::MDNode *getTBAAStructInfo(QualType QTy);<br>+  /// Return the MDNode in the type DAG for the given struct type.<br>+  llvm::MDNode *getTBAAStructTypeInfo(QualType QTy);<br>+  /// Return the path-aware tag for given base type, access node and offset.<br>+  llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN,<br>+                                     uint64_t O);<br><br>  bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor);<br><br><br>Modified: cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp Thu Apr  4 15:14:17 2013<br>@@ -21,6 +21,7 @@<br>#include "clang/AST/Mangle.h"<br>#include "clang/AST/RecordLayout.h"<br>#include "clang/Frontend/CodeGenOptions.h"<br>+#include "llvm/ADT/SmallSet.h"<br>#include "llvm/IR/Constants.h"<br>#include "llvm/IR/LLVMContext.h"<br>#include "llvm/IR/Metadata.h"<br>@@ -225,3 +226,87 @@ CodeGenTBAA::getTBAAStructInfo(QualType<br>  // For now, handle any other kind of type conservatively.<br>  return StructMetadataCache[Ty] = NULL;<br>}<br>+<br>+/// Check if the given type can be handled by path-aware TBAA.<br>+static bool isTBAAPathStruct(QualType QTy) {<br>+  if (const RecordType *TTy = QTy->getAs<RecordType>()) {<br>+    const RecordDecl *RD = TTy->getDecl()->getDefinition();<br>+    // RD can be struct, union, class, interface or enum.<br>+    // For now, we only handle struct.<br>+    if (RD->isStruct() && !RD->hasFlexibleArrayMember())<br>+      return true;<br>+  }<br>+  return false;<br>+}<br>+<br>+llvm::MDNode *<br>+CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {<br>+  const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();<br>+  assert(isTBAAPathStruct(QTy));<br>+<br>+  if (llvm::MDNode *N = StructTypeMetadataCache[Ty])<br>+    return N;<br>+<br>+  if (const RecordType *TTy = QTy->getAs<RecordType>()) {<br>+    const RecordDecl *RD = TTy->getDecl()->getDefinition();<br>+<br>+    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);<br>+    SmallVector <std::pair<uint64_t, llvm::MDNode*>, 4> Fields;<br>+    // To reduce the size of MDNode for a given struct type, we only output<br>+    // once for all the fields with the same scalar types.<br>+    // Offsets for scalar fields in the type DAG are not used.<br>+    llvm::SmallSet <llvm::MDNode*, 4> ScalarFieldTypes;<br>+    unsigned idx = 0;<br>+    for (RecordDecl::field_iterator i = RD->field_begin(),<br>+         e = RD->field_end(); i != e; ++i, ++idx) {<br>+      QualType FieldQTy = i->getType();<br>+      llvm::MDNode *FieldNode;<br>+      if (isTBAAPathStruct(FieldQTy))<br>+        FieldNode = getTBAAStructTypeInfo(FieldQTy);<br>+      else {<br>+        FieldNode = getTBAAInfo(FieldQTy);<br>+        // Ignore this field if the type already exists.<br>+        if (ScalarFieldTypes.count(FieldNode))<br>+          continue;<br>+        ScalarFieldTypes.insert(FieldNode);<br>+       }<br>+      if (!FieldNode)<br>+        return StructTypeMetadataCache[Ty] = NULL;<br>+      Fields.push_back(std::make_pair(<br>+          Layout.getFieldOffset(idx) / Context.getCharWidth(), FieldNode));<br>+    }<br>+<br>+    // TODO: This is using the RTTI name. Is there a better way to get<br>+    // a unique string for a type?<br>+    SmallString<256> OutName;<br>+    llvm::raw_svector_ostream Out(OutName);<br>+    MContext.mangleCXXRTTIName(QualType(Ty, 0), Out);<br>+    Out.flush();<br>+    // Create the struct type node with a vector of pairs (offset, type).<br>+    return StructTypeMetadataCache[Ty] =<br>+      MDHelper.createTBAAStructTypeNode(OutName, Fields);<br>+  }<br>+<br>+  return StructMetadataCache[Ty] = NULL;<br>+}<br>+<br>+llvm::MDNode *<br>+CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode,<br>+                                  uint64_t Offset) {<br>+  if (!CodeGenOpts.StructPathTBAA)<br>+    return AccessNode;<br>+<br>+  const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr();<br>+  TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset);<br>+  if (llvm::MDNode *N = StructTagMetadataCache[PathTag])<br>+    return N;<br>+<br>+  llvm::MDNode *BNode = 0;<br>+  if (isTBAAPathStruct(BaseQTy))<br>+    BNode  = getTBAAStructTypeInfo(BaseQTy);<br>+  if (!BNode)<br>+    return StructTagMetadataCache[PathTag] = AccessNode;<br>+<br>+  return StructTagMetadataCache[PathTag] =<br>+    MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset);<br>+}<br><br>Modified: cfe/trunk/lib/CodeGen/CodeGenTBAA.h<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTBAA.h?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTBAA.h?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CodeGenTBAA.h (original)<br>+++ cfe/trunk/lib/CodeGen/CodeGenTBAA.h Thu Apr  4 15:14:17 2013<br>@@ -35,6 +35,14 @@ namespace clang {<br>namespace CodeGen {<br>  class CGRecordLayout;<br><br>+  struct TBAAPathTag {<br>+    TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O)<br>+      : BaseT(B), AccessN(A), Offset(O) {}<br>+    const Type *BaseT;<br>+    const llvm::MDNode *AccessN;<br>+    uint64_t Offset;<br>+  };<br>+<br>/// CodeGenTBAA - This class organizes the cross-module state that is used<br>/// while lowering AST types to LLVM types.<br>class CodeGenTBAA {<br>@@ -46,8 +54,13 @@ class CodeGenTBAA {<br>  // MDHelper - Helper for creating metadata.<br>  llvm::MDBuilder MDHelper;<br><br>-  /// MetadataCache - This maps clang::Types to llvm::MDNodes describing them.<br>+  /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing<br>+  /// them.<br>  llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;<br>+  /// This maps clang::Types to a struct node in the type DAG.<br>+  llvm::DenseMap<const Type *, llvm::MDNode *> StructTypeMetadataCache;<br>+  /// This maps TBAAPathTags to a tag node.<br>+  llvm::DenseMap<TBAAPathTag, llvm::MDNode *> StructTagMetadataCache;<br><br>  /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing<br>  /// them for struct assignments.<br>@@ -89,9 +102,49 @@ public:<br>  /// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of<br>  /// the given type.<br>  llvm::MDNode *getTBAAStructInfo(QualType QTy);<br>+<br>+  /// Get the MDNode in the type DAG for given struct type QType.<br>+  llvm::MDNode *getTBAAStructTypeInfo(QualType QType);<br>+  /// Get the tag MDNode for a given base type, the actual sclar access MDNode<br>+  /// and offset into the base type.<br>+  llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType,<br>+                                     llvm::MDNode *AccessNode, uint64_t Offset);<br>};<br><br>}  // end namespace CodeGen<br>}  // end namespace clang<br><br>+namespace llvm {<br>+<br>+template<> struct DenseMapInfo<clang::CodeGen::TBAAPathTag> {<br>+  static clang::CodeGen::TBAAPathTag getEmptyKey() {<br>+    return clang::CodeGen::TBAAPathTag(<br>+      DenseMapInfo<const clang::Type *>::getEmptyKey(),<br>+      DenseMapInfo<const MDNode *>::getEmptyKey(),<br>+      DenseMapInfo<uint64_t>::getEmptyKey());<br>+  }<br>+<br>+  static clang::CodeGen::TBAAPathTag getTombstoneKey() {<br>+    return clang::CodeGen::TBAAPathTag(<br>+      DenseMapInfo<const clang::Type *>::getTombstoneKey(),<br>+      DenseMapInfo<const MDNode *>::getTombstoneKey(),<br>+      DenseMapInfo<uint64_t>::getTombstoneKey());<br>+  }<br>+<br>+  static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) {<br>+    return DenseMapInfo<const clang::Type *>::getHashValue(Val.BaseT) ^<br>+           DenseMapInfo<const MDNode *>::getHashValue(Val.AccessN) ^<br>+           DenseMapInfo<uint64_t>::getHashValue(Val.Offset);<br>+  }<br>+<br>+  static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS,<br>+                      const clang::CodeGen::TBAAPathTag &RHS) {<br>+    return LHS.BaseT == RHS.BaseT &&<br>+           LHS.AccessN == RHS.AccessN &&<br>+           LHS.Offset == RHS.Offset;<br>+  }<br>+};<br>+<br>+}  // end namespace llvm<br>+<br>#endif<br><br>Modified: cfe/trunk/lib/Driver/Tools.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Driver/Tools.cpp (original)<br>+++ cfe/trunk/lib/Driver/Tools.cpp Thu Apr  4 15:14:17 2013<br>@@ -2105,6 +2105,8 @@ void Clang::ConstructJob(Compilation &C,<br>                    options::OPT_fno_strict_aliasing,<br>                    getToolChain().IsStrictAliasingDefault()))<br>    CmdArgs.push_back("-relaxed-aliasing");<br>+  if (Args.hasArg(options::OPT_fstruct_path_tbaa))<br>+    CmdArgs.push_back("-struct-path-tbaa");<br>  if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,<br>                   false))<br>    CmdArgs.push_back("-fstrict-enums");<br><br>Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=178784&r1=178783&r2=178784&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=178784&r1=178783&r2=178784&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)<br>+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Thu Apr  4 15:14:17 2013<br>@@ -324,6 +324,7 @@ static bool ParseCodeGenArgs(CodeGenOpti<br>  Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(<br>    OPT_fuse_register_sized_bitfield_access);<br>  Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing);<br>+  Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa);<br>  Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);<br>  Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);<br>  Opts.NoCommon = Args.hasArg(OPT_fno_common);<br><br>Added: cfe/trunk/test/CodeGen/tbaa.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/tbaa.cpp?rev=178784&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/tbaa.cpp?rev=178784&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGen/tbaa.cpp (added)<br>+++ cfe/trunk/test/CodeGen/tbaa.cpp Thu Apr  4 15:14:17 2013<br>@@ -0,0 +1,217 @@<br>+// RUN: %clang_cc1 -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s<br>+// RUN: %clang_cc1 -O1 -struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH<br>+// Test TBAA metadata generated by front-end.<br>+<br>+#include <stdint.h><br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   uint32_t f32;<br>+   uint16_t f16_2;<br>+   uint32_t f32_2;<br>+} StructA;<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   StructA a;<br>+   uint32_t f32;<br>+} StructB;<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   StructB b;<br>+   uint32_t f32;<br>+} StructC;<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   StructB b;<br>+   uint32_t f32;<br>+   uint8_t f8;<br>+} StructD;<br>+<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   uint32_t f32;<br>+} StructS;<br>+typedef struct<br>+{<br>+   uint16_t f16;<br>+   uint32_t f32;<br>+} StructS2;<br>+<br>+uint32_t g(uint32_t *s, StructA *A, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !5<br>+  *s = 1;<br>+  A->f32 = 4;<br>+  return *s;<br>+}<br>+<br>+uint32_t g2(uint32_t *s, StructA *A, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !8<br>+  *s = 1;<br>+  A->f16 = 4;<br>+  return *s;<br>+}<br>+<br>+uint32_t g3(StructA *A, StructB *B, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9<br>+  A->f32 = 1;<br>+  B->a.f32 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g4(StructA *A, StructB *B, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !11<br>+  A->f32 = 1;<br>+  B->a.f16 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g5(StructA *A, StructB *B, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !12<br>+  A->f32 = 1;<br>+  B->f32 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g6(StructA *A, StructB *B, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !13<br>+  A->f32 = 1;<br>+  B->a.f32_2 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g7(StructA *A, StructS *S, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !14<br>+  A->f32 = 1;<br>+  S->f32 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g8(StructA *A, StructS *S, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5<br>+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !16<br>+  A->f32 = 1;<br>+  S->f16 = 4;<br>+  return A->f32;<br>+}<br>+<br>+uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !17<br>+  S->f32 = 1;<br>+  S2->f32 = 4;<br>+  return S->f32;<br>+}<br>+<br>+uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14<br>+// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !19<br>+  S->f32 = 1;<br>+  S2->f16 = 4;<br>+  return S->f32;<br>+}<br>+<br>+uint32_t g11(StructC *C, StructD *D, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !20<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !22<br>+  C->b.a.f32 = 1;<br>+  D->b.a.f32 = 4;<br>+  return C->b.a.f32;<br>+}<br>+<br>+uint32_t g12(StructC *C, StructD *D, uint64_t count) {<br>+// CHECK: define i32 @{{.*}}(<br>+// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4<br>+// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4<br>+// TODO: differentiate the two accesses.<br>+// PATH: define i32 @{{.*}}(<br>+// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !9<br>+// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9<br>+  StructB *b1 = &(C->b);<br>+  StructB *b2 = &(D->b);<br>+  // b1, b2 have different context.<br>+  b1->a.f32 = 1;<br>+  b2->a.f32 = 4;<br>+  return b1->a.f32;<br>+}<br>+<br>+// CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2}<br>+// CHECK: !2 = metadata !{metadata !"Simple C/C++ TBAA"}<br>+// CHECK: !4 = metadata !{metadata !"int", metadata !1}<br>+// CHECK: !5 = metadata !{metadata !"short", metadata !1}<br>+<br>+// PATH: !1 = metadata !{metadata !"omnipotent char", metadata !2}<br>+// PATH: !4 = metadata !{metadata !"int", metadata !1}<br>+// PATH: !5 = metadata !{metadata !6, metadata !4, i64 4}<br>+// PATH: !6 = metadata !{metadata !"_ZTS7StructA", i64 0, metadata !7, i64 4, metadata !4}<br>+// PATH: !7 = metadata !{metadata !"short", metadata !1}<br>+// PATH: !8 = metadata !{metadata !6, metadata !7, i64 0}<br>+// PATH: !9 = metadata !{metadata !10, metadata !4, i64 8}<br>+// PATH: !10 = metadata !{metadata !"_ZTS7StructB", i64 0, metadata !7, i64 4, metadata !6, i64 20, metadata !4}<br>+// PATH: !11 = metadata !{metadata !10, metadata !7, i64 4}<br>+// PATH: !12 = metadata !{metadata !10, metadata !4, i64 20}<br>+// PATH: !13 = metadata !{metadata !10, metadata !4, i64 16}<br>+// PATH: !14 = metadata !{metadata !15, metadata !4, i64 4}<br>+// PATH: !15 = metadata !{metadata !"_ZTS7StructS", i64 0, metadata !7, i64 4, metadata !4}<br>+// PATH: !16 = metadata !{metadata !15, metadata !7, i64 0}<br>+// PATH: !17 = metadata !{metadata !18, metadata !4, i64 4}<br>+// PATH: !18 = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata !7, i64 4, metadata !4}<br>+// PATH: !19 = metadata !{metadata !18, metadata !7, i64 0}<br>+// PATH: !20 = metadata !{metadata !21, metadata !4, i64 12}<br>+// PATH: !21 = metadata !{metadata !"_ZTS7StructC", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4}<br>+// PATH: !22 = metadata !{metadata !23, metadata !4, i64 12}<br>+// PATH: !23 = metadata !{metadata !"_ZTS7StructD", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4, i64 32, metadata !1}<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a></div></blockquote></div><br></div></div></blockquote></body></html>