llvm.org GIT mirror llvm / eacca30
[RISCV] Codegen for conditional branches A good portion of this patch is the extra functions that needed to be implemented to support the test case. e.g. storeRegToStackSlot, loadRegFromStackSlot, eliminateFrameIndex. Setting ISD::BR_CC to Expand may appear non-obvious on an architecture with branch+cmp instructions. However, I found it much easier to deal with matching the expanded form. I had to change simm13_lsb0 and simm21_lsb0 to inherit from the Operand<OtherVT> class rather than Operand<i32> in order to keep tablegen happy. This isn't a big deal, but it does seem a shame to lose the uniformity across immediate types when there's not an obvious benefit (I'm hoping a tablegen expert will educate me on what I'm missing here!). Differential Revision: https://reviews.llvm.org/D29935 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317690 91177308-0d34-0410-b5e6-96231b3b80d8 Alex Bradbury 1 year, 11 months ago
9 changed file(s) with 239 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
2626 ]>;
2727
2828 def CSR : CalleeSavedRegs<(add X1, X3, X4, X8, X9, (sequence "X%u", 18, 27))>;
29
30 // Needed for implementation of RISCVRegisterInfo::getNoPreservedMask()
31 def CSR_NoRegs : CalleeSavedRegs<(add)>;
5454 // TODO: add all necessary setOperationAction calls.
5555 setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
5656
57 setOperationAction(ISD::BR_CC, XLenVT, Expand);
5758 setBooleanContents(ZeroOrOneBooleanContent);
5859
5960 // Function alignments (log2).
4040 .addReg(SrcReg, getKillRegState(KillSrc))
4141 .addImm(0);
4242 }
43
44 void RISCVInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
45 MachineBasicBlock::iterator I,
46 unsigned SrcReg, bool IsKill, int FI,
47 const TargetRegisterClass *RC,
48 const TargetRegisterInfo *TRI) const {
49 DebugLoc DL;
50 if (I != MBB.end())
51 DL = I->getDebugLoc();
52
53 if (RC == &RISCV::GPRRegClass)
54 BuildMI(MBB, I, DL, get(RISCV::SW))
55 .addReg(SrcReg, getKillRegState(IsKill))
56 .addFrameIndex(FI)
57 .addImm(0);
58 else
59 llvm_unreachable("Can't store this register to stack slot");
60 }
61
62 void RISCVInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
63 MachineBasicBlock::iterator I,
64 unsigned DstReg, int FI,
65 const TargetRegisterClass *RC,
66 const TargetRegisterInfo *TRI) const {
67 DebugLoc DL;
68 if (I != MBB.end())
69 DL = I->getDebugLoc();
70
71 if (RC == &RISCV::GPRRegClass)
72 BuildMI(MBB, I, DL, get(RISCV::LW), DstReg).addFrameIndex(FI).addImm(0);
73 else
74 llvm_unreachable("Can't load this register from stack slot");
75 }
2929 void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
3030 const DebugLoc &DL, unsigned DstReg, unsigned SrcReg,
3131 bool KillSrc) const override;
32
33 void storeRegToStackSlot(MachineBasicBlock &MBB,
34 MachineBasicBlock::iterator MBBI, unsigned SrcReg,
35 bool IsKill, int FrameIndex,
36 const TargetRegisterClass *RC,
37 const TargetRegisterInfo *TRI) const override;
38
39 void loadRegFromStackSlot(MachineBasicBlock &MBB,
40 MachineBasicBlock::iterator MBBI, unsigned DstReg,
41 int FrameIndex, const TargetRegisterClass *RC,
42 const TargetRegisterInfo *TRI) const override;
3243 };
3344 }
34
3545 #endif
6666 }
6767
6868 // A 13-bit signed immediate where the least significant bit is zero.
69 def simm13_lsb0 : Operand<XLenVT> {
69 def simm13_lsb0 : Operand<OtherVT> {
7070 let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
7171 let EncoderMethod = "getImmOpValueAsr1";
7272 let DecoderMethod = "decodeSImmOperandAndLsl1<13>";
7979 }
8080
8181 // A 21-bit signed immediate where the least significant bit is zero.
82 def simm21_lsb0 : Operand<XLenVT> {
82 def simm21_lsb0 : Operand<OtherVT> {
8383 let ParserMatchClass = SImmAsmOperand<21, "Lsb0">;
8484 let EncoderMethod = "getImmOpValueAsr1";
8585 let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
307307
308308 /// Branches and jumps
309309
310 // Match `(brcond (CondOp ..), ..)` and lower to the appropriate RISC-V branch
311 // instruction.
312 class BccPat
313 : Pat<(brcond (i32 (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
314 (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>;
315
316 def : BccPat;
317 def : BccPat;
318 def : BccPat;
319 def : BccPat;
320 def : BccPat;
321 def : BccPat;
322
323 class BccSwapPat
324 : Pat<(brcond (i32 (CondOp GPR:$rs1, GPR:$rs2)), bb:$imm12),
325 (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm12)>;
326
327 // Condition codes that don't have matching RISC-V branch instructions, but
328 // are trivially supported by swapping the two input operands
329 def : BccSwapPat;
330 def : BccSwapPat;
331 def : BccSwapPat;
332 def : BccSwapPat;
333
334 // An extra pattern is needed for a brcond without a setcc (i.e. where the
335 // condition was calculated elsewhere).
336 def : Pat<(brcond GPR:$cond, bb:$imm12), (BNE GPR:$cond, X0, bb:$imm12)>;
337
338 let isBarrier = 1, isBranch = 1, isTerminator = 1 in
339 def PseudoBR : Pseudo<(outs), (ins simm21_lsb0:$imm20), [(br bb:$imm20)]>,
340 PseudoInstExpansion<(JAL X0, simm21_lsb0:$imm20)>;
341
310342 let isBarrier = 1, isReturn = 1, isTerminator = 1 in
311343 def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>,
312344 PseudoInstExpansion<(JALR X0, X1, 0)>;
7070 case MachineOperand::MO_Immediate:
7171 MCOp = MCOperand::createImm(MO.getImm());
7272 break;
73 case MachineOperand::MO_MachineBasicBlock:
74 MCOp = MCOperand::createExpr(
75 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext));
76 break;
7377 case MachineOperand::MO_GlobalAddress:
7478 MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP);
7579 break;
4949 return Reserved;
5050 }
5151
52 const uint32_t *RISCVRegisterInfo::getNoPreservedMask() const {
53 return CSR_NoRegs_RegMask;
54 }
55
5256 void RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
5357 int SPAdj, unsigned FIOperandNum,
5458 RegScavenger *RS) const {
55 report_fatal_error("Subroutines not supported yet");
59 // TODO: this implementation is a temporary placeholder which does just
60 // enough to allow other aspects of code generation to be tested
61
62 assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
63
64 MachineInstr &MI = *II;
65 MachineFunction &MF = *MI.getParent()->getParent();
66 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
67 DebugLoc DL = MI.getDebugLoc();
68
69 unsigned FrameReg = getFrameRegister(MF);
70 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
71 int Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg);
72 Offset += MI.getOperand(FIOperandNum + 1).getImm();
73
74 assert(TFI->hasFP(MF) && "eliminateFrameIndex currently requires hasFP");
75
76 // Offsets must be directly encoded in a 12-bit immediate field
77 if (!isInt<12>(Offset)) {
78 report_fatal_error(
79 "Frame offsets outside of the signed 12-bit range not supported");
80 }
81
82 MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
83 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
84 return;
5685 }
5786
5887 unsigned RISCVRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
2828
2929 BitVector getReservedRegs(const MachineFunction &MF) const override;
3030
31 const uint32_t *getNoPreservedMask() const override;
32
3133 void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
3234 unsigned FIOperandNum,
3335 RegScavenger *RS = nullptr) const override;
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
2 ; RUN: | FileCheck -check-prefix=RV32I %s
3
4 define void @foo(i32 %a, i32 *%b, i1 %c) {
5 ; RV32I-LABEL: foo:
6 ; RV32I: # BB#0:
7 ; RV32I-NEXT: lw a3, 0(a1)
8 ; RV32I-NEXT: beq a3, a0, .LBB0_12
9 ; RV32I-NEXT: jal zero, .LBB0_1
10 ; RV32I-NEXT: .LBB0_1: # %test2
11 ; RV32I-NEXT: lw a3, 0(a1)
12 ; RV32I-NEXT: bne a3, a0, .LBB0_12
13 ; RV32I-NEXT: jal zero, .LBB0_2
14 ; RV32I-NEXT: .LBB0_2: # %test3
15 ; RV32I-NEXT: lw a3, 0(a1)
16 ; RV32I-NEXT: blt a3, a0, .LBB0_12
17 ; RV32I-NEXT: jal zero, .LBB0_3
18 ; RV32I-NEXT: .LBB0_3: # %test4
19 ; RV32I-NEXT: lw a3, 0(a1)
20 ; RV32I-NEXT: bge a3, a0, .LBB0_12
21 ; RV32I-NEXT: jal zero, .LBB0_4
22 ; RV32I-NEXT: .LBB0_4: # %test5
23 ; RV32I-NEXT: lw a3, 0(a1)
24 ; RV32I-NEXT: bltu a3, a0, .LBB0_12
25 ; RV32I-NEXT: jal zero, .LBB0_5
26 ; RV32I-NEXT: .LBB0_5: # %test6
27 ; RV32I-NEXT: lw a3, 0(a1)
28 ; RV32I-NEXT: bgeu a3, a0, .LBB0_12
29 ; RV32I-NEXT: jal zero, .LBB0_6
30 ; RV32I-NEXT: .LBB0_6: # %test7
31 ; RV32I-NEXT: lw a3, 0(a1)
32 ; RV32I-NEXT: blt a0, a3, .LBB0_12
33 ; RV32I-NEXT: jal zero, .LBB0_7
34 ; RV32I-NEXT: .LBB0_7: # %test8
35 ; RV32I-NEXT: lw a3, 0(a1)
36 ; RV32I-NEXT: bge a0, a3, .LBB0_12
37 ; RV32I-NEXT: jal zero, .LBB0_8
38 ; RV32I-NEXT: .LBB0_8: # %test9
39 ; RV32I-NEXT: lw a3, 0(a1)
40 ; RV32I-NEXT: bltu a0, a3, .LBB0_12
41 ; RV32I-NEXT: jal zero, .LBB0_9
42 ; RV32I-NEXT: .LBB0_9: # %test10
43 ; RV32I-NEXT: lw a3, 0(a1)
44 ; RV32I-NEXT: bgeu a0, a3, .LBB0_12
45 ; RV32I-NEXT: jal zero, .LBB0_10
46 ; RV32I-NEXT: .LBB0_10: # %test11
47 ; RV32I-NEXT: lw a0, 0(a1)
48 ; RV32I-NEXT: andi a0, a2, 1
49 ; RV32I-NEXT: bne a0, zero, .LBB0_12
50 ; RV32I-NEXT: jal zero, .LBB0_11
51 ; RV32I-NEXT: .LBB0_11: # %test12
52 ; RV32I-NEXT: lw a0, 0(a1)
53 ; RV32I-NEXT: .LBB0_12: # %end
54 ; RV32I-NEXT: jalr zero, ra, 0
55
56 %val1 = load volatile i32, i32* %b
57 %tst1 = icmp eq i32 %val1, %a
58 br i1 %tst1, label %end, label %test2
59
60 test2:
61 %val2 = load volatile i32, i32* %b
62 %tst2 = icmp ne i32 %val2, %a
63 br i1 %tst2, label %end, label %test3
64
65 test3:
66 %val3 = load volatile i32, i32* %b
67 %tst3 = icmp slt i32 %val3, %a
68 br i1 %tst3, label %end, label %test4
69
70 test4:
71 %val4 = load volatile i32, i32* %b
72 %tst4 = icmp sge i32 %val4, %a
73 br i1 %tst4, label %end, label %test5
74
75 test5:
76 %val5 = load volatile i32, i32* %b
77 %tst5 = icmp ult i32 %val5, %a
78 br i1 %tst5, label %end, label %test6
79
80 test6:
81 %val6 = load volatile i32, i32* %b
82 %tst6 = icmp uge i32 %val6, %a
83 br i1 %tst6, label %end, label %test7
84
85 ; Check for condition codes that don't have a matching instruction
86
87 test7:
88 %val7 = load volatile i32, i32* %b
89 %tst7 = icmp sgt i32 %val7, %a
90 br i1 %tst7, label %end, label %test8
91
92 test8:
93 %val8 = load volatile i32, i32* %b
94 %tst8 = icmp sle i32 %val8, %a
95 br i1 %tst8, label %end, label %test9
96
97 test9:
98 %val9 = load volatile i32, i32* %b
99 %tst9 = icmp ugt i32 %val9, %a
100 br i1 %tst9, label %end, label %test10
101
102 test10:
103 %val10 = load volatile i32, i32* %b
104 %tst10 = icmp ule i32 %val10, %a
105 br i1 %tst10, label %end, label %test11
106
107 ; Check the case of a branch where the condition was generated in another
108 ; function
109
110 test11:
111 %val11 = load volatile i32, i32* %b
112 br i1 %c, label %end, label %test12
113
114 test12:
115 %val12 = load volatile i32, i32* %b
116 br label %end
117
118 end:
119 ret void
120 }