diff options
Diffstat (limited to 'llvm/test/Transforms')
| -rw-r--r-- | llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/split-gep.ll | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/split-gep.ll b/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/split-gep.ll index 4d07ab35b51..ea0d3f5673a 100644 --- a/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/split-gep.ll +++ b/llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/split-gep.ll @@ -253,3 +253,27 @@ entry: ret float* %p ; CHECK-NEXT: ret } + +; The source code used to be buggy in checking +; (AccumulativeByteOffset % ElementTypeSizeOfGEP == 0) +; where AccumulativeByteOffset is signed but ElementTypeSizeOfGEP is unsigned. +; The compiler would promote AccumulativeByteOffset to unsigned, causing +; unexpected results. For example, while -64 % (int64_t)24 != 0, +; -64 % (uint64_t)24 == 0. +%struct3 = type { i64, i32 } +%struct2 = type { %struct3, i32 } +%struct1 = type { i64, %struct2 } +%struct0 = type { i32, i32, i64*, [100 x %struct1] } +define %struct2* @sign_mod_unsign(%struct0* %ptr, i64 %idx) { +; CHECK-LABEL: @sign_mod_unsign( +entry: + %arrayidx = add nsw i64 %idx, -2 +; CHECK-NOT: add + %ptr2 = getelementptr inbounds %struct0* %ptr, i64 0, i32 3, i64 %arrayidx, i32 1 +; CHECK: [[PTR:%[a-zA-Z0-9]+]] = getelementptr %struct0* %ptr, i64 0, i32 3, i64 %idx, i32 1 +; CHECK: [[PTR1:%[a-zA-Z0-9]+]] = bitcast %struct2* [[PTR]] to i8* +; CHECK: getelementptr i8* [[PTR1]], i64 -64 +; CHECK: bitcast + ret %struct2* %ptr2 +; CHECK-NEXT: ret +} |

