1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4declare void @llvm.assume(i1 noundef) #0 5 6define i1 @gep_constant_positive_index(ptr %A, ptr %upper) { 7; CHECK-LABEL: @gep_constant_positive_index( 8; CHECK-NEXT: [[ADD_I8_4:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 4 9; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]] 10; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 11; CHECK-NEXT: [[ADD_I16_4:%.*]] = getelementptr inbounds i16, ptr [[A]], i64 4 12; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I16_4]], [[UPPER]] 13; CHECK-NEXT: [[ADD_I16_2:%.*]] = getelementptr inbounds i16, ptr [[A]], i64 2 14; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true 15; CHECK-NEXT: ret i1 [[RES_1]] 16; 17 %add.i8.4 = getelementptr inbounds i8, ptr %A, i64 4 18 %c.0 = icmp ult ptr %add.i8.4, %upper 19 call void @llvm.assume(i1 %c.0) 20 21 %add.i16.4 = getelementptr inbounds i16, ptr %A, i64 4 22 %c.1 = icmp ult ptr %add.i16.4, %upper 23 24 %add.i16.2 = getelementptr inbounds i16, ptr %A, i64 2 25 %t.1 = icmp ult ptr %add.i16.2, %upper 26 %res.1 = xor i1 %c.1, %t.1 27 ret i1 %res.1 28} 29 30define i1 @gep_constant_positive_index_chained(ptr %A, ptr %upper) { 31; CHECK-LABEL: @gep_constant_positive_index_chained( 32; CHECK-NEXT: [[ADD_I8_4:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 4 33; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]] 34; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 35; CHECK-NEXT: [[ADD_I8_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 1 36; CHECK-NEXT: [[ADD_I16_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_I8_1]], i64 1 37; CHECK-NEXT: [[ADD_I16_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_I8_1]], i64 2 38; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I16_2]], [[UPPER]] 39; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, [[C_1]] 40; CHECK-NEXT: ret i1 [[RES_1]] 41; 42 %add.i8.4 = getelementptr inbounds i8, ptr %A, i64 4 43 %c.0 = icmp ult ptr %add.i8.4, %upper 44 call void @llvm.assume(i1 %c.0) 45 46 %add.i8.1 = getelementptr inbounds i8, ptr %A, i64 1 47 48 %add.i16.1 = getelementptr inbounds i16, ptr %add.i8.1, i64 1 49 %t.1 = icmp ult ptr %add.i16.1, %upper 50 %add.i16.2 = getelementptr inbounds i16, ptr %add.i8.1, i64 2 51 %c.1 = icmp ult ptr %add.i16.2, %upper 52 %res.1 = xor i1 %t.1, %c.1 53 ret i1 %res.1 54} 55 56define i1 @gep_var_positive_index(ptr %A, ptr %upper, i8 %idx) { 57; CHECK-LABEL: @gep_var_positive_index( 58; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0 59; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]]) 60; CHECK-NEXT: [[ADD_I16_IDX:%.*]] = getelementptr inbounds i16, ptr [[A:%.*]], i8 [[IDX]] 61; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I16_IDX]], [[UPPER:%.*]] 62; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 63; CHECK-NEXT: [[ADD_I32_IDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX]] 64; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX]], [[UPPER]] 65; CHECK-NEXT: [[ADD_I8_IDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX]] 66; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true 67; CHECK-NEXT: ret i1 [[RES_1]] 68; 69 %idx.pos = icmp sge i8 %idx, 0 70 call void @llvm.assume(i1 %idx.pos) 71 %add.i16.idx = getelementptr inbounds i16, ptr %A, i8 %idx 72 %c.0 = icmp ult ptr %add.i16.idx, %upper 73 call void @llvm.assume(i1 %c.0) 74 75 %add.i32.idx = getelementptr inbounds i32, ptr %A, i8 %idx 76 %c.1 = icmp ult ptr %add.i32.idx, %upper 77 %add.i8.idx = getelementptr inbounds i8, ptr %A, i8 %idx 78 %t.1 = icmp ult ptr %add.i8.idx, %upper 79 %res.1 = xor i1 %c.1, %t.1 80 ret i1 %res.1 81} 82 83define i1 @gep_add_nsw_positive_index(ptr %A, ptr %upper, i8 %idx) { 84; CHECK-LABEL: @gep_add_nsw_positive_index( 85; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0 86; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]]) 87; CHECK-NEXT: [[IDX_3:%.*]] = add nsw i8 [[IDX]], 3 88; CHECK-NEXT: [[ADD_I8_IDX_3:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i8 [[IDX_3]] 89; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_3]], [[UPPER:%.*]] 90; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 91; CHECK-NEXT: [[IDX_1:%.*]] = add nsw i8 [[IDX]], 1 92; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_1]] 93; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]] 94; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX_1]] 95; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true 96; CHECK-NEXT: [[ADD_I16_IDX_1:%.*]] = getelementptr inbounds i16, ptr [[A]], i8 [[IDX_1]] 97; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[ADD_I16_IDX_1]], [[UPPER]] 98; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_2]] 99; CHECK-NEXT: ret i1 [[RES_2]] 100; 101 %idx.pos = icmp sge i8 %idx, 0 102 call void @llvm.assume(i1 %idx.pos) 103 %idx.3 = add nsw i8 %idx, 3 104 %add.i8.idx.3 = getelementptr inbounds i8, ptr %A, i8 %idx.3 105 %c.0 = icmp ult ptr %add.i8.idx.3, %upper 106 call void @llvm.assume(i1 %c.0) 107 108 %idx.1 = add nsw i8 %idx, 1 109 %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i8 %idx.1 110 %c.1 = icmp ult ptr %add.i32.idx.1, %upper 111 %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i8 %idx.1 112 %t.1 = icmp ult ptr %add.i8.idx.1, %upper 113 %res.1 = xor i1 %c.1, %t.1 114 115 %add.i16.idx.1 = getelementptr inbounds i16, ptr %A, i8 %idx.1 116 %c.2 = icmp ult ptr %add.i16.idx.1, %upper 117 %res.2 = xor i1 %res.1, %c.2 118 ret i1 %res.2 119} 120 121 122define i1 @gep_shl_nsw_positive_index(ptr %A, ptr %upper, i8 %idx) { 123; CHECK-LABEL: @gep_shl_nsw_positive_index( 124; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0 125; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]]) 126; CHECK-NEXT: [[IDX_2:%.*]] = shl nsw i8 [[IDX]], 2 127; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i8 [[IDX_2]] 128; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]] 129; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 130; CHECK-NEXT: [[IDX_1:%.*]] = shl nsw i8 [[IDX]], 1 131; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_1]] 132; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]] 133; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX_1]] 134; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I8_IDX_1]], [[UPPER]] 135; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]] 136; CHECK-NEXT: ret i1 [[RES_1]] 137; 138 %idx.pos = icmp sge i8 %idx, 0 139 call void @llvm.assume(i1 %idx.pos) 140 %idx.2 = shl nsw i8 %idx, 2 141 %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i8 %idx.2 142 %c.0 = icmp ult ptr %add.i8.idx.2, %upper 143 call void @llvm.assume(i1 %c.0) 144 145 %idx.1 = shl nsw i8 %idx, 1 146 %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i8 %idx.1 147 %c.1 = icmp ult ptr %add.i32.idx.1, %upper 148 %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i8 %idx.1 149 %t.1 = icmp ult ptr %add.i8.idx.1, %upper 150 %res.1 = xor i1 %c.1, %t.1 151 ret i1 %res.1 152} 153 154define i1 @gep_zext_add_nuw_nsw_index(ptr %A, ptr %upper, i8 %idx) { 155; CHECK-LABEL: @gep_zext_add_nuw_nsw_index( 156; CHECK-NEXT: [[IDX_3:%.*]] = add nuw nsw i8 [[IDX:%.*]], 3 157; CHECK-NEXT: [[IDX_3_EXT:%.*]] = zext i8 [[IDX_3]] to i16 158; CHECK-NEXT: [[ADD_I8_IDX_3:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_3_EXT]] 159; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_3]], [[UPPER:%.*]] 160; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 161; CHECK-NEXT: [[IDX_1:%.*]] = add nuw nsw i8 [[IDX]], 1 162; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16 163; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]] 164; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]] 165; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]] 166; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true 167; CHECK-NEXT: [[ADD_I16_IDX_1:%.*]] = getelementptr inbounds i16, ptr [[A]], i16 [[IDX_1_EXT]] 168; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[ADD_I16_IDX_1]], [[UPPER]] 169; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_2]] 170; CHECK-NEXT: ret i1 [[RES_2]] 171; 172 %idx.3 = add nuw nsw i8 %idx, 3 173 %idx.3.ext = zext i8 %idx.3 to i16 174 %add.i8.idx.3 = getelementptr inbounds i8, ptr %A, i16 %idx.3.ext 175 %c.0 = icmp ult ptr %add.i8.idx.3, %upper 176 call void @llvm.assume(i1 %c.0) 177 178 %idx.1 = add nuw nsw i8 %idx, 1 179 %idx.1.ext = zext i8 %idx.1 to i16 180 %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext 181 %c.1 = icmp ult ptr %add.i32.idx.1, %upper 182 %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext 183 %t.1 = icmp ult ptr %add.i8.idx.1, %upper 184 %res.1 = xor i1 %c.1, %t.1 185 186 %add.i16.idx.1 = getelementptr inbounds i16, ptr %A, i16 %idx.1.ext 187 %c.2 = icmp ult ptr %add.i16.idx.1, %upper 188 %res.2 = xor i1 %res.1, %c.2 189 190 ret i1 %res.2 191} 192 193define i1 @gep_zext_add_nuw_index(ptr %A, ptr %upper, i8 %idx) { 194; CHECK-LABEL: @gep_zext_add_nuw_index( 195; CHECK-NEXT: [[IDX_2:%.*]] = add nuw i8 [[IDX:%.*]], 2 196; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16 197; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]] 198; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]] 199; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 200; CHECK-NEXT: [[IDX_1:%.*]] = add nuw i8 [[IDX]], 1 201; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16 202; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]] 203; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]] 204; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]] 205; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true 206; CHECK-NEXT: ret i1 [[RES_1]] 207; 208 %idx.2 = add nuw i8 %idx, 2 209 %idx.2.ext = zext i8 %idx.2 to i16 210 %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext 211 %c.0 = icmp ult ptr %add.i8.idx.2, %upper 212 call void @llvm.assume(i1 %c.0) 213 214 %idx.1 = add nuw i8 %idx, 1 215 %idx.1.ext = zext i8 %idx.1 to i16 216 %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext 217 %c.1 = icmp ult ptr %add.i32.idx.1, %upper 218 %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext 219 %t.1 = icmp ult ptr %add.i8.idx.1, %upper 220 %res.1 = xor i1 %c.1, %t.1 221 ret i1 %res.1 222} 223 224define i1 @gep_zext_add_nsw_index(ptr %A, ptr %upper, i8 %idx) { 225; CHECK-LABEL: @gep_zext_add_nsw_index( 226; CHECK-NEXT: [[IDX_2:%.*]] = add nsw i8 [[IDX:%.*]], 2 227; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16 228; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]] 229; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]] 230; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 231; CHECK-NEXT: [[IDX_1:%.*]] = add nsw i8 [[IDX]], 1 232; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16 233; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]] 234; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]] 235; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]] 236; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I8_IDX_1]], [[UPPER]] 237; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]] 238; CHECK-NEXT: ret i1 [[RES_1]] 239; 240 %idx.2 = add nsw i8 %idx, 2 241 %idx.2.ext = zext i8 %idx.2 to i16 242 %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext 243 %c.0 = icmp ult ptr %add.i8.idx.2, %upper 244 call void @llvm.assume(i1 %c.0) 245 246 %idx.1 = add nsw i8 %idx, 1 247 %idx.1.ext = zext i8 %idx.1 to i16 248 %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext 249 %c.1 = icmp ult ptr %add.i32.idx.1, %upper 250 %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext 251 %t.1 = icmp ult ptr %add.i8.idx.1, %upper 252 %res.1 = xor i1 %c.1, %t.1 253 ret i1 %res.1 254} 255 256define i1 @gep_zext_index(ptr %A, ptr %upper, i8 %idx.1, i8 %idx.2) { 257; CHECK-LABEL: @gep_zext_index( 258; CHECK-NEXT: [[C_0:%.*]] = icmp ult i8 [[IDX_1:%.*]], [[IDX_2:%.*]] 259; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 260; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16 261; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]] 262; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16 263; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]] 264; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[ADD_I8_IDX_2]] 265; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]] 266; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true 267; CHECK-NEXT: ret i1 [[RES_1]] 268; 269 %c.0 = icmp ult i8 %idx.1, %idx.2 270 call void @llvm.assume(i1 %c.0) 271 272 273 %idx.2.ext = zext i8 %idx.2 to i16 274 %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext 275 %idx.1.ext = zext i8 %idx.1 to i16 276 %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext 277 %c.1 = icmp ult ptr %add.i32.idx.1, %add.i8.idx.2 278 %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext 279 %t.1 = icmp ult ptr %add.i8.idx.1, %add.i8.idx.2 280 %res.1 = xor i1 %c.1, %t.1 281 ret i1 %res.1 282} 283 284define i1 @gep_zext_shl_nsw_index(ptr %A, ptr %upper, i8 %idx) { 285; CHECK-LABEL: @gep_zext_shl_nsw_index( 286; CHECK-NEXT: [[IDX_2:%.*]] = shl nsw i8 [[IDX:%.*]], 2 287; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16 288; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]] 289; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]] 290; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 291; CHECK-NEXT: [[IDX_1:%.*]] = shl nsw i8 [[IDX]], 1 292; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16 293; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]] 294; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]] 295; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]] 296; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I8_IDX_1]], [[UPPER]] 297; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]] 298; CHECK-NEXT: ret i1 [[RES_1]] 299; 300 %idx.2 = shl nsw i8 %idx, 2 301 %idx.2.ext = zext i8 %idx.2 to i16 302 %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext 303 %c.0 = icmp ult ptr %add.i8.idx.2, %upper 304 call void @llvm.assume(i1 %c.0) 305 306 %idx.1 = shl nsw i8 %idx, 1 307 %idx.1.ext = zext i8 %idx.1 to i16 308 %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext 309 %c.1 = icmp ult ptr %add.i32.idx.1, %upper 310 %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext 311 %t.1 = icmp ult ptr %add.i8.idx.1, %upper 312 %res.1 = xor i1 %c.1, %t.1 313 ret i1 %res.1 314} 315 316define i1 @gep_zext_shl_nuw_index(ptr %A, ptr %upper, i8 %idx) { 317; CHECK-LABEL: @gep_zext_shl_nuw_index( 318; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sgt i8 [[IDX:%.*]], 0 319; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]]) 320; CHECK-NEXT: [[IDX_2:%.*]] = shl nuw i8 [[IDX]], 2 321; CHECK-NEXT: [[IDX_2_EXT:%.*]] = zext i8 [[IDX_2]] to i16 322; CHECK-NEXT: [[ADD_I8_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i16 [[IDX_2_EXT]] 323; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_2]], [[UPPER:%.*]] 324; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 325; CHECK-NEXT: [[IDX_1:%.*]] = shl nuw i8 [[IDX]], 1 326; CHECK-NEXT: [[IDX_1_EXT:%.*]] = zext i8 [[IDX_1]] to i16 327; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i16 [[IDX_1_EXT]] 328; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]] 329; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i16 [[IDX_1_EXT]] 330; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true 331; CHECK-NEXT: ret i1 [[RES_1]] 332; 333 %idx.pos = icmp sgt i8 %idx, 0 334 call void @llvm.assume(i1 %idx.pos) 335 %idx.2 = shl nuw i8 %idx, 2 336 %idx.2.ext = zext i8 %idx.2 to i16 337 %add.i8.idx.2 = getelementptr inbounds i8, ptr %A, i16 %idx.2.ext 338 %c.0 = icmp ult ptr %add.i8.idx.2, %upper 339 call void @llvm.assume(i1 %c.0) 340 341 %idx.1 = shl nuw i8 %idx, 1 342 %idx.1.ext = zext i8 %idx.1 to i16 343 %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i16 %idx.1.ext 344 %c.1 = icmp ult ptr %add.i32.idx.1, %upper 345 %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i16 %idx.1.ext 346 %t.1 = icmp ult ptr %add.i8.idx.1, %upper 347 %res.1 = xor i1 %c.1, %t.1 348 ret i1 %res.1 349} 350 351%struct.t = type { i8, i8 } 352 353define i1 @gep_add_nsw_positive_index_struct(ptr %A, ptr %upper, i8 %idx) { 354; CHECK-LABEL: @gep_add_nsw_positive_index_struct( 355; CHECK-NEXT: [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0 356; CHECK-NEXT: call void @llvm.assume(i1 [[IDX_POS]]) 357; CHECK-NEXT: [[IDX_3:%.*]] = add nsw i8 [[IDX]], 2 358; CHECK-NEXT: [[ADD_I8_IDX_3:%.*]] = getelementptr inbounds [[STRUCT_T:%.*]], ptr [[A:%.*]], i8 [[IDX_3]] 359; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_IDX_3]], [[UPPER:%.*]] 360; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 361; CHECK-NEXT: [[IDX_1:%.*]] = add nsw i8 [[IDX]], 1 362; CHECK-NEXT: [[ADD_I32_IDX_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i8 [[IDX_1]] 363; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I32_IDX_1]], [[UPPER]] 364; CHECK-NEXT: [[ADD_I8_IDX_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i8 [[IDX_1]] 365; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], true 366; CHECK-NEXT: [[ADD_I16_IDX_1:%.*]] = getelementptr inbounds i16, ptr [[A]], i8 [[IDX_1]] 367; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], true 368; CHECK-NEXT: [[ADD_I64_IDX_1:%.*]] = getelementptr inbounds i64, ptr [[A]], i8 [[IDX_1]] 369; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I64_IDX_1]], [[UPPER]] 370; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[RES_2]], [[C_1]] 371; CHECK-NEXT: ret i1 [[RES_3]] 372; 373 %idx.pos = icmp sge i8 %idx, 0 374 call void @llvm.assume(i1 %idx.pos) 375 %idx.3 = add nsw i8 %idx, 2 376 %add.i8.idx.3 = getelementptr inbounds %struct.t, ptr %A, i8 %idx.3 377 %c.0 = icmp ult ptr %add.i8.idx.3, %upper 378 call void @llvm.assume(i1 %c.0) 379 380 %idx.1 = add nsw i8 %idx, 1 381 %add.i32.idx.1 = getelementptr inbounds i32, ptr %A, i8 %idx.1 382 %t.1 = icmp ult ptr %add.i32.idx.1, %upper 383 %add.i8.idx.1 = getelementptr inbounds i8, ptr %A, i8 %idx.1 384 %t.2 = icmp ult ptr %add.i8.idx.1, %upper 385 %res.1 = xor i1 %t.1, %t.2 386 387 %add.i16.idx.1 = getelementptr inbounds i16, ptr %A, i8 %idx.1 388 %t.3 = icmp ult ptr %add.i16.idx.1, %upper 389 %res.2 = xor i1 %res.1, %t.3 390 391 %add.i64.idx.1 = getelementptr inbounds i64, ptr %A, i8 %idx.1 392 %c.1 = icmp ult ptr %add.i64.idx.1, %upper 393 %res.3 = xor i1 %res.2, %c.1 394 395 ret i1 %res.3 396} 397 398define i1 @gep_constant_positive_index_fixed_vector_ty(ptr %A, ptr %upper) { 399; CHECK-LABEL: @gep_constant_positive_index_fixed_vector_ty( 400; CHECK-NEXT: [[ADD_I8_4:%.*]] = getelementptr inbounds <4 x i8>, ptr [[A:%.*]], i64 4 401; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]] 402; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 403; CHECK-NEXT: [[ADD_I16_4:%.*]] = getelementptr inbounds <4 x i16>, ptr [[A]], i64 4 404; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I16_4]], [[UPPER]] 405; CHECK-NEXT: [[ADD_I16_2:%.*]] = getelementptr inbounds <4 x i16>, ptr [[A]], i64 2 406; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], true 407; CHECK-NEXT: ret i1 [[RES_1]] 408; 409 %add.i8.4 = getelementptr inbounds <4 x i8>, ptr %A, i64 4 410 %c.0 = icmp ult ptr %add.i8.4, %upper 411 call void @llvm.assume(i1 %c.0) 412 413 %add.i16.4 = getelementptr inbounds <4 x i16>, ptr %A, i64 4 414 %c.1 = icmp ult ptr %add.i16.4, %upper 415 416 %add.i16.2 = getelementptr inbounds <4 x i16>, ptr %A, i64 2 417 %t.1 = icmp ult ptr %add.i16.2, %upper 418 %res.1 = xor i1 %c.1, %t.1 419 ret i1 %res.1 420} 421 422define i1 @gep_constant_positive_index_scalable_vector_ty(ptr %A, ptr %upper) { 423; CHECK-LABEL: @gep_constant_positive_index_scalable_vector_ty( 424; CHECK-NEXT: [[ADD_I8_4:%.*]] = getelementptr inbounds <vscale x 4 x i8>, ptr [[A:%.*]], i64 4 425; CHECK-NEXT: [[C_0:%.*]] = icmp ult ptr [[ADD_I8_4]], [[UPPER:%.*]] 426; CHECK-NEXT: call void @llvm.assume(i1 [[C_0]]) 427; CHECK-NEXT: [[ADD_I16_4:%.*]] = getelementptr inbounds <vscale x 4 x i16>, ptr [[A]], i64 4 428; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[ADD_I16_4]], [[UPPER]] 429; CHECK-NEXT: [[ADD_I16_2:%.*]] = getelementptr inbounds <vscale x 4 x i16>, ptr [[A]], i64 2 430; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[ADD_I16_2]], [[UPPER]] 431; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[T_1]] 432; CHECK-NEXT: ret i1 [[RES_1]] 433; 434 %add.i8.4 = getelementptr inbounds <vscale x 4 x i8>, ptr %A, i64 4 435 %c.0 = icmp ult ptr %add.i8.4, %upper 436 call void @llvm.assume(i1 %c.0) 437 438 %add.i16.4 = getelementptr inbounds <vscale x 4 x i16>, ptr %A, i64 4 439 %c.1 = icmp ult ptr %add.i16.4, %upper 440 441 %add.i16.2 = getelementptr inbounds <vscale x 4 x i16>, ptr %A, i64 2 442 %t.1 = icmp ult ptr %add.i16.2, %upper 443 %res.1 = xor i1 %c.1, %t.1 444 ret i1 %res.1 445} 446