brintos

brintos / llvm-project-archived public Read only

0
0
Text · 33.0 KiB · 30a5072 Raw
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