diff options
-rw-r--r-- | lib/Transforms/InstCombine/InstructionCombining.cpp | 7 | ||||
-rw-r--r-- | test/Transforms/InstCombine/getelementptr.ll | 16 |
2 files changed, 22 insertions, 1 deletions
diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index e9e05ceb65..dc7fe5cf6b 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -758,7 +758,12 @@ Type *InstCombiner::FindElementAtOffset(Type *Ty, int64_t Offset, FirstIdx = Offset/TySize; Offset -= FirstIdx*TySize; - assert(Offset >= 0 && "Offset should never be negative!"); + // Handle hosts where % returns negative instead of values [0..TySize). + if (Offset < 0) { + --FirstIdx; + Offset += TySize; + assert(Offset >= 0); + } assert((uint64_t)Offset < (uint64_t)TySize && "Out of range offset"); } diff --git a/test/Transforms/InstCombine/getelementptr.ll b/test/Transforms/InstCombine/getelementptr.ll index 1c120ecbe9..03e26eb67e 100644 --- a/test/Transforms/InstCombine/getelementptr.ll +++ b/test/Transforms/InstCombine/getelementptr.ll @@ -492,3 +492,19 @@ define void @three_gep_f(%three_gep_t2* %x) { declare void @three_gep_g(i32*) declare void @three_gep_h(%three_gep_t2*) + +%struct.ham = type { i32, %struct.zot*, %struct.zot*, %struct.zot* } +%struct.zot = type { i64, i8 } + +define void @test39(%struct.ham* %arg, i8 %arg1) nounwind { + %tmp = getelementptr inbounds %struct.ham* %arg, i64 0, i32 2 + %tmp2 = load %struct.zot** %tmp, align 8 + %tmp3 = bitcast %struct.zot* %tmp2 to i8* + %tmp4 = getelementptr inbounds i8* %tmp3, i64 -8 + store i8 %arg1, i8* %tmp4, align 8 + ret void + +; CHECK: @test39 +; CHECK: getelementptr inbounds %struct.ham* %arg, i64 0, i32 2 +; CHECK: getelementptr inbounds i8* %tmp3, i64 -8 +} |