842 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; Here we subtract two values, check that subtraction did not overflow AND5; that the result is non-zero. This can be simplified just to a comparison6; between the base and offset.7 8declare void @use8(i8)9declare void @use64(i64)10declare void @use1(i1)11 12declare {i8, i1} @llvm.usub.with.overflow(i8, i8)13declare void @useagg({i8, i1})14 15declare void @llvm.assume(i1)16 17; There is a number of base patterns..18 19define i1 @t0_noncanonical_ignoreme(i8 %base, i8 %offset) {20; CHECK-LABEL: @t0_noncanonical_ignoreme(21; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]22; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])23; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]]24; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])25; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]26; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])27; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[OFFSET]], [[BASE]]28; CHECK-NEXT: ret i1 [[R]]29;30 %adjusted = sub i8 %base, %offset31 call void @use8(i8 %adjusted)32 %no_underflow = icmp ule i8 %adjusted, %base33 call void @use1(i1 %no_underflow)34 %not_null = icmp ne i8 %adjusted, 035 call void @use1(i1 %not_null)36 %r = and i1 %not_null, %no_underflow37 ret i1 %r38}39 40define i1 @t0_noncanonical_ignoreme_logical(i8 %base, i8 %offset) {41; CHECK-LABEL: @t0_noncanonical_ignoreme_logical(42; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]43; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])44; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]]45; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])46; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]47; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])48; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[OFFSET]], [[BASE]]49; CHECK-NEXT: ret i1 [[R]]50;51 %adjusted = sub i8 %base, %offset52 call void @use8(i8 %adjusted)53 %no_underflow = icmp ule i8 %adjusted, %base54 call void @use1(i1 %no_underflow)55 %not_null = icmp ne i8 %adjusted, 056 call void @use1(i1 %not_null)57 %r = select i1 %not_null, i1 %no_underflow, i1 false58 ret i1 %r59}60 61define i1 @t1(i8 %base, i8 %offset) {62; CHECK-LABEL: @t1(63; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]64; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])65; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]66; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])67; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]68; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])69; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]70; CHECK-NEXT: ret i1 [[R]]71;72 %adjusted = sub i8 %base, %offset73 call void @use8(i8 %adjusted)74 %no_underflow = icmp uge i8 %base, %offset75 call void @use1(i1 %no_underflow)76 %not_null = icmp ne i8 %adjusted, 077 call void @use1(i1 %not_null)78 %r = and i1 %not_null, %no_underflow79 ret i1 %r80}81 82define i1 @t1_logical(i8 %base, i8 %offset) {83; CHECK-LABEL: @t1_logical(84; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]85; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])86; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]87; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])88; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]89; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])90; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]91; CHECK-NEXT: ret i1 [[R]]92;93 %adjusted = sub i8 %base, %offset94 call void @use8(i8 %adjusted)95 %no_underflow = icmp uge i8 %base, %offset96 call void @use1(i1 %no_underflow)97 %not_null = icmp ne i8 %adjusted, 098 call void @use1(i1 %not_null)99 %r = select i1 %not_null, i1 %no_underflow, i1 false100 ret i1 %r101}102define i1 @t1_strict(i8 %base, i8 %offset) {103; CHECK-LABEL: @t1_strict(104; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]105; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])106; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]107; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])108; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]109; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])110; CHECK-NEXT: ret i1 [[NO_UNDERFLOW]]111;112 %adjusted = sub i8 %base, %offset113 call void @use8(i8 %adjusted)114 %no_underflow = icmp ugt i8 %base, %offset ; same is valid for strict predicate115 call void @use1(i1 %no_underflow)116 %not_null = icmp ne i8 %adjusted, 0117 call void @use1(i1 %not_null)118 %r = and i1 %not_null, %no_underflow119 ret i1 %r120}121 122define i1 @t1_strict_logical(i8 %base, i8 %offset) {123; CHECK-LABEL: @t1_strict_logical(124; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]125; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])126; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]127; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])128; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]129; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])130; CHECK-NEXT: ret i1 [[NO_UNDERFLOW]]131;132 %adjusted = sub i8 %base, %offset133 call void @use8(i8 %adjusted)134 %no_underflow = icmp ugt i8 %base, %offset ; same is valid for strict predicate135 call void @use1(i1 %no_underflow)136 %not_null = icmp ne i8 %adjusted, 0137 call void @use1(i1 %not_null)138 %r = select i1 %not_null, i1 %no_underflow, i1 false139 ret i1 %r140}141 142define i1 @t2(i8 %base, i8 %offset) {143; CHECK-LABEL: @t2(144; CHECK-NEXT: [[AGG:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[BASE:%.*]], i8 [[OFFSET:%.*]])145; CHECK-NEXT: call void @useagg({ i8, i1 } [[AGG]])146; CHECK-NEXT: [[ADJUSTED:%.*]] = extractvalue { i8, i1 } [[AGG]], 0147; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])148; CHECK-NEXT: [[UNDERFLOW:%.*]] = extractvalue { i8, i1 } [[AGG]], 1149; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])150; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = xor i1 [[UNDERFLOW]], true151; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])152; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0153; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]154; CHECK-NEXT: ret i1 [[R]]155;156 %agg = call {i8, i1} @llvm.usub.with.overflow(i8 %base, i8 %offset)157 call void @useagg({i8, i1} %agg)158 %adjusted = extractvalue {i8, i1} %agg, 0159 call void @use8(i8 %adjusted)160 %underflow = extractvalue {i8, i1} %agg, 1161 call void @use1(i1 %underflow)162 %no_underflow = xor i1 %underflow, -1163 call void @use1(i1 %no_underflow)164 %not_null = icmp ne i8 %adjusted, 0165 %r = and i1 %not_null, %no_underflow166 ret i1 %r167}168 169define i1 @t2_logical(i8 %base, i8 %offset) {170; CHECK-LABEL: @t2_logical(171; CHECK-NEXT: [[AGG:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[BASE:%.*]], i8 [[OFFSET:%.*]])172; CHECK-NEXT: call void @useagg({ i8, i1 } [[AGG]])173; CHECK-NEXT: [[ADJUSTED:%.*]] = extractvalue { i8, i1 } [[AGG]], 0174; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])175; CHECK-NEXT: [[UNDERFLOW:%.*]] = extractvalue { i8, i1 } [[AGG]], 1176; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])177; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = xor i1 [[UNDERFLOW]], true178; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])179; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0180; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]181; CHECK-NEXT: ret i1 [[R]]182;183 %agg = call {i8, i1} @llvm.usub.with.overflow(i8 %base, i8 %offset)184 call void @useagg({i8, i1} %agg)185 %adjusted = extractvalue {i8, i1} %agg, 0186 call void @use8(i8 %adjusted)187 %underflow = extractvalue {i8, i1} %agg, 1188 call void @use1(i1 %underflow)189 %no_underflow = xor i1 %underflow, -1190 call void @use1(i1 %no_underflow)191 %not_null = icmp ne i8 %adjusted, 0192 %r = select i1 %not_null, i1 %no_underflow, i1 false193 ret i1 %r194}195 196; Commutativity197 198define i1 @t3_commutability0(i8 %base, i8 %offset) {199; CHECK-LABEL: @t3_commutability0(200; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]201; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])202; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]]203; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])204; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]205; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])206; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[OFFSET]], [[BASE]]207; CHECK-NEXT: ret i1 [[R]]208;209 %adjusted = sub i8 %base, %offset210 call void @use8(i8 %adjusted)211 %no_underflow = icmp ule i8 %offset, %base ; swapped212 call void @use1(i1 %no_underflow)213 %not_null = icmp ne i8 %adjusted, 0214 call void @use1(i1 %not_null)215 %r = and i1 %not_null, %no_underflow216 ret i1 %r217}218 219define i1 @t3_commutability0_logical(i8 %base, i8 %offset) {220; CHECK-LABEL: @t3_commutability0_logical(221; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]222; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])223; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]]224; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])225; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]226; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])227; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[OFFSET]], [[BASE]]228; CHECK-NEXT: ret i1 [[R]]229;230 %adjusted = sub i8 %base, %offset231 call void @use8(i8 %adjusted)232 %no_underflow = icmp ule i8 %offset, %base ; swapped233 call void @use1(i1 %no_underflow)234 %not_null = icmp ne i8 %adjusted, 0235 call void @use1(i1 %not_null)236 %r = select i1 %not_null, i1 %no_underflow, i1 false237 ret i1 %r238}239define i1 @t4_commutability1(i8 %base, i8 %offset) {240; CHECK-LABEL: @t4_commutability1(241; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]242; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])243; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]244; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])245; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]246; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])247; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]248; CHECK-NEXT: ret i1 [[R]]249;250 %adjusted = sub i8 %base, %offset251 call void @use8(i8 %adjusted)252 %no_underflow = icmp uge i8 %base, %offset253 call void @use1(i1 %no_underflow)254 %not_null = icmp ne i8 %adjusted, 0255 call void @use1(i1 %not_null)256 %r = and i1 %no_underflow, %not_null ; swapped257 ret i1 %r258}259 260define i1 @t4_commutability1_logical(i8 %base, i8 %offset) {261; CHECK-LABEL: @t4_commutability1_logical(262; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]263; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])264; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]265; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])266; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]267; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])268; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]269; CHECK-NEXT: ret i1 [[R]]270;271 %adjusted = sub i8 %base, %offset272 call void @use8(i8 %adjusted)273 %no_underflow = icmp uge i8 %base, %offset274 call void @use1(i1 %no_underflow)275 %not_null = icmp ne i8 %adjusted, 0276 call void @use1(i1 %not_null)277 %r = select i1 %no_underflow, i1 %not_null, i1 false ; swapped278 ret i1 %r279}280define i1 @t5_commutability2(i8 %base, i8 %offset) {281; CHECK-LABEL: @t5_commutability2(282; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]283; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])284; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]]285; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])286; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]287; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])288; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]289; CHECK-NEXT: ret i1 [[R]]290;291 %adjusted = sub i8 %base, %offset292 call void @use8(i8 %adjusted)293 %no_underflow = icmp ule i8 %offset, %base ; swapped294 call void @use1(i1 %no_underflow)295 %not_null = icmp ne i8 %adjusted, 0296 call void @use1(i1 %not_null)297 %r = and i1 %no_underflow, %not_null ; swapped298 ret i1 %r299}300 301define i1 @t5_commutability2_logical(i8 %base, i8 %offset) {302; CHECK-LABEL: @t5_commutability2_logical(303; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]304; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])305; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]]306; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])307; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[BASE]], [[OFFSET]]308; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])309; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]310; CHECK-NEXT: ret i1 [[R]]311;312 %adjusted = sub i8 %base, %offset313 call void @use8(i8 %adjusted)314 %no_underflow = icmp ule i8 %offset, %base ; swapped315 call void @use1(i1 %no_underflow)316 %not_null = icmp ne i8 %adjusted, 0317 call void @use1(i1 %not_null)318 %r = select i1 %no_underflow, i1 %not_null, i1 false ; swapped319 ret i1 %r320}321 322define i1 @t6_commutability(i8 %base, i8 %offset) {323; CHECK-LABEL: @t6_commutability(324; CHECK-NEXT: [[AGG:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[BASE:%.*]], i8 [[OFFSET:%.*]])325; CHECK-NEXT: call void @useagg({ i8, i1 } [[AGG]])326; CHECK-NEXT: [[ADJUSTED:%.*]] = extractvalue { i8, i1 } [[AGG]], 0327; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])328; CHECK-NEXT: [[UNDERFLOW:%.*]] = extractvalue { i8, i1 } [[AGG]], 1329; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])330; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = xor i1 [[UNDERFLOW]], true331; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])332; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0333; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]334; CHECK-NEXT: ret i1 [[R]]335;336 %agg = call {i8, i1} @llvm.usub.with.overflow(i8 %base, i8 %offset)337 call void @useagg({i8, i1} %agg)338 %adjusted = extractvalue {i8, i1} %agg, 0339 call void @use8(i8 %adjusted)340 %underflow = extractvalue {i8, i1} %agg, 1341 call void @use1(i1 %underflow)342 %no_underflow = xor i1 %underflow, -1343 call void @use1(i1 %no_underflow)344 %not_null = icmp ne i8 %adjusted, 0345 %r = and i1 %no_underflow, %not_null ; swapped346 ret i1 %r347}348 349define i1 @t6_commutability_logical(i8 %base, i8 %offset) {350; CHECK-LABEL: @t6_commutability_logical(351; CHECK-NEXT: [[AGG:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[BASE:%.*]], i8 [[OFFSET:%.*]])352; CHECK-NEXT: call void @useagg({ i8, i1 } [[AGG]])353; CHECK-NEXT: [[ADJUSTED:%.*]] = extractvalue { i8, i1 } [[AGG]], 0354; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])355; CHECK-NEXT: [[UNDERFLOW:%.*]] = extractvalue { i8, i1 } [[AGG]], 1356; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])357; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = xor i1 [[UNDERFLOW]], true358; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])359; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0360; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]361; CHECK-NEXT: ret i1 [[R]]362;363 %agg = call {i8, i1} @llvm.usub.with.overflow(i8 %base, i8 %offset)364 call void @useagg({i8, i1} %agg)365 %adjusted = extractvalue {i8, i1} %agg, 0366 call void @use8(i8 %adjusted)367 %underflow = extractvalue {i8, i1} %agg, 1368 call void @use1(i1 %underflow)369 %no_underflow = xor i1 %underflow, -1370 call void @use1(i1 %no_underflow)371 %not_null = icmp ne i8 %adjusted, 0372 %r = select i1 %no_underflow, i1 %not_null, i1 false ; swapped373 ret i1 %r374}375 376; What if we were checking the opposite question, that we either got null,377; or overflow happened?378 379define i1 @t7(i8 %base, i8 %offset) {380; CHECK-LABEL: @t7(381; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]382; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])383; CHECK-NEXT: [[UNDERFLOW:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]]384; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])385; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[BASE]], [[OFFSET]]386; CHECK-NEXT: call void @use1(i1 [[NULL]])387; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]]388; CHECK-NEXT: ret i1 [[R]]389;390 %adjusted = sub i8 %base, %offset391 call void @use8(i8 %adjusted)392 %underflow = icmp ult i8 %base, %offset393 call void @use1(i1 %underflow)394 %null = icmp eq i8 %adjusted, 0395 call void @use1(i1 %null)396 %r = or i1 %null, %underflow397 ret i1 %r398}399 400define i1 @t7_logical(i8 %base, i8 %offset) {401; CHECK-LABEL: @t7_logical(402; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]403; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])404; CHECK-NEXT: [[UNDERFLOW:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]]405; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])406; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[BASE]], [[OFFSET]]407; CHECK-NEXT: call void @use1(i1 [[NULL]])408; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]]409; CHECK-NEXT: ret i1 [[R]]410;411 %adjusted = sub i8 %base, %offset412 call void @use8(i8 %adjusted)413 %underflow = icmp ult i8 %base, %offset414 call void @use1(i1 %underflow)415 %null = icmp eq i8 %adjusted, 0416 call void @use1(i1 %null)417 %r = select i1 %null, i1 true, i1 %underflow418 ret i1 %r419}420define i1 @t7_nonstrict(i8 %base, i8 %offset) {421; CHECK-LABEL: @t7_nonstrict(422; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]423; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])424; CHECK-NEXT: [[UNDERFLOW:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]]425; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])426; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[BASE]], [[OFFSET]]427; CHECK-NEXT: call void @use1(i1 [[NULL]])428; CHECK-NEXT: ret i1 [[UNDERFLOW]]429;430 %adjusted = sub i8 %base, %offset431 call void @use8(i8 %adjusted)432 %underflow = icmp ule i8 %base, %offset ; same is valid for non-strict predicate433 call void @use1(i1 %underflow)434 %null = icmp eq i8 %adjusted, 0435 call void @use1(i1 %null)436 %r = or i1 %null, %underflow437 ret i1 %r438}439 440define i1 @t7_nonstrict_logical(i8 %base, i8 %offset) {441; CHECK-LABEL: @t7_nonstrict_logical(442; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]443; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])444; CHECK-NEXT: [[UNDERFLOW:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]]445; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])446; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[BASE]], [[OFFSET]]447; CHECK-NEXT: call void @use1(i1 [[NULL]])448; CHECK-NEXT: ret i1 [[UNDERFLOW]]449;450 %adjusted = sub i8 %base, %offset451 call void @use8(i8 %adjusted)452 %underflow = icmp ule i8 %base, %offset ; same is valid for non-strict predicate453 call void @use1(i1 %underflow)454 %null = icmp eq i8 %adjusted, 0455 call void @use1(i1 %null)456 %r = select i1 %null, i1 true, i1 %underflow457 ret i1 %r458}459 460define i1 @t8(i8 %base, i8 %offset) {461; CHECK-LABEL: @t8(462; CHECK-NEXT: [[AGG:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[BASE:%.*]], i8 [[OFFSET:%.*]])463; CHECK-NEXT: call void @useagg({ i8, i1 } [[AGG]])464; CHECK-NEXT: [[ADJUSTED:%.*]] = extractvalue { i8, i1 } [[AGG]], 0465; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])466; CHECK-NEXT: [[UNDERFLOW:%.*]] = extractvalue { i8, i1 } [[AGG]], 1467; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])468; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0469; CHECK-NEXT: [[R:%.*]] = or i1 [[NULL]], [[UNDERFLOW]]470; CHECK-NEXT: ret i1 [[R]]471;472 %agg = call {i8, i1} @llvm.usub.with.overflow(i8 %base, i8 %offset)473 call void @useagg({i8, i1} %agg)474 %adjusted = extractvalue {i8, i1} %agg, 0475 call void @use8(i8 %adjusted)476 %underflow = extractvalue {i8, i1} %agg, 1477 call void @use1(i1 %underflow)478 %null = icmp eq i8 %adjusted, 0479 %r = or i1 %null, %underflow480 ret i1 %r481}482 483define i1 @t8_logical(i8 %base, i8 %offset) {484; CHECK-LABEL: @t8_logical(485; CHECK-NEXT: [[AGG:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[BASE:%.*]], i8 [[OFFSET:%.*]])486; CHECK-NEXT: call void @useagg({ i8, i1 } [[AGG]])487; CHECK-NEXT: [[ADJUSTED:%.*]] = extractvalue { i8, i1 } [[AGG]], 0488; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])489; CHECK-NEXT: [[UNDERFLOW:%.*]] = extractvalue { i8, i1 } [[AGG]], 1490; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])491; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0492; CHECK-NEXT: [[R:%.*]] = or i1 [[NULL]], [[UNDERFLOW]]493; CHECK-NEXT: ret i1 [[R]]494;495 %agg = call {i8, i1} @llvm.usub.with.overflow(i8 %base, i8 %offset)496 call void @useagg({i8, i1} %agg)497 %adjusted = extractvalue {i8, i1} %agg, 0498 call void @use8(i8 %adjusted)499 %underflow = extractvalue {i8, i1} %agg, 1500 call void @use1(i1 %underflow)501 %null = icmp eq i8 %adjusted, 0502 %r = select i1 %null, i1 true, i1 %underflow503 ret i1 %r504}505 506; And these patterns also have commutative variants507 508define i1 @t9_commutative(i8 %base, i8 %offset) {509; CHECK-LABEL: @t9_commutative(510; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]511; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])512; CHECK-NEXT: [[UNDERFLOW:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]]513; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])514; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[BASE]], [[OFFSET]]515; CHECK-NEXT: call void @use1(i1 [[NULL]])516; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]]517; CHECK-NEXT: ret i1 [[R]]518;519 %adjusted = sub i8 %base, %offset520 call void @use8(i8 %adjusted)521 %underflow = icmp ult i8 %base, %adjusted ; swapped522 call void @use1(i1 %underflow)523 %null = icmp eq i8 %adjusted, 0524 call void @use1(i1 %null)525 %r = or i1 %null, %underflow526 ret i1 %r527}528 529define i1 @t9_commutative_logical(i8 %base, i8 %offset) {530; CHECK-LABEL: @t9_commutative_logical(531; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]532; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])533; CHECK-NEXT: [[UNDERFLOW:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]]534; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]])535; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[BASE]], [[OFFSET]]536; CHECK-NEXT: call void @use1(i1 [[NULL]])537; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]]538; CHECK-NEXT: ret i1 [[R]]539;540 %adjusted = sub i8 %base, %offset541 call void @use8(i8 %adjusted)542 %underflow = icmp ult i8 %base, %adjusted ; swapped543 call void @use1(i1 %underflow)544 %null = icmp eq i8 %adjusted, 0545 call void @use1(i1 %null)546 %r = select i1 %null, i1 true, i1 %underflow547 ret i1 %r548}549 550;-------------------------------------------------------------------------------551 552define i1 @t10(i64 %base, ptr nonnull %offsetptr) {553; CHECK-LABEL: @t10(554; CHECK-NEXT: [[OFFSET:%.*]] = ptrtoint ptr [[OFFSETPTR:%.*]] to i64555; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET]]556; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])557; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i64 [[BASE]], [[OFFSET]]558; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])559; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i64 [[BASE]], [[OFFSET]]560; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])561; CHECK-NEXT: [[R:%.*]] = icmp ugt i64 [[BASE]], [[OFFSET]]562; CHECK-NEXT: ret i1 [[R]]563;564 %offset = ptrtoint ptr %offsetptr to i64565 566 %adjusted = sub i64 %base, %offset567 call void @use64(i64 %adjusted)568 %no_underflow = icmp ult i64 %adjusted, %base569 call void @use1(i1 %no_underflow)570 %not_null = icmp ne i64 %adjusted, 0571 call void @use1(i1 %not_null)572 %r = and i1 %not_null, %no_underflow573 ret i1 %r574}575 576define i1 @t10_logical(i64 %base, ptr nonnull %offsetptr) {577; CHECK-LABEL: @t10_logical(578; CHECK-NEXT: [[OFFSET:%.*]] = ptrtoint ptr [[OFFSETPTR:%.*]] to i64579; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET]]580; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])581; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i64 [[BASE]], [[OFFSET]]582; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])583; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i64 [[BASE]], [[OFFSET]]584; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])585; CHECK-NEXT: [[R:%.*]] = icmp ugt i64 [[BASE]], [[OFFSET]]586; CHECK-NEXT: ret i1 [[R]]587;588 %offset = ptrtoint ptr %offsetptr to i64589 590 %adjusted = sub i64 %base, %offset591 call void @use64(i64 %adjusted)592 %no_underflow = icmp ult i64 %adjusted, %base593 call void @use1(i1 %no_underflow)594 %not_null = icmp ne i64 %adjusted, 0595 call void @use1(i1 %not_null)596 %r = select i1 %not_null, i1 %no_underflow, i1 false597 ret i1 %r598}599define i1 @t11_commutative(i64 %base, ptr nonnull %offsetptr) {600; CHECK-LABEL: @t11_commutative(601; CHECK-NEXT: [[OFFSET:%.*]] = ptrtoint ptr [[OFFSETPTR:%.*]] to i64602; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET]]603; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])604; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i64 [[BASE]], [[OFFSET]]605; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])606; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i64 [[BASE]], [[OFFSET]]607; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])608; CHECK-NEXT: [[R:%.*]] = icmp ugt i64 [[BASE]], [[OFFSET]]609; CHECK-NEXT: ret i1 [[R]]610;611 %offset = ptrtoint ptr %offsetptr to i64612 613 %adjusted = sub i64 %base, %offset614 call void @use64(i64 %adjusted)615 %no_underflow = icmp ugt i64 %base, %adjusted ; swapped616 call void @use1(i1 %no_underflow)617 %not_null = icmp ne i64 %adjusted, 0618 call void @use1(i1 %not_null)619 %r = and i1 %not_null, %no_underflow620 ret i1 %r621}622 623define i1 @t11_commutative_logical(i64 %base, ptr nonnull %offsetptr) {624; CHECK-LABEL: @t11_commutative_logical(625; CHECK-NEXT: [[OFFSET:%.*]] = ptrtoint ptr [[OFFSETPTR:%.*]] to i64626; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET]]627; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])628; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i64 [[BASE]], [[OFFSET]]629; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])630; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i64 [[BASE]], [[OFFSET]]631; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])632; CHECK-NEXT: [[R:%.*]] = icmp ugt i64 [[BASE]], [[OFFSET]]633; CHECK-NEXT: ret i1 [[R]]634;635 %offset = ptrtoint ptr %offsetptr to i64636 637 %adjusted = sub i64 %base, %offset638 call void @use64(i64 %adjusted)639 %no_underflow = icmp ugt i64 %base, %adjusted ; swapped640 call void @use1(i1 %no_underflow)641 %not_null = icmp ne i64 %adjusted, 0642 call void @use1(i1 %not_null)643 %r = select i1 %not_null, i1 %no_underflow, i1 false644 ret i1 %r645}646 647define i1 @t12(i64 %base, ptr nonnull %offsetptr) {648; CHECK-LABEL: @t12(649; CHECK-NEXT: [[OFFSET:%.*]] = ptrtoint ptr [[OFFSETPTR:%.*]] to i64650; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET]]651; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])652; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i64 [[BASE]], [[OFFSET]]653; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])654; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i64 [[BASE]], [[OFFSET]]655; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])656; CHECK-NEXT: [[R:%.*]] = icmp ule i64 [[BASE]], [[OFFSET]]657; CHECK-NEXT: ret i1 [[R]]658;659 %offset = ptrtoint ptr %offsetptr to i64660 661 %adjusted = sub i64 %base, %offset662 call void @use64(i64 %adjusted)663 %no_underflow = icmp uge i64 %adjusted, %base664 call void @use1(i1 %no_underflow)665 %not_null = icmp eq i64 %adjusted, 0666 call void @use1(i1 %not_null)667 %r = or i1 %not_null, %no_underflow668 ret i1 %r669}670 671define i1 @t12_logical(i64 %base, ptr nonnull %offsetptr) {672; CHECK-LABEL: @t12_logical(673; CHECK-NEXT: [[OFFSET:%.*]] = ptrtoint ptr [[OFFSETPTR:%.*]] to i64674; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET]]675; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])676; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i64 [[BASE]], [[OFFSET]]677; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])678; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i64 [[BASE]], [[OFFSET]]679; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])680; CHECK-NEXT: [[R:%.*]] = icmp ule i64 [[BASE]], [[OFFSET]]681; CHECK-NEXT: ret i1 [[R]]682;683 %offset = ptrtoint ptr %offsetptr to i64684 685 %adjusted = sub i64 %base, %offset686 call void @use64(i64 %adjusted)687 %no_underflow = icmp uge i64 %adjusted, %base688 call void @use1(i1 %no_underflow)689 %not_null = icmp eq i64 %adjusted, 0690 call void @use1(i1 %not_null)691 %r = select i1 %not_null, i1 true, i1 %no_underflow692 ret i1 %r693}694define i1 @t13(i64 %base, ptr nonnull %offsetptr) {695; CHECK-LABEL: @t13(696; CHECK-NEXT: [[OFFSET:%.*]] = ptrtoint ptr [[OFFSETPTR:%.*]] to i64697; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET]]698; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])699; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i64 [[BASE]], [[OFFSET]]700; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])701; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i64 [[BASE]], [[OFFSET]]702; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])703; CHECK-NEXT: [[R:%.*]] = icmp ule i64 [[BASE]], [[OFFSET]]704; CHECK-NEXT: ret i1 [[R]]705;706 %offset = ptrtoint ptr %offsetptr to i64707 708 %adjusted = sub i64 %base, %offset709 call void @use64(i64 %adjusted)710 %no_underflow = icmp ule i64 %base, %adjusted ; swapped711 call void @use1(i1 %no_underflow)712 %not_null = icmp eq i64 %adjusted, 0713 call void @use1(i1 %not_null)714 %r = or i1 %not_null, %no_underflow715 ret i1 %r716}717 718define i1 @t13_logical(i64 %base, ptr nonnull %offsetptr) {719; CHECK-LABEL: @t13_logical(720; CHECK-NEXT: [[OFFSET:%.*]] = ptrtoint ptr [[OFFSETPTR:%.*]] to i64721; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET]]722; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])723; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i64 [[BASE]], [[OFFSET]]724; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])725; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i64 [[BASE]], [[OFFSET]]726; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])727; CHECK-NEXT: [[R:%.*]] = icmp ule i64 [[BASE]], [[OFFSET]]728; CHECK-NEXT: ret i1 [[R]]729;730 %offset = ptrtoint ptr %offsetptr to i64731 732 %adjusted = sub i64 %base, %offset733 call void @use64(i64 %adjusted)734 %no_underflow = icmp ule i64 %base, %adjusted ; swapped735 call void @use1(i1 %no_underflow)736 %not_null = icmp eq i64 %adjusted, 0737 call void @use1(i1 %not_null)738 %r = select i1 %not_null, i1 true, i1 %no_underflow739 ret i1 %r740}741 742define i1 @t14_bad(i64 %base, i64 %offset) {743; CHECK-LABEL: @t14_bad(744; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET:%.*]]745; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])746; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i64 [[ADJUSTED]], [[BASE]]747; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])748; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i64 [[BASE]], [[OFFSET]]749; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])750; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]751; CHECK-NEXT: ret i1 [[R]]752;753 %adjusted = sub i64 %base, %offset754 call void @use64(i64 %adjusted)755 %no_underflow = icmp ult i64 %adjusted, %base756 call void @use1(i1 %no_underflow)757 %not_null = icmp ne i64 %adjusted, 0758 call void @use1(i1 %not_null)759 %r = and i1 %not_null, %no_underflow760 ret i1 %r761}762 763define i1 @t14_bad_logical(i64 %base, i64 %offset) {764; CHECK-LABEL: @t14_bad_logical(765; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i64 [[BASE:%.*]], [[OFFSET:%.*]]766; CHECK-NEXT: call void @use64(i64 [[ADJUSTED]])767; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i64 [[ADJUSTED]], [[BASE]]768; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])769; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i64 [[BASE]], [[OFFSET]]770; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])771; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]772; CHECK-NEXT: ret i1 [[R]]773;774 %adjusted = sub i64 %base, %offset775 call void @use64(i64 %adjusted)776 %no_underflow = icmp ult i64 %adjusted, %base777 call void @use1(i1 %no_underflow)778 %not_null = icmp ne i64 %adjusted, 0779 call void @use1(i1 %not_null)780 %r = select i1 %not_null, i1 %no_underflow, i1 false781 ret i1 %r782}783 784define i1 @base_ult_offset(i8 %base, i8 %offset) {785; CHECK-LABEL: @base_ult_offset(786; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]787; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])788; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]]789; CHECK-NEXT: ret i1 [[R]]790;791 %adjusted = sub i8 %base, %offset792 call void @use8(i8 %adjusted)793 %not_null = icmp ne i8 %adjusted, 0794 %no_underflow = icmp ule i8 %base, %offset795 %r = and i1 %no_underflow, %not_null796 ret i1 %r797}798 799define i1 @base_ult_offset_logical(i8 %base, i8 %offset) {800; CHECK-LABEL: @base_ult_offset_logical(801; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]802; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])803; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]]804; CHECK-NEXT: ret i1 [[R]]805;806 %adjusted = sub i8 %base, %offset807 call void @use8(i8 %adjusted)808 %not_null = icmp ne i8 %adjusted, 0809 %no_underflow = icmp ule i8 %base, %offset810 %r = select i1 %no_underflow, i1 %not_null, i1 false811 ret i1 %r812}813define i1 @base_uge_offset(i8 %base, i8 %offset) {814; CHECK-LABEL: @base_uge_offset(815; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]816; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])817; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]818; CHECK-NEXT: ret i1 [[R]]819;820 %adjusted = sub i8 %base, %offset821 call void @use8(i8 %adjusted)822 %not_null = icmp eq i8 %adjusted, 0823 %no_underflow = icmp ugt i8 %base, %offset824 %r = or i1 %no_underflow, %not_null825 ret i1 %r826}827 828define i1 @base_uge_offset_logical(i8 %base, i8 %offset) {829; CHECK-LABEL: @base_uge_offset_logical(830; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]831; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])832; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]833; CHECK-NEXT: ret i1 [[R]]834;835 %adjusted = sub i8 %base, %offset836 call void @use8(i8 %adjusted)837 %not_null = icmp eq i8 %adjusted, 0838 %no_underflow = icmp ugt i8 %base, %offset839 %r = select i1 %no_underflow, i1 true, i1 %not_null840 ret i1 %r841}842