Index: lib/Transforms/InstCombine/InstCombinePHI.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombinePHI.cpp +++ lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Transforms/Utils/Local.h" using namespace llvm; #define DEBUG_TYPE "instcombine" @@ -350,9 +351,11 @@ Value *InVal = FirstLI->getOperand(0); NewPN->addIncoming(InVal, PN.getIncomingBlock(0)); - // Add all operands to the new PHI. + // Add all operands to the new PHI and combine TBAA metadata. for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) { - Value *NewInVal = cast(PN.getIncomingValue(i))->getOperand(0); + LoadInst *LI = cast(PN.getIncomingValue(i)); + combineMetadata(FirstLI, LI, { LLVMContext::MD_tbaa }); + Value *NewInVal = LI->getOperand(0); if (NewInVal != InVal) InVal = nullptr; NewPN->addIncoming(NewInVal, PN.getIncomingBlock(i)); @@ -377,6 +380,8 @@ cast(IncValue)->setVolatile(false); LoadInst *NewLI = new LoadInst(PhiVal, "", isVolatile, LoadAlignment); + NewLI->setMetadata(LLVMContext::MD_tbaa, + FirstLI->getMetadata(LLVMContext::MD_tbaa)); NewLI->setDebugLoc(FirstLI->getDebugLoc()); return NewLI; } Index: test/Transforms/InstCombine/fold-phi-load-tbaa.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/fold-phi-load-tbaa.ll @@ -0,0 +1,42 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +%struct.S1 = type { i32, float } +%struct.S2 = type { float, i32 } + +; Check that tbaa metadata is preserved after merging the two loads. +; +; CHECK: return: +; CHECK: load i32, i32* %{{[a-z0-9.]+}}, align 4, !tbaa !0 + +; Function Attrs: nounwind ssp uwtable +define i32 @phi_load_tbaa(%struct.S1* %s1, %struct.S2* %s2, i32 %c) #0 { +entry: + %tobool = icmp eq i32 %c, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + %i = getelementptr inbounds %struct.S2, %struct.S2* %s2, i64 0, i32 1 + %val = load i32, i32* %i, align 4, !tbaa !0 + br label %return + +if.end: ; preds = %entry + %i2 = getelementptr inbounds %struct.S1, %struct.S1* %s1, i64 0, i32 0 + %val2 = load i32, i32* %i2, align 4, !tbaa !2 + br label %return + +return: ; preds = %if.end, %if.then + %retval = phi i32 [ %val, %if.then ], [ %val2, %if.end ] + ret i32 %retval +} + +; CHECK: !0 = !{!1, !1, i64 0} +; CHECK: !1 = !{!"int", !{{[0-9]}}, i64 0} + +!0 = !{!1, !4, i64 4} +!1 = !{!"", !7, i64 0, !4, i64 4} +!2 = !{!3, !4, i64 0} +!3 = !{!"", !4, i64 0, !7, i64 4} +!4 = !{!"int", !5, i64 0} +!5 = !{!"omnipotent char", !6, i64 0} +!6 = !{!"Simple C/C++ TBAA"} +!7 = !{!"float", !5, i64 0}