486 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4declare void @use8(i8)5 6declare void @use1(i1)7declare void @llvm.assume(i1)8 9; Here we don't know that at least one of the values being added is non-zero10define i1 @t0_bad(i8 %base, i8 %offset) {11; CHECK-LABEL: @t0_bad(12; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]13; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])14; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 015; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]16; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]17; CHECK-NEXT: ret i1 [[R]]18;19 %adjusted = add i8 %base, %offset20 call void @use8(i8 %adjusted)21 %not_null = icmp ne i8 %adjusted, 022 %no_underflow = icmp ult i8 %adjusted, %base23 %r = and i1 %not_null, %no_underflow24 ret i1 %r25}26 27define i1 @t0_bad_logical(i8 %base, i8 %offset) {28; CHECK-LABEL: @t0_bad_logical(29; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]30; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])31; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 032; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]33; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]34; CHECK-NEXT: ret i1 [[R]]35;36 %adjusted = add i8 %base, %offset37 call void @use8(i8 %adjusted)38 %not_null = icmp ne i8 %adjusted, 039 %no_underflow = icmp ult i8 %adjusted, %base40 %r = select i1 %not_null, i1 %no_underflow, i1 false41 ret i1 %r42}43 44; Ok, base is non-zero.45define i1 @t1(i8 %base, i8 %offset) {46; CHECK-LABEL: @t1(47; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 048; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])49; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]50; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])51; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]52; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]53; CHECK-NEXT: ret i1 [[R]]54;55 %cmp = icmp slt i8 %base, 056 call void @llvm.assume(i1 %cmp)57 58 %adjusted = add i8 %base, %offset59 call void @use8(i8 %adjusted)60 %not_null = icmp ne i8 %adjusted, 061 %no_underflow = icmp ult i8 %adjusted, %base62 %r = and i1 %not_null, %no_underflow63 ret i1 %r64}65 66define i1 @t1_logical(i8 %base, i8 %offset) {67; CHECK-LABEL: @t1_logical(68; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 069; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])70; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]71; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])72; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]73; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]74; CHECK-NEXT: ret i1 [[R]]75;76 %cmp = icmp slt i8 %base, 077 call void @llvm.assume(i1 %cmp)78 79 %adjusted = add i8 %base, %offset80 call void @use8(i8 %adjusted)81 %not_null = icmp ne i8 %adjusted, 082 %no_underflow = icmp ult i8 %adjusted, %base83 %r = select i1 %not_null, i1 %no_underflow, i1 false84 ret i1 %r85}86 87; Ok, offset is non-zero.88define i1 @t2(i8 %base, i8 %offset) {89; CHECK-LABEL: @t2(90; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[OFFSET:%.*]], 091; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])92; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET]]93; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])94; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]95; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[BASE]], [[TMP1]]96; CHECK-NEXT: ret i1 [[R]]97;98 %cmp = icmp slt i8 %offset, 099 call void @llvm.assume(i1 %cmp)100 101 %adjusted = add i8 %base, %offset102 call void @use8(i8 %adjusted)103 %not_null = icmp ne i8 %adjusted, 0104 %no_underflow = icmp ult i8 %adjusted, %base105 %r = and i1 %not_null, %no_underflow106 ret i1 %r107}108 109define i1 @t2_logical(i8 %base, i8 %offset) {110; CHECK-LABEL: @t2_logical(111; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[OFFSET:%.*]], 0112; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])113; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET]]114; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])115; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]116; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[BASE]], [[TMP1]]117; CHECK-NEXT: ret i1 [[R]]118;119 %cmp = icmp slt i8 %offset, 0120 call void @llvm.assume(i1 %cmp)121 122 %adjusted = add i8 %base, %offset123 call void @use8(i8 %adjusted)124 %not_null = icmp ne i8 %adjusted, 0125 %no_underflow = icmp ult i8 %adjusted, %base126 %r = select i1 %not_null, i1 %no_underflow, i1 false127 ret i1 %r128}129 130; We need to produce extra instruction, so one of icmp's must go away.131define i1 @t3_oneuse0(i8 %base, i8 %offset) {132; CHECK-LABEL: @t3_oneuse0(133; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0134; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])135; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]136; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])137; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0138; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])139; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]140; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]141; CHECK-NEXT: ret i1 [[R]]142;143 %cmp = icmp slt i8 %base, 0144 call void @llvm.assume(i1 %cmp)145 146 %adjusted = add i8 %base, %offset147 call void @use8(i8 %adjusted)148 %not_null = icmp ne i8 %adjusted, 0149 call void @use1(i1 %not_null)150 %no_underflow = icmp ult i8 %adjusted, %base151 %r = and i1 %not_null, %no_underflow152 ret i1 %r153}154 155define i1 @t3_oneuse0_logical(i8 %base, i8 %offset) {156; CHECK-LABEL: @t3_oneuse0_logical(157; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0158; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])159; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]160; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])161; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0162; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])163; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]164; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]165; CHECK-NEXT: ret i1 [[R]]166;167 %cmp = icmp slt i8 %base, 0168 call void @llvm.assume(i1 %cmp)169 170 %adjusted = add i8 %base, %offset171 call void @use8(i8 %adjusted)172 %not_null = icmp ne i8 %adjusted, 0173 call void @use1(i1 %not_null)174 %no_underflow = icmp ult i8 %adjusted, %base175 %r = select i1 %not_null, i1 %no_underflow, i1 false176 ret i1 %r177}178define i1 @t4_oneuse1(i8 %base, i8 %offset) {179; CHECK-LABEL: @t4_oneuse1(180; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0181; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])182; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]183; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])184; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]185; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])186; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]187; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]188; CHECK-NEXT: ret i1 [[R]]189;190 %cmp = icmp slt i8 %base, 0191 call void @llvm.assume(i1 %cmp)192 193 %adjusted = add i8 %base, %offset194 call void @use8(i8 %adjusted)195 %not_null = icmp ne i8 %adjusted, 0196 %no_underflow = icmp ult i8 %adjusted, %base197 call void @use1(i1 %no_underflow)198 %r = and i1 %not_null, %no_underflow199 ret i1 %r200}201 202define i1 @t4_oneuse1_logical(i8 %base, i8 %offset) {203; CHECK-LABEL: @t4_oneuse1_logical(204; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0205; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])206; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]207; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])208; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]209; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])210; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]211; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]212; CHECK-NEXT: ret i1 [[R]]213;214 %cmp = icmp slt i8 %base, 0215 call void @llvm.assume(i1 %cmp)216 217 %adjusted = add i8 %base, %offset218 call void @use8(i8 %adjusted)219 %not_null = icmp ne i8 %adjusted, 0220 %no_underflow = icmp ult i8 %adjusted, %base221 call void @use1(i1 %no_underflow)222 %r = select i1 %not_null, i1 %no_underflow, i1 false223 ret i1 %r224}225define i1 @t5_oneuse2_bad(i8 %base, i8 %offset) {226; CHECK-LABEL: @t5_oneuse2_bad(227; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0228; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])229; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]230; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])231; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0232; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])233; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]234; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])235; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]236; CHECK-NEXT: ret i1 [[R]]237;238 %cmp = icmp slt i8 %base, 0239 call void @llvm.assume(i1 %cmp)240 241 %adjusted = add i8 %base, %offset242 call void @use8(i8 %adjusted)243 %not_null = icmp ne i8 %adjusted, 0244 call void @use1(i1 %not_null)245 %no_underflow = icmp ult i8 %adjusted, %base246 call void @use1(i1 %no_underflow)247 %r = and i1 %not_null, %no_underflow248 ret i1 %r249}250 251define i1 @t5_oneuse2_bad_logical(i8 %base, i8 %offset) {252; CHECK-LABEL: @t5_oneuse2_bad_logical(253; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0254; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])255; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]256; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])257; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0258; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])259; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]260; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])261; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]262; CHECK-NEXT: ret i1 [[R]]263;264 %cmp = icmp slt i8 %base, 0265 call void @llvm.assume(i1 %cmp)266 267 %adjusted = add i8 %base, %offset268 call void @use8(i8 %adjusted)269 %not_null = icmp ne i8 %adjusted, 0270 call void @use1(i1 %not_null)271 %no_underflow = icmp ult i8 %adjusted, %base272 call void @use1(i1 %no_underflow)273 %r = select i1 %not_null, i1 %no_underflow, i1 false274 ret i1 %r275}276 277define i1 @t6_commutativity0(i8 %base, i8 %offset) {278; CHECK-LABEL: @t6_commutativity0(279; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0280; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])281; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]282; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])283; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]284; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]285; CHECK-NEXT: ret i1 [[R]]286;287 %cmp = icmp slt i8 %base, 0288 call void @llvm.assume(i1 %cmp)289 290 %adjusted = add i8 %base, %offset291 call void @use8(i8 %adjusted)292 %not_null = icmp ne i8 %adjusted, 0293 %no_underflow = icmp ult i8 %adjusted, %base294 %r = and i1 %no_underflow, %not_null ; swapped295 ret i1 %r296}297 298define i1 @t6_commutativity0_logical(i8 %base, i8 %offset) {299; CHECK-LABEL: @t6_commutativity0_logical(300; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0301; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])302; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]303; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])304; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]305; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]306; CHECK-NEXT: ret i1 [[R]]307;308 %cmp = icmp slt i8 %base, 0309 call void @llvm.assume(i1 %cmp)310 311 %adjusted = add i8 %base, %offset312 call void @use8(i8 %adjusted)313 %not_null = icmp ne i8 %adjusted, 0314 %no_underflow = icmp ult i8 %adjusted, %base315 %r = select i1 %no_underflow, i1 %not_null, i1 false ; swapped316 ret i1 %r317}318define i1 @t7_commutativity1(i8 %base, i8 %offset) {319; CHECK-LABEL: @t7_commutativity1(320; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0321; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])322; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]323; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])324; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]325; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]326; CHECK-NEXT: ret i1 [[R]]327;328 %cmp = icmp slt i8 %base, 0329 call void @llvm.assume(i1 %cmp)330 331 %adjusted = add i8 %base, %offset332 call void @use8(i8 %adjusted)333 %not_null = icmp ne i8 %adjusted, 0334 %no_underflow = icmp ugt i8 %base, %adjusted ; swapped335 %r = and i1 %not_null, %no_underflow336 ret i1 %r337}338 339define i1 @t7_commutativity1_logical(i8 %base, i8 %offset) {340; CHECK-LABEL: @t7_commutativity1_logical(341; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0342; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])343; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]344; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])345; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]346; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]347; CHECK-NEXT: ret i1 [[R]]348;349 %cmp = icmp slt i8 %base, 0350 call void @llvm.assume(i1 %cmp)351 352 %adjusted = add i8 %base, %offset353 call void @use8(i8 %adjusted)354 %not_null = icmp ne i8 %adjusted, 0355 %no_underflow = icmp ugt i8 %base, %adjusted ; swapped356 %r = select i1 %not_null, i1 %no_underflow, i1 false357 ret i1 %r358}359define i1 @t7_commutativity3(i8 %base, i8 %offset) {360; CHECK-LABEL: @t7_commutativity3(361; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0362; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])363; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]364; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])365; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]366; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]367; CHECK-NEXT: ret i1 [[R]]368;369 %cmp = icmp slt i8 %base, 0370 call void @llvm.assume(i1 %cmp)371 372 %adjusted = add i8 %base, %offset373 call void @use8(i8 %adjusted)374 %not_null = icmp ne i8 %adjusted, 0375 %no_underflow = icmp ugt i8 %base, %adjusted ; swapped376 %r = and i1 %no_underflow, %not_null ; swapped377 ret i1 %r378}379 380define i1 @t7_commutativity3_logical(i8 %base, i8 %offset) {381; CHECK-LABEL: @t7_commutativity3_logical(382; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0383; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])384; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]385; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])386; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]387; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]388; CHECK-NEXT: ret i1 [[R]]389;390 %cmp = icmp slt i8 %base, 0391 call void @llvm.assume(i1 %cmp)392 393 %adjusted = add i8 %base, %offset394 call void @use8(i8 %adjusted)395 %not_null = icmp ne i8 %adjusted, 0396 %no_underflow = icmp ugt i8 %base, %adjusted ; swapped397 %r = select i1 %no_underflow, i1 %not_null, i1 false ; swapped398 ret i1 %r399}400 401; We could have the opposite question, did we get null or overflow happened?402define i1 @t8(i8 %base, i8 %offset) {403; CHECK-LABEL: @t8(404; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0405; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])406; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]407; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])408; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]409; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[OFFSET]], [[TMP1]]410; CHECK-NEXT: ret i1 [[R]]411;412 %cmp = icmp slt i8 %base, 0413 call void @llvm.assume(i1 %cmp)414 415 %adjusted = add i8 %base, %offset416 call void @use8(i8 %adjusted)417 %not_null = icmp eq i8 %adjusted, 0418 %no_underflow = icmp uge i8 %adjusted, %base419 %r = or i1 %not_null, %no_underflow420 ret i1 %r421}422 423define i1 @t8_logical(i8 %base, i8 %offset) {424; CHECK-LABEL: @t8_logical(425; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0426; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])427; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]428; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])429; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]430; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[OFFSET]], [[TMP1]]431; CHECK-NEXT: ret i1 [[R]]432;433 %cmp = icmp slt i8 %base, 0434 call void @llvm.assume(i1 %cmp)435 436 %adjusted = add i8 %base, %offset437 call void @use8(i8 %adjusted)438 %not_null = icmp eq i8 %adjusted, 0439 %no_underflow = icmp uge i8 %adjusted, %base440 %r = select i1 %not_null, i1 true, i1 %no_underflow441 ret i1 %r442}443 444; The comparison can be with any of the values being added.445define i1 @t9(i8 %base, i8 %offset) {446; CHECK-LABEL: @t9(447; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0448; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])449; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]450; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])451; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]452; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]453; CHECK-NEXT: ret i1 [[R]]454;455 %cmp = icmp slt i8 %base, 0456 call void @llvm.assume(i1 %cmp)457 458 %adjusted = add i8 %base, %offset459 call void @use8(i8 %adjusted)460 %not_null = icmp ne i8 %adjusted, 0461 %no_underflow = icmp ult i8 %adjusted, %offset462 %r = and i1 %not_null, %no_underflow463 ret i1 %r464}465 466define i1 @t9_logical(i8 %base, i8 %offset) {467; CHECK-LABEL: @t9_logical(468; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0469; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])470; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]471; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])472; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]473; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[OFFSET]], [[TMP1]]474; CHECK-NEXT: ret i1 [[R]]475;476 %cmp = icmp slt i8 %base, 0477 call void @llvm.assume(i1 %cmp)478 479 %adjusted = add i8 %base, %offset480 call void @use8(i8 %adjusted)481 %not_null = icmp ne i8 %adjusted, 0482 %no_underflow = icmp ult i8 %adjusted, %offset483 %r = select i1 %not_null, i1 %no_underflow, i1 false484 ret i1 %r485}486