1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4target datalayout = "p1:64:64:64:32" 5 6declare ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1), i32) 7declare ptr @llvm.ptrmask.p0.i64(ptr, i64) 8declare <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) >, <2 x i32>) 9declare <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr>, <2 x i64>) 10 11define ptr @ptrmask_combine_consecutive_preserve_attrs(ptr %p0, i64 %m1) { 12; CHECK-LABEL: define ptr @ptrmask_combine_consecutive_preserve_attrs 13; CHECK-SAME: (ptr [[P0:%.*]], i64 [[M1:%.*]]) { 14; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[M1]], 224 15; CHECK-NEXT: [[R:%.*]] = call noalias align 32 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[TMP1]]) 16; CHECK-NEXT: ret ptr [[R]] 17; 18 %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 224) 19 %r = call noalias ptr @llvm.ptrmask.p0.i64(ptr %pm0, i64 %m1) 20 ret ptr %r 21} 22 23define <2 x ptr> @ptrmask_combine_consecutive_preserve_attrs_vecs(<2 x ptr> %p0, <2 x i64> %m1) { 24; CHECK-LABEL: define <2 x ptr> @ptrmask_combine_consecutive_preserve_attrs_vecs 25; CHECK-SAME: (<2 x ptr> [[P0:%.*]], <2 x i64> [[M1:%.*]]) { 26; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i64> [[M1]], splat (i64 12345) 27; CHECK-NEXT: [[R:%.*]] = call align 128 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[P0]], <2 x i64> [[TMP1]]) 28; CHECK-NEXT: ret <2 x ptr> [[R]] 29; 30 %pm0 = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p0, <2 x i64> <i64 12345, i64 12345>) 31 %r = call align 128 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %pm0, <2 x i64> %m1) 32 ret <2 x ptr> %r 33} 34 35define ptr @ptrmask_combine_consecutive_preserve_attrs_fail(ptr %p0, i64 %m0) { 36; CHECK-LABEL: define ptr @ptrmask_combine_consecutive_preserve_attrs_fail 37; CHECK-SAME: (ptr [[P0:%.*]], i64 [[M0:%.*]]) { 38; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[M0]], 193 39; CHECK-NEXT: [[R:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[TMP1]]) 40; CHECK-NEXT: ret ptr [[R]] 41; 42 %pm0 = call noalias ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0) 43 %r = call ptr @llvm.ptrmask.p0.i64(ptr %pm0, i64 193) 44 ret ptr %r 45} 46 47define ptr @ptrmask_combine_consecutive_preserve_attrs_todo0(ptr %p0) { 48; CHECK-LABEL: define ptr @ptrmask_combine_consecutive_preserve_attrs_todo0 49; CHECK-SAME: (ptr [[P0:%.*]]) { 50; CHECK-NEXT: [[PM0:%.*]] = call noalias align 32 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 224) 51; CHECK-NEXT: ret ptr [[PM0]] 52; 53 %pm0 = call noalias ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 224) 54 %r = call ptr @llvm.ptrmask.p0.i64(ptr %pm0, i64 224) 55 ret ptr %r 56} 57 58define ptr @ptrmask_combine_consecutive_preserve_attrs_todo1(ptr %p0) { 59; CHECK-LABEL: define ptr @ptrmask_combine_consecutive_preserve_attrs_todo1 60; CHECK-SAME: (ptr [[P0:%.*]]) { 61; CHECK-NEXT: [[PM0:%.*]] = call align 32 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 224) 62; CHECK-NEXT: ret ptr [[PM0]] 63; 64 %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 224) 65 %r = call noalias ptr @llvm.ptrmask.p0.i64(ptr %pm0, i64 224) 66 ret ptr %r 67} 68 69define ptr addrspace(1) @ptrmask_combine_consecutive_preserve_attrs_todo2(ptr addrspace(1) %p0) { 70; CHECK-LABEL: define ptr addrspace(1) @ptrmask_combine_consecutive_preserve_attrs_todo2 71; CHECK-SAME: (ptr addrspace(1) [[P0:%.*]]) { 72; CHECK-NEXT: [[PM0:%.*]] = call noalias align 32 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P0]], i32 224) 73; CHECK-NEXT: ret ptr addrspace(1) [[PM0]] 74; 75 %pm0 = call noalias ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p0, i32 224) 76 %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %pm0, i32 224) 77 ret ptr addrspace(1) %r 78} 79 80define ptr @ptrmask_combine_add_nonnull(ptr %p) { 81; CHECK-LABEL: define ptr @ptrmask_combine_add_nonnull 82; CHECK-SAME: (ptr [[P:%.*]]) { 83; CHECK-NEXT: [[PM0:%.*]] = call align 4 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -60) 84; CHECK-NEXT: [[PGEP1:%.*]] = getelementptr i8, ptr [[PM0]], i64 32 85; CHECK-NEXT: [[R:%.*]] = call nonnull align 32 ptr @llvm.ptrmask.p0.i64(ptr [[PGEP1]], i64 -32) 86; CHECK-NEXT: ret ptr [[R]] 87; 88 %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -60) 89 %pgep = getelementptr i8, ptr %pm0, i64 33 90 %r = call ptr @llvm.ptrmask.p0.i64(ptr %pgep, i64 -16) 91 ret ptr %r 92} 93 94define ptr @ptrmask_combine_add_alignment(ptr %p) { 95; CHECK-LABEL: define ptr @ptrmask_combine_add_alignment 96; CHECK-SAME: (ptr [[P:%.*]]) { 97; CHECK-NEXT: [[R:%.*]] = call align 64 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -64) 98; CHECK-NEXT: ret ptr [[R]] 99; 100 %r = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -64) 101 ret ptr %r 102} 103 104define ptr addrspace(1) @ptrmask_combine_add_alignment2(ptr addrspace(1) align 32 %p) { 105; CHECK-LABEL: define ptr addrspace(1) @ptrmask_combine_add_alignment2 106; CHECK-SAME: (ptr addrspace(1) align 32 [[P:%.*]]) { 107; CHECK-NEXT: [[R:%.*]] = call align 64 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 -64) 108; CHECK-NEXT: ret ptr addrspace(1) [[R]] 109; 110 %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 -64) 111 ret ptr addrspace(1) %r 112} 113 114define <2 x ptr> @ptrmask_combine_add_alignment_vec(<2 x ptr> %p) { 115; CHECK-LABEL: define <2 x ptr> @ptrmask_combine_add_alignment_vec 116; CHECK-SAME: (<2 x ptr> [[P:%.*]]) { 117; CHECK-NEXT: [[R:%.*]] = call align 32 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[P]], <2 x i64> splat (i64 -96)) 118; CHECK-NEXT: ret <2 x ptr> [[R]] 119; 120 %r = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p, <2 x i64> <i64 -96, i64 -96>) 121 ret <2 x ptr> %r 122} 123 124define ptr addrspace(1) @ptrmask_combine_improve_alignment(ptr addrspace(1) %p) { 125; CHECK-LABEL: define ptr addrspace(1) @ptrmask_combine_improve_alignment 126; CHECK-SAME: (ptr addrspace(1) [[P:%.*]]) { 127; CHECK-NEXT: [[R:%.*]] = call align 64 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 -64) 128; CHECK-NEXT: ret ptr addrspace(1) [[R]] 129; 130 %r = call align 32 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 -64) 131 ret ptr addrspace(1) %r 132} 133 134define <2 x ptr addrspace(1) > @ptrmask_combine_improve_alignment_vec(<2 x ptr addrspace(1) > %p) { 135; CHECK-LABEL: define <2 x ptr addrspace(1)> @ptrmask_combine_improve_alignment_vec 136; CHECK-SAME: (<2 x ptr addrspace(1)> [[P:%.*]]) { 137; CHECK-NEXT: [[R:%.*]] = call align 64 <2 x ptr addrspace(1)> @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1)> [[P]], <2 x i32> <i32 -64, i32 -128>) 138; CHECK-NEXT: ret <2 x ptr addrspace(1)> [[R]] 139; 140 %r = call align 32 <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) > %p, <2 x i32> <i32 -64, i32 -128>) 141 ret <2 x ptr addrspace(1) > %r 142} 143 144define ptr addrspace(1) @ptrmask_combine_improve_alignment_fail(ptr addrspace(1) %p) { 145; CHECK-LABEL: define ptr addrspace(1) @ptrmask_combine_improve_alignment_fail 146; CHECK-SAME: (ptr addrspace(1) [[P:%.*]]) { 147; CHECK-NEXT: [[R:%.*]] = call align 128 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 -64) 148; CHECK-NEXT: ret ptr addrspace(1) [[R]] 149; 150 %r = call align 128 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 -64) 151 ret ptr addrspace(1) %r 152} 153 154define i64 @ptrtoint_of_ptrmask(ptr %p, i64 %m) { 155; CHECK-LABEL: define i64 @ptrtoint_of_ptrmask 156; CHECK-SAME: (ptr [[P:%.*]], i64 [[M:%.*]]) { 157; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 158; CHECK-NEXT: [[R:%.*]] = and i64 [[M]], [[TMP1]] 159; CHECK-NEXT: ret i64 [[R]] 160; 161 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m) 162 %r = ptrtoint ptr %pm to i64 163 ret i64 %r 164} 165 166; This succeeds because (ptrtoint i32) gets folded to (trunc i32 (ptrtoint i64)) 167define i32 @ptrtoint_of_ptrmask2(ptr %p, i64 %m) { 168; CHECK-LABEL: define i32 @ptrtoint_of_ptrmask2 169; CHECK-SAME: (ptr [[P:%.*]], i64 [[M:%.*]]) { 170; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 171; CHECK-NEXT: [[TMP2:%.*]] = and i64 [[M]], [[TMP1]] 172; CHECK-NEXT: [[R:%.*]] = trunc i64 [[TMP2]] to i32 173; CHECK-NEXT: ret i32 [[R]] 174; 175 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m) 176 %r = ptrtoint ptr %pm to i32 177 ret i32 %r 178} 179 180define <2 x i64> @ptrtoint_of_ptrmask_vec(<2 x ptr> %p, <2 x i64> %m) { 181; CHECK-LABEL: define <2 x i64> @ptrtoint_of_ptrmask_vec 182; CHECK-SAME: (<2 x ptr> [[P:%.*]], <2 x i64> [[M:%.*]]) { 183; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint <2 x ptr> [[P]] to <2 x i64> 184; CHECK-NEXT: [[R:%.*]] = and <2 x i64> [[M]], [[TMP1]] 185; CHECK-NEXT: ret <2 x i64> [[R]] 186; 187 %pm = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p, <2 x i64> %m) 188 %r = ptrtoint <2 x ptr> %pm to <2 x i64> 189 ret <2 x i64> %r 190} 191 192define <2 x i32> @ptrtoint_of_ptrmask_vec2(<2 x ptr> %p, <2 x i64> %m) { 193; CHECK-LABEL: define <2 x i32> @ptrtoint_of_ptrmask_vec2 194; CHECK-SAME: (<2 x ptr> [[P:%.*]], <2 x i64> [[M:%.*]]) { 195; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint <2 x ptr> [[P]] to <2 x i64> 196; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i64> [[M]], [[TMP1]] 197; CHECK-NEXT: [[R:%.*]] = trunc <2 x i64> [[TMP2]] to <2 x i32> 198; CHECK-NEXT: ret <2 x i32> [[R]] 199; 200 %pm = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p, <2 x i64> %m) 201 %r = ptrtoint <2 x ptr> %pm to <2 x i32> 202 ret <2 x i32> %r 203} 204 205define i64 @ptrtoint_of_ptrmask_fail(ptr addrspace(1) %p, i32 %m) { 206; CHECK-LABEL: define i64 @ptrtoint_of_ptrmask_fail 207; CHECK-SAME: (ptr addrspace(1) [[P:%.*]], i32 [[M:%.*]]) { 208; CHECK-NEXT: [[PM:%.*]] = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 [[M]]) 209; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr addrspace(1) [[PM]] to i64 210; CHECK-NEXT: ret i64 [[R]] 211; 212 %pm = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 %m) 213 %r = ptrtoint ptr addrspace(1) %pm to i64 214 ret i64 %r 215} 216 217define <2 x i32> @ptrtoint_of_ptrmask_vec_fail(<2 x ptr addrspace(1) > %p, <2 x i32> %m) { 218; CHECK-LABEL: define <2 x i32> @ptrtoint_of_ptrmask_vec_fail 219; CHECK-SAME: (<2 x ptr addrspace(1)> [[P:%.*]], <2 x i32> [[M:%.*]]) { 220; CHECK-NEXT: [[PM:%.*]] = call <2 x ptr addrspace(1)> @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1)> [[P]], <2 x i32> [[M]]) 221; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint <2 x ptr addrspace(1)> [[PM]] to <2 x i64> 222; CHECK-NEXT: [[R:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32> 223; CHECK-NEXT: ret <2 x i32> [[R]] 224; 225 %pm = call <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) > %p, <2 x i32> %m) 226 %r = ptrtoint <2 x ptr addrspace(1) > %pm to <2 x i32> 227 ret <2 x i32> %r 228} 229 230define ptr addrspace(1) @ptrmask_is_null(ptr addrspace(1) align 32 %p) { 231; CHECK-LABEL: define ptr addrspace(1) @ptrmask_is_null 232; CHECK-SAME: (ptr addrspace(1) align 32 [[P:%.*]]) { 233; CHECK-NEXT: [[R:%.*]] = call align 4294967296 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 0) 234; CHECK-NEXT: ret ptr addrspace(1) [[R]] 235; 236 %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 31) 237 ret ptr addrspace(1) %r 238} 239 240define <2 x ptr addrspace(1) > @ptrmask_is_null_vec(<2 x ptr addrspace(1) > align 64 %p) { 241; CHECK-LABEL: define <2 x ptr addrspace(1)> @ptrmask_is_null_vec 242; CHECK-SAME: (<2 x ptr addrspace(1)> align 64 [[P:%.*]]) { 243; CHECK-NEXT: [[R:%.*]] = call <2 x ptr addrspace(1)> @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1)> [[P]], <2 x i32> <i32 31, i32 63>) 244; CHECK-NEXT: ret <2 x ptr addrspace(1)> [[R]] 245; 246 %r = call <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) > %p, <2 x i32> <i32 31, i32 63>) 247 ret <2 x ptr addrspace(1) > %r 248} 249 250define ptr addrspace(1) @ptrmask_is_null_fail(ptr addrspace(1) align 16 %p) { 251; CHECK-LABEL: define ptr addrspace(1) @ptrmask_is_null_fail 252; CHECK-SAME: (ptr addrspace(1) align 16 [[P:%.*]]) { 253; CHECK-NEXT: [[R:%.*]] = call align 16 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P]], i32 16) 254; CHECK-NEXT: ret ptr addrspace(1) [[R]] 255; 256 %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p, i32 31) 257 ret ptr addrspace(1) %r 258} 259 260define <2 x ptr addrspace(1) > @ptrmask_is_null_vec_fail(<2 x ptr addrspace(1) > align 32 %p) { 261; CHECK-LABEL: define <2 x ptr addrspace(1)> @ptrmask_is_null_vec_fail 262; CHECK-SAME: (<2 x ptr addrspace(1)> align 32 [[P:%.*]]) { 263; CHECK-NEXT: [[R:%.*]] = call <2 x ptr addrspace(1)> @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1)> [[P]], <2 x i32> <i32 31, i32 63>) 264; CHECK-NEXT: ret <2 x ptr addrspace(1)> [[R]] 265; 266 %r = call <2 x ptr addrspace(1) > @llvm.ptrmask.v2p1.v2i32(<2 x ptr addrspace(1) > %p, <2 x i32> <i32 31, i32 63>) 267 ret <2 x ptr addrspace(1) > %r 268} 269 270define ptr @ptrmask_maintain_provenance_i64(ptr %p0) { 271; CHECK-LABEL: define ptr @ptrmask_maintain_provenance_i64 272; CHECK-SAME: (ptr [[P0:%.*]]) { 273; CHECK-NEXT: [[R:%.*]] = call align 4294967296 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 0) 274; CHECK-NEXT: ret ptr [[R]] 275; 276 %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 0) 277 ret ptr %r 278} 279 280define ptr addrspace(1) @ptrmask_maintain_provenance_i32(ptr addrspace(1) %p0) { 281; CHECK-LABEL: define ptr addrspace(1) @ptrmask_maintain_provenance_i32 282; CHECK-SAME: (ptr addrspace(1) [[P0:%.*]]) { 283; CHECK-NEXT: [[R:%.*]] = call align 4294967296 ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) [[P0]], i32 0) 284; CHECK-NEXT: ret ptr addrspace(1) [[R]] 285; 286 %r = call ptr addrspace(1) @llvm.ptrmask.p1.i32(ptr addrspace(1) %p0, i32 0) 287 ret ptr addrspace(1) %r 288} 289 290define ptr @ptrmask_is_nop0(ptr align 8 %p) { 291; CHECK-LABEL: define ptr @ptrmask_is_nop0 292; CHECK-SAME: (ptr align 8 [[P:%.*]]) { 293; CHECK-NEXT: ret ptr [[P]] 294; 295 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -8) 296 ret ptr %pm 297} 298 299define ptr @ptrmask_is_nop1(ptr align 8 %p) { 300; CHECK-LABEL: define ptr @ptrmask_is_nop1 301; CHECK-SAME: (ptr align 8 [[P:%.*]]) { 302; CHECK-NEXT: ret ptr [[P]] 303; 304 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -4) 305 ret ptr %pm 306} 307 308define ptr @ptrmask_to_modified_gep0(ptr align 8 %p) { 309; CHECK-LABEL: define ptr @ptrmask_to_modified_gep0 310; CHECK-SAME: (ptr align 8 [[P:%.*]]) { 311; CHECK-NEXT: [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -16) 312; CHECK-NEXT: ret ptr [[PM]] 313; 314 %gep = getelementptr i8, ptr %p, i32 5 315 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16) 316 ret ptr %pm 317} 318 319define ptr @ptrmask_to_modified_gep1(ptr align 8 %p) { 320; CHECK-LABEL: define ptr @ptrmask_to_modified_gep1 321; CHECK-SAME: (ptr align 8 [[P:%.*]]) { 322; CHECK-NEXT: ret ptr [[P]] 323; 324 %gep = getelementptr i8, ptr %p, i32 6 325 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -8) 326 ret ptr %pm 327} 328 329define ptr @ptrmask_to_modified_gep2(ptr align 16 %p) { 330; CHECK-LABEL: define ptr @ptrmask_to_modified_gep2 331; CHECK-SAME: (ptr align 16 [[P:%.*]]) { 332; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 12 333; CHECK-NEXT: ret ptr [[GEP1]] 334; 335 %gep = getelementptr i8, ptr %p, i32 15 336 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4) 337 ret ptr %pm 338} 339 340define ptr @ptrmask_to_modified_gep4(ptr align 8 %p) { 341; CHECK-LABEL: define ptr @ptrmask_to_modified_gep4 342; CHECK-SAME: (ptr align 8 [[P:%.*]]) { 343; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 24 344; CHECK-NEXT: [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[GEP1]], i64 -16) 345; CHECK-NEXT: ret ptr [[PM]] 346; 347 %gep = getelementptr i8, ptr %p, i32 29 348 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16) 349 ret ptr %pm 350} 351 352define ptr @ptrmask_to_modified_gep5(ptr align 8 %p) { 353; CHECK-LABEL: define ptr @ptrmask_to_modified_gep5 354; CHECK-SAME: (ptr align 8 [[P:%.*]]) { 355; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 24 356; CHECK-NEXT: ret ptr [[GEP1]] 357; 358 %gep = getelementptr i8, ptr %p, i32 30 359 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -8) 360 ret ptr %pm 361} 362 363define ptr @ptrmask_to_modified_gep6(ptr align 16 %p) { 364; CHECK-LABEL: define ptr @ptrmask_to_modified_gep6 365; CHECK-SAME: (ptr align 16 [[P:%.*]]) { 366; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 28 367; CHECK-NEXT: ret ptr [[GEP1]] 368; 369 %gep = getelementptr i8, ptr %p, i32 31 370 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4) 371 ret ptr %pm 372} 373 374define ptr @ptrmask_to_modified_gep_indirect0(ptr align 16 %p) { 375; CHECK-LABEL: define ptr @ptrmask_to_modified_gep_indirect0 376; CHECK-SAME: (ptr align 16 [[P:%.*]]) { 377; CHECK-NEXT: [[GEP11:%.*]] = getelementptr i8, ptr [[P]], i64 44 378; CHECK-NEXT: ret ptr [[GEP11]] 379; 380; 44 from 4*sizeof(i32) + (31 & -4) 381 %gep0 = getelementptr i32, ptr %p, i32 4 382 %gep1 = getelementptr i8, ptr %gep0, i32 31 383 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep1, i64 -4) 384 ret ptr %pm 385} 386 387define ptr @ptrmask_to_modified_gep_indirect1(ptr %p) { 388; CHECK-LABEL: define ptr @ptrmask_to_modified_gep_indirect1 389; CHECK-SAME: (ptr [[P:%.*]]) { 390; CHECK-NEXT: [[PM0:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 -16) 391; CHECK-NEXT: [[PGEP1:%.*]] = getelementptr i8, ptr [[PM0]], i64 32 392; CHECK-NEXT: ret ptr [[PGEP1]] 393; 394 395 %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 -16) 396 %pgep = getelementptr i8, ptr %pm0, i64 33 397 %r = call ptr @llvm.ptrmask.p0.i64(ptr %pgep, i64 -16) 398 ret ptr %r 399} 400 401define ptr @ptrmask_to_modified_gep_zero_argument() { 402; CHECK-LABEL: define ptr @ptrmask_to_modified_gep_zero_argument() { 403; CHECK-NEXT: [[P:%.*]] = call nonnull align 4 ptr @llvm.ptrmask.p0.i64(ptr nonnull inttoptr (i64 31 to ptr), i64 28) 404; CHECK-NEXT: ret ptr [[P]] 405; 406 %gep = getelementptr inbounds i8, ptr null, i32 31 407 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4) 408 ret ptr %pm 409} 410 411define ptr @ptrmask_to_preserves_inbounds(ptr align 16 %p) { 412; CHECK-LABEL: define ptr @ptrmask_to_preserves_inbounds 413; CHECK-SAME: (ptr align 16 [[P:%.*]]) { 414; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 28 415; CHECK-NEXT: ret ptr [[GEP1]] 416; 417 %gep = getelementptr inbounds i8, ptr %p, i32 31 418 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -4) 419 ret ptr %pm 420} 421 422define ptr @ptrmask_of_gep_requires_i8(ptr align 8 %p) { 423; CHECK-LABEL: define ptr @ptrmask_of_gep_requires_i8 424; CHECK-SAME: (ptr align 8 [[P:%.*]]) { 425; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 8 426; CHECK-NEXT: [[PM:%.*]] = call align 16 ptr @llvm.ptrmask.p0.i64(ptr [[GEP1]], i64 -16) 427; CHECK-NEXT: ret ptr [[PM]] 428; 429 %gep = getelementptr i16, ptr %p, i32 5 430 %pm = call ptr @llvm.ptrmask.p0.i64(ptr %gep, i64 -16) 431 ret ptr %pm 432} 433 434define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented(<2 x ptr> align 8 %p) { 435; CHECK-LABEL: define <2 x ptr> @ptrmask_of_gep_vector_type_unimplemented 436; CHECK-SAME: (<2 x ptr> align 8 [[P:%.*]]) { 437; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, <2 x ptr> [[P]], i64 17 438; CHECK-NEXT: [[PM:%.*]] = call align 32 <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[GEP]], <2 x i64> splat (i64 -96)) 439; CHECK-NEXT: ret <2 x ptr> [[PM]] 440; 441 %gep = getelementptr i8, <2 x ptr> %p, i32 17 442 %pm = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %gep, <2 x i64> <i64 -96, i64 -96>) 443 ret <2 x ptr> %pm 444} 445 446define ptr @ptrmask_is_useless0(i64 %i, i64 %m) { 447; CHECK-LABEL: define ptr @ptrmask_is_useless0 448; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) { 449; CHECK-NEXT: [[I0:%.*]] = and i64 [[I]], -4 450; CHECK-NEXT: [[P0:%.*]] = inttoptr i64 [[I0]] to ptr 451; CHECK-NEXT: [[R:%.*]] = call align 4 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M]]) 452; CHECK-NEXT: ret ptr [[R]] 453; 454 %m0 = and i64 %m, -4 455 %i0 = and i64 %i, -4 456 %p0 = inttoptr i64 %i0 to ptr 457 %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0) 458 ret ptr %r 459} 460 461define ptr @ptrmask_is_useless1(i64 %i, i64 %m) { 462; CHECK-LABEL: define ptr @ptrmask_is_useless1 463; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) { 464; CHECK-NEXT: [[I0:%.*]] = and i64 [[I]], -8 465; CHECK-NEXT: [[P0:%.*]] = inttoptr i64 [[I0]] to ptr 466; CHECK-NEXT: [[R:%.*]] = call align 8 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M]]) 467; CHECK-NEXT: ret ptr [[R]] 468; 469 %m0 = and i64 %m, -4 470 %i0 = and i64 %i, -8 471 %p0 = inttoptr i64 %i0 to ptr 472 %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0) 473 ret ptr %r 474} 475 476define ptr @ptrmask_is_useless2(i64 %i, i64 %m) { 477; CHECK-LABEL: define ptr @ptrmask_is_useless2 478; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) { 479; CHECK-NEXT: [[I0:%.*]] = and i64 [[I]], 31 480; CHECK-NEXT: [[P0:%.*]] = inttoptr i64 [[I0]] to ptr 481; CHECK-NEXT: [[R:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M]]) 482; CHECK-NEXT: ret ptr [[R]] 483; 484 %m0 = and i64 %m, 127 485 %i0 = and i64 %i, 31 486 %p0 = inttoptr i64 %i0 to ptr 487 %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0) 488 ret ptr %r 489} 490 491define ptr @ptrmask_is_useless3(i64 %i, i64 %m) { 492; CHECK-LABEL: define ptr @ptrmask_is_useless3 493; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) { 494; CHECK-NEXT: [[I0:%.*]] = and i64 [[I]], 127 495; CHECK-NEXT: [[P0:%.*]] = inttoptr i64 [[I0]] to ptr 496; CHECK-NEXT: [[R:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M]]) 497; CHECK-NEXT: ret ptr [[R]] 498; 499 %m0 = and i64 %m, 127 500 %i0 = and i64 %i, 127 501 %p0 = inttoptr i64 %i0 to ptr 502 %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0) 503 ret ptr %r 504} 505 506define ptr @ptrmask_is_useless4(i64 %i, i64 %m) { 507; CHECK-LABEL: define ptr @ptrmask_is_useless4 508; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) { 509; CHECK-NEXT: [[I0:%.*]] = and i64 [[I]], -4 510; CHECK-NEXT: [[P0:%.*]] = inttoptr i64 [[I0]] to ptr 511; CHECK-NEXT: ret ptr [[P0]] 512; 513 %m0 = or i64 %m, -4 514 %i0 = and i64 %i, -4 515 %p0 = inttoptr i64 %i0 to ptr 516 %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0) 517 ret ptr %r 518} 519 520define <2 x ptr> @ptrmask_is_useless_vec(<2 x i64> %i, <2 x i64> %m) { 521; CHECK-LABEL: define <2 x ptr> @ptrmask_is_useless_vec 522; CHECK-SAME: (<2 x i64> [[I:%.*]], <2 x i64> [[M:%.*]]) { 523; CHECK-NEXT: [[I0:%.*]] = and <2 x i64> [[I]], splat (i64 31) 524; CHECK-NEXT: [[P0:%.*]] = inttoptr <2 x i64> [[I0]] to <2 x ptr> 525; CHECK-NEXT: [[R:%.*]] = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[P0]], <2 x i64> [[M]]) 526; CHECK-NEXT: ret <2 x ptr> [[R]] 527; 528 %m0 = and <2 x i64> %m, <i64 127, i64 127> 529 %i0 = and <2 x i64> %i, <i64 31, i64 31> 530 %p0 = inttoptr <2 x i64> %i0 to <2 x ptr> 531 %r = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p0, <2 x i64> %m0) 532 ret <2 x ptr> %r 533} 534 535define <2 x ptr> @ptrmask_is_useless_vec_todo(<2 x i64> %i, <2 x i64> %m) { 536; CHECK-LABEL: define <2 x ptr> @ptrmask_is_useless_vec_todo 537; CHECK-SAME: (<2 x i64> [[I:%.*]], <2 x i64> [[M:%.*]]) { 538; CHECK-NEXT: [[I0:%.*]] = and <2 x i64> [[I]], <i64 31, i64 127> 539; CHECK-NEXT: [[P0:%.*]] = inttoptr <2 x i64> [[I0]] to <2 x ptr> 540; CHECK-NEXT: [[R:%.*]] = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> [[P0]], <2 x i64> [[M]]) 541; CHECK-NEXT: ret <2 x ptr> [[R]] 542; 543 %m0 = and <2 x i64> %m, <i64 127, i64 127> 544 %i0 = and <2 x i64> %i, <i64 31, i64 127> 545 %p0 = inttoptr <2 x i64> %i0 to <2 x ptr> 546 %r = call <2 x ptr> @llvm.ptrmask.v2p0.v2i64(<2 x ptr> %p0, <2 x i64> %m0) 547 ret <2 x ptr> %r 548} 549 550define ptr @ptrmask_is_useless_fail0(i64 %i, i64 %m) { 551; CHECK-LABEL: define ptr @ptrmask_is_useless_fail0 552; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) { 553; CHECK-NEXT: [[M0:%.*]] = and i64 [[M]], -4 554; CHECK-NEXT: [[I0:%.*]] = or i64 [[I]], -4 555; CHECK-NEXT: [[P0:%.*]] = inttoptr i64 [[I0]] to ptr 556; CHECK-NEXT: [[R:%.*]] = call align 4 ptr @llvm.ptrmask.p0.i64(ptr nonnull [[P0]], i64 [[M0]]) 557; CHECK-NEXT: ret ptr [[R]] 558; 559 %m0 = and i64 %m, -4 560 %i0 = or i64 %i, -4 561 %p0 = inttoptr i64 %i0 to ptr 562 %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0) 563 ret ptr %r 564} 565 566define ptr @ptrmask_is_useless_fail1(i64 %i, i64 %m) { 567; CHECK-LABEL: define ptr @ptrmask_is_useless_fail1 568; CHECK-SAME: (i64 [[I:%.*]], i64 [[M:%.*]]) { 569; CHECK-NEXT: [[M0:%.*]] = and i64 [[M]], 127 570; CHECK-NEXT: [[I0:%.*]] = and i64 [[I]], 511 571; CHECK-NEXT: [[P0:%.*]] = inttoptr i64 [[I0]] to ptr 572; CHECK-NEXT: [[R:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[M0]]) 573; CHECK-NEXT: ret ptr [[R]] 574; 575 %m0 = and i64 %m, 127 576 %i0 = and i64 %i, 511 577 %p0 = inttoptr i64 %i0 to ptr 578 %r = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 %m0) 579 ret ptr %r 580} 581 582@GC_arrays = external global { i8, i8, i64 } 583 584define ptr @ptrmask_demandedbits_constantexpr() { 585; CHECK-LABEL: define ptr @ptrmask_demandedbits_constantexpr() { 586; CHECK-NEXT: entry: 587; CHECK-NEXT: [[ALIGNED_RESULT:%.*]] = call align 8 ptr @llvm.ptrmask.p0.i64(ptr nonnull @GC_arrays, i64 -8) 588; CHECK-NEXT: ret ptr [[ALIGNED_RESULT]] 589; 590entry: 591 %aligned_result = call ptr @llvm.ptrmask.p0.i64(ptr getelementptr inbounds (i8, ptr @GC_arrays, i64 1), i64 -8) 592 ret ptr %aligned_result 593} 594