diff --git a/llvm/test/tools/llvm-diff/initializers.ll b/llvm/test/tools/llvm-diff/initializers.ll --- a/llvm/test/tools/llvm-diff/initializers.ll +++ b/llvm/test/tools/llvm-diff/initializers.ll @@ -10,3 +10,16 @@ %1 = getelementptr [2 x i16*], [2 x i16*]* @gv2, i64 0, i64 undef ret void } + +; A named structure may be renamed when the right module is read. This is due +; to the LLParser being different between the left and right modules, and the +; context renaming one. + +%struct.ty1 = type { i16, i16 } + +@gv3 = internal global [1 x %struct.ty1] [%struct.ty1 { i16 928, i16 0 }], align 16 + +define void @bar() { + %1 = getelementptr [1 x %struct.ty1], [1 x %struct.ty1]* @gv3, i64 0, i64 undef + ret void +} diff --git a/llvm/tools/llvm-diff/DifferenceEngine.cpp b/llvm/tools/llvm-diff/DifferenceEngine.cpp --- a/llvm/tools/llvm-diff/DifferenceEngine.cpp +++ b/llvm/tools/llvm-diff/DifferenceEngine.cpp @@ -404,6 +404,9 @@ return false; } +private: + std::vector StructStack; + public: bool equivalentAsOperands(const Constant *L, const Constant *R) { // Use equality as a preliminary filter. @@ -465,6 +468,41 @@ return true; } + // If L and R are ConstantStructs, compare each field and type. + if (isa(L)) { + const ConstantStruct *CSL = cast(L); + const ConstantStruct *CSR = cast(R); + + const StructType *LTy = cast(CSL->getType()); + const StructType *RTy = cast(CSR->getType()); + + // The StructTypes should have the same attributes. Don't use + // isLayoutIdentical(), because that just checks the element pointers, + // which may not work here. + if (LTy->getNumElements() != RTy->getNumElements() || + LTy->isPacked() != RTy->isPacked()) + return false; + + StructStack.push_back(CSL->getName()); + + for (unsigned I = 0; I < LTy->getNumElements(); I++) { + const Value *LAgg = CSL->getAggregateElement(I); + const Value *RAgg = CSR->getAggregateElement(I); + + if (std::find(StructStack.begin(), StructStack.end(), + LAgg->getName()) != StructStack.end()) + continue; + + if (!equivalentAsOperands(LAgg, RAgg)) { + StructStack.pop_back(); + return false; + } + } + + StructStack.pop_back(); + return true; + } + return false; }