[ConstantFolding] Fold ptrtoint(gep i8 null, x) -> x
authorAlex Richardson <Alexander.Richardson@cl.cam.ac.uk>
Tue, 28 Sep 2021 14:32:18 +0000 (15:32 +0100)
committerAlex Richardson <Alexander.Richardson@cl.cam.ac.uk>
Tue, 28 Sep 2021 16:57:36 +0000 (17:57 +0100)
I was looking at some missed optimizations in CHERI-enabled targets and
noticed that we weren't removing vtable indirection for calls via known
pointers-to-members. The underlying reason for this is that we represent
pointers-to-function-members as {i8 addrspace(200)*, i64} and generate the
constant offsets using (gep i8 null, <index>). We use a constant GEP here
since inttoptr should be avoided for CHERI capabilities. The pointer-to-member
call uses ptrtoint to extract the index, and due to this missing fold we can't
infer the actual value loaded from the vtable.
This is the initial constant folding change for this pattern, I will add
an InstCombine fold as a follow-up.

We could fold all inbounds GEP to null (and therefore the ptrtoint to
zero) since zero is the only valid offset for an inbounds GEP. If the
offset is not zero, that GEP is poison and therefore returning 0 is valid
(https://alive2.llvm.org/ce/z/Gzb5iH). However, Clang currently generates
inbounds GEPs on NULL for hand-written offsetof() expressions, so this
could lead to miscompilations.

Reviewed By: lebedev.ri

Differential Revision: https://reviews.llvm.org/D110245

llvm/lib/Analysis/ConstantFolding.cpp
llvm/test/Transforms/InstCombine/ptrtoint-nullgep.ll

index bddbc2f..2543670 100644 (file)
@@ -1345,21 +1345,31 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
   default:
     llvm_unreachable("Missing case");
   case Instruction::PtrToInt:
-    // If the input is a inttoptr, eliminate the pair.  This requires knowing
-    // the width of a pointer, so it can't be done in ConstantExpr::getCast.
     if (auto *CE = dyn_cast<ConstantExpr>(C)) {
+      Constant *FoldedValue = nullptr;
+      // If the input is a inttoptr, eliminate the pair.  This requires knowing
+      // the width of a pointer, so it can't be done in ConstantExpr::getCast.
       if (CE->getOpcode() == Instruction::IntToPtr) {
-        Constant *Input = CE->getOperand(0);
-        unsigned InWidth = Input->getType()->getScalarSizeInBits();
-        unsigned PtrWidth = DL.getPointerTypeSizeInBits(CE->getType());
-        if (PtrWidth < InWidth) {
-          Constant *Mask =
-            ConstantInt::get(CE->getContext(),
-                             APInt::getLowBitsSet(InWidth, PtrWidth));
-          Input = ConstantExpr::getAnd(Input, Mask);
+        // zext/trunc the inttoptr to pointer size.
+        FoldedValue = ConstantExpr::getIntegerCast(
+            CE->getOperand(0), DL.getIntPtrType(CE->getType()),
+            /*IsSigned=*/false);
+      } else if (auto *GEP = dyn_cast<GEPOperator>(CE)) {
+        // If we have GEP, we can perform the following folds:
+        // (ptrtoint (gep null, x)) -> x
+        // (ptrtoint (gep (gep null, x), y) -> x + y, etc.
+        unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
+        APInt BaseOffset(BitWidth, 0);
+        auto *Base = cast<Constant>(GEP->stripAndAccumulateConstantOffsets(
+            DL, BaseOffset, /*AllowNonInbounds=*/true));
+        if (Base->isNullValue()) {
+          FoldedValue = ConstantInt::get(CE->getContext(), BaseOffset);
         }
-        // Do a zext or trunc to get to the dest size.
-        return ConstantExpr::getIntegerCast(Input, DestTy, false);
+      }
+      if (FoldedValue) {
+        // Do a zext or trunc to get to the ptrtoint dest size.
+        return ConstantExpr::getIntegerCast(FoldedValue, DestTy,
+                                            /*IsSigned=*/false);
       }
     }
     return ConstantExpr::getCast(Opcode, C, DestTy);
index f219271..f3293ab 100644 (file)
@@ -25,14 +25,11 @@ define i64 @constant_fold_ptrtoint_gep_nonzero() {
 ; LLPARSER-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {
 ; LLPARSER-NEXT:    ret i64 ptrtoint (i32 addrspace(1)* getelementptr (i32, i32 addrspace(1)* null, i64 1234) to i64)
 ;
-; INTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {
-; INTEGRAL-INSTSIMPLIFY-NEXT:    ret i64 ptrtoint (i32 addrspace(1)* getelementptr (i32, i32 addrspace(1)* null, i64 1234) to i64)
+; INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {
+; INSTSIMPLIFY-NEXT:    ret i64 ptrtoint (i32 addrspace(1)* getelementptr (i32, i32 addrspace(1)* null, i64 1234) to i64)
 ;
-; INTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {
-; INTEGRAL-INSTCOMBINE-NEXT:    ret i64 4936
-;
-; NONINTEGRAL-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {
-; NONINTEGRAL-NEXT:    ret i64 ptrtoint (i32 addrspace(1)* getelementptr (i32, i32 addrspace(1)* null, i64 1234) to i64)
+; INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {
+; INSTCOMBINE-NEXT:    ret i64 4936
 ;
   ret i64 ptrtoint (i32 addrspace(1)* getelementptr (i32, i32 addrspace(1)* null, i64 1234) to i64)
 }
@@ -51,14 +48,11 @@ define i64 @constant_fold_ptrtoint_gep_nonzero_inbounds() {
 ; LLPARSER-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {
 ; LLPARSER-NEXT:    ret i64 ptrtoint (i32 addrspace(1)* getelementptr inbounds (i32, i32 addrspace(1)* null, i64 1234) to i64)
 ;
-; INTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {
-; INTEGRAL-INSTSIMPLIFY-NEXT:    ret i64 ptrtoint (i32 addrspace(1)* getelementptr inbounds (i32, i32 addrspace(1)* null, i64 1234) to i64)
-;
-; INTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {
-; INTEGRAL-INSTCOMBINE-NEXT:    ret i64 4936
+; INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {
+; INSTSIMPLIFY-NEXT:    ret i64 ptrtoint (i32 addrspace(1)* getelementptr inbounds (i32, i32 addrspace(1)* null, i64 1234) to i64)
 ;
-; NONINTEGRAL-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {
-; NONINTEGRAL-NEXT:    ret i64 ptrtoint (i32 addrspace(1)* getelementptr inbounds (i32, i32 addrspace(1)* null, i64 1234) to i64)
+; INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {
+; INSTCOMBINE-NEXT:    ret i64 4936
 ;
   ret i64 ptrtoint (i32 addrspace(1)* getelementptr inbounds (i32, i32 addrspace(1)* null, i64 1234) to i64)
 }
@@ -80,50 +74,35 @@ define void @constant_fold_ptrtoint_of_gep_of_nullgep() {
 ; LLPARSER-NEXT:    call void @use_i64(i64 0)
 ; LLPARSER-NEXT:    ret void
 ;
-; INTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 0)
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 0)
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 0)
-; INTEGRAL-INSTSIMPLIFY-NEXT:    call void @use_i64(i64 0)
-; INTEGRAL-INSTSIMPLIFY-NEXT:    ret void
-;
-; INTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
-; INTEGRAL-INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
-; INTEGRAL-INSTCOMBINE-NEXT:    ret void
-;
-; NONINTEGRAL-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 0)
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 0)
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 0)
-; NONINTEGRAL-NEXT:    call void @use_i64(i64 0)
-; NONINTEGRAL-NEXT:    ret void
+; INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64))
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64))
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 0)
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 0)
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 0)
+; INSTSIMPLIFY-NEXT:    call void @use_i64(i64 0)
+; INSTSIMPLIFY-NEXT:    ret void
+;
+; INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 1234)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
+; INSTCOMBINE-NEXT:    call void @use_i64(i64 0)
+; INSTCOMBINE-NEXT:    ret void
 ;
   call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 0), i64 1234) to i64))
   call void @use_i64(i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 0), i64 1234) to i64))
