312 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 62; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4; The ptrtoaddr folds are also valid for pointers that have external state.5target datalayout = "pe1:64:64:64:32"6 7declare void @use.i1(i1)8declare void @use.i32(i32)9declare void @use.i64(i64)10 11; ptrtoaddr result type is fixed, and can't be combined with integer cast.12define i32 @ptrtoaddr_trunc(ptr %p) {13; CHECK-LABEL: define i32 @ptrtoaddr_trunc(14; CHECK-SAME: ptr [[P:%.*]]) {15; CHECK-NEXT: [[P_ADDR:%.*]] = ptrtoaddr ptr [[P]] to i6416; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[P_ADDR]] to i3217; CHECK-NEXT: ret i32 [[TRUNC]]18;19 %p.addr = ptrtoaddr ptr %p to i6420 %trunc = trunc i64 %p.addr to i3221 ret i32 %trunc22}23 24define i128 @ptrtoaddr_zext(ptr %p) {25; CHECK-LABEL: define i128 @ptrtoaddr_zext(26; CHECK-SAME: ptr [[P:%.*]]) {27; CHECK-NEXT: [[P_ADDR:%.*]] = ptrtoaddr ptr [[P]] to i6428; CHECK-NEXT: [[EXT:%.*]] = zext i64 [[P_ADDR]] to i12829; CHECK-NEXT: ret i128 [[EXT]]30;31 %p.addr = ptrtoaddr ptr %p to i6432 %ext = zext i64 %p.addr to i12833 ret i128 %ext34}35 36define i128 @ptrtoaddr_sext(ptr %p) {37; CHECK-LABEL: define i128 @ptrtoaddr_sext(38; CHECK-SAME: ptr [[P:%.*]]) {39; CHECK-NEXT: [[P_ADDR:%.*]] = ptrtoaddr ptr [[P]] to i6440; CHECK-NEXT: [[EXT:%.*]] = sext i64 [[P_ADDR]] to i12841; CHECK-NEXT: ret i128 [[EXT]]42;43 %p.addr = ptrtoaddr ptr %p to i6444 %ext = sext i64 %p.addr to i12845 ret i128 %ext46}47 48define i64 @sub_ptrtoaddr(ptr %p, i64 %offset) {49; CHECK-LABEL: define i64 @sub_ptrtoaddr(50; CHECK-SAME: ptr [[P:%.*]], i64 [[OFFSET:%.*]]) {51; CHECK-NEXT: ret i64 [[OFFSET]]52;53 %p2 = getelementptr i8, ptr %p, i64 %offset54 %p.addr = ptrtoaddr ptr %p to i6455 %p2.addr = ptrtoaddr ptr %p2 to i6456 %sub = sub i64 %p2.addr, %p.addr57 ret i64 %sub58}59 60define i64 @sub_ptrtoint_ptrtoaddr(ptr %p, i64 %offset) {61; CHECK-LABEL: define i64 @sub_ptrtoint_ptrtoaddr(62; CHECK-SAME: ptr [[P:%.*]], i64 [[OFFSET:%.*]]) {63; CHECK-NEXT: ret i64 [[OFFSET]]64;65 %p2 = getelementptr i8, ptr %p, i64 %offset66 %p.int = ptrtoint ptr %p to i6467 %p2.addr = ptrtoaddr ptr %p2 to i6468 %sub = sub i64 %p2.addr, %p.int69 ret i64 %sub70}71 72define i32 @sub_ptrtoaddr_addrsize(ptr addrspace(1) %p, i32 %offset) {73; CHECK-LABEL: define i32 @sub_ptrtoaddr_addrsize(74; CHECK-SAME: ptr addrspace(1) [[P:%.*]], i32 [[OFFSET:%.*]]) {75; CHECK-NEXT: ret i32 [[OFFSET]]76;77 %p2 = getelementptr i8, ptr addrspace(1) %p, i32 %offset78 %p.addr = ptrtoaddr ptr addrspace(1) %p to i3279 %p2.addr = ptrtoaddr ptr addrspace(1) %p2 to i3280 %sub = sub i32 %p2.addr, %p.addr81 ret i32 %sub82}83 84define i32 @sub_trunc_ptrtoaddr(ptr %p, i64 %offset) {85; CHECK-LABEL: define i32 @sub_trunc_ptrtoaddr(86; CHECK-SAME: ptr [[P:%.*]], i64 [[OFFSET:%.*]]) {87; CHECK-NEXT: [[SUB:%.*]] = trunc i64 [[OFFSET]] to i3288; CHECK-NEXT: ret i32 [[SUB]]89;90 %p2 = getelementptr i8, ptr %p, i64 %offset91 %p.addr = ptrtoaddr ptr %p to i6492 %p2.addr = ptrtoaddr ptr %p2 to i6493 %p.addr.trunc = trunc i64 %p.addr to i3294 %p2.addr.trunc = trunc i64 %p2.addr to i3295 %sub = sub i32 %p2.addr.trunc, %p.addr.trunc96 ret i32 %sub97}98 99define i16 @sub_trunc_ptrtoaddr_addrsize(ptr addrspace(1) %p, i32 %offset) {100; CHECK-LABEL: define i16 @sub_trunc_ptrtoaddr_addrsize(101; CHECK-SAME: ptr addrspace(1) [[P:%.*]], i32 [[OFFSET:%.*]]) {102; CHECK-NEXT: [[SUB:%.*]] = trunc i32 [[OFFSET]] to i16103; CHECK-NEXT: ret i16 [[SUB]]104;105 %p2 = getelementptr i8, ptr addrspace(1) %p, i32 %offset106 %p.addr = ptrtoaddr ptr addrspace(1) %p to i32107 %p2.addr = ptrtoaddr ptr addrspace(1) %p2 to i32108 %p.addr.trunc = trunc i32 %p.addr to i16109 %p2.addr.trunc = trunc i32 %p2.addr to i16110 %sub = sub i16 %p2.addr.trunc, %p.addr.trunc111 ret i16 %sub112}113 114define i16 @sub_trunc_ptrtoint_ptrtoaddr_addrsize(ptr addrspace(1) %p, i32 %offset) {115; CHECK-LABEL: define i16 @sub_trunc_ptrtoint_ptrtoaddr_addrsize(116; CHECK-SAME: ptr addrspace(1) [[P:%.*]], i32 [[OFFSET:%.*]]) {117; CHECK-NEXT: [[SUB:%.*]] = trunc i32 [[OFFSET]] to i16118; CHECK-NEXT: ret i16 [[SUB]]119;120 %p2 = getelementptr i8, ptr addrspace(1) %p, i32 %offset121 %p.int = ptrtoint ptr addrspace(1) %p to i64122 %p2.addr = ptrtoaddr ptr addrspace(1) %p2 to i32123 %p.int.trunc = trunc i64 %p.int to i16124 %p2.addr.trunc = trunc i32 %p2.addr to i16125 %sub = sub i16 %p2.addr.trunc, %p.int.trunc126 ret i16 %sub127}128 129define i128 @sub_zext_ptrtoaddr(ptr %p, i64 %offset) {130; CHECK-LABEL: define i128 @sub_zext_ptrtoaddr(131; CHECK-SAME: ptr [[P:%.*]], i64 [[OFFSET:%.*]]) {132; CHECK-NEXT: [[SUB:%.*]] = zext i64 [[OFFSET]] to i128133; CHECK-NEXT: ret i128 [[SUB]]134;135 %p2 = getelementptr nuw i8, ptr %p, i64 %offset136 %p.addr = ptrtoaddr ptr %p to i64137 %p2.addr = ptrtoaddr ptr %p2 to i64138 %p.addr.ext = zext i64 %p.addr to i128139 %p2.addr.ext = zext i64 %p2.addr to i128140 %sub = sub i128 %p2.addr.ext, %p.addr.ext141 ret i128 %sub142}143 144define i64 @sub_zext_ptrtoaddr_addrsize(ptr addrspace(1) %p, i32 %offset) {145; CHECK-LABEL: define i64 @sub_zext_ptrtoaddr_addrsize(146; CHECK-SAME: ptr addrspace(1) [[P:%.*]], i32 [[OFFSET:%.*]]) {147; CHECK-NEXT: [[SUB:%.*]] = zext i32 [[OFFSET]] to i64148; CHECK-NEXT: ret i64 [[SUB]]149;150 %p2 = getelementptr nuw i8, ptr addrspace(1) %p, i32 %offset151 %p.addr = ptrtoaddr ptr addrspace(1) %p to i32152 %p2.addr = ptrtoaddr ptr addrspace(1) %p2 to i32153 %p.addr.ext = zext i32 %p.addr to i64154 %p2.addr.ext = zext i32 %p2.addr to i64155 %sub = sub i64 %p2.addr.ext, %p.addr.ext156 ret i64 %sub157}158 159define i128 @sub_zext_ptrtoint_ptrtoaddr_addrsize(ptr addrspace(1) %p, i32 %offset) {160; CHECK-LABEL: define i128 @sub_zext_ptrtoint_ptrtoaddr_addrsize(161; CHECK-SAME: ptr addrspace(1) [[P:%.*]], i32 [[OFFSET:%.*]]) {162; CHECK-NEXT: [[P2:%.*]] = getelementptr nuw i8, ptr addrspace(1) [[P]], i32 [[OFFSET]]163; CHECK-NEXT: [[P_INT:%.*]] = ptrtoint ptr addrspace(1) [[P]] to i64164; CHECK-NEXT: [[P2_ADDR:%.*]] = ptrtoaddr ptr addrspace(1) [[P2]] to i32165; CHECK-NEXT: [[P_INT_EXT:%.*]] = zext i64 [[P_INT]] to i128166; CHECK-NEXT: [[P2_ADDR_EXT:%.*]] = zext i32 [[P2_ADDR]] to i128167; CHECK-NEXT: [[SUB:%.*]] = sub nsw i128 [[P2_ADDR_EXT]], [[P_INT_EXT]]168; CHECK-NEXT: ret i128 [[SUB]]169;170 %p2 = getelementptr nuw i8, ptr addrspace(1) %p, i32 %offset171 %p.int = ptrtoint ptr addrspace(1) %p to i64172 %p2.addr = ptrtoaddr ptr addrspace(1) %p2 to i32173 %p.int.ext = zext i64 %p.int to i128174 %p2.addr.ext = zext i32 %p2.addr to i128175 %sub = sub i128 %p2.addr.ext, %p.int.ext176 ret i128 %sub177}178 179; The uses in icmp, ptrtoint, ptrtoaddr should be replaced. The one in the180; return value should not, as the provenance differs.181define ptr @gep_sub_ptrtoaddr_different_obj(ptr %p, ptr %p2, ptr %p3) {182; CHECK-LABEL: define ptr @gep_sub_ptrtoaddr_different_obj(183; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) {184; CHECK-NEXT: [[P_ADDR:%.*]] = ptrtoaddr ptr [[P]] to i64185; CHECK-NEXT: [[P2_ADDR:%.*]] = ptrtoaddr ptr [[P2]] to i64186; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[P2_ADDR]], [[P_ADDR]]187; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P]], i64 [[SUB]]188; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P2]], [[P3]]189; CHECK-NEXT: call void @use.i1(i1 [[CMP]])190; CHECK-NEXT: [[INT:%.*]] = ptrtoint ptr [[P2]] to i64191; CHECK-NEXT: call void @use.i64(i64 [[INT]])192; CHECK-NEXT: [[ADDR:%.*]] = ptrtoaddr ptr [[P2]] to i64193; CHECK-NEXT: call void @use.i64(i64 [[ADDR]])194; CHECK-NEXT: ret ptr [[GEP]]195;196 %p.addr = ptrtoaddr ptr %p to i64197 %p2.addr = ptrtoaddr ptr %p2 to i64198 %sub = sub i64 %p2.addr, %p.addr199 %gep = getelementptr i8, ptr %p, i64 %sub200 %cmp = icmp eq ptr %gep, %p3201 call void @use.i1(i1 %cmp)202 %int = ptrtoint ptr %gep to i64203 call void @use.i64(i64 %int)204 %addr = ptrtoaddr ptr %gep to i64205 call void @use.i64(i64 %addr)206 ret ptr %gep207}208 209; The use in ptrtoaddr should be replaced. The uses in ptrtoint and icmp should210; not be replaced, as the non-address bits differ. The use in the return value211; should not be replaced as the provenace differs.212define ptr addrspace(1) @gep_sub_ptrtoaddr_different_obj_addrsize(ptr addrspace(1) %p, ptr addrspace(1) %p2, ptr addrspace(1) %p3) {213; CHECK-LABEL: define ptr addrspace(1) @gep_sub_ptrtoaddr_different_obj_addrsize(214; CHECK-SAME: ptr addrspace(1) [[P:%.*]], ptr addrspace(1) [[P2:%.*]], ptr addrspace(1) [[P3:%.*]]) {215; CHECK-NEXT: [[P_ADDR:%.*]] = ptrtoaddr ptr addrspace(1) [[P]] to i32216; CHECK-NEXT: [[P2_ADDR:%.*]] = ptrtoaddr ptr addrspace(1) [[P2]] to i32217; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[P2_ADDR]], [[P_ADDR]]218; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr addrspace(1) [[P]], i32 [[SUB]]219; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr addrspace(1) [[GEP]], [[P3]]220; CHECK-NEXT: call void @use.i1(i1 [[CMP]])221; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(1) [[GEP]] to i64222; CHECK-NEXT: [[INT:%.*]] = trunc i64 [[TMP1]] to i32223; CHECK-NEXT: call void @use.i32(i32 [[INT]])224; CHECK-NEXT: [[ADDR:%.*]] = ptrtoaddr ptr addrspace(1) [[P2]] to i32225; CHECK-NEXT: call void @use.i32(i32 [[ADDR]])226; CHECK-NEXT: ret ptr addrspace(1) [[GEP]]227;228 %p.addr = ptrtoaddr ptr addrspace(1) %p to i32229 %p2.addr = ptrtoaddr ptr addrspace(1) %p2 to i32230 %sub = sub i32 %p2.addr, %p.addr231 %gep = getelementptr i8, ptr addrspace(1) %p, i32 %sub232 %cmp = icmp eq ptr addrspace(1) %gep, %p3233 call void @use.i1(i1 %cmp)234 %int = ptrtoint ptr addrspace(1) %gep to i32235 call void @use.i32(i32 %int)236 %addr = ptrtoaddr ptr addrspace(1) %gep to i32237 call void @use.i32(i32 %addr)238 ret ptr addrspace(1) %gep239}240 241define i64 @ptrtoaddr_of_ptrmask(ptr %p, i64 %mask) {242; CHECK-LABEL: define i64 @ptrtoaddr_of_ptrmask(243; CHECK-SAME: ptr [[P:%.*]], i64 [[MASK:%.*]]) {244; CHECK-NEXT: [[TMP1:%.*]] = ptrtoaddr ptr [[P]] to i64245; CHECK-NEXT: [[ADDR:%.*]] = and i64 [[MASK]], [[TMP1]]246; CHECK-NEXT: ret i64 [[ADDR]]247;248 %masked = call ptr @llvm.ptrmask(ptr %p, i64 %mask)249 %addr = ptrtoaddr ptr %masked to i64250 ret i64 %addr251}252 253define i32 @ptrtoaddr_of_ptrmask_addrsize(ptr addrspace(1) %p, i32 %mask) {254; CHECK-LABEL: define i32 @ptrtoaddr_of_ptrmask_addrsize(255; CHECK-SAME: ptr addrspace(1) [[P:%.*]], i32 [[MASK:%.*]]) {256; CHECK-NEXT: [[TMP1:%.*]] = ptrtoaddr ptr addrspace(1) [[P]] to i32257; CHECK-NEXT: [[ADDR:%.*]] = and i32 [[MASK]], [[TMP1]]258; CHECK-NEXT: ret i32 [[ADDR]]259;260 %masked = call ptr addrspace(1) @llvm.ptrmask(ptr addrspace(1) %p, i32 %mask)261 %addr = ptrtoaddr ptr addrspace(1) %masked to i32262 ret i32 %addr263}264 265define i64 @ptrtoaddr_of_gep_of_inttoptr(i64 %int, i64 %offset) {266; CHECK-LABEL: define i64 @ptrtoaddr_of_gep_of_inttoptr(267; CHECK-SAME: i64 [[INT:%.*]], i64 [[OFFSET:%.*]]) {268; CHECK-NEXT: [[ADDR:%.*]] = add i64 [[INT]], [[OFFSET]]269; CHECK-NEXT: ret i64 [[ADDR]]270;271 %ptr = inttoptr i64 %int to ptr272 %gep = getelementptr i8, ptr %ptr, i64 %offset273 %addr = ptrtoaddr ptr %gep to i64274 ret i64 %addr275}276 277; FIXME: This could be supported by truncating %int before performing the278; arithmetic.279define i32 @ptrtoaddr_of_gep_of_inttoptr_addrsize(i64 %int, i32 %offset) {280; CHECK-LABEL: define i32 @ptrtoaddr_of_gep_of_inttoptr_addrsize(281; CHECK-SAME: i64 [[INT:%.*]], i32 [[OFFSET:%.*]]) {282; CHECK-NEXT: [[PTR:%.*]] = inttoptr i64 [[INT]] to ptr addrspace(1)283; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr addrspace(1) [[PTR]], i32 [[OFFSET]]284; CHECK-NEXT: [[ADDR:%.*]] = ptrtoaddr ptr addrspace(1) [[GEP]] to i32285; CHECK-NEXT: ret i32 [[ADDR]]286;287 %ptr = inttoptr i64 %int to ptr addrspace(1)288 %gep = getelementptr i8, ptr addrspace(1) %ptr, i32 %offset289 %addr = ptrtoaddr ptr addrspace(1) %gep to i32290 ret i32 %addr291}292 293define i64 @ptrtoaddr_of_gep_of_null(i64 %offset) {294; CHECK-LABEL: define i64 @ptrtoaddr_of_gep_of_null(295; CHECK-SAME: i64 [[OFFSET:%.*]]) {296; CHECK-NEXT: ret i64 [[OFFSET]]297;298 %gep = getelementptr i8, ptr null, i64 %offset299 %addr = ptrtoaddr ptr %gep to i64300 ret i64 %addr301}302 303define i32 @ptrtoaddr_of_gep_of_null_addrsize(i32 %offset) {304; CHECK-LABEL: define i32 @ptrtoaddr_of_gep_of_null_addrsize(305; CHECK-SAME: i32 [[OFFSET:%.*]]) {306; CHECK-NEXT: ret i32 [[OFFSET]]307;308 %gep = getelementptr i8, ptr addrspace(1) null, i32 %offset309 %addr = ptrtoaddr ptr addrspace(1) %gep to i32310 ret i32 %addr311}312