392 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s3 4@g = private unnamed_addr constant [5 x i8] c"test\00"5@g_overaligned = private unnamed_addr constant [5 x i8] c"test\00", align 86@g_external = external global [5 x i8]7 8declare void @free(ptr allocptr noundef captures(none)) mustprogress nounwind willreturn allockind("free") memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc"9declare ptr @malloc(i64) mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite) "alloc-family"="malloc"10declare void @may_not_return(i1)11 12define i8 @load_global(i64 %idx) {13; CHECK-LABEL: define i8 @load_global(14; CHECK-SAME: i64 [[IDX:%.*]]) {15; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g, i64 [[IDX]]16; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 117; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i818; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]19; CHECK-NEXT: ret i8 [[ADD]]20;21 %gep = getelementptr nuw i8, ptr @g, i64 %idx22 %load = load i8, ptr %gep23 %cmp = icmp ult i64 %idx, 524 %zext = zext i1 %cmp to i825 %add = add i8 %load, %zext26 ret i8 %add27}28 29define i8 @load_global_const_offset(i64 %idx) {30; CHECK-LABEL: define i8 @load_global_const_offset(31; CHECK-SAME: i64 [[IDX:%.*]]) {32; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i8, ptr @g, i64 133; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[GEP1]], i64 [[IDX]]34; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 135; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i836; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]37; CHECK-NEXT: ret i8 [[ADD]]38;39 %gep1 = getelementptr nuw i8, ptr @g, i64 140 %gep = getelementptr nuw i8, ptr %gep1, i64 %idx41 %load = load i8, ptr %gep42 %cmp = icmp ult i64 %idx, 443 %zext = zext i1 %cmp to i844 %add = add i8 %load, %zext45 ret i8 %add46}47 48define i8 @load_global_atomic(i64 %idx) {49; CHECK-LABEL: define i8 @load_global_atomic(50; CHECK-SAME: i64 [[IDX:%.*]]) {51; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g, i64 [[IDX]]52; CHECK-NEXT: [[LOAD:%.*]] = load atomic i8, ptr [[GEP]] unordered, align 153; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i854; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]55; CHECK-NEXT: ret i8 [[ADD]]56;57 %gep = getelementptr nuw i8, ptr @g, i64 %idx58 %load = load atomic i8, ptr %gep unordered, align 159 %cmp = icmp ult i64 %idx, 560 %zext = zext i1 %cmp to i861 %add = add i8 %load, %zext62 ret i8 %add63}64 65define i1 @store_global(i64 %idx) {66; CHECK-LABEL: define i1 @store_global(67; CHECK-SAME: i64 [[IDX:%.*]]) {68; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g, i64 [[IDX]]69; CHECK-NEXT: store i8 0, ptr [[GEP]], align 170; CHECK-NEXT: ret i1 true71;72 %gep = getelementptr nuw i8, ptr @g, i64 %idx73 store i8 0, ptr %gep74 %cmp = icmp ult i64 %idx, 575 ret i1 %cmp76}77 78define i1 @store_global_atomic(i64 %idx) {79; CHECK-LABEL: define i1 @store_global_atomic(80; CHECK-SAME: i64 [[IDX:%.*]]) {81; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g, i64 [[IDX]]82; CHECK-NEXT: store atomic i8 0, ptr [[GEP]] release, align 183; CHECK-NEXT: ret i1 true84;85 %gep = getelementptr nuw i8, ptr @g, i64 %idx86 store atomic i8 0, ptr %gep release, align 187 %cmp = icmp ult i64 %idx, 588 ret i1 %cmp89}90 91define i8 @load_byval(ptr byval([5 x i8]) %p, i64 %idx) {92; CHECK-LABEL: define i8 @load_byval(93; CHECK-SAME: ptr byval([5 x i8]) [[P:%.*]], i64 [[IDX:%.*]]) {94; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[IDX]]95; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 196; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i897; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]98; CHECK-NEXT: ret i8 [[ADD]]99;100 %gep = getelementptr nuw i8, ptr %p, i64 %idx101 %load = load i8, ptr %gep102 %cmp = icmp ult i64 %idx, 5103 %zext = zext i1 %cmp to i8104 %add = add i8 %load, %zext105 ret i8 %add106}107 108define i8 @load_alloca(i64 %idx) {109; CHECK-LABEL: define i8 @load_alloca(110; CHECK-SAME: i64 [[IDX:%.*]]) {111; CHECK-NEXT: [[ALLOC:%.*]] = alloca [5 x i8], align 1112; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[ALLOC]], ptr @g, i64 5, i1 false)113; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[ALLOC]], i64 [[IDX]]114; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 1115; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i8116; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]117; CHECK-NEXT: ret i8 [[ADD]]118;119 %alloc = alloca [5 x i8], align 1120 call void @llvm.memcpy.p0.p0.i64(ptr %alloc, ptr @g, i64 5, i1 false)121 %gep = getelementptr nuw i8, ptr %alloc, i64 %idx122 %load = load i8, ptr %gep123 %cmp = icmp ult i64 %idx, 5124 %zext = zext i1 %cmp to i8125 %add = add i8 %load, %zext126 ret i8 %add127}128 129define i8 @load_malloc(i64 %idx) {130; CHECK-LABEL: define i8 @load_malloc(131; CHECK-SAME: i64 [[IDX:%.*]]) {132; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 5)133; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[ALLOC]], ptr @g, i64 5, i1 false)134; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[ALLOC]], i64 [[IDX]]135; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 1136; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i8137; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]138; CHECK-NEXT: call void @free(ptr [[ALLOC]])139; CHECK-NEXT: ret i8 [[ADD]]140;141 %alloc = call ptr @malloc(i64 5)142 call void @llvm.memcpy.p0.p0.i64(ptr %alloc, ptr @g, i64 5, i1 false)143 %gep = getelementptr nuw i8, ptr %alloc, i64 %idx144 %load = load i8, ptr %gep145 %cmp = icmp ult i64 %idx, 5146 %zext = zext i1 %cmp to i8147 %add = add i8 %load, %zext148 call void @free(ptr %alloc)149 ret i8 %add150}151 152define i32 @load_byval_i32(ptr byval([10 x i8]) %p, i64 %idx) {153; CHECK-LABEL: define i32 @load_byval_i32(154; CHECK-SAME: ptr byval([10 x i8]) [[P:%.*]], i64 [[IDX:%.*]]) {155; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[IDX]]156; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4157; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i32158; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD]], [[ZEXT]]159; CHECK-NEXT: ret i32 [[ADD]]160;161 %gep = getelementptr nuw i8, ptr %p, i64 %idx162 %load = load i32, ptr %gep163 %cmp = icmp ult i64 %idx, 7164 %zext = zext i1 %cmp to i32165 %add = add i32 %load, %zext166 ret i32 %add167}168 169define i8 @load_global_may_noreturn_dom_bb(i64 %idx) {170; CHECK-LABEL: define i8 @load_global_may_noreturn_dom_bb(171; CHECK-SAME: i64 [[IDX:%.*]]) {172; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g, i64 [[IDX]]173; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[IDX]], 5174; CHECK-NEXT: call void @may_not_return(i1 [[CMP1]])175; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 1176; CHECK-NEXT: br label %[[NEXT:.*]]177; CHECK: [[NEXT]]:178; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i8179; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]180; CHECK-NEXT: ret i8 [[ADD]]181;182 %gep = getelementptr nuw i8, ptr @g, i64 %idx183 %cmp1 = icmp ult i64 %idx, 5184 call void @may_not_return(i1 %cmp1) ; %cmp1 should not be simplified.185 %load = load i8, ptr %gep186 br label %next187 188next:189 %cmp2 = icmp ult i64 %idx, 5190 %zext = zext i1 %cmp2 to i8191 %add = add i8 %load, %zext192 ret i8 %add193}194 195; Negative tests.196 197define i8 @load_global_overaligned(i64 %idx) {198; CHECK-LABEL: define i8 @load_global_overaligned(199; CHECK-SAME: i64 [[IDX:%.*]]) {200; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g_overaligned, i64 [[IDX]]201; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 1202; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX]], 5203; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8204; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]205; CHECK-NEXT: ret i8 [[ADD]]206;207 %gep = getelementptr nuw i8, ptr @g_overaligned, i64 %idx208 %load = load i8, ptr %gep209 %cmp = icmp ult i64 %idx, 5210 %zext = zext i1 %cmp to i8211 %add = add i8 %load, %zext212 ret i8 %add213}214 215define i8 @load_global_external(i64 %idx) {216; CHECK-LABEL: define i8 @load_global_external(217; CHECK-SAME: i64 [[IDX:%.*]]) {218; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g_external, i64 [[IDX]]219; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 1220; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX]], 5221; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8222; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]223; CHECK-NEXT: ret i8 [[ADD]]224;225 %gep = getelementptr nuw i8, ptr @g_external, i64 %idx226 %load = load i8, ptr %gep227 %cmp = icmp ult i64 %idx, 5228 %zext = zext i1 %cmp to i8229 %add = add i8 %load, %zext230 ret i8 %add231}232 233define i8 @load_from_non_gep(ptr %p, i64 %idx) {234; CHECK-LABEL: define i8 @load_from_non_gep(235; CHECK-SAME: ptr [[P:%.*]], i64 [[IDX:%.*]]) {236; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[P]], align 1237; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX]], 5238; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8239; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]240; CHECK-NEXT: ret i8 [[ADD]]241;242 %load = load i8, ptr %p243 %cmp = icmp ult i64 %idx, 5244 %zext = zext i1 %cmp to i8245 %add = add i8 %load, %zext246 ret i8 %add247}248 249define i8 @load_global_multi_indices(i64 %idx1, i64 %idx2) {250; CHECK-LABEL: define i8 @load_global_multi_indices(251; CHECK-SAME: i64 [[IDX1:%.*]], i64 [[IDX2:%.*]]) {252; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i8, ptr @g, i64 [[IDX1]]253; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nuw i8, ptr [[GEP1]], i64 [[IDX2]]254; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP2]], align 1255; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX1]], 5256; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8257; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]258; CHECK-NEXT: ret i8 [[ADD]]259;260 %gep1 = getelementptr nuw i8, ptr @g, i64 %idx1261 %gep2 = getelementptr nuw i8, ptr %gep1, i64 %idx2262 %load = load i8, ptr %gep2263 %cmp = icmp ult i64 %idx1, 5264 %zext = zext i1 %cmp to i8265 %add = add i8 %load, %zext266 ret i8 %add267}268 269define i8 @load_global_without_nuw(i64 %idx) {270; CHECK-LABEL: define i8 @load_global_without_nuw(271; CHECK-SAME: i64 [[IDX:%.*]]) {272; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr @g, i64 [[IDX]]273; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 1274; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX]], 5275; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8276; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]277; CHECK-NEXT: ret i8 [[ADD]]278;279 %gep = getelementptr i8, ptr @g, i64 %idx280 %load = load i8, ptr %gep281 %cmp = icmp ult i64 %idx, 5282 %zext = zext i1 %cmp to i8283 %add = add i8 %load, %zext284 ret i8 %add285}286 287define i32 @load_byval_i32_smaller_range(ptr byval([10 x i8]) %p, i64 %idx) {288; CHECK-LABEL: define i32 @load_byval_i32_smaller_range(289; CHECK-SAME: ptr byval([10 x i8]) [[P:%.*]], i64 [[IDX:%.*]]) {290; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[P]], i64 [[IDX]]291; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4292; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX]], 6293; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32294; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD]], [[ZEXT]]295; CHECK-NEXT: ret i32 [[ADD]]296;297 %gep = getelementptr nuw i8, ptr %p, i64 %idx298 %load = load i32, ptr %gep299 %cmp = icmp ult i64 %idx, 6300 %zext = zext i1 %cmp to i32301 %add = add i32 %load, %zext302 ret i32 %add303}304 305define i8 @load_global_volatile(i64 %idx) {306; CHECK-LABEL: define i8 @load_global_volatile(307; CHECK-SAME: i64 [[IDX:%.*]]) {308; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g, i64 [[IDX]]309; CHECK-NEXT: [[LOAD:%.*]] = load volatile i8, ptr [[GEP]], align 1310; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX]], 5311; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8312; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]313; CHECK-NEXT: ret i8 [[ADD]]314;315 %gep = getelementptr nuw i8, ptr @g, i64 %idx316 %load = load volatile i8, ptr %gep317 %cmp = icmp ult i64 %idx, 5318 %zext = zext i1 %cmp to i8319 %add = add i8 %load, %zext320 ret i8 %add321}322 323define i1 @store_global_volatile(i64 %idx) {324; CHECK-LABEL: define i1 @store_global_volatile(325; CHECK-SAME: i64 [[IDX:%.*]]) {326; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g, i64 [[IDX]]327; CHECK-NEXT: store volatile i8 0, ptr [[GEP]], align 1328; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX]], 5329; CHECK-NEXT: ret i1 [[CMP]]330;331 %gep = getelementptr nuw i8, ptr @g, i64 %idx332 store volatile i8 0, ptr %gep333 %cmp = icmp ult i64 %idx, 5334 ret i1 %cmp335}336 337define i8 @load_global_vscale(i64 %idx) {338; CHECK-LABEL: define i8 @load_global_vscale(339; CHECK-SAME: i64 [[IDX:%.*]]) {340; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g, i64 [[IDX]]341; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 1 x i8>, ptr [[GEP]], align 1342; CHECK-NEXT: [[EXT:%.*]] = extractelement <vscale x 1 x i8> [[LOAD]], i64 0343; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX]], 5344; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8345; CHECK-NEXT: [[ADD:%.*]] = add i8 [[EXT]], [[ZEXT]]346; CHECK-NEXT: ret i8 [[ADD]]347;348 %gep = getelementptr nuw i8, ptr @g, i64 %idx349 %load = load <vscale x 1 x i8>, ptr %gep350 %ext = extractelement <vscale x 1 x i8> %load, i64 0351 %cmp = icmp ult i64 %idx, 5352 %zext = zext i1 %cmp to i8353 %add = add i8 %ext, %zext354 ret i8 %add355}356 357define i8 @load_from_null(i64 %idx) {358; CHECK-LABEL: define i8 @load_from_null(359; CHECK-SAME: i64 [[IDX:%.*]]) {360; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr null, i64 [[IDX]]361; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 1362; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX]], 5363; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8364; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]365; CHECK-NEXT: ret i8 [[ADD]]366;367 %gep = getelementptr nuw i8, ptr null, i64 %idx368 %load = load i8, ptr %gep369 %cmp = icmp ult i64 %idx, 5370 %zext = zext i1 %cmp to i8371 %add = add i8 %load, %zext372 ret i8 %add373}374 375define i8 @load_global_non_canonical_gep(i32 %idx) {376; CHECK-LABEL: define i8 @load_global_non_canonical_gep(377; CHECK-SAME: i32 [[IDX:%.*]]) {378; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr @g, i32 [[IDX]]379; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GEP]], align 1380; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX]], 5381; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8382; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD]], [[ZEXT]]383; CHECK-NEXT: ret i8 [[ADD]]384;385 %gep = getelementptr nuw i8, ptr @g, i32 %idx386 %load = load i8, ptr %gep387 %cmp = icmp ult i32 %idx, 5388 %zext = zext i1 %cmp to i8389 %add = add i8 %load, %zext390 ret i8 %add391}392