@@ -182,11 +161,8 @@ define i64 @fold_ptrtoint_nullgep_nonzero() {
 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
 ; LLPARSER-NEXT:    ret i64 [[RET]]
 ;
-; INTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero() {
-; INTEGRAL-NEXT:    ret i64 1234
-;
-; NONINTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero() {
-; NONINTEGRAL-NEXT:    ret i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64)
+; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero() {
+; CHECK-NEXT:    ret i64 1234
 ;
   %offset = add i64 1234, 0
   %ptr = getelementptr i8, i8 addrspace(1)* null, i64 %offset
@@ -203,11 +179,8 @@ define i64 @fold_ptrtoint_nullgep_nonzero_inbounds() {
 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
 ; LLPARSER-NEXT:    ret i64 [[RET]]
 ;
-; INTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero_inbounds() {
-; INTEGRAL-NEXT:    ret i64 1234
-;
-; NONINTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero_inbounds() {
-; NONINTEGRAL-NEXT:    ret i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64)
+; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero_inbounds() {
+; CHECK-NEXT:    ret i64 1234
 ;
   %offset = add i64 1234, 0
   %ptr = getelementptr inbounds i8, i8 addrspace(1)* null, i64 %offset
@@ -280,33 +253,19 @@ define i64 @fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indic
 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
 ; LLPARSER-NEXT:    ret i64 [[RET]]
 ;
-; INTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices
-; INTEGRAL-INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
-; INTEGRAL-INSTSIMPLIFY-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
-; INTEGRAL-INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr inbounds [2 x i8], [2 x i8] addrspace(1)* null, i64 [[NON_ZERO_OFFSET]], i32 1
-; INTEGRAL-INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
-; INTEGRAL-INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
-;
-; INTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices
-; INTEGRAL-INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
-; INTEGRAL-INSTCOMBINE-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
-; INTEGRAL-INSTCOMBINE-NEXT:    [[PTR:%.*]] = getelementptr inbounds [2 x i8], [2 x i8] addrspace(1)* null, i64 [[NON_ZERO_OFFSET]], i64 1
-; INTEGRAL-INSTCOMBINE-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
-; INTEGRAL-INSTCOMBINE-NEXT:    ret i64 [[RET]]
-;
-; NONINTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices
-; NONINTEGRAL-INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
-; NONINTEGRAL-INSTSIMPLIFY-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
-; NONINTEGRAL-INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr inbounds [2 x i8], [2 x i8] addrspace(1)* null, i64 [[NON_ZERO_OFFSET]], i32 1
-; NONINTEGRAL-INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
-; NONINTEGRAL-INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
-;
-; NONINTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices
-; NONINTEGRAL-INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
-; NONINTEGRAL-INSTCOMBINE-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
-; NONINTEGRAL-INSTCOMBINE-NEXT:    [[PTR:%.*]] = getelementptr inbounds [2 x i8], [2 x i8] addrspace(1)* null, i64 [[NON_ZERO_OFFSET]], i64 1
-; NONINTEGRAL-INSTCOMBINE-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
-; NONINTEGRAL-INSTCOMBINE-NEXT:    ret i64 [[RET]]
+; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices
+; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
+; INSTSIMPLIFY-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
+; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr inbounds [2 x i8], [2 x i8] addrspace(1)* null, i64 [[NON_ZERO_OFFSET]], i32 1
+; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
+; INSTSIMPLIFY-NEXT:    ret i64 [[RET]]
+;
+; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices
+; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
+; INSTCOMBINE-NEXT:    [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1
+; INSTCOMBINE-NEXT:    [[PTR:%.*]] = getelementptr inbounds [2 x i8], [2 x i8] addrspace(1)* null, i64 [[NON_ZERO_OFFSET]], i64 1
+; INSTCOMBINE-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
+; INSTCOMBINE-NEXT:    ret i64 [[RET]]
 ;
   %non_zero_offset = or i64 %val, 1
   %ptr = getelementptr inbounds [2 x i8], [2 x i8] addrspace(1)* null, i64 %non_zero_offset, i32 1
@@ -336,31 +295,18 @@ define i32 @fold_ptrtoint_nullgep_variable_trunc(i64 %val) {
 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i32
 ; LLPARSER-NEXT:    ret i32 [[RET]]
 ;
-; INTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc
-; INTEGRAL-INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
-; INTEGRAL-INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr i8, i8 addrspace(1)* null, i64 [[VAL]]
-; INTEGRAL-INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i32
-; INTEGRAL-INSTSIMPLIFY-NEXT:    ret i32 [[RET]]
-;
-; INTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc
-; INTEGRAL-INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
-; INTEGRAL-INSTCOMBINE-NEXT:    [[PTR:%.*]] = getelementptr i8, i8 addrspace(1)* null, i64 [[VAL]]
-; INTEGRAL-INSTCOMBINE-NEXT:    [[TMP1:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
-; INTEGRAL-INSTCOMBINE-NEXT:    [[RET:%.*]] = trunc i64 [[TMP1]] to i32
-; INTEGRAL-INSTCOMBINE-NEXT:    ret i32 [[RET]]
-;
-; NONINTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc
-; NONINTEGRAL-INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
-; NONINTEGRAL-INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr i8, i8 addrspace(1)* null, i64 [[VAL]]
-; NONINTEGRAL-INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i32
-; NONINTEGRAL-INSTSIMPLIFY-NEXT:    ret i32 [[RET]]
-;
-; NONINTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc
-; NONINTEGRAL-INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
-; NONINTEGRAL-INSTCOMBINE-NEXT:    [[PTR:%.*]] = getelementptr i8, i8 addrspace(1)* null, i64 [[VAL]]
-; NONINTEGRAL-INSTCOMBINE-NEXT:    [[TMP1:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
-; NONINTEGRAL-INSTCOMBINE-NEXT:    [[RET:%.*]] = trunc i64 [[TMP1]] to i32
-; NONINTEGRAL-INSTCOMBINE-NEXT:    ret i32 [[RET]]
+; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc
+; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {
+; INSTSIMPLIFY-NEXT:    [[PTR:%.*]] = getelementptr i8, i8 addrspace(1)* null, i64 [[VAL]]
+; INSTSIMPLIFY-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i32
+; INSTSIMPLIFY-NEXT:    ret i32 [[RET]]
+;
+; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc
+; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {
+; INSTCOMBINE-NEXT:    [[PTR:%.*]] = getelementptr i8, i8 addrspace(1)* null, i64 [[VAL]]
+; INSTCOMBINE-NEXT:    [[TMP1:%.*]] = ptrtoint i8 addrspace(1)* [[PTR]] to i64
+; INSTCOMBINE-NEXT:    [[RET:%.*]] = trunc i64 [[TMP1]] to i32
+; INSTCOMBINE-NEXT:    ret i32 [[RET]]
 ;
   %ptr = getelementptr i8, i8 addrspace(1)* null, i64 %val
   %ret = ptrtoint i8 addrspace(1)* %ptr to i32
@@ -378,14 +324,8 @@ define i64 @fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {
 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR2]] to i64
 ; LLPARSER-NEXT:    ret i64 [[RET]]
 ;
-; INTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {
-; INTEGRAL-NEXT:    ret i64 1234
-;
-; NONINTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {
-; NONINTEGRAL-INSTSIMPLIFY-NEXT:    ret i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64)
-;
-; NONINTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {
-; NONINTEGRAL-INSTCOMBINE-NEXT:    ret i64 ptrtoint (i8 addrspace(1)* getelementptr (i8, i8 addrspace(1)* null, i64 1234) to i64)
+; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {
+; CHECK-NEXT:    ret i64 1234
 ;
   %nonzero_offset = add i64 1234, 0
   %zero_offset = sub i64 %nonzero_offset, 1234
@@ -404,11 +344,8 @@ define i64 @fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep()
 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR2]] to i64
 ; LLPARSER-NEXT:    ret i64 [[RET]]
 ;
-; INTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep() {
-; INTEGRAL-NEXT:    ret i64 1234
-;
-; NONINTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep() {
-; NONINTEGRAL-NEXT:    ret i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64)
+; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep() {
+; CHECK-NEXT:    ret i64 1234
 ;
   %nonzero_offset = add i64 1234, 0
   %zero_offset = sub i64 %nonzero_offset, 1234
@@ -459,11 +396,8 @@ define i64 @fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {
 ; LLPARSER-NEXT:    [[RET:%.*]] = ptrtoint i8 addrspace(1)* [[PTR2]] to i64
 ; LLPARSER-NEXT:    ret i64 [[RET]]
 ;
-; INTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {
-; INTEGRAL-NEXT:    ret i64 1234
-;
-; NONINTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {
-; NONINTEGRAL-NEXT:    ret i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 1234) to i64)
+; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {
+; CHECK-NEXT:    ret i64 1234
 ;
   %nonzero_offset = add i64 1234, 0
   %zero_offset = sub i64 %nonzero_offset, 1234