1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=riscv32 -mattr=+m | FileCheck %s --check-prefix=RV32I 3; RUN: llc < %s -mtriple=riscv64 -mattr=+m | FileCheck %s --check-prefix=RV64I 4; RUN: llc < %s -mtriple=riscv32 -mattr=+m,+zbb | FileCheck %s --check-prefix=RV32IZbb 5; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+zbb | FileCheck %s --check-prefix=RV64IZbb 6 7declare i4 @llvm.uadd.sat.i4(i4, i4) 8declare i8 @llvm.uadd.sat.i8(i8, i8) 9declare i16 @llvm.uadd.sat.i16(i16, i16) 10declare i32 @llvm.uadd.sat.i32(i32, i32) 11declare i64 @llvm.uadd.sat.i64(i64, i64) 12 13define i32 @func32(i32 %x, i32 %y, i32 %z) nounwind { 14; RV32I-LABEL: func32: 15; RV32I: # %bb.0: 16; RV32I-NEXT: mul a1, a1, a2 17; RV32I-NEXT: add a1, a0, a1 18; RV32I-NEXT: sltu a0, a1, a0 19; RV32I-NEXT: neg a0, a0 20; RV32I-NEXT: or a0, a0, a1 21; RV32I-NEXT: ret 22; 23; RV64I-LABEL: func32: 24; RV64I: # %bb.0: 25; RV64I-NEXT: mul a1, a1, a2 26; RV64I-NEXT: addw a1, a0, a1 27; RV64I-NEXT: sext.w a0, a0 28; RV64I-NEXT: sltu a0, a1, a0 29; RV64I-NEXT: neg a0, a0 30; RV64I-NEXT: or a0, a0, a1 31; RV64I-NEXT: ret 32; 33; RV32IZbb-LABEL: func32: 34; RV32IZbb: # %bb.0: 35; RV32IZbb-NEXT: mul a1, a1, a2 36; RV32IZbb-NEXT: not a2, a1 37; RV32IZbb-NEXT: minu a0, a0, a2 38; RV32IZbb-NEXT: add a0, a0, a1 39; RV32IZbb-NEXT: ret 40; 41; RV64IZbb-LABEL: func32: 42; RV64IZbb: # %bb.0: 43; RV64IZbb-NEXT: sext.w a0, a0 44; RV64IZbb-NEXT: mulw a1, a1, a2 45; RV64IZbb-NEXT: not a2, a1 46; RV64IZbb-NEXT: minu a0, a0, a2 47; RV64IZbb-NEXT: add a0, a0, a1 48; RV64IZbb-NEXT: ret 49 %a = mul i32 %y, %z 50 %tmp = call i32 @llvm.uadd.sat.i32(i32 %x, i32 %a) 51 ret i32 %tmp 52} 53 54define i64 @func64(i64 %x, i64 %y, i64 %z) nounwind { 55; RV32I-LABEL: func64: 56; RV32I: # %bb.0: 57; RV32I-NEXT: add a2, a1, a5 58; RV32I-NEXT: add a4, a0, a4 59; RV32I-NEXT: sltu a0, a4, a0 60; RV32I-NEXT: add a2, a2, a0 61; RV32I-NEXT: beq a2, a1, .LBB1_2 62; RV32I-NEXT: # %bb.1: 63; RV32I-NEXT: sltu a0, a2, a1 64; RV32I-NEXT: .LBB1_2: 65; RV32I-NEXT: neg a1, a0 66; RV32I-NEXT: or a0, a1, a4 67; RV32I-NEXT: or a1, a1, a2 68; RV32I-NEXT: ret 69; 70; RV64I-LABEL: func64: 71; RV64I: # %bb.0: 72; RV64I-NEXT: add a2, a0, a2 73; RV64I-NEXT: sltu a0, a2, a0 74; RV64I-NEXT: neg a0, a0 75; RV64I-NEXT: or a0, a0, a2 76; RV64I-NEXT: ret 77; 78; RV32IZbb-LABEL: func64: 79; RV32IZbb: # %bb.0: 80; RV32IZbb-NEXT: add a2, a1, a5 81; RV32IZbb-NEXT: add a4, a0, a4 82; RV32IZbb-NEXT: sltu a0, a4, a0 83; RV32IZbb-NEXT: add a2, a2, a0 84; RV32IZbb-NEXT: beq a2, a1, .LBB1_2 85; RV32IZbb-NEXT: # %bb.1: 86; RV32IZbb-NEXT: sltu a0, a2, a1 87; RV32IZbb-NEXT: .LBB1_2: 88; RV32IZbb-NEXT: neg a1, a0 89; RV32IZbb-NEXT: or a0, a1, a4 90; RV32IZbb-NEXT: or a1, a1, a2 91; RV32IZbb-NEXT: ret 92; 93; RV64IZbb-LABEL: func64: 94; RV64IZbb: # %bb.0: 95; RV64IZbb-NEXT: not a1, a2 96; RV64IZbb-NEXT: minu a0, a0, a1 97; RV64IZbb-NEXT: add a0, a0, a2 98; RV64IZbb-NEXT: ret 99 %a = mul i64 %y, %z 100 %tmp = call i64 @llvm.uadd.sat.i64(i64 %x, i64 %z) 101 ret i64 %tmp 102} 103 104define i16 @func16(i16 %x, i16 %y, i16 %z) nounwind { 105; RV32I-LABEL: func16: 106; RV32I: # %bb.0: 107; RV32I-NEXT: lui a3, 16 108; RV32I-NEXT: mul a2, a1, a2 109; RV32I-NEXT: addi a1, a3, -1 110; RV32I-NEXT: and a0, a0, a1 111; RV32I-NEXT: and a2, a2, a1 112; RV32I-NEXT: add a0, a0, a2 113; RV32I-NEXT: bltu a0, a1, .LBB2_2 114; RV32I-NEXT: # %bb.1: 115; RV32I-NEXT: mv a0, a1 116; RV32I-NEXT: .LBB2_2: 117; RV32I-NEXT: ret 118; 119; RV64I-LABEL: func16: 120; RV64I: # %bb.0: 121; RV64I-NEXT: lui a3, 16 122; RV64I-NEXT: mul a2, a1, a2 123; RV64I-NEXT: addiw a1, a3, -1 124; RV64I-NEXT: and a0, a0, a1 125; RV64I-NEXT: and a2, a2, a1 126; RV64I-NEXT: add a0, a0, a2 127; RV64I-NEXT: bltu a0, a1, .LBB2_2 128; RV64I-NEXT: # %bb.1: 129; RV64I-NEXT: mv a0, a1 130; RV64I-NEXT: .LBB2_2: 131; RV64I-NEXT: ret 132; 133; RV32IZbb-LABEL: func16: 134; RV32IZbb: # %bb.0: 135; RV32IZbb-NEXT: zext.h a0, a0 136; RV32IZbb-NEXT: mul a1, a1, a2 137; RV32IZbb-NEXT: lui a2, 16 138; RV32IZbb-NEXT: zext.h a1, a1 139; RV32IZbb-NEXT: add a0, a0, a1 140; RV32IZbb-NEXT: addi a2, a2, -1 141; RV32IZbb-NEXT: minu a0, a0, a2 142; RV32IZbb-NEXT: ret 143; 144; RV64IZbb-LABEL: func16: 145; RV64IZbb: # %bb.0: 146; RV64IZbb-NEXT: zext.h a0, a0 147; RV64IZbb-NEXT: mul a1, a1, a2 148; RV64IZbb-NEXT: lui a2, 16 149; RV64IZbb-NEXT: zext.h a1, a1 150; RV64IZbb-NEXT: add a0, a0, a1 151; RV64IZbb-NEXT: addiw a2, a2, -1 152; RV64IZbb-NEXT: minu a0, a0, a2 153; RV64IZbb-NEXT: ret 154 %a = mul i16 %y, %z 155 %tmp = call i16 @llvm.uadd.sat.i16(i16 %x, i16 %a) 156 ret i16 %tmp 157} 158 159define i8 @func8(i8 %x, i8 %y, i8 %z) nounwind { 160; RV32I-LABEL: func8: 161; RV32I: # %bb.0: 162; RV32I-NEXT: andi a0, a0, 255 163; RV32I-NEXT: mul a1, a1, a2 164; RV32I-NEXT: andi a1, a1, 255 165; RV32I-NEXT: add a0, a0, a1 166; RV32I-NEXT: li a1, 255 167; RV32I-NEXT: bltu a0, a1, .LBB3_2 168; RV32I-NEXT: # %bb.1: 169; RV32I-NEXT: li a0, 255 170; RV32I-NEXT: .LBB3_2: 171; RV32I-NEXT: ret 172; 173; RV64I-LABEL: func8: 174; RV64I: # %bb.0: 175; RV64I-NEXT: andi a0, a0, 255 176; RV64I-NEXT: mul a1, a1, a2 177; RV64I-NEXT: andi a1, a1, 255 178; RV64I-NEXT: add a0, a0, a1 179; RV64I-NEXT: li a1, 255 180; RV64I-NEXT: bltu a0, a1, .LBB3_2 181; RV64I-NEXT: # %bb.1: 182; RV64I-NEXT: li a0, 255 183; RV64I-NEXT: .LBB3_2: 184; RV64I-NEXT: ret 185; 186; RV32IZbb-LABEL: func8: 187; RV32IZbb: # %bb.0: 188; RV32IZbb-NEXT: andi a0, a0, 255 189; RV32IZbb-NEXT: mul a1, a1, a2 190; RV32IZbb-NEXT: andi a1, a1, 255 191; RV32IZbb-NEXT: add a0, a0, a1 192; RV32IZbb-NEXT: li a1, 255 193; RV32IZbb-NEXT: minu a0, a0, a1 194; RV32IZbb-NEXT: ret 195; 196; RV64IZbb-LABEL: func8: 197; RV64IZbb: # %bb.0: 198; RV64IZbb-NEXT: andi a0, a0, 255 199; RV64IZbb-NEXT: mul a1, a1, a2 200; RV64IZbb-NEXT: andi a1, a1, 255 201; RV64IZbb-NEXT: add a0, a0, a1 202; RV64IZbb-NEXT: li a1, 255 203; RV64IZbb-NEXT: minu a0, a0, a1 204; RV64IZbb-NEXT: ret 205 %a = mul i8 %y, %z 206 %tmp = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %a) 207 ret i8 %tmp 208} 209 210define i4 @func4(i4 %x, i4 %y, i4 %z) nounwind { 211; RV32I-LABEL: func4: 212; RV32I: # %bb.0: 213; RV32I-NEXT: andi a0, a0, 15 214; RV32I-NEXT: mul a1, a1, a2 215; RV32I-NEXT: andi a1, a1, 15 216; RV32I-NEXT: add a0, a0, a1 217; RV32I-NEXT: li a1, 15 218; RV32I-NEXT: bltu a0, a1, .LBB4_2 219; RV32I-NEXT: # %bb.1: 220; RV32I-NEXT: li a0, 15 221; RV32I-NEXT: .LBB4_2: 222; RV32I-NEXT: ret 223; 224; RV64I-LABEL: func4: 225; RV64I: # %bb.0: 226; RV64I-NEXT: andi a0, a0, 15 227; RV64I-NEXT: mul a1, a1, a2 228; RV64I-NEXT: andi a1, a1, 15 229; RV64I-NEXT: add a0, a0, a1 230; RV64I-NEXT: li a1, 15 231; RV64I-NEXT: bltu a0, a1, .LBB4_2 232; RV64I-NEXT: # %bb.1: 233; RV64I-NEXT: li a0, 15 234; RV64I-NEXT: .LBB4_2: 235; RV64I-NEXT: ret 236; 237; RV32IZbb-LABEL: func4: 238; RV32IZbb: # %bb.0: 239; RV32IZbb-NEXT: andi a0, a0, 15 240; RV32IZbb-NEXT: mul a1, a1, a2 241; RV32IZbb-NEXT: andi a1, a1, 15 242; RV32IZbb-NEXT: add a0, a0, a1 243; RV32IZbb-NEXT: li a1, 15 244; RV32IZbb-NEXT: minu a0, a0, a1 245; RV32IZbb-NEXT: ret 246; 247; RV64IZbb-LABEL: func4: 248; RV64IZbb: # %bb.0: 249; RV64IZbb-NEXT: andi a0, a0, 15 250; RV64IZbb-NEXT: mul a1, a1, a2 251; RV64IZbb-NEXT: andi a1, a1, 15 252; RV64IZbb-NEXT: add a0, a0, a1 253; RV64IZbb-NEXT: li a1, 15 254; RV64IZbb-NEXT: minu a0, a0, a1 255; RV64IZbb-NEXT: ret 256 %a = mul i4 %y, %z 257 %tmp = call i4 @llvm.uadd.sat.i4(i4 %x, i4 %a) 258 ret i4 %tmp 259} 260