1032 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=riscv32-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,RV32,RV32I3; RUN: llc -mtriple=riscv64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,RV64,RV64I4; RUN: llc -mtriple=riscv32-unknown-linux-gnu -mattr=+zbb < %s | FileCheck %s --check-prefixes=CHECK,RV32,RV32ZBB5; RUN: llc -mtriple=riscv64-unknown-linux-gnu -mattr=+zbb < %s | FileCheck %s --check-prefixes=CHECK,RV64,RV64ZBB6 7; https://bugs.llvm.org/show_bug.cgi?id=381498 9; We are truncating from wider width, and then sign-extending10; back to the original width. Then we inequality-comparing orig and src.11; If they don't match, then we had signed truncation during truncation.12 13; This can be expressed in a several ways in IR:14; trunc + sext + icmp ne <- not canonical15; shl + ashr + icmp ne16; add + icmp ult/ule17; add + icmp uge/ugt18; However only the simplest form (with two shifts) gets lowered best.19 20; ---------------------------------------------------------------------------- ;21; shl + ashr + icmp ne22; ---------------------------------------------------------------------------- ;23 24define i1 @shifts_necmp_i16_i8(i16 %x) nounwind {25; RV32I-LABEL: shifts_necmp_i16_i8:26; RV32I: # %bb.0:27; RV32I-NEXT: slli a1, a0, 1628; RV32I-NEXT: slli a0, a0, 2429; RV32I-NEXT: srli a1, a1, 1630; RV32I-NEXT: srai a0, a0, 831; RV32I-NEXT: srli a0, a0, 1632; RV32I-NEXT: xor a0, a0, a133; RV32I-NEXT: snez a0, a034; RV32I-NEXT: ret35;36; RV64I-LABEL: shifts_necmp_i16_i8:37; RV64I: # %bb.0:38; RV64I-NEXT: slli a1, a0, 4839; RV64I-NEXT: slli a0, a0, 5640; RV64I-NEXT: srli a1, a1, 4841; RV64I-NEXT: srai a0, a0, 842; RV64I-NEXT: srli a0, a0, 4843; RV64I-NEXT: xor a0, a0, a144; RV64I-NEXT: snez a0, a045; RV64I-NEXT: ret46;47; RV32ZBB-LABEL: shifts_necmp_i16_i8:48; RV32ZBB: # %bb.0:49; RV32ZBB-NEXT: zext.h a1, a050; RV32ZBB-NEXT: sext.b a0, a051; RV32ZBB-NEXT: zext.h a0, a052; RV32ZBB-NEXT: xor a0, a0, a153; RV32ZBB-NEXT: snez a0, a054; RV32ZBB-NEXT: ret55;56; RV64ZBB-LABEL: shifts_necmp_i16_i8:57; RV64ZBB: # %bb.0:58; RV64ZBB-NEXT: zext.h a1, a059; RV64ZBB-NEXT: sext.b a0, a060; RV64ZBB-NEXT: zext.h a0, a061; RV64ZBB-NEXT: xor a0, a0, a162; RV64ZBB-NEXT: snez a0, a063; RV64ZBB-NEXT: ret64 %tmp0 = shl i16 %x, 8 ; 16-865 %tmp1 = ashr exact i16 %tmp0, 8 ; 16-866 %tmp2 = icmp ne i16 %tmp1, %x67 ret i1 %tmp268}69 70define i1 @shifts_necmp_i32_i16(i32 %x) nounwind {71; RV32I-LABEL: shifts_necmp_i32_i16:72; RV32I: # %bb.0:73; RV32I-NEXT: slli a1, a0, 1674; RV32I-NEXT: srai a1, a1, 1675; RV32I-NEXT: xor a0, a1, a076; RV32I-NEXT: snez a0, a077; RV32I-NEXT: ret78;79; RV64I-LABEL: shifts_necmp_i32_i16:80; RV64I: # %bb.0:81; RV64I-NEXT: sext.w a1, a082; RV64I-NEXT: slli a0, a0, 4883; RV64I-NEXT: srai a0, a0, 4884; RV64I-NEXT: xor a0, a0, a185; RV64I-NEXT: snez a0, a086; RV64I-NEXT: ret87;88; RV32ZBB-LABEL: shifts_necmp_i32_i16:89; RV32ZBB: # %bb.0:90; RV32ZBB-NEXT: sext.h a1, a091; RV32ZBB-NEXT: xor a0, a1, a092; RV32ZBB-NEXT: snez a0, a093; RV32ZBB-NEXT: ret94;95; RV64ZBB-LABEL: shifts_necmp_i32_i16:96; RV64ZBB: # %bb.0:97; RV64ZBB-NEXT: sext.w a1, a098; RV64ZBB-NEXT: sext.h a0, a099; RV64ZBB-NEXT: xor a0, a0, a1100; RV64ZBB-NEXT: snez a0, a0101; RV64ZBB-NEXT: ret102 %tmp0 = shl i32 %x, 16 ; 32-16103 %tmp1 = ashr exact i32 %tmp0, 16 ; 32-16104 %tmp2 = icmp ne i32 %tmp1, %x105 ret i1 %tmp2106}107 108define i1 @shifts_necmp_i32_i8(i32 %x) nounwind {109; RV32I-LABEL: shifts_necmp_i32_i8:110; RV32I: # %bb.0:111; RV32I-NEXT: slli a1, a0, 24112; RV32I-NEXT: srai a1, a1, 24113; RV32I-NEXT: xor a0, a1, a0114; RV32I-NEXT: snez a0, a0115; RV32I-NEXT: ret116;117; RV64I-LABEL: shifts_necmp_i32_i8:118; RV64I: # %bb.0:119; RV64I-NEXT: sext.w a1, a0120; RV64I-NEXT: slli a0, a0, 56121; RV64I-NEXT: srai a0, a0, 56122; RV64I-NEXT: xor a0, a0, a1123; RV64I-NEXT: snez a0, a0124; RV64I-NEXT: ret125;126; RV32ZBB-LABEL: shifts_necmp_i32_i8:127; RV32ZBB: # %bb.0:128; RV32ZBB-NEXT: sext.b a1, a0129; RV32ZBB-NEXT: xor a0, a1, a0130; RV32ZBB-NEXT: snez a0, a0131; RV32ZBB-NEXT: ret132;133; RV64ZBB-LABEL: shifts_necmp_i32_i8:134; RV64ZBB: # %bb.0:135; RV64ZBB-NEXT: sext.w a1, a0136; RV64ZBB-NEXT: sext.b a0, a0137; RV64ZBB-NEXT: xor a0, a0, a1138; RV64ZBB-NEXT: snez a0, a0139; RV64ZBB-NEXT: ret140 %tmp0 = shl i32 %x, 24 ; 32-8141 %tmp1 = ashr exact i32 %tmp0, 24 ; 32-8142 %tmp2 = icmp ne i32 %tmp1, %x143 ret i1 %tmp2144}145 146define i1 @shifts_necmp_i64_i32(i64 %x) nounwind {147; RV32-LABEL: shifts_necmp_i64_i32:148; RV32: # %bb.0:149; RV32-NEXT: srai a0, a0, 31150; RV32-NEXT: xor a0, a0, a1151; RV32-NEXT: snez a0, a0152; RV32-NEXT: ret153;154; RV64-LABEL: shifts_necmp_i64_i32:155; RV64: # %bb.0:156; RV64-NEXT: sext.w a1, a0157; RV64-NEXT: xor a0, a1, a0158; RV64-NEXT: snez a0, a0159; RV64-NEXT: ret160 %tmp0 = shl i64 %x, 32 ; 64-32161 %tmp1 = ashr exact i64 %tmp0, 32 ; 64-32162 %tmp2 = icmp ne i64 %tmp1, %x163 ret i1 %tmp2164}165 166define i1 @shifts_necmp_i64_i16(i64 %x) nounwind {167; RV32I-LABEL: shifts_necmp_i64_i16:168; RV32I: # %bb.0:169; RV32I-NEXT: slli a2, a0, 16170; RV32I-NEXT: srai a3, a2, 16171; RV32I-NEXT: srai a2, a2, 31172; RV32I-NEXT: xor a1, a2, a1173; RV32I-NEXT: xor a0, a3, a0174; RV32I-NEXT: or a0, a0, a1175; RV32I-NEXT: snez a0, a0176; RV32I-NEXT: ret177;178; RV64I-LABEL: shifts_necmp_i64_i16:179; RV64I: # %bb.0:180; RV64I-NEXT: slli a1, a0, 48181; RV64I-NEXT: srai a1, a1, 48182; RV64I-NEXT: xor a0, a1, a0183; RV64I-NEXT: snez a0, a0184; RV64I-NEXT: ret185;186; RV32ZBB-LABEL: shifts_necmp_i64_i16:187; RV32ZBB: # %bb.0:188; RV32ZBB-NEXT: sext.h a2, a0189; RV32ZBB-NEXT: srai a3, a2, 31190; RV32ZBB-NEXT: xor a0, a2, a0191; RV32ZBB-NEXT: xor a1, a3, a1192; RV32ZBB-NEXT: or a0, a0, a1193; RV32ZBB-NEXT: snez a0, a0194; RV32ZBB-NEXT: ret195;196; RV64ZBB-LABEL: shifts_necmp_i64_i16:197; RV64ZBB: # %bb.0:198; RV64ZBB-NEXT: sext.h a1, a0199; RV64ZBB-NEXT: xor a0, a1, a0200; RV64ZBB-NEXT: snez a0, a0201; RV64ZBB-NEXT: ret202 %tmp0 = shl i64 %x, 48 ; 64-16203 %tmp1 = ashr exact i64 %tmp0, 48 ; 64-16204 %tmp2 = icmp ne i64 %tmp1, %x205 ret i1 %tmp2206}207 208define i1 @shifts_necmp_i64_i8(i64 %x) nounwind {209; RV32I-LABEL: shifts_necmp_i64_i8:210; RV32I: # %bb.0:211; RV32I-NEXT: slli a2, a0, 24212; RV32I-NEXT: srai a3, a2, 24213; RV32I-NEXT: srai a2, a2, 31214; RV32I-NEXT: xor a1, a2, a1215; RV32I-NEXT: xor a0, a3, a0216; RV32I-NEXT: or a0, a0, a1217; RV32I-NEXT: snez a0, a0218; RV32I-NEXT: ret219;220; RV64I-LABEL: shifts_necmp_i64_i8:221; RV64I: # %bb.0:222; RV64I-NEXT: slli a1, a0, 56223; RV64I-NEXT: srai a1, a1, 56224; RV64I-NEXT: xor a0, a1, a0225; RV64I-NEXT: snez a0, a0226; RV64I-NEXT: ret227;228; RV32ZBB-LABEL: shifts_necmp_i64_i8:229; RV32ZBB: # %bb.0:230; RV32ZBB-NEXT: sext.b a2, a0231; RV32ZBB-NEXT: srai a3, a2, 31232; RV32ZBB-NEXT: xor a0, a2, a0233; RV32ZBB-NEXT: xor a1, a3, a1234; RV32ZBB-NEXT: or a0, a0, a1235; RV32ZBB-NEXT: snez a0, a0236; RV32ZBB-NEXT: ret237;238; RV64ZBB-LABEL: shifts_necmp_i64_i8:239; RV64ZBB: # %bb.0:240; RV64ZBB-NEXT: sext.b a1, a0241; RV64ZBB-NEXT: xor a0, a1, a0242; RV64ZBB-NEXT: snez a0, a0243; RV64ZBB-NEXT: ret244 %tmp0 = shl i64 %x, 56 ; 64-8245 %tmp1 = ashr exact i64 %tmp0, 56 ; 64-8246 %tmp2 = icmp ne i64 %tmp1, %x247 ret i1 %tmp2248}249 250; ---------------------------------------------------------------------------- ;251; add + icmp ult252; ---------------------------------------------------------------------------- ;253 254define i1 @add_ultcmp_i16_i8(i16 %x) nounwind {255; RV32I-LABEL: add_ultcmp_i16_i8:256; RV32I: # %bb.0:257; RV32I-NEXT: slli a0, a0, 16258; RV32I-NEXT: srli a0, a0, 16259; RV32I-NEXT: addi a0, a0, -128260; RV32I-NEXT: srli a0, a0, 8261; RV32I-NEXT: sltiu a0, a0, 255262; RV32I-NEXT: ret263;264; RV64I-LABEL: add_ultcmp_i16_i8:265; RV64I: # %bb.0:266; RV64I-NEXT: slli a0, a0, 48267; RV64I-NEXT: srli a0, a0, 48268; RV64I-NEXT: addi a0, a0, -128269; RV64I-NEXT: srli a0, a0, 8270; RV64I-NEXT: sltiu a0, a0, 255271; RV64I-NEXT: ret272;273; RV32ZBB-LABEL: add_ultcmp_i16_i8:274; RV32ZBB: # %bb.0:275; RV32ZBB-NEXT: zext.h a0, a0276; RV32ZBB-NEXT: addi a0, a0, -128277; RV32ZBB-NEXT: srli a0, a0, 8278; RV32ZBB-NEXT: sltiu a0, a0, 255279; RV32ZBB-NEXT: ret280;281; RV64ZBB-LABEL: add_ultcmp_i16_i8:282; RV64ZBB: # %bb.0:283; RV64ZBB-NEXT: zext.h a0, a0284; RV64ZBB-NEXT: addi a0, a0, -128285; RV64ZBB-NEXT: srli a0, a0, 8286; RV64ZBB-NEXT: sltiu a0, a0, 255287; RV64ZBB-NEXT: ret288 %tmp0 = add i16 %x, -128 ; ~0U << (8-1)289 %tmp1 = icmp ult i16 %tmp0, -256 ; ~0U << 8290 ret i1 %tmp1291}292 293define i1 @add_ultcmp_i32_i16(i32 %x) nounwind {294; RV32I-LABEL: add_ultcmp_i32_i16:295; RV32I: # %bb.0:296; RV32I-NEXT: lui a1, 1048568297; RV32I-NEXT: add a0, a0, a1298; RV32I-NEXT: lui a1, 1048560299; RV32I-NEXT: sltu a0, a0, a1300; RV32I-NEXT: ret301;302; RV64I-LABEL: add_ultcmp_i32_i16:303; RV64I: # %bb.0:304; RV64I-NEXT: lui a1, 1048568305; RV64I-NEXT: addw a0, a0, a1306; RV64I-NEXT: lui a1, 1048560307; RV64I-NEXT: sltu a0, a0, a1308; RV64I-NEXT: ret309;310; RV32ZBB-LABEL: add_ultcmp_i32_i16:311; RV32ZBB: # %bb.0:312; RV32ZBB-NEXT: sext.h a1, a0313; RV32ZBB-NEXT: xor a0, a1, a0314; RV32ZBB-NEXT: snez a0, a0315; RV32ZBB-NEXT: ret316;317; RV64ZBB-LABEL: add_ultcmp_i32_i16:318; RV64ZBB: # %bb.0:319; RV64ZBB-NEXT: sext.w a1, a0320; RV64ZBB-NEXT: sext.h a0, a0321; RV64ZBB-NEXT: xor a0, a0, a1322; RV64ZBB-NEXT: snez a0, a0323; RV64ZBB-NEXT: ret324 %tmp0 = add i32 %x, -32768 ; ~0U << (16-1)325 %tmp1 = icmp ult i32 %tmp0, -65536 ; ~0U << 16326 ret i1 %tmp1327}328 329define i1 @add_ultcmp_i32_i8(i32 %x) nounwind {330; RV32-LABEL: add_ultcmp_i32_i8:331; RV32: # %bb.0:332; RV32-NEXT: addi a0, a0, -128333; RV32-NEXT: sltiu a0, a0, -256334; RV32-NEXT: ret335;336; RV64-LABEL: add_ultcmp_i32_i8:337; RV64: # %bb.0:338; RV64-NEXT: addiw a0, a0, -128339; RV64-NEXT: sltiu a0, a0, -256340; RV64-NEXT: ret341 %tmp0 = add i32 %x, -128 ; ~0U << (8-1)342 %tmp1 = icmp ult i32 %tmp0, -256 ; ~0U << 8343 ret i1 %tmp1344}345 346define i1 @add_ultcmp_i64_i32(i64 %x) nounwind {347; RV32-LABEL: add_ultcmp_i64_i32:348; RV32: # %bb.0:349; RV32-NEXT: srai a0, a0, 31350; RV32-NEXT: xor a0, a0, a1351; RV32-NEXT: snez a0, a0352; RV32-NEXT: ret353;354; RV64-LABEL: add_ultcmp_i64_i32:355; RV64: # %bb.0:356; RV64-NEXT: sext.w a1, a0357; RV64-NEXT: xor a0, a1, a0358; RV64-NEXT: snez a0, a0359; RV64-NEXT: ret360 %tmp0 = add i64 %x, -2147483648 ; ~0U << (32-1)361 %tmp1 = icmp ult i64 %tmp0, -4294967296 ; ~0U << 32362 ret i1 %tmp1363}364 365define i1 @add_ultcmp_i64_i16(i64 %x) nounwind {366; RV32I-LABEL: add_ultcmp_i64_i16:367; RV32I: # %bb.0:368; RV32I-NEXT: lui a2, 1048568369; RV32I-NEXT: add a2, a0, a2370; RV32I-NEXT: sltu a0, a2, a0371; RV32I-NEXT: add a0, a1, a0372; RV32I-NEXT: lui a1, 1048560373; RV32I-NEXT: sltu a1, a2, a1374; RV32I-NEXT: snez a0, a0375; RV32I-NEXT: or a0, a1, a0376; RV32I-NEXT: ret377;378; RV64I-LABEL: add_ultcmp_i64_i16:379; RV64I: # %bb.0:380; RV64I-NEXT: lui a1, 1048568381; RV64I-NEXT: add a0, a0, a1382; RV64I-NEXT: lui a1, 1048560383; RV64I-NEXT: sltu a0, a0, a1384; RV64I-NEXT: ret385;386; RV32ZBB-LABEL: add_ultcmp_i64_i16:387; RV32ZBB: # %bb.0:388; RV32ZBB-NEXT: sext.h a2, a0389; RV32ZBB-NEXT: xor a0, a2, a0390; RV32ZBB-NEXT: srai a2, a2, 31391; RV32ZBB-NEXT: xor a1, a2, a1392; RV32ZBB-NEXT: or a0, a0, a1393; RV32ZBB-NEXT: snez a0, a0394; RV32ZBB-NEXT: ret395;396; RV64ZBB-LABEL: add_ultcmp_i64_i16:397; RV64ZBB: # %bb.0:398; RV64ZBB-NEXT: sext.h a1, a0399; RV64ZBB-NEXT: xor a0, a1, a0400; RV64ZBB-NEXT: snez a0, a0401; RV64ZBB-NEXT: ret402 %tmp0 = add i64 %x, -32768 ; ~0U << (16-1)403 %tmp1 = icmp ult i64 %tmp0, -65536 ; ~0U << 16404 ret i1 %tmp1405}406 407define i1 @add_ultcmp_i64_i8(i64 %x) nounwind {408; RV32I-LABEL: add_ultcmp_i64_i8:409; RV32I: # %bb.0:410; RV32I-NEXT: addi a2, a0, -128411; RV32I-NEXT: sltu a0, a2, a0412; RV32I-NEXT: add a0, a1, a0413; RV32I-NEXT: snez a0, a0414; RV32I-NEXT: sltiu a1, a2, -256415; RV32I-NEXT: or a0, a1, a0416; RV32I-NEXT: ret417;418; RV64-LABEL: add_ultcmp_i64_i8:419; RV64: # %bb.0:420; RV64-NEXT: addi a0, a0, -128421; RV64-NEXT: sltiu a0, a0, -256422; RV64-NEXT: ret423;424; RV32ZBB-LABEL: add_ultcmp_i64_i8:425; RV32ZBB: # %bb.0:426; RV32ZBB-NEXT: sext.b a2, a0427; RV32ZBB-NEXT: xor a0, a2, a0428; RV32ZBB-NEXT: srai a2, a2, 31429; RV32ZBB-NEXT: xor a1, a2, a1430; RV32ZBB-NEXT: or a0, a0, a1431; RV32ZBB-NEXT: snez a0, a0432; RV32ZBB-NEXT: ret433 %tmp0 = add i64 %x, -128 ; ~0U << (8-1)434 %tmp1 = icmp ult i64 %tmp0, -256 ; ~0U << 8435 ret i1 %tmp1436}437 438; Slightly more canonical variant439define i1 @add_ulecmp_i16_i8(i16 %x) nounwind {440; RV32I-LABEL: add_ulecmp_i16_i8:441; RV32I: # %bb.0:442; RV32I-NEXT: slli a0, a0, 16443; RV32I-NEXT: srli a0, a0, 16444; RV32I-NEXT: addi a0, a0, -128445; RV32I-NEXT: srli a0, a0, 8446; RV32I-NEXT: sltiu a0, a0, 255447; RV32I-NEXT: ret448;449; RV64I-LABEL: add_ulecmp_i16_i8:450; RV64I: # %bb.0:451; RV64I-NEXT: slli a0, a0, 48452; RV64I-NEXT: srli a0, a0, 48453; RV64I-NEXT: addi a0, a0, -128454; RV64I-NEXT: srli a0, a0, 8455; RV64I-NEXT: sltiu a0, a0, 255456; RV64I-NEXT: ret457;458; RV32ZBB-LABEL: add_ulecmp_i16_i8:459; RV32ZBB: # %bb.0:460; RV32ZBB-NEXT: zext.h a0, a0461; RV32ZBB-NEXT: addi a0, a0, -128462; RV32ZBB-NEXT: srli a0, a0, 8463; RV32ZBB-NEXT: sltiu a0, a0, 255464; RV32ZBB-NEXT: ret465;466; RV64ZBB-LABEL: add_ulecmp_i16_i8:467; RV64ZBB: # %bb.0:468; RV64ZBB-NEXT: zext.h a0, a0469; RV64ZBB-NEXT: addi a0, a0, -128470; RV64ZBB-NEXT: srli a0, a0, 8471; RV64ZBB-NEXT: sltiu a0, a0, 255472; RV64ZBB-NEXT: ret473 %tmp0 = add i16 %x, -128 ; ~0U << (8-1)474 %tmp1 = icmp ule i16 %tmp0, -257 ; ~0U << 8 - 1475 ret i1 %tmp1476}477 478; ---------------------------------------------------------------------------- ;479; add + icmp uge480; ---------------------------------------------------------------------------- ;481 482define i1 @add_ugecmp_i16_i8(i16 %x) nounwind {483; RV32I-LABEL: add_ugecmp_i16_i8:484; RV32I: # %bb.0:485; RV32I-NEXT: addi a0, a0, 128486; RV32I-NEXT: slli a0, a0, 16487; RV32I-NEXT: srli a0, a0, 16488; RV32I-NEXT: sltiu a0, a0, 256489; RV32I-NEXT: xori a0, a0, 1490; RV32I-NEXT: ret491;492; RV64I-LABEL: add_ugecmp_i16_i8:493; RV64I: # %bb.0:494; RV64I-NEXT: addi a0, a0, 128495; RV64I-NEXT: slli a0, a0, 48496; RV64I-NEXT: srli a0, a0, 48497; RV64I-NEXT: sltiu a0, a0, 256498; RV64I-NEXT: xori a0, a0, 1499; RV64I-NEXT: ret500;501; RV32ZBB-LABEL: add_ugecmp_i16_i8:502; RV32ZBB: # %bb.0:503; RV32ZBB-NEXT: addi a0, a0, 128504; RV32ZBB-NEXT: zext.h a0, a0505; RV32ZBB-NEXT: sltiu a0, a0, 256506; RV32ZBB-NEXT: xori a0, a0, 1507; RV32ZBB-NEXT: ret508;509; RV64ZBB-LABEL: add_ugecmp_i16_i8:510; RV64ZBB: # %bb.0:511; RV64ZBB-NEXT: addi a0, a0, 128512; RV64ZBB-NEXT: zext.h a0, a0513; RV64ZBB-NEXT: sltiu a0, a0, 256514; RV64ZBB-NEXT: xori a0, a0, 1515; RV64ZBB-NEXT: ret516 %tmp0 = add i16 %x, 128 ; 1U << (8-1)517 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8518 ret i1 %tmp1519}520 521define i1 @add_ugecmp_i32_i16(i32 %x) nounwind {522; RV32I-LABEL: add_ugecmp_i32_i16:523; RV32I: # %bb.0:524; RV32I-NEXT: lui a1, 8525; RV32I-NEXT: add a0, a0, a1526; RV32I-NEXT: srli a0, a0, 16527; RV32I-NEXT: snez a0, a0528; RV32I-NEXT: ret529;530; RV64I-LABEL: add_ugecmp_i32_i16:531; RV64I: # %bb.0:532; RV64I-NEXT: lui a1, 8533; RV64I-NEXT: add a0, a0, a1534; RV64I-NEXT: srliw a0, a0, 16535; RV64I-NEXT: snez a0, a0536; RV64I-NEXT: ret537;538; RV32ZBB-LABEL: add_ugecmp_i32_i16:539; RV32ZBB: # %bb.0:540; RV32ZBB-NEXT: sext.h a1, a0541; RV32ZBB-NEXT: xor a0, a1, a0542; RV32ZBB-NEXT: snez a0, a0543; RV32ZBB-NEXT: ret544;545; RV64ZBB-LABEL: add_ugecmp_i32_i16:546; RV64ZBB: # %bb.0:547; RV64ZBB-NEXT: sext.w a1, a0548; RV64ZBB-NEXT: sext.h a0, a0549; RV64ZBB-NEXT: xor a0, a0, a1550; RV64ZBB-NEXT: snez a0, a0551; RV64ZBB-NEXT: ret552 %tmp0 = add i32 %x, 32768 ; 1U << (16-1)553 %tmp1 = icmp uge i32 %tmp0, 65536 ; 1U << 16554 ret i1 %tmp1555}556 557define i1 @add_ugecmp_i32_i8(i32 %x) nounwind {558; RV32-LABEL: add_ugecmp_i32_i8:559; RV32: # %bb.0:560; RV32-NEXT: addi a0, a0, 128561; RV32-NEXT: sltiu a0, a0, 256562; RV32-NEXT: xori a0, a0, 1563; RV32-NEXT: ret564;565; RV64-LABEL: add_ugecmp_i32_i8:566; RV64: # %bb.0:567; RV64-NEXT: addiw a0, a0, 128568; RV64-NEXT: sltiu a0, a0, 256569; RV64-NEXT: xori a0, a0, 1570; RV64-NEXT: ret571 %tmp0 = add i32 %x, 128 ; 1U << (8-1)572 %tmp1 = icmp uge i32 %tmp0, 256 ; 1U << 8573 ret i1 %tmp1574}575 576define i1 @add_ugecmp_i64_i32(i64 %x) nounwind {577; RV32-LABEL: add_ugecmp_i64_i32:578; RV32: # %bb.0:579; RV32-NEXT: srai a0, a0, 31580; RV32-NEXT: xor a0, a0, a1581; RV32-NEXT: snez a0, a0582; RV32-NEXT: ret583;584; RV64-LABEL: add_ugecmp_i64_i32:585; RV64: # %bb.0:586; RV64-NEXT: sext.w a1, a0587; RV64-NEXT: xor a0, a1, a0588; RV64-NEXT: snez a0, a0589; RV64-NEXT: ret590 %tmp0 = add i64 %x, 2147483648 ; 1U << (32-1)591 %tmp1 = icmp uge i64 %tmp0, 4294967296 ; 1U << 32592 ret i1 %tmp1593}594 595define i1 @add_ugecmp_i64_i16(i64 %x) nounwind {596; RV32I-LABEL: add_ugecmp_i64_i16:597; RV32I: # %bb.0:598; RV32I-NEXT: lui a2, 8599; RV32I-NEXT: add a2, a0, a2600; RV32I-NEXT: sltu a0, a2, a0601; RV32I-NEXT: add a0, a1, a0602; RV32I-NEXT: srli a2, a2, 16603; RV32I-NEXT: or a0, a0, a2604; RV32I-NEXT: snez a0, a0605; RV32I-NEXT: ret606;607; RV64I-LABEL: add_ugecmp_i64_i16:608; RV64I: # %bb.0:609; RV64I-NEXT: lui a1, 8610; RV64I-NEXT: add a0, a0, a1611; RV64I-NEXT: srli a0, a0, 16612; RV64I-NEXT: snez a0, a0613; RV64I-NEXT: ret614;615; RV32ZBB-LABEL: add_ugecmp_i64_i16:616; RV32ZBB: # %bb.0:617; RV32ZBB-NEXT: sext.h a2, a0618; RV32ZBB-NEXT: xor a0, a2, a0619; RV32ZBB-NEXT: srai a2, a2, 31620; RV32ZBB-NEXT: xor a1, a2, a1621; RV32ZBB-NEXT: or a0, a0, a1622; RV32ZBB-NEXT: snez a0, a0623; RV32ZBB-NEXT: ret624;625; RV64ZBB-LABEL: add_ugecmp_i64_i16:626; RV64ZBB: # %bb.0:627; RV64ZBB-NEXT: sext.h a1, a0628; RV64ZBB-NEXT: xor a0, a1, a0629; RV64ZBB-NEXT: snez a0, a0630; RV64ZBB-NEXT: ret631 %tmp0 = add i64 %x, 32768 ; 1U << (16-1)632 %tmp1 = icmp uge i64 %tmp0, 65536 ; 1U << 16633 ret i1 %tmp1634}635 636define i1 @add_ugecmp_i64_i8(i64 %x) nounwind {637; RV32I-LABEL: add_ugecmp_i64_i8:638; RV32I: # %bb.0:639; RV32I-NEXT: addi a2, a0, 128640; RV32I-NEXT: sltu a0, a2, a0641; RV32I-NEXT: sltiu a2, a2, 256642; RV32I-NEXT: add a0, a1, a0643; RV32I-NEXT: snez a0, a0644; RV32I-NEXT: xori a1, a2, 1645; RV32I-NEXT: or a0, a1, a0646; RV32I-NEXT: ret647;648; RV64-LABEL: add_ugecmp_i64_i8:649; RV64: # %bb.0:650; RV64-NEXT: addi a0, a0, 128651; RV64-NEXT: sltiu a0, a0, 256652; RV64-NEXT: xori a0, a0, 1653; RV64-NEXT: ret654;655; RV32ZBB-LABEL: add_ugecmp_i64_i8:656; RV32ZBB: # %bb.0:657; RV32ZBB-NEXT: sext.b a2, a0658; RV32ZBB-NEXT: xor a0, a2, a0659; RV32ZBB-NEXT: srai a2, a2, 31660; RV32ZBB-NEXT: xor a1, a2, a1661; RV32ZBB-NEXT: or a0, a0, a1662; RV32ZBB-NEXT: snez a0, a0663; RV32ZBB-NEXT: ret664 %tmp0 = add i64 %x, 128 ; 1U << (8-1)665 %tmp1 = icmp uge i64 %tmp0, 256 ; 1U << 8666 ret i1 %tmp1667}668 669; Slightly more canonical variant670define i1 @add_ugtcmp_i16_i8(i16 %x) nounwind {671; RV32I-LABEL: add_ugtcmp_i16_i8:672; RV32I: # %bb.0:673; RV32I-NEXT: addi a0, a0, 128674; RV32I-NEXT: slli a0, a0, 16675; RV32I-NEXT: srli a0, a0, 16676; RV32I-NEXT: sltiu a0, a0, 256677; RV32I-NEXT: xori a0, a0, 1678; RV32I-NEXT: ret679;680; RV64I-LABEL: add_ugtcmp_i16_i8:681; RV64I: # %bb.0:682; RV64I-NEXT: addi a0, a0, 128683; RV64I-NEXT: slli a0, a0, 48684; RV64I-NEXT: srli a0, a0, 48685; RV64I-NEXT: sltiu a0, a0, 256686; RV64I-NEXT: xori a0, a0, 1687; RV64I-NEXT: ret688;689; RV32ZBB-LABEL: add_ugtcmp_i16_i8:690; RV32ZBB: # %bb.0:691; RV32ZBB-NEXT: addi a0, a0, 128692; RV32ZBB-NEXT: zext.h a0, a0693; RV32ZBB-NEXT: sltiu a0, a0, 256694; RV32ZBB-NEXT: xori a0, a0, 1695; RV32ZBB-NEXT: ret696;697; RV64ZBB-LABEL: add_ugtcmp_i16_i8:698; RV64ZBB: # %bb.0:699; RV64ZBB-NEXT: addi a0, a0, 128700; RV64ZBB-NEXT: zext.h a0, a0701; RV64ZBB-NEXT: sltiu a0, a0, 256702; RV64ZBB-NEXT: xori a0, a0, 1703; RV64ZBB-NEXT: ret704 %tmp0 = add i16 %x, 128 ; 1U << (8-1)705 %tmp1 = icmp ugt i16 %tmp0, 255 ; (1U << 8) - 1706 ret i1 %tmp1707}708 709; Negative tests710; ---------------------------------------------------------------------------- ;711 712; Adding not a constant713define i1 @add_ugecmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind {714; RV32I-LABEL: add_ugecmp_bad_i16_i8_add:715; RV32I: # %bb.0:716; RV32I-NEXT: add a0, a0, a1717; RV32I-NEXT: slli a0, a0, 16718; RV32I-NEXT: srli a0, a0, 16719; RV32I-NEXT: sltiu a0, a0, 256720; RV32I-NEXT: xori a0, a0, 1721; RV32I-NEXT: ret722;723; RV64I-LABEL: add_ugecmp_bad_i16_i8_add:724; RV64I: # %bb.0:725; RV64I-NEXT: add a0, a0, a1726; RV64I-NEXT: slli a0, a0, 48727; RV64I-NEXT: srli a0, a0, 48728; RV64I-NEXT: sltiu a0, a0, 256729; RV64I-NEXT: xori a0, a0, 1730; RV64I-NEXT: ret731;732; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_add:733; RV32ZBB: # %bb.0:734; RV32ZBB-NEXT: add a0, a0, a1735; RV32ZBB-NEXT: zext.h a0, a0736; RV32ZBB-NEXT: sltiu a0, a0, 256737; RV32ZBB-NEXT: xori a0, a0, 1738; RV32ZBB-NEXT: ret739;740; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_add:741; RV64ZBB: # %bb.0:742; RV64ZBB-NEXT: add a0, a0, a1743; RV64ZBB-NEXT: zext.h a0, a0744; RV64ZBB-NEXT: sltiu a0, a0, 256745; RV64ZBB-NEXT: xori a0, a0, 1746; RV64ZBB-NEXT: ret747 %tmp0 = add i16 %x, %y748 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8749 ret i1 %tmp1750}751 752; Comparing not with a constant753define i1 @add_ugecmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind {754; RV32I-LABEL: add_ugecmp_bad_i16_i8_cmp:755; RV32I: # %bb.0:756; RV32I-NEXT: lui a2, 16757; RV32I-NEXT: addi a0, a0, 128758; RV32I-NEXT: addi a2, a2, -1759; RV32I-NEXT: and a1, a1, a2760; RV32I-NEXT: and a0, a0, a2761; RV32I-NEXT: sltu a0, a0, a1762; RV32I-NEXT: xori a0, a0, 1763; RV32I-NEXT: ret764;765; RV64I-LABEL: add_ugecmp_bad_i16_i8_cmp:766; RV64I: # %bb.0:767; RV64I-NEXT: lui a2, 16768; RV64I-NEXT: addi a0, a0, 128769; RV64I-NEXT: addi a2, a2, -1770; RV64I-NEXT: and a1, a1, a2771; RV64I-NEXT: and a0, a0, a2772; RV64I-NEXT: sltu a0, a0, a1773; RV64I-NEXT: xori a0, a0, 1774; RV64I-NEXT: ret775;776; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_cmp:777; RV32ZBB: # %bb.0:778; RV32ZBB-NEXT: zext.h a1, a1779; RV32ZBB-NEXT: addi a0, a0, 128780; RV32ZBB-NEXT: zext.h a0, a0781; RV32ZBB-NEXT: sltu a0, a0, a1782; RV32ZBB-NEXT: xori a0, a0, 1783; RV32ZBB-NEXT: ret784;785; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_cmp:786; RV64ZBB: # %bb.0:787; RV64ZBB-NEXT: zext.h a1, a1788; RV64ZBB-NEXT: addi a0, a0, 128789; RV64ZBB-NEXT: zext.h a0, a0790; RV64ZBB-NEXT: sltu a0, a0, a1791; RV64ZBB-NEXT: xori a0, a0, 1792; RV64ZBB-NEXT: ret793 %tmp0 = add i16 %x, 128 ; 1U << (8-1)794 %tmp1 = icmp uge i16 %tmp0, %y795 ret i1 %tmp1796}797 798; Second constant is not larger than the first one799define i1 @add_ugecmp_bad_i8_i16(i16 %x) nounwind {800; RV32I-LABEL: add_ugecmp_bad_i8_i16:801; RV32I: # %bb.0:802; RV32I-NEXT: addi a0, a0, 128803; RV32I-NEXT: slli a0, a0, 16804; RV32I-NEXT: srli a0, a0, 16805; RV32I-NEXT: sltiu a0, a0, 128806; RV32I-NEXT: xori a0, a0, 1807; RV32I-NEXT: ret808;809; RV64I-LABEL: add_ugecmp_bad_i8_i16:810; RV64I: # %bb.0:811; RV64I-NEXT: addi a0, a0, 128812; RV64I-NEXT: slli a0, a0, 48813; RV64I-NEXT: srli a0, a0, 48814; RV64I-NEXT: sltiu a0, a0, 128815; RV64I-NEXT: xori a0, a0, 1816; RV64I-NEXT: ret817;818; RV32ZBB-LABEL: add_ugecmp_bad_i8_i16:819; RV32ZBB: # %bb.0:820; RV32ZBB-NEXT: addi a0, a0, 128821; RV32ZBB-NEXT: zext.h a0, a0822; RV32ZBB-NEXT: sltiu a0, a0, 128823; RV32ZBB-NEXT: xori a0, a0, 1824; RV32ZBB-NEXT: ret825;826; RV64ZBB-LABEL: add_ugecmp_bad_i8_i16:827; RV64ZBB: # %bb.0:828; RV64ZBB-NEXT: addi a0, a0, 128829; RV64ZBB-NEXT: zext.h a0, a0830; RV64ZBB-NEXT: sltiu a0, a0, 128831; RV64ZBB-NEXT: xori a0, a0, 1832; RV64ZBB-NEXT: ret833 %tmp0 = add i16 %x, 128 ; 1U << (8-1)834 %tmp1 = icmp uge i16 %tmp0, 128 ; 1U << (8-1)835 ret i1 %tmp1836}837 838; First constant is not power of two839define i1 @add_ugecmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind {840; RV32I-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:841; RV32I: # %bb.0:842; RV32I-NEXT: addi a0, a0, 192843; RV32I-NEXT: slli a0, a0, 16844; RV32I-NEXT: srli a0, a0, 16845; RV32I-NEXT: sltiu a0, a0, 256846; RV32I-NEXT: xori a0, a0, 1847; RV32I-NEXT: ret848;849; RV64I-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:850; RV64I: # %bb.0:851; RV64I-NEXT: addi a0, a0, 192852; RV64I-NEXT: slli a0, a0, 48853; RV64I-NEXT: srli a0, a0, 48854; RV64I-NEXT: sltiu a0, a0, 256855; RV64I-NEXT: xori a0, a0, 1856; RV64I-NEXT: ret857;858; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:859; RV32ZBB: # %bb.0:860; RV32ZBB-NEXT: addi a0, a0, 192861; RV32ZBB-NEXT: zext.h a0, a0862; RV32ZBB-NEXT: sltiu a0, a0, 256863; RV32ZBB-NEXT: xori a0, a0, 1864; RV32ZBB-NEXT: ret865;866; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:867; RV64ZBB: # %bb.0:868; RV64ZBB-NEXT: addi a0, a0, 192869; RV64ZBB-NEXT: zext.h a0, a0870; RV64ZBB-NEXT: sltiu a0, a0, 256871; RV64ZBB-NEXT: xori a0, a0, 1872; RV64ZBB-NEXT: ret873 %tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1))874 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8875 ret i1 %tmp1876}877 878; Second constant is not power of two879define i1 @add_ugecmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind {880; RV32I-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:881; RV32I: # %bb.0:882; RV32I-NEXT: addi a0, a0, 128883; RV32I-NEXT: slli a0, a0, 16884; RV32I-NEXT: srli a0, a0, 16885; RV32I-NEXT: sltiu a0, a0, 768886; RV32I-NEXT: xori a0, a0, 1887; RV32I-NEXT: ret888;889; RV64I-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:890; RV64I: # %bb.0:891; RV64I-NEXT: addi a0, a0, 128892; RV64I-NEXT: slli a0, a0, 48893; RV64I-NEXT: srli a0, a0, 48894; RV64I-NEXT: sltiu a0, a0, 768895; RV64I-NEXT: xori a0, a0, 1896; RV64I-NEXT: ret897;898; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:899; RV32ZBB: # %bb.0:900; RV32ZBB-NEXT: addi a0, a0, 128901; RV32ZBB-NEXT: zext.h a0, a0902; RV32ZBB-NEXT: sltiu a0, a0, 768903; RV32ZBB-NEXT: xori a0, a0, 1904; RV32ZBB-NEXT: ret905;906; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:907; RV64ZBB: # %bb.0:908; RV64ZBB-NEXT: addi a0, a0, 128909; RV64ZBB-NEXT: zext.h a0, a0910; RV64ZBB-NEXT: sltiu a0, a0, 768911; RV64ZBB-NEXT: xori a0, a0, 1912; RV64ZBB-NEXT: ret913 %tmp0 = add i16 %x, 128 ; 1U << (8-1)914 %tmp1 = icmp uge i16 %tmp0, 768 ; (1U << 8)) + (1U << (8+1))915 ret i1 %tmp1916}917 918; Magic check fails, 64 << 1 != 256919define i1 @add_ugecmp_bad_i16_i8_magic(i16 %x) nounwind {920; RV32I-LABEL: add_ugecmp_bad_i16_i8_magic:921; RV32I: # %bb.0:922; RV32I-NEXT: addi a0, a0, 64923; RV32I-NEXT: slli a0, a0, 16924; RV32I-NEXT: srli a0, a0, 16925; RV32I-NEXT: sltiu a0, a0, 256926; RV32I-NEXT: xori a0, a0, 1927; RV32I-NEXT: ret928;929; RV64I-LABEL: add_ugecmp_bad_i16_i8_magic:930; RV64I: # %bb.0:931; RV64I-NEXT: addi a0, a0, 64932; RV64I-NEXT: slli a0, a0, 48933; RV64I-NEXT: srli a0, a0, 48934; RV64I-NEXT: sltiu a0, a0, 256935; RV64I-NEXT: xori a0, a0, 1936; RV64I-NEXT: ret937;938; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_magic:939; RV32ZBB: # %bb.0:940; RV32ZBB-NEXT: addi a0, a0, 64941; RV32ZBB-NEXT: zext.h a0, a0942; RV32ZBB-NEXT: sltiu a0, a0, 256943; RV32ZBB-NEXT: xori a0, a0, 1944; RV32ZBB-NEXT: ret945;946; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_magic:947; RV64ZBB: # %bb.0:948; RV64ZBB-NEXT: addi a0, a0, 64949; RV64ZBB-NEXT: zext.h a0, a0950; RV64ZBB-NEXT: sltiu a0, a0, 256951; RV64ZBB-NEXT: xori a0, a0, 1952; RV64ZBB-NEXT: ret953 %tmp0 = add i16 %x, 64 ; 1U << (8-1-1)954 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8955 ret i1 %tmp1956}957 958; Bad 'destination type'959define i1 @add_ugecmp_bad_i16_i4(i16 %x) nounwind {960; RV32I-LABEL: add_ugecmp_bad_i16_i4:961; RV32I: # %bb.0:962; RV32I-NEXT: addi a0, a0, 8963; RV32I-NEXT: slli a0, a0, 16964; RV32I-NEXT: srli a0, a0, 16965; RV32I-NEXT: sltiu a0, a0, 16966; RV32I-NEXT: xori a0, a0, 1967; RV32I-NEXT: ret968;969; RV64I-LABEL: add_ugecmp_bad_i16_i4:970; RV64I: # %bb.0:971; RV64I-NEXT: addi a0, a0, 8972; RV64I-NEXT: slli a0, a0, 48973; RV64I-NEXT: srli a0, a0, 48974; RV64I-NEXT: sltiu a0, a0, 16975; RV64I-NEXT: xori a0, a0, 1976; RV64I-NEXT: ret977;978; RV32ZBB-LABEL: add_ugecmp_bad_i16_i4:979; RV32ZBB: # %bb.0:980; RV32ZBB-NEXT: addi a0, a0, 8981; RV32ZBB-NEXT: zext.h a0, a0982; RV32ZBB-NEXT: sltiu a0, a0, 16983; RV32ZBB-NEXT: xori a0, a0, 1984; RV32ZBB-NEXT: ret985;986; RV64ZBB-LABEL: add_ugecmp_bad_i16_i4:987; RV64ZBB: # %bb.0:988; RV64ZBB-NEXT: addi a0, a0, 8989; RV64ZBB-NEXT: zext.h a0, a0990; RV64ZBB-NEXT: sltiu a0, a0, 16991; RV64ZBB-NEXT: xori a0, a0, 1992; RV64ZBB-NEXT: ret993 %tmp0 = add i16 %x, 8 ; 1U << (4-1)994 %tmp1 = icmp uge i16 %tmp0, 16 ; 1U << 4995 ret i1 %tmp1996}997 998; Bad storage type999define i1 @add_ugecmp_bad_i24_i8(i24 %x) nounwind {1000; RV32-LABEL: add_ugecmp_bad_i24_i8:1001; RV32: # %bb.0:1002; RV32-NEXT: addi a0, a0, 1281003; RV32-NEXT: slli a0, a0, 81004; RV32-NEXT: srli a0, a0, 81005; RV32-NEXT: sltiu a0, a0, 2561006; RV32-NEXT: xori a0, a0, 11007; RV32-NEXT: ret1008;1009; RV64-LABEL: add_ugecmp_bad_i24_i8:1010; RV64: # %bb.0:1011; RV64-NEXT: addi a0, a0, 1281012; RV64-NEXT: slli a0, a0, 401013; RV64-NEXT: srli a0, a0, 401014; RV64-NEXT: sltiu a0, a0, 2561015; RV64-NEXT: xori a0, a0, 11016; RV64-NEXT: ret1017 %tmp0 = add i24 %x, 128 ; 1U << (8-1)1018 %tmp1 = icmp uge i24 %tmp0, 256 ; 1U << 81019 ret i1 %tmp11020}1021 1022; Slightly more canonical variant1023define i1 @add_ugtcmp_bad_i16_i8(i16 %x) nounwind {1024; CHECK-LABEL: add_ugtcmp_bad_i16_i8:1025; CHECK: # %bb.0:1026; CHECK-NEXT: li a0, 01027; CHECK-NEXT: ret1028 %tmp0 = add i16 %x, 128 ; 1U << (8-1)1029 %tmp1 = icmp ugt i16 %tmp0, -1 ; when we +1 it, it will wrap to 01030 ret i1 %tmp11031}1032