642 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes2; Check that we can fold operations with (gep null) inputs.3; Note: the LLParser already does some constant folding, check that output first:4; RUN: opt -passes=verify -S < %s | FileCheck %s --check-prefixes=ALL,LLPARSER5; We should be able to fold almost everything in InstSimplify other than the final test which requries InstCombine6; RUN: opt -S -passes=instsimplify < %s | FileCheck %s --check-prefixes=ALL,CHECK,INSTSIMPLIFY7; RUN: opt -S -passes=instcombine < %s | FileCheck %s --check-prefixes=ALL,CHECK,INSTCOMBINE8; Non-integral pointers limit certain transformations on pointers:9; RUN: sed -e 's/p:64:64:64:64/p:64:64:64:64-ni:1/g' %s | opt -S -passes=instsimplify | \10; RUN: FileCheck %s --check-prefixes=ALL,CHECK,INSTSIMPLIFY11; RUN: sed -e 's/p:64:64:64:64/p:64:64:64:64-ni:1/g' %s | opt -S -passes=instcombine | \12; RUN: FileCheck %s --check-prefixes=ALL,CHECK,INSTCOMBINE13target datalayout = "p:64:64:64:64"14 15declare void @use_i64(i64)16declare void @use_ptr(ptr addrspace(1))17 18define i64 @constant_fold_ptrtoint_gep_zero() {19; ALL-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_zero() {20; ALL-NEXT: ret i64 021;22 ret i64 ptrtoint (ptr addrspace(1) null to i64)23}24define i64 @constant_fold_ptrtoint_gep_nonzero() {25; LLPARSER-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {26; LLPARSER-NEXT: ret i64 ptrtoint (ptr addrspace(1) getelementptr (i32, ptr addrspace(1) null, i64 1234) to i64)27;28; INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {29; INSTSIMPLIFY-NEXT: ret i64 ptrtoint (ptr addrspace(1) getelementptr (i32, ptr addrspace(1) null, i64 1234) to i64)30;31; INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero() {32; INSTCOMBINE-NEXT: ret i64 493633;34 ret i64 ptrtoint (ptr addrspace(1) getelementptr (i32, ptr addrspace(1) null, i64 1234) to i64)35}36 37define i64 @constant_fold_ptrtoint_gep_zero_inbounds() {38; ALL-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_zero_inbounds() {39; ALL-NEXT: ret i64 040;41 ret i64 ptrtoint (ptr addrspace(1) null to i64)42}43 44; In theory we could fold this to poison/null, but that would break offsetof45; implementations that don't use __builtin_offsetof.46; TODO: should Clang special case ((INTEGER)&((TYPE *)0)->MEMBER) to emit a non-inbounds GEP?47define i64 @constant_fold_ptrtoint_gep_nonzero_inbounds() {48; LLPARSER-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {49; LLPARSER-NEXT: ret i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i32, ptr addrspace(1) null, i64 1234) to i64)50;51; INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {52; INSTSIMPLIFY-NEXT: ret i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i32, ptr addrspace(1) null, i64 1234) to i64)53;54; INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_gep_nonzero_inbounds() {55; INSTCOMBINE-NEXT: ret i64 493656;57 ret i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i32, ptr addrspace(1) null, i64 1234) to i64)58}59 60; Check all combinations of inbounds+non-inbounds GEP with the outer GEP having a non-zero offset61define void @constant_fold_ptrtoint_of_gep_of_nullgep() {62; LLPARSER-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {63; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))64; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))65; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))66; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))67; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))68; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))69; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))70; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))71; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))72; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))73; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))74; LLPARSER-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))75; LLPARSER-NEXT: ret void76;77; INSTSIMPLIFY-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {78; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))79; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))80; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))81; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))82; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))83; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))84; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))85; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))86; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))87; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))88; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))89; INSTSIMPLIFY-NEXT: call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))90; INSTSIMPLIFY-NEXT: ret void91;92; INSTCOMBINE-LABEL: define {{[^@]+}}@constant_fold_ptrtoint_of_gep_of_nullgep() {93; INSTCOMBINE-NEXT: call void @use_i64(i64 1234)94; INSTCOMBINE-NEXT: call void @use_i64(i64 1234)95; INSTCOMBINE-NEXT: call void @use_i64(i64 1234)96; INSTCOMBINE-NEXT: call void @use_i64(i64 1234)97; INSTCOMBINE-NEXT: call void @use_i64(i64 1234)98; INSTCOMBINE-NEXT: call void @use_i64(i64 1234)99; INSTCOMBINE-NEXT: call void @use_i64(i64 1234)100; INSTCOMBINE-NEXT: call void @use_i64(i64 1234)101; INSTCOMBINE-NEXT: call void @use_i64(i64 0)102; INSTCOMBINE-NEXT: call void @use_i64(i64 0)103; INSTCOMBINE-NEXT: call void @use_i64(i64 0)104; INSTCOMBINE-NEXT: call void @use_i64(i64 0)105; INSTCOMBINE-NEXT: ret void106;107 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))108 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))109 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234) to i64))110 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234) to i64))111 ; Same again but this time with the inner GEP using the non-zero offset112 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234), i64 0) to i64))113 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 1234), i64 0) to i64))114 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234), i64 0) to i64))115 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 1234), i64 0) to i64))116 ; And finally with two constants that sum to zero117 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))118 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))119 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))120 call void @use_i64(i64 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i64 -1), i64 1) to i64))121 ret void122}123 124; Another set of tests for instructions instead of constants125define i64 @fold_ptrtoint_nullgep_zero() {126; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_zero() {127; LLPARSER-NEXT: [[OFFSET:%.*]] = add i64 0, 0128; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[OFFSET]]129; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64130; LLPARSER-NEXT: ret i64 [[RET]]131;132; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_zero() {133; CHECK-NEXT: ret i64 0134;135 %offset = add i64 0, 0136 %ptr = getelementptr i8, ptr addrspace(1) null, i64 %offset137 %ret = ptrtoint ptr addrspace(1) %ptr to i64138 ret i64 %ret139}140 141define i64 @fold_ptrtoint_nullgep_zero_inbounds() {142; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_zero_inbounds() {143; LLPARSER-NEXT: [[OFFSET:%.*]] = add i64 0, 0144; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[OFFSET]]145; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64146; LLPARSER-NEXT: ret i64 [[RET]]147;148; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_zero_inbounds() {149; CHECK-NEXT: ret i64 0150;151 %offset = add i64 0, 0152 %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %offset153 %ret = ptrtoint ptr addrspace(1) %ptr to i64154 ret i64 %ret155}156 157define i64 @fold_ptrtoint_nullgep_nonzero() {158; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero() {159; LLPARSER-NEXT: [[OFFSET:%.*]] = add i64 1234, 0160; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[OFFSET]]161; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64162; LLPARSER-NEXT: ret i64 [[RET]]163;164; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero() {165; CHECK-NEXT: ret i64 1234166;167 %offset = add i64 1234, 0168 %ptr = getelementptr i8, ptr addrspace(1) null, i64 %offset169 %ret = ptrtoint ptr addrspace(1) %ptr to i64170 ret i64 %ret171}172 173; Inbounds constant null-GEP with non-zero could be constant-folded to null/poison,174; but folding it to the value makes ((INTEGER)&((TYPE *)0)->MEMBER) work.175define i64 @fold_ptrtoint_nullgep_nonzero_inbounds() {176; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero_inbounds() {177; LLPARSER-NEXT: [[OFFSET:%.*]] = add i64 1234, 0178; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[OFFSET]]179; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64180; LLPARSER-NEXT: ret i64 [[RET]]181;182; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_nonzero_inbounds() {183; CHECK-NEXT: ret i64 1234184;185 %offset = add i64 1234, 0186 %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %offset187 %ret = ptrtoint ptr addrspace(1) %ptr to i64188 ret i64 %ret189}190 191; We should be able to fold ptrtoint(gep null, x) to x192define i64 @fold_ptrtoint_nullgep_variable(i64 %val) {193; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable194; LLPARSER-SAME: (i64 [[VAL:%.*]]) {195; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[VAL]]196; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64197; LLPARSER-NEXT: ret i64 [[RET]]198;199; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable200; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {201; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[VAL]]202; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64203; INSTSIMPLIFY-NEXT: ret i64 [[RET]]204;205; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable206; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {207; INSTCOMBINE-NEXT: ret i64 [[VAL]]208;209 %ptr = getelementptr i8, ptr addrspace(1) null, i64 %val210 %ret = ptrtoint ptr addrspace(1) %ptr to i64211 ret i64 %ret212}213 214; Inbounds null-GEP with non-zero offset could be folded to poison/null.215define i64 @fold_ptrtoint_nullgep_variable_known_nonzero(i64 %val) {216; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero217; LLPARSER-SAME: (i64 [[VAL:%.*]]) {218; LLPARSER-NEXT: [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1219; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]]220; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64221; LLPARSER-NEXT: ret i64 [[RET]]222;223; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero224; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {225; INSTSIMPLIFY-NEXT: [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1226; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]]227; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64228; INSTSIMPLIFY-NEXT: ret i64 [[RET]]229;230; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero231; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {232; INSTCOMBINE-NEXT: [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1233; INSTCOMBINE-NEXT: ret i64 [[NON_ZERO_OFFSET]]234;235 %non_zero_offset = or i64 %val, 1236 %ptr = getelementptr i8, ptr addrspace(1) null, i64 %non_zero_offset237 %ret = ptrtoint ptr addrspace(1) %ptr to i64238 ret i64 %ret239}240 241; This is only valid if %val is zero so we could fold the result to 0.242define i64 @fold_ptrtoint_nullgep_variable_inbounds(i64 %val) {243; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_inbounds244; LLPARSER-SAME: (i64 [[VAL:%.*]]) {245; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[VAL]]246; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64247; LLPARSER-NEXT: ret i64 [[RET]]248;249; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_inbounds250; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {251; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[VAL]]252; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64253; INSTSIMPLIFY-NEXT: ret i64 [[RET]]254;255; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_inbounds256; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {257; INSTCOMBINE-NEXT: ret i64 [[VAL]]258;259 %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %val260 %ret = ptrtoint ptr addrspace(1) %ptr to i64261 ret i64 %ret262}263 264; A non-constant but known-non-zero GEP could be folded to poison/null265define i64 @fold_ptrtoint_nullgep_variable_known_nonzero_inbounds(i64 %val) {266; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds267; LLPARSER-SAME: (i64 [[VAL:%.*]]) {268; LLPARSER-NEXT: [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1269; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]]270; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64271; LLPARSER-NEXT: ret i64 [[RET]]272;273; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds274; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {275; INSTSIMPLIFY-NEXT: [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1276; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]]277; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64278; INSTSIMPLIFY-NEXT: ret i64 [[RET]]279;280; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds281; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {282; INSTCOMBINE-NEXT: [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1283; INSTCOMBINE-NEXT: ret i64 [[NON_ZERO_OFFSET]]284;285 %non_zero_offset = or i64 %val, 1286 %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %non_zero_offset287 %ret = ptrtoint ptr addrspace(1) %ptr to i64288 ret i64 %ret289}290 291; A non-constant but known-non-zero GEP could be folded to poison/null292define i64 @fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices(i64 %val) {293; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices294; LLPARSER-SAME: (i64 [[VAL:%.*]]) {295; LLPARSER-NEXT: [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1296; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr inbounds [2 x i8], ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]], i32 1297; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64298; LLPARSER-NEXT: ret i64 [[RET]]299;300; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices301; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {302; INSTSIMPLIFY-NEXT: [[NON_ZERO_OFFSET:%.*]] = or i64 [[VAL]], 1303; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr inbounds [2 x i8], ptr addrspace(1) null, i64 [[NON_ZERO_OFFSET]], i32 1304; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64305; INSTSIMPLIFY-NEXT: ret i64 [[RET]]306;307; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_known_nonzero_inbounds_multiple_indices308; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {309; INSTCOMBINE-NEXT: [[NON_ZERO_OFFSET:%.*]] = shl i64 [[VAL]], 1310; INSTCOMBINE-NEXT: [[RET:%.*]] = or i64 [[NON_ZERO_OFFSET]], 3311; INSTCOMBINE-NEXT: ret i64 [[RET]]312;313 %non_zero_offset = or i64 %val, 1314 %ptr = getelementptr inbounds [2 x i8], ptr addrspace(1) null, i64 %non_zero_offset, i32 1315 %ret = ptrtoint ptr addrspace(1) %ptr to i64316 ret i64 %ret317}318 319; We can't fold non-i8 GEPs in InstSimplify since that would require adding new arithmetic.320; However, InstCombine can decompose the null gep and convert it to a shift.321define i64 @fold_ptrtoint_nullgep_i32_variable(i64 %val) {322; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_i32_variable323; LLPARSER-SAME: (i64 [[VAL:%.*]]) {324; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr i32, ptr addrspace(1) null, i64 [[VAL]]325; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64326; LLPARSER-NEXT: ret i64 [[RET]]327;328; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_i32_variable329; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {330; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr i32, ptr addrspace(1) null, i64 [[VAL]]331; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64332; INSTSIMPLIFY-NEXT: ret i64 [[RET]]333;334; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_i32_variable335; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {336; INSTCOMBINE-NEXT: [[PTR_IDX:%.*]] = shl i64 [[VAL]], 2337; INSTCOMBINE-NEXT: ret i64 [[PTR_IDX]]338;339 %ptr = getelementptr i32, ptr addrspace(1) null, i64 %val340 %ret = ptrtoint ptr addrspace(1) %ptr to i64341 ret i64 %ret342}343 344; ptrtoint type does not match index type so requires requite a new trunc instruction345define i32 @fold_ptrtoint_nullgep_variable_trunc(i64 %val) {346; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc347; LLPARSER-SAME: (i64 [[VAL:%.*]]) {348; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[VAL]]349; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i32350; LLPARSER-NEXT: ret i32 [[RET]]351;352; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc353; INSTSIMPLIFY-SAME: (i64 [[VAL:%.*]]) {354; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[VAL]]355; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i32356; INSTSIMPLIFY-NEXT: ret i32 [[RET]]357;358; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_variable_trunc359; INSTCOMBINE-SAME: (i64 [[VAL:%.*]]) {360; INSTCOMBINE-NEXT: [[RET:%.*]] = trunc i64 [[VAL]] to i32361; INSTCOMBINE-NEXT: ret i32 [[RET]]362;363 %ptr = getelementptr i8, ptr addrspace(1) null, i64 %val364 %ret = ptrtoint ptr addrspace(1) %ptr to i32365 ret i32 %ret366}367 368; For the following three tests, we could fold the result to poison/null since there is at least369; one inbounds GEP on null with a non-zero offset.370define i64 @fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {371; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {372; LLPARSER-NEXT: [[NONZERO_OFFSET:%.*]] = add i64 1234, 0373; LLPARSER-NEXT: [[ZERO_OFFSET:%.*]] = sub i64 [[NONZERO_OFFSET]], 1234374; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[NONZERO_OFFSET]]375; LLPARSER-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr addrspace(1) [[PTR]], i64 [[ZERO_OFFSET]]376; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR2]] to i64377; LLPARSER-NEXT: ret i64 [[RET]]378;379; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_zero_nullgep_of_nonzero_inbounds_nullgep() {380; CHECK-NEXT: ret i64 1234381;382 %nonzero_offset = add i64 1234, 0383 %zero_offset = sub i64 %nonzero_offset, 1234384 %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %nonzero_offset385 %ptr2 = getelementptr i8, ptr addrspace(1) %ptr, i64 %zero_offset386 %ret = ptrtoint ptr addrspace(1) %ptr2 to i64387 ret i64 %ret388}389 390define i64 @fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep() {391; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep() {392; LLPARSER-NEXT: [[NONZERO_OFFSET:%.*]] = add i64 1234, 0393; LLPARSER-NEXT: [[ZERO_OFFSET:%.*]] = sub i64 [[NONZERO_OFFSET]], 1234394; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(1) null, i64 [[ZERO_OFFSET]]395; LLPARSER-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[PTR]], i64 [[NONZERO_OFFSET]]396; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR2]] to i64397; LLPARSER-NEXT: ret i64 [[RET]]398;399; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_nonzero_inbounds_nullgep_of_zero_noninbounds_nullgep() {400; CHECK-NEXT: ret i64 1234401;402 %nonzero_offset = add i64 1234, 0403 %zero_offset = sub i64 %nonzero_offset, 1234404 %ptr = getelementptr i8, ptr addrspace(1) null, i64 %zero_offset405 %ptr2 = getelementptr inbounds i8, ptr addrspace(1) %ptr, i64 %nonzero_offset406 %ret = ptrtoint ptr addrspace(1) %ptr2 to i64407 ret i64 %ret408}409 410; We should also be able to fold GEPs with multiple indices.411%struct.S = type { [2 x %struct.K] }412%struct.K = type { [32 x i8] }413 414define i64 @fold_complex_index_last_nonzero(i64 %x) local_unnamed_addr #0 {415; LLPARSER-LABEL: define {{[^@]+}}@fold_complex_index_last_nonzero416; LLPARSER-SAME: (i64 [[X:%.*]]) local_unnamed_addr {417; LLPARSER-NEXT: entry:418; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr addrspace(1) null, i64 0, i32 0, i64 0, i32 0, i64 [[X]]419; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64420; LLPARSER-NEXT: ret i64 [[RET]]421;422; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_complex_index_last_nonzero423; INSTSIMPLIFY-SAME: (i64 [[X:%.*]]) local_unnamed_addr {424; INSTSIMPLIFY-NEXT: entry:425; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr addrspace(1) null, i64 0, i32 0, i64 0, i32 0, i64 [[X]]426; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64427; INSTSIMPLIFY-NEXT: ret i64 [[RET]]428;429; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_complex_index_last_nonzero430; INSTCOMBINE-SAME: (i64 [[X:%.*]]) local_unnamed_addr {431; INSTCOMBINE-NEXT: entry:432; INSTCOMBINE-NEXT: ret i64 [[X]]433;434entry:435 %ptr = getelementptr inbounds %struct.S, ptr addrspace(1) null, i64 0, i32 0, i64 0, i32 0, i64 %x436 %ret = ptrtoint ptr addrspace(1) %ptr to i64437 ret i64 %ret438}439 440define i64 @fold_complex_index_multiple_nonzero(i64 %x) local_unnamed_addr #0 {441; LLPARSER-LABEL: define {{[^@]+}}@fold_complex_index_multiple_nonzero442; LLPARSER-SAME: (i64 [[X:%.*]]) local_unnamed_addr {443; LLPARSER-NEXT: entry:444; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr addrspace(1) null, i64 1, i32 0, i64 1, i32 0, i64 [[X]]445; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64446; LLPARSER-NEXT: ret i64 [[RET]]447;448; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_complex_index_multiple_nonzero449; INSTSIMPLIFY-SAME: (i64 [[X:%.*]]) local_unnamed_addr {450; INSTSIMPLIFY-NEXT: entry:451; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr addrspace(1) null, i64 1, i32 0, i64 1, i32 0, i64 [[X]]452; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64453; INSTSIMPLIFY-NEXT: ret i64 [[RET]]454;455; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_complex_index_multiple_nonzero456; INSTCOMBINE-SAME: (i64 [[X:%.*]]) local_unnamed_addr {457; INSTCOMBINE-NEXT: entry:458; INSTCOMBINE-NEXT: [[RET:%.*]] = add i64 [[X]], 96459; INSTCOMBINE-NEXT: ret i64 [[RET]]460;461entry:462 %ptr = getelementptr inbounds %struct.S, ptr addrspace(1) null, i64 1, i32 0, i64 1, i32 0, i64 %x463 %ret = ptrtoint ptr addrspace(1) %ptr to i64464 ret i64 %ret465}466 467define i64 @fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {468; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {469; LLPARSER-NEXT: [[NONZERO_OFFSET:%.*]] = add i64 1234, 0470; LLPARSER-NEXT: [[ZERO_OFFSET:%.*]] = sub i64 [[NONZERO_OFFSET]], 1234471; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr inbounds i8, ptr addrspace(1) null, i64 [[NONZERO_OFFSET]]472; LLPARSER-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[PTR]], i64 [[ZERO_OFFSET]]473; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR2]] to i64474; LLPARSER-NEXT: ret i64 [[RET]]475;476; CHECK-LABEL: define {{[^@]+}}@fold_ptrtoint_inbounds_nullgep_of_nonzero_inbounds_nullgep() {477; CHECK-NEXT: ret i64 1234478;479 %nonzero_offset = add i64 1234, 0480 %zero_offset = sub i64 %nonzero_offset, 1234481 %ptr = getelementptr inbounds i8, ptr addrspace(1) null, i64 %nonzero_offset482 %ptr2 = getelementptr inbounds i8, ptr addrspace(1) %ptr, i64 %zero_offset483 %ret = ptrtoint ptr addrspace(1) %ptr2 to i64484 ret i64 %ret485}486 487; Check that InstCombine can convert ptrtoint(gep null) with multiple indices488define i64 @fold_ptrtoint_nullgep_array_one_var_1(i64 %x) {489; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_1490; LLPARSER-SAME: (i64 [[X:%.*]]) {491; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 3492; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64493; LLPARSER-NEXT: ret i64 [[RET]]494;495; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_1496; INSTSIMPLIFY-SAME: (i64 [[X:%.*]]) {497; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 3498; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64499; INSTSIMPLIFY-NEXT: ret i64 [[RET]]500;501; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_1502; INSTCOMBINE-SAME: (i64 [[X:%.*]]) {503; INSTCOMBINE-NEXT: [[PTR_SPLIT_IDX:%.*]] = shl i64 [[X]], 2504; INSTCOMBINE-NEXT: [[RET:%.*]] = add i64 [[PTR_SPLIT_IDX]], 6505; INSTCOMBINE-NEXT: ret i64 [[RET]]506;507 %ptr = getelementptr [2 x i16], ptr addrspace(1) null, i64 %x, i64 3508 %ret = ptrtoint ptr addrspace(1) %ptr to i64509 ret i64 %ret510}511 512define i64 @fold_ptrtoint_nullgep_array_one_var_2(i64 %x) {513; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_2514; LLPARSER-SAME: (i64 [[X:%.*]]) {515; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 7, i64 [[X]]516; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64517; LLPARSER-NEXT: ret i64 [[RET]]518;519; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_2520; INSTSIMPLIFY-SAME: (i64 [[X:%.*]]) {521; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 7, i64 [[X]]522; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64523; INSTSIMPLIFY-NEXT: ret i64 [[RET]]524;525; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nullgep_array_one_var_2526; INSTCOMBINE-SAME: (i64 [[X:%.*]]) {527; INSTCOMBINE-NEXT: [[PTR_IDX:%.*]] = shl i64 [[X]], 1528; INSTCOMBINE-NEXT: [[RET:%.*]] = add i64 [[PTR_IDX]], 28529; INSTCOMBINE-NEXT: ret i64 [[RET]]530;531 %ptr = getelementptr [2 x i16], ptr addrspace(1) null, i64 7, i64 %x532 %ret = ptrtoint ptr addrspace(1) %ptr to i64533 ret i64 %ret534}535 536define i64 @fold_ptrtoint_nested_array_two_vars(i64 %x, i64 %y) {537; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars538; LLPARSER-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {539; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 [[Y]]540; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64541; LLPARSER-NEXT: ret i64 [[RET]]542;543; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars544; INSTSIMPLIFY-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {545; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 [[Y]]546; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64547; INSTSIMPLIFY-NEXT: ret i64 [[RET]]548;549; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars550; INSTCOMBINE-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {551; INSTCOMBINE-NEXT: [[PTR_SPLIT_IDX:%.*]] = shl i64 [[X]], 2552; INSTCOMBINE-NEXT: [[PTR_IDX:%.*]] = shl i64 [[Y]], 1553; INSTCOMBINE-NEXT: [[RET:%.*]] = add i64 [[PTR_SPLIT_IDX]], [[PTR_IDX]]554; INSTCOMBINE-NEXT: ret i64 [[RET]]555;556 557 %ptr = getelementptr [2 x i16], ptr addrspace(1) null, i64 %x, i64 %y558 %ret = ptrtoint ptr addrspace(1) %ptr to i64559 ret i64 %ret560}561 562define i64 @fold_ptrtoint_nested_array_two_vars_plus_zero(i64 %x, i64 %y) {563; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero564; LLPARSER-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {565; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 [[X]], i64 [[Y]], i64 0566; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64567; LLPARSER-NEXT: ret i64 [[RET]]568;569; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero570; INSTSIMPLIFY-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {571; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 [[X]], i64 [[Y]], i64 0572; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64573; INSTSIMPLIFY-NEXT: ret i64 [[RET]]574;575; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_zero576; INSTCOMBINE-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {577; INSTCOMBINE-NEXT: [[PTR_SPLIT_IDX:%.*]] = shl i64 [[X]], 3578; INSTCOMBINE-NEXT: [[PTR_IDX:%.*]] = shl i64 [[Y]], 2579; INSTCOMBINE-NEXT: [[RET:%.*]] = add i64 [[PTR_SPLIT_IDX]], [[PTR_IDX]]580; INSTCOMBINE-NEXT: ret i64 [[RET]]581;582 %ptr = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 %x, i64 %y, i64 0583 %ret = ptrtoint ptr addrspace(1) %ptr to i64584 ret i64 %ret585}586 587define i64 @fold_ptrtoint_nested_array_two_vars_plus_const(i64 %x, i64 %y) {588; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_const589; LLPARSER-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {590; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 [[X]], i64 [[Y]], i64 1591; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64592; LLPARSER-NEXT: ret i64 [[RET]]593;594; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_const595; INSTSIMPLIFY-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {596; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 [[X]], i64 [[Y]], i64 1597; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64598; INSTSIMPLIFY-NEXT: ret i64 [[RET]]599;600; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_array_two_vars_plus_const601; INSTCOMBINE-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {602; INSTCOMBINE-NEXT: [[PTR_SPLIT_IDX:%.*]] = shl i64 [[X]], 3603; INSTCOMBINE-NEXT: [[PTR_SPLIT1_IDX:%.*]] = shl i64 [[Y]], 2604; INSTCOMBINE-NEXT: [[TMP1:%.*]] = add i64 [[PTR_SPLIT_IDX]], [[PTR_SPLIT1_IDX]]605; INSTCOMBINE-NEXT: [[RET:%.*]] = or disjoint i64 [[TMP1]], 2606; INSTCOMBINE-NEXT: ret i64 [[RET]]607;608 %ptr = getelementptr [2 x [2 x i16]], ptr addrspace(1) null, i64 %x, i64 %y, i64 1609 %ret = ptrtoint ptr addrspace(1) %ptr to i64610 ret i64 %ret611}612 613; Negative test -- should not be folded since there are multiple GEP uses614define i64 @fold_ptrtoint_nested_nullgep_array_variable_multiple_uses(i64 %x, i64 %y) {615; LLPARSER-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_nullgep_array_variable_multiple_uses616; LLPARSER-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {617; LLPARSER-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 [[Y]]618; LLPARSER-NEXT: call void @use_ptr(ptr addrspace(1) [[PTR]])619; LLPARSER-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64620; LLPARSER-NEXT: ret i64 [[RET]]621;622; INSTSIMPLIFY-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_nullgep_array_variable_multiple_uses623; INSTSIMPLIFY-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {624; INSTSIMPLIFY-NEXT: [[PTR:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]], i64 [[Y]]625; INSTSIMPLIFY-NEXT: call void @use_ptr(ptr addrspace(1) [[PTR]])626; INSTSIMPLIFY-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64627; INSTSIMPLIFY-NEXT: ret i64 [[RET]]628;629; INSTCOMBINE-LABEL: define {{[^@]+}}@fold_ptrtoint_nested_nullgep_array_variable_multiple_uses630; INSTCOMBINE-SAME: (i64 [[X:%.*]], i64 [[Y:%.*]]) {631; INSTCOMBINE-NEXT: [[PTR_SPLIT:%.*]] = getelementptr [2 x i16], ptr addrspace(1) null, i64 [[X]]632; INSTCOMBINE-NEXT: [[PTR:%.*]] = getelementptr i16, ptr addrspace(1) [[PTR_SPLIT]], i64 [[Y]]633; INSTCOMBINE-NEXT: call void @use_ptr(ptr addrspace(1) [[PTR]])634; INSTCOMBINE-NEXT: [[RET:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64635; INSTCOMBINE-NEXT: ret i64 [[RET]]636;637 %ptr = getelementptr [2 x i16], ptr addrspace(1) null, i64 %x, i64 %y638 call void @use_ptr(ptr addrspace(1) %ptr)639 %ret = ptrtoint ptr addrspace(1) %ptr to i64640 ret i64 %ret641}642