diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2095,6 +2095,15 @@ Value *Mul = Builder.CreateMul(ValAndFactor.first, Builder.getInt(ValAndFactor.second)); Result = Builder.CreateAdd(Mul, Builder.getInt(ConstantOffset)); + } else if (VariableOffsets.size() == 2 && ConstantOffset.isZero()) { + auto &ValAndFactor1 = VariableOffsets.back(); + Value *Mul1 = Builder.CreateMul(ValAndFactor1.first, + Builder.getInt(ValAndFactor1.second)); + VariableOffsets.pop_back(); + auto &ValAndFactor2 = VariableOffsets.back(); + Value *Mul2 = Builder.CreateMul(ValAndFactor2.first, + Builder.getInt(ValAndFactor2.second)); + Result = Builder.CreateAdd(Mul1, Mul2); } if (Result) return replaceInstUsesWith( diff --git a/llvm/test/Transforms/InstCombine/ptrtoint-nullgep.ll b/llvm/test/Transforms/InstCombine/ptrtoint-nullgep.ll --- a/llvm/test/Transforms/InstCombine/ptrtoint-nullgep.ll +++ b/llvm/test/Transforms/InstCombine/ptrtoint-nullgep.ll @@ -514,13 +514,32 @@ ret i64 %ret } -; Negative test -- should not be folded since there are two variable indices +; Can be folded since there are two variable indices and no constant define i64 @fold_ptrtoint_nested_array_two_vars(i64 %x, i64 %y) { -; ALL-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars -; ALL-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { -; ALL-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], [2 x i16] addrspace(1)* null, i64 [[X]], i64 [[Y]] -; ALL-NEXT: [[RET:%.*]] = ptrtoint i16 addrspace(1)* [[PTR]] to i64 -; ALL-NEXT: ret i64 [[RET]] +; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars +; LLPARSER-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { +; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], [2 x i16] addrspace(1)* null, i64 [[X]], i64 [[Y]] +; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint i16 addrspace(1)* [[PTR]] to i64 +; LLPARSER-NEXT: ret i64 [[RET]] +; +; INTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars +; INTEGRAL-INSTSIMPLIFY-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { +; INTEGRAL-INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], [2 x i16] addrspace(1)* null, i64 [[X]], i64 [[Y]] +; INTEGRAL-INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint i16 addrspace(1)* [[PTR]] to i64 +; INTEGRAL-INSTSIMPLIFY-NEXT: ret i64 [[RET]] +; +; INTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars +; INTEGRAL-INSTCOMBINE-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { +; INTEGRAL-INSTCOMBINE-NEXT: [[TMP1:%.*]] = shl i64 [[Y]], 1 +; INTEGRAL-INSTCOMBINE-NEXT: [[TMP2:%.*]] = shl i64 [[X]], 2 +; INTEGRAL-INSTCOMBINE-NEXT: [[TMP3:%.*]] = add i64 [[TMP1]], [[TMP2]] +; INTEGRAL-INSTCOMBINE-NEXT: ret i64 [[TMP3]] +; +; NONINTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars +; NONINTEGRAL-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { +; NONINTEGRAL-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], [2 x i16] addrspace(1)* null, i64 [[X]], i64 [[Y]] +; NONINTEGRAL-NEXT: [[RET:%.*]] = ptrtoint i16 addrspace(1)* [[PTR]] to i64 +; NONINTEGRAL-NEXT: ret i64 [[RET]] ; %ptr = getelementptr [2 x i16], [2 x i16] addrspace(1)* null, i64 %x, i64 %y @@ -528,13 +547,32 @@ ret i64 %ret } -; Negative test -- should not be folded since there are two variable indices and a zero constant +; Can be folded since there are two variable indices and a zero constant define i64 @fold_ptrtoint_nested_array_two_vars_plus_zero(i64 %x, i64 %y) { -; ALL-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero -; ALL-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { -; ALL-NEXT: [[PTR:%.*]] = getelementptr [2 x [2 x i16]], [2 x [2 x i16]] addrspace(1)* null, i64 [[X]], i64 [[Y]], i64 0 -; ALL-NEXT: [[RET:%.*]] = ptrtoint i16 addrspace(1)* [[PTR]] to i64 -; ALL-NEXT: ret i64 [[RET]] +; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero +; LLPARSER-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { +; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr [2 x [2 x i16]], [2 x [2 x i16]] addrspace(1)* null, i64 [[X]], i64 [[Y]], i64 0 +; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint i16 addrspace(1)* [[PTR]] to i64 +; LLPARSER-NEXT: ret i64 [[RET]] +; +; INTEGRAL-INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero +; INTEGRAL-INSTSIMPLIFY-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { +; INTEGRAL-INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr [2 x [2 x i16]], [2 x [2 x i16]] addrspace(1)* null, i64 [[X]], i64 [[Y]], i64 0 +; INTEGRAL-INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint i16 addrspace(1)* [[PTR]] to i64 +; INTEGRAL-INSTSIMPLIFY-NEXT: ret i64 [[RET]] +; +; INTEGRAL-INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero +; INTEGRAL-INSTCOMBINE-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { +; INTEGRAL-INSTCOMBINE-NEXT: [[TMP1:%.*]] = shl i64 [[Y]], 2 +; INTEGRAL-INSTCOMBINE-NEXT: [[TMP2:%.*]] = shl i64 [[X]], 3 +; INTEGRAL-INSTCOMBINE-NEXT: [[TMP3:%.*]] = add i64 [[TMP1]], [[TMP2]] +; INTEGRAL-INSTCOMBINE-NEXT: ret i64 [[TMP3]] +; +; NONINTEGRAL-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero +; NONINTEGRAL-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) { +; NONINTEGRAL-NEXT: [[PTR:%.*]] = getelementptr [2 x [2 x i16]], [2 x [2 x i16]] addrspace(1)* null, i64 [[X]], i64 [[Y]], i64 0 +; NONINTEGRAL-NEXT: [[RET:%.*]] = ptrtoint i16 addrspace(1)* [[PTR]] to i64 +; NONINTEGRAL-NEXT: ret i64 [[RET]] ; %ptr = getelementptr [2 x [2 x i16]], [2 x [2 x i16]] addrspace(1)* null, i64 %x, i64 %y, i64 0 %ret = ptrtoint i16 addrspace(1)* %ptr to i64