[InstCombine] Fold icmp eq of non-inbounds gep with base pointer
authorNikita Popov <npopov@redhat.com>
Tue, 21 Mar 2023 09:16:51 +0000 (10:16 +0100)
committerNikita Popov <npopov@redhat.com>
Tue, 21 Mar 2023 09:20:11 +0000 (10:20 +0100)
For equality comparisons, we don't need the gep to be inbounds:
https://alive2.llvm.org/ce/z/Fe_kn2

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/compare-alloca.ll
llvm/test/Transforms/InstCombine/icmp-gep.ll

index b1d59d355eb737952e8cbeaaebdbffa73ce0dfda..b9473634e6dc77a1ead8289f2b84ecfd3cc60326 100644 (file)
@@ -741,7 +741,7 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
     RHS = RHS->stripPointerCasts();
 
   Value *PtrBase = GEPLHS->getOperand(0);
-  if (PtrBase == RHS && GEPLHS->isInBounds()) {
+  if (PtrBase == RHS && (GEPLHS->isInBounds() || ICmpInst::isEquality(Cond))) {
     // ((gep Ptr, OFFSET) cmp Ptr)   ---> (OFFSET cmp 0).
     Value *Offset = EmitGEPOffset(GEPLHS);
     return new ICmpInst(ICmpInst::getSignedPredicate(Cond), Offset,
index 6ba1850cba3bb727e657869ea36d8662bf126bc0..164398382e9e0c45642dc6c0af0c34622dd5eb9c 100644 (file)
@@ -292,11 +292,8 @@ define void @select_alloca_unrelated_ptr(i1 %c, ptr %p, ptr %p2) {
 
 define void @alloca_offset_icmp(ptr %p, i32 %offset) {
 ; CHECK-LABEL: @alloca_offset_icmp(
-; CHECK-NEXT:    [[M:%.*]] = alloca [4 x i8], align 1
-; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, ptr [[M]], i32 [[OFFSET:%.*]]
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[M]], [[P:%.*]]
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq ptr [[M]], [[G]]
-; CHECK-NEXT:    call void @witness(i1 [[CMP1]], i1 [[CMP2]])
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[OFFSET:%.*]], 0
+; CHECK-NEXT:    call void @witness(i1 false, i1 [[CMP2]])
 ; CHECK-NEXT:    ret void
 ;
   %m = alloca [4 x i8]
index bc8bc7b74d3b4bd1326424f9525cd50d34b2e9d4..1ccd3819e6593f67b4fae1126ae7cd4dfe2eddb7 100644 (file)
@@ -8,8 +8,7 @@ declare void @use(ptr)
 
 define i1 @eq_base(ptr %x, i64 %y) {
 ; CHECK-LABEL: @eq_base(
-; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp eq ptr [[G]], [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[Y:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %g = getelementptr i8, ptr %x, i64 %y
@@ -20,8 +19,7 @@ define i1 @eq_base(ptr %x, i64 %y) {
 define i1 @ne_base_commute(i64 %y) {
 ; CHECK-LABEL: @ne_base_commute(
 ; CHECK-NEXT:    [[X:%.*]] = call ptr @getptr()
-; CHECK-NEXT:    [[G:%.*]] = getelementptr i8, ptr [[X]], i64 [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp ne ptr [[X]], [[G]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %x = call ptr @getptr() ; thwart complexity-based canonicalization
@@ -176,8 +174,8 @@ define i1 @eq_base_inbounds_commute_use(i64 %y) {
 
 define i1 @eq_bitcast_base(ptr %p, i64 %x) {
 ; CHECK-LABEL: @eq_bitcast_base(
-; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [2 x i8], ptr [[P:%.*]], i64 [[X:%.*]], i64 0
-; CHECK-NEXT:    [[R:%.*]] = icmp eq ptr [[GEP]], [[P]]
+; CHECK-NEXT:    [[GEP_IDX_MASK:%.*]] = and i64 [[X:%.*]], 9223372036854775807
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i64 [[GEP_IDX_MASK]], 0
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %gep = getelementptr [2 x i8], ptr %p, i64 %x, i64 0
@@ -305,8 +303,8 @@ define i1 @test60_as1(ptr addrspace(1) %foo, i64 %i, i64 %j) {
 define i1 @test60_addrspacecast(ptr %foo, i64 %i, i64 %j) {
 ; CHECK-LABEL: @test60_addrspacecast(
 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP1]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %bit = addrspacecast ptr %foo to ptr addrspace(3)
   %gep1 = getelementptr inbounds i32, ptr addrspace(3) %bit, i64 %i
@@ -320,8 +318,8 @@ define i1 @test60_addrspacecast_smaller(ptr %foo, i16 %i, i64 %j) {
 ; CHECK-LABEL: @test60_addrspacecast_smaller(
 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[J:%.*]] to i16
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]]
-; CHECK-NEXT:    ret i1 [[TMP2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]]
+; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %bit = addrspacecast ptr %foo to ptr addrspace(1)
   %gep1 = getelementptr inbounds i32, ptr addrspace(1) %bit, i16 %i
@@ -335,8 +333,8 @@ define i1 @test60_addrspacecast_larger(ptr addrspace(1) %foo, i32 %i, i16 %j) {
 ; CHECK-LABEL: @test60_addrspacecast_larger(
 ; CHECK-NEXT:    [[I_TR:%.*]] = trunc i32 [[I:%.*]] to i16
 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i16 [[I_TR]], 2
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i16 [[TMP1]], [[J:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP2]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[TMP1]], [[J:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %bit = addrspacecast ptr addrspace(1) %foo to ptr addrspace(2)
   %gep1 = getelementptr inbounds i32, ptr addrspace(2) %bit, i32 %i