1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 3; RUN: | FileCheck -check-prefix=RV32I %s 4; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ 5; RUN: | FileCheck -check-prefix=RV64I %s 6 7@gi = external global i32 8 9define i32 @constraint_r(i32 %a) nounwind { 10; RV32I-LABEL: constraint_r: 11; RV32I: # %bb.0: 12; RV32I-NEXT: lui a1, %hi(gi) 13; RV32I-NEXT: lw a1, %lo(gi)(a1) 14; RV32I-NEXT: #APP 15; RV32I-NEXT: add a0, a0, a1 16; RV32I-NEXT: #NO_APP 17; RV32I-NEXT: ret 18; 19; RV64I-LABEL: constraint_r: 20; RV64I: # %bb.0: 21; RV64I-NEXT: lui a1, %hi(gi) 22; RV64I-NEXT: lwu a1, %lo(gi)(a1) 23; RV64I-NEXT: #APP 24; RV64I-NEXT: add a0, a0, a1 25; RV64I-NEXT: #NO_APP 26; RV64I-NEXT: ret 27 %1 = load i32, i32* @gi 28 %2 = tail call i32 asm "add $0, $1, $2", "=r,r,r"(i32 %a, i32 %1) 29 ret i32 %2 30} 31 32define i32 @constraint_i(i32 %a) nounwind { 33; RV32I-LABEL: constraint_i: 34; RV32I: # %bb.0: 35; RV32I-NEXT: #APP 36; RV32I-NEXT: addi a0, a0, 113 37; RV32I-NEXT: #NO_APP 38; RV32I-NEXT: ret 39; 40; RV64I-LABEL: constraint_i: 41; RV64I: # %bb.0: 42; RV64I-NEXT: #APP 43; RV64I-NEXT: addi a0, a0, 113 44; RV64I-NEXT: #NO_APP 45; RV64I-NEXT: ret 46 %1 = load i32, i32* @gi 47 %2 = tail call i32 asm "addi $0, $1, $2", "=r,r,i"(i32 %a, i32 113) 48 ret i32 %2 49} 50 51define void @constraint_m(i32* %a) nounwind { 52; RV32I-LABEL: constraint_m: 53; RV32I: # %bb.0: 54; RV32I-NEXT: #APP 55; RV32I-NEXT: #NO_APP 56; RV32I-NEXT: ret 57; 58; RV64I-LABEL: constraint_m: 59; RV64I: # %bb.0: 60; RV64I-NEXT: #APP 61; RV64I-NEXT: #NO_APP 62; RV64I-NEXT: ret 63 call void asm sideeffect "", "=*m"(i32* %a) 64 ret void 65} 66 67define i32 @constraint_m2(i32* %a) nounwind { 68; RV32I-LABEL: constraint_m2: 69; RV32I: # %bb.0: 70; RV32I-NEXT: #APP 71; RV32I-NEXT: lw a0, 0(a0) 72; RV32I-NEXT: #NO_APP 73; RV32I-NEXT: ret 74; 75; RV64I-LABEL: constraint_m2: 76; RV64I: # %bb.0: 77; RV64I-NEXT: #APP 78; RV64I-NEXT: lw a0, 0(a0) 79; RV64I-NEXT: #NO_APP 80; RV64I-NEXT: ret 81 %1 = tail call i32 asm "lw $0, $1", "=r,*m"(i32* %a) 82 ret i32 %1 83} 84 85define void @constraint_I() nounwind { 86; RV32I-LABEL: constraint_I: 87; RV32I: # %bb.0: 88; RV32I-NEXT: #APP 89; RV32I-NEXT: addi a0, a0, 2047 90; RV32I-NEXT: #NO_APP 91; RV32I-NEXT: #APP 92; RV32I-NEXT: addi a0, a0, -2048 93; RV32I-NEXT: #NO_APP 94; RV32I-NEXT: ret 95; 96; RV64I-LABEL: constraint_I: 97; RV64I: # %bb.0: 98; RV64I-NEXT: #APP 99; RV64I-NEXT: addi a0, a0, 2047 100; RV64I-NEXT: #NO_APP 101; RV64I-NEXT: #APP 102; RV64I-NEXT: addi a0, a0, -2048 103; RV64I-NEXT: #NO_APP 104; RV64I-NEXT: ret 105 tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 2047) 106 tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 -2048) 107 ret void 108} 109 110define void @constraint_J() nounwind { 111; RV32I-LABEL: constraint_J: 112; RV32I: # %bb.0: 113; RV32I-NEXT: #APP 114; RV32I-NEXT: addi a0, a0, 0 115; RV32I-NEXT: #NO_APP 116; RV32I-NEXT: ret 117; 118; RV64I-LABEL: constraint_J: 119; RV64I: # %bb.0: 120; RV64I-NEXT: #APP 121; RV64I-NEXT: addi a0, a0, 0 122; RV64I-NEXT: #NO_APP 123; RV64I-NEXT: ret 124 tail call void asm sideeffect "addi a0, a0, $0", "J"(i32 0) 125 ret void 126} 127 128define void @constraint_K() nounwind { 129; RV32I-LABEL: constraint_K: 130; RV32I: # %bb.0: 131; RV32I-NEXT: #APP 132; RV32I-NEXT: csrwi mstatus, 31 133; RV32I-NEXT: #NO_APP 134; RV32I-NEXT: #APP 135; RV32I-NEXT: csrwi mstatus, 0 136; RV32I-NEXT: #NO_APP 137; RV32I-NEXT: ret 138; 139; RV64I-LABEL: constraint_K: 140; RV64I: # %bb.0: 141; RV64I-NEXT: #APP 142; RV64I-NEXT: csrwi mstatus, 31 143; RV64I-NEXT: #NO_APP 144; RV64I-NEXT: #APP 145; RV64I-NEXT: csrwi mstatus, 0 146; RV64I-NEXT: #NO_APP 147; RV64I-NEXT: ret 148 tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 31) 149 tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 0) 150 ret void 151} 152 153define void @constraint_A(i8* %a) nounwind { 154; RV32I-LABEL: constraint_A: 155; RV32I: # %bb.0: 156; RV32I-NEXT: #APP 157; RV32I-NEXT: sb s0, 0(a0) 158; RV32I-NEXT: #NO_APP 159; RV32I-NEXT: #APP 160; RV32I-NEXT: lb s1, 0(a0) 161; RV32I-NEXT: #NO_APP 162; RV32I-NEXT: ret 163; 164; RV64I-LABEL: constraint_A: 165; RV64I: # %bb.0: 166; RV64I-NEXT: #APP 167; RV64I-NEXT: sb s0, 0(a0) 168; RV64I-NEXT: #NO_APP 169; RV64I-NEXT: #APP 170; RV64I-NEXT: lb s1, 0(a0) 171; RV64I-NEXT: #NO_APP 172; RV64I-NEXT: ret 173 tail call void asm sideeffect "sb s0, $0", "*A"(i8* %a) 174 tail call void asm sideeffect "lb s1, $0", "*A"(i8* %a) 175 ret void 176} 177 178define i32 @modifier_z_zero(i32 %a) nounwind { 179; RV32I-LABEL: modifier_z_zero: 180; RV32I: # %bb.0: 181; RV32I-NEXT: #APP 182; RV32I-NEXT: add a0, a0, zero 183; RV32I-NEXT: #NO_APP 184; RV32I-NEXT: ret 185; 186; RV64I-LABEL: modifier_z_zero: 187; RV64I: # %bb.0: 188; RV64I-NEXT: #APP 189; RV64I-NEXT: add a0, a0, zero 190; RV64I-NEXT: #NO_APP 191; RV64I-NEXT: ret 192 %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,r"(i32 %a, i32 0) 193 ret i32 %1 194} 195 196define i32 @modifier_z_nonzero(i32 %a) nounwind { 197; RV32I-LABEL: modifier_z_nonzero: 198; RV32I: # %bb.0: 199; RV32I-NEXT: addi a1, zero, 1 200; RV32I-NEXT: #APP 201; RV32I-NEXT: add a0, a0, a1 202; RV32I-NEXT: #NO_APP 203; RV32I-NEXT: ret 204; 205; RV64I-LABEL: modifier_z_nonzero: 206; RV64I: # %bb.0: 207; RV64I-NEXT: addi a1, zero, 1 208; RV64I-NEXT: #APP 209; RV64I-NEXT: add a0, a0, a1 210; RV64I-NEXT: #NO_APP 211; RV64I-NEXT: ret 212 %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,r"(i32 %a, i32 1) 213 ret i32 %1 214} 215 216define i32 @modifier_i_imm(i32 %a) nounwind { 217; RV32I-LABEL: modifier_i_imm: 218; RV32I: # %bb.0: 219; RV32I-NEXT: #APP 220; RV32I-NEXT: addi a0, a0, 1 221; RV32I-NEXT: #NO_APP 222; RV32I-NEXT: ret 223; 224; RV64I-LABEL: modifier_i_imm: 225; RV64I: # %bb.0: 226; RV64I-NEXT: #APP 227; RV64I-NEXT: addi a0, a0, 1 228; RV64I-NEXT: #NO_APP 229; RV64I-NEXT: ret 230 %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 1) 231 ret i32 %1 232} 233 234define i32 @modifier_i_reg(i32 %a, i32 %b) nounwind { 235; RV32I-LABEL: modifier_i_reg: 236; RV32I: # %bb.0: 237; RV32I-NEXT: #APP 238; RV32I-NEXT: add a0, a0, a1 239; RV32I-NEXT: #NO_APP 240; RV32I-NEXT: ret 241; 242; RV64I-LABEL: modifier_i_reg: 243; RV64I: # %bb.0: 244; RV64I-NEXT: #APP 245; RV64I-NEXT: add a0, a0, a1 246; RV64I-NEXT: #NO_APP 247; RV64I-NEXT: ret 248 %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 %b) 249 ret i32 %1 250} 251 252define void @operand_global() nounwind { 253; RV32I-LABEL: operand_global: 254; RV32I: # %bb.0: 255; RV32I-NEXT: #APP 256; RV32I-NEXT: .8byte gi 257; RV32I-NEXT: #NO_APP 258; RV32I-NEXT: ret 259; 260; RV64I-LABEL: operand_global: 261; RV64I: # %bb.0: 262; RV64I-NEXT: #APP 263; RV64I-NEXT: .8byte gi 264; RV64I-NEXT: #NO_APP 265; RV64I-NEXT: ret 266 tail call void asm sideeffect ".8byte $0", "i"(i32* @gi) 267 ret void 268} 269 270define void @operand_block_address() nounwind { 271; RV32I-LABEL: operand_block_address: 272; RV32I: # %bb.0: 273; RV32I-NEXT: #APP 274; RV32I-NEXT: j .Ltmp0 275; RV32I-NEXT: #NO_APP 276; RV32I-NEXT: .Ltmp0: # Block address taken 277; RV32I-NEXT: # %bb.1: # %bb 278; RV32I-NEXT: ret 279; 280; RV64I-LABEL: operand_block_address: 281; RV64I: # %bb.0: 282; RV64I-NEXT: #APP 283; RV64I-NEXT: j .Ltmp0 284; RV64I-NEXT: #NO_APP 285; RV64I-NEXT: .Ltmp0: # Block address taken 286; RV64I-NEXT: # %bb.1: # %bb 287; RV64I-NEXT: ret 288 call void asm sideeffect "j $0", "i"(i8* blockaddress(@operand_block_address, %bb)) 289 br label %bb 290bb: 291 ret void 292} 293 294; TODO: expand tests for more complex constraints, out of range immediates etc 295