Index: llvm/lib/IR/ConstantFold.cpp =================================================================== --- llvm/lib/IR/ConstantFold.cpp +++ llvm/lib/IR/ConstantFold.cpp @@ -1832,6 +1832,12 @@ case Instruction::GetElementPtr: { GEPOperator *CE1GEP = cast(CE1); + + // The foldings below assume the GEP to be inbounds. + // TODO: Some of the logic can be applied for non-inbounds GEPs as well. + if (!CE1GEP->isInBounds()) + return ICmpInst::BAD_ICMP_PREDICATE; + // Ok, since this is a getelementptr, we know that the constant has a // pointer type. Check the various cases. if (isa(V2)) { Index: llvm/test/Transforms/InstSimplify/ConstProp/icmp-null.ll =================================================================== --- llvm/test/Transforms/InstSimplify/ConstProp/icmp-null.ll +++ llvm/test/Transforms/InstSimplify/ConstProp/icmp-null.ll @@ -119,7 +119,7 @@ define i1 @null_gep_ne_null() { ; CHECK-LABEL: @null_gep_ne_null( -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 icmp ne (i8* getelementptr (i8, i8* null, i64 ptrtoint (i32* @g2 to i64)), i8* null) ; %gep = getelementptr i8, i8* null, i64 ptrtoint (i32* @g2 to i64) %cmp = icmp ne i8* %gep, null @@ -128,7 +128,7 @@ define i1 @null_gep_ugt_null() { ; CHECK-LABEL: @null_gep_ugt_null( -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 icmp ugt (i8* getelementptr (i8, i8* null, i64 ptrtoint (i32* @g2 to i64)), i8* null) ; %gep = getelementptr i8, i8* null, i64 ptrtoint (i32* @g2 to i64) %cmp = icmp ugt i8* %gep, null @@ -146,7 +146,7 @@ define i1 @null_gep_ne_global() { ; CHECK-LABEL: @null_gep_ne_global( -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 icmp ne ([2 x i32]* getelementptr ([2 x i32], [2 x i32]* null, i64 ptrtoint (i32* @g2 to i64)), [2 x i32]* @g) ; %gep = getelementptr [2 x i32], [2 x i32]* null, i64 ptrtoint (i32* @g2 to i64) %cmp = icmp ne [2 x i32]* %gep, @g @@ -155,7 +155,7 @@ define i1 @null_gep_ult_global() { ; CHECK-LABEL: @null_gep_ult_global( -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 icmp ult ([2 x i32]* getelementptr ([2 x i32], [2 x i32]* null, i64 ptrtoint (i32* @g2 to i64)), [2 x i32]* @g) ; %gep = getelementptr [2 x i32], [2 x i32]* null, i64 ptrtoint (i32* @g2 to i64) %cmp = icmp ult [2 x i32]* %gep, @g @@ -200,7 +200,7 @@ define i1 @global_gep_ugt_global_neg_offset() { ; CHECK-LABEL: @global_gep_ugt_global_neg_offset( -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 icmp ugt ([2 x i32]* getelementptr ([2 x i32], [2 x i32]* @g, i64 -1), [2 x i32]* @g) ; %gep = getelementptr [2 x i32], [2 x i32]* @g, i64 -1 %cmp = icmp ugt [2 x i32]* %gep, @g @@ -215,3 +215,25 @@ %cmp = icmp sgt [2 x i32]* %gep, @g ret i1 %cmp } + +; The offset is negative and equal to the base pointer. + +define i1 @global_gep_eq_global_offset_neg() { +; CHECK-LABEL: @global_gep_eq_global_offset_neg( +; CHECK-NEXT: ret i1 icmp eq ([2 x i32]* getelementptr ([2 x i32], [2 x i32]* @g, i64 sub (i64 0, i64 ptrtoint ([2 x i32]* @g to i64))), [2 x i32]* null) +; + %off = sub i64 0, ptrtoint ([2 x i32]* @g to i64) + %gep = getelementptr [2 x i32], [2 x i32]* @g, i64 %off + %cmp = icmp eq [2 x i32]* %gep, null + ret i1 %cmp +} + +define i1 @global_gep_ne_global_offset_neg() { +; CHECK-LABEL: @global_gep_ne_global_offset_neg( +; CHECK-NEXT: ret i1 icmp ne ([2 x i32]* getelementptr ([2 x i32], [2 x i32]* @g, i64 sub (i64 0, i64 ptrtoint ([2 x i32]* @g to i64))), [2 x i32]* null) +; + %off = sub i64 0, ptrtoint ([2 x i32]* @g to i64) + %gep = getelementptr [2 x i32], [2 x i32]* @g, i64 %off + %cmp = icmp ne [2 x i32]* %gep, null + ret i1 %cmp +}