[llvm] r322222 - [RISCV] Implement branch analysis
Alex Bradbury via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 10 12:47:00 PST 2018
Author: asb
Date: Wed Jan 10 12:47:00 2018
New Revision: 322222
URL: http://llvm.org/viewvc/llvm-project?rev=322222&view=rev
Log:
[RISCV] Implement branch analysis
This is a prerequisite for the branch relaxation pass, and allows a number of
optimisation passes (e.g. BranchFolding and MachineBlockPlacement) to work.
Differential Revision: https://reviews.llvm.org/D40808
Added:
llvm/trunk/test/CodeGen/RISCV/analyze-branch.ll
Modified:
llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp
llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.h
llvm/trunk/test/CodeGen/RISCV/branch.ll
llvm/trunk/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll
llvm/trunk/test/CodeGen/RISCV/jumptable.ll
llvm/trunk/test/CodeGen/RISCV/select-cc.ll
Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp?rev=322222&r1=322221&r2=322222&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp Wed Jan 10 12:47:00 2018
@@ -95,3 +95,169 @@ void RISCVInstrInfo::movImm32(MachineBas
.addImm(Lo12)
.setMIFlag(Flag);
}
+
+// The contents of values added to Cond are not examined outside of
+// RISCVInstrInfo, giving us flexibility in what to push to it. For RISCV, we
+// push BranchOpcode, Reg1, Reg2.
+static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
+ SmallVectorImpl<MachineOperand> &Cond) {
+ // Block ends with fall-through condbranch.
+ assert(LastInst.getDesc().isConditionalBranch() &&
+ "Unknown conditional branch");
+ Target = LastInst.getOperand(2).getMBB();
+ Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
+ Cond.push_back(LastInst.getOperand(0));
+ Cond.push_back(LastInst.getOperand(1));
+}
+
+static unsigned getOppositeBranchOpcode(int Opc) {
+ switch (Opc) {
+ default:
+ llvm_unreachable("Unrecognized conditional branch");
+ case RISCV::BEQ:
+ return RISCV::BNE;
+ case RISCV::BNE:
+ return RISCV::BEQ;
+ case RISCV::BLT:
+ return RISCV::BGE;
+ case RISCV::BGE:
+ return RISCV::BLT;
+ case RISCV::BLTU:
+ return RISCV::BGEU;
+ case RISCV::BGEU:
+ return RISCV::BLTU;
+ }
+}
+
+bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const {
+ TBB = FBB = nullptr;
+ Cond.clear();
+
+ // If the block has no terminators, it just falls into the block after it.
+ MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
+ if (I == MBB.end() || !isUnpredicatedTerminator(*I))
+ return false;
+
+ // Count the number of terminators and find the first unconditional or
+ // indirect branch.
+ MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
+ int NumTerminators = 0;
+ for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
+ J++) {
+ NumTerminators++;
+ if (J->getDesc().isUnconditionalBranch() ||
+ J->getDesc().isIndirectBranch()) {
+ FirstUncondOrIndirectBr = J.getReverse();
+ }
+ }
+
+ // If AllowModify is true, we can erase any terminators after
+ // FirstUncondOrIndirectBR.
+ if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
+ while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
+ std::next(FirstUncondOrIndirectBr)->eraseFromParent();
+ NumTerminators--;
+ }
+ I = FirstUncondOrIndirectBr;
+ }
+
+ // We can't handle blocks that end in an indirect branch.
+ if (I->getDesc().isIndirectBranch())
+ return true;
+
+ // We can't handle blocks with more than 2 terminators.
+ if (NumTerminators > 2)
+ return true;
+
+ // Handle a single unconditional branch.
+ if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
+ TBB = I->getOperand(0).getMBB();
+ return false;
+ }
+
+ // Handle a single conditional branch.
+ if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
+ parseCondBranch(*I, TBB, Cond);
+ return false;
+ }
+
+ // Handle a conditional branch followed by an unconditional branch.
+ if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
+ I->getDesc().isUnconditionalBranch()) {
+ parseCondBranch(*std::prev(I), TBB, Cond);
+ FBB = I->getOperand(0).getMBB();
+ return false;
+ }
+
+ // Otherwise, we can't handle this.
+ return true;
+}
+
+unsigned RISCVInstrInfo::removeBranch(MachineBasicBlock &MBB,
+ int *BytesRemoved) const {
+ assert(!BytesRemoved && "Code size not handled");
+ MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
+ if (I == MBB.end())
+ return 0;
+
+ if (!I->getDesc().isUnconditionalBranch() &&
+ !I->getDesc().isConditionalBranch())
+ return 0;
+
+ // Remove the branch.
+ I->eraseFromParent();
+
+ I = MBB.end();
+
+ if (I == MBB.begin())
+ return 1;
+ --I;
+ if (!I->getDesc().isConditionalBranch())
+ return 1;
+
+ // Remove the branch.
+ I->eraseFromParent();
+ return 2;
+}
+
+// Inserts a branch into the end of the specific MachineBasicBlock, returning
+// the number of instructions inserted.
+unsigned RISCVInstrInfo::insertBranch(
+ MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
+ ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
+ assert(!BytesAdded && "Code size not handled.");
+
+ // Shouldn't be a fall through.
+ assert(TBB && "InsertBranch must not be told to insert a fallthrough");
+ assert((Cond.size() == 3 || Cond.size() == 0) &&
+ "RISCV branch conditions have two components!");
+
+ // Unconditional branch.
+ if (Cond.empty()) {
+ BuildMI(&MBB, DL, get(RISCV::PseudoBR)).addMBB(TBB);
+ return 1;
+ }
+
+ // Either a one or two-way conditional branch.
+ unsigned Opc = Cond[0].getImm();
+ BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).add(Cond[2]).addMBB(TBB);
+
+ // One-way conditional branch.
+ if (!FBB)
+ return 1;
+
+ // Two-way conditional branch.
+ BuildMI(&MBB, DL, get(RISCV::PseudoBR)).addMBB(FBB);
+ return 2;
+}
+
+bool RISCVInstrInfo::reverseBranchCondition(
+ SmallVectorImpl<MachineOperand> &Cond) const {
+ assert((Cond.size() == 3) && "Invalid branch condition!");
+ Cond[0].setImm(getOppositeBranchOpcode(Cond[0].getImm()));
+ return false;
+}
Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.h?rev=322222&r1=322221&r2=322222&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.h (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.h Wed Jan 10 12:47:00 2018
@@ -46,6 +46,22 @@ public:
void movImm32(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, unsigned DstReg, uint64_t Val,
MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const;
+
+ bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const override;
+
+ unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
+ const DebugLoc &dl,
+ int *BytesAdded = nullptr) const override;
+
+ unsigned removeBranch(MachineBasicBlock &MBB,
+ int *BytesRemoved = nullptr) const override;
+
+ bool
+ reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
};
}
#endif
Added: llvm/trunk/test/CodeGen/RISCV/analyze-branch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/analyze-branch.ll?rev=322222&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/analyze-branch.ll (added)
+++ llvm/trunk/test/CodeGen/RISCV/analyze-branch.ll Wed Jan 10 12:47:00 2018
@@ -0,0 +1,91 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=RV32I %s
+
+; This test checks that LLVM can do basic stripping and reapplying of branches
+; to basic blocks.
+
+declare void @test_true()
+declare void @test_false()
+
+; !0 corresponds to a branch being taken, !1 to not being takne.
+!0 = !{!"branch_weights", i32 64, i32 4}
+!1 = !{!"branch_weights", i32 4, i32 64}
+
+define void @test_bcc_fallthrough_taken(i32 %in) nounwind {
+; RV32I-LABEL: test_bcc_fallthrough_taken:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp)
+; RV32I-NEXT: sw s0, 8(sp)
+; RV32I-NEXT: addi s0, sp, 16
+; RV32I-NEXT: addi a1, zero, 42
+; RV32I-NEXT: bne a0, a1, .LBB0_3
+; RV32I-NEXT: # %bb.1: # %true
+; RV32I-NEXT: lui a0, %hi(test_true)
+; RV32I-NEXT: addi a0, a0, %lo(test_true)
+; RV32I-NEXT: .LBB0_2: # %true
+; RV32I-NEXT: jalr a0
+; RV32I-NEXT: lw s0, 8(sp)
+; RV32I-NEXT: lw ra, 12(sp)
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+; RV32I-NEXT: .LBB0_3: # %false
+; RV32I-NEXT: lui a0, %hi(test_false)
+; RV32I-NEXT: addi a0, a0, %lo(test_false)
+; RV32I-NEXT: j .LBB0_2
+ %tst = icmp eq i32 %in, 42
+ br i1 %tst, label %true, label %false, !prof !0
+
+; Expected layout order is: Entry, TrueBlock, FalseBlock
+; Entry->TrueBlock is the common path, which should be taken whenever the
+; conditional branch is false.
+
+true:
+ call void @test_true()
+ ret void
+
+false:
+ call void @test_false()
+ ret void
+}
+
+define void @test_bcc_fallthrough_nottaken(i32 %in) nounwind {
+; RV32I-LABEL: test_bcc_fallthrough_nottaken:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp)
+; RV32I-NEXT: sw s0, 8(sp)
+; RV32I-NEXT: addi s0, sp, 16
+; RV32I-NEXT: addi a1, zero, 42
+; RV32I-NEXT: beq a0, a1, .LBB1_1
+; RV32I-NEXT: # %bb.3: # %false
+; RV32I-NEXT: lui a0, %hi(test_false)
+; RV32I-NEXT: addi a0, a0, %lo(test_false)
+; RV32I-NEXT: .LBB1_2: # %true
+; RV32I-NEXT: jalr a0
+; RV32I-NEXT: lw s0, 8(sp)
+; RV32I-NEXT: lw ra, 12(sp)
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+; RV32I-NEXT: .LBB1_1: # %true
+; RV32I-NEXT: lui a0, %hi(test_true)
+; RV32I-NEXT: addi a0, a0, %lo(test_true)
+; RV32I-NEXT: j .LBB1_2
+ %tst = icmp eq i32 %in, 42
+ br i1 %tst, label %true, label %false, !prof !1
+
+; Expected layout order is: Entry, FalseBlock, TrueBlock
+; Entry->FalseBlock is the common path, which should be taken whenever the
+; conditional branch is false
+
+true:
+ call void @test_true()
+ ret void
+
+false:
+ call void @test_false()
+ ret void
+}
+
+; TODO: how can we expand the coverage of the branch analysis functions?
Modified: llvm/trunk/test/CodeGen/RISCV/branch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/branch.ll?rev=322222&r1=322221&r2=322222&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/branch.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/branch.ll Wed Jan 10 12:47:00 2018
@@ -11,49 +11,38 @@ define void @foo(i32 %a, i32 *%b, i1 %c)
; RV32I-NEXT: addi s0, sp, 16
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: beq a3, a0, .LBB0_12
-; RV32I-NEXT: j .LBB0_1
-; RV32I-NEXT: .LBB0_1: # %test2
+; RV32I-NEXT: # %bb.1: # %test2
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: bne a3, a0, .LBB0_12
-; RV32I-NEXT: j .LBB0_2
-; RV32I-NEXT: .LBB0_2: # %test3
+; RV32I-NEXT: # %bb.2: # %test3
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: blt a3, a0, .LBB0_12
-; RV32I-NEXT: j .LBB0_3
-; RV32I-NEXT: .LBB0_3: # %test4
+; RV32I-NEXT: # %bb.3: # %test4
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: bge a3, a0, .LBB0_12
-; RV32I-NEXT: j .LBB0_4
-; RV32I-NEXT: .LBB0_4: # %test5
+; RV32I-NEXT: # %bb.4: # %test5
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: bltu a3, a0, .LBB0_12
-; RV32I-NEXT: j .LBB0_5
-; RV32I-NEXT: .LBB0_5: # %test6
+; RV32I-NEXT: # %bb.5: # %test6
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: bgeu a3, a0, .LBB0_12
-; RV32I-NEXT: j .LBB0_6
-; RV32I-NEXT: .LBB0_6: # %test7
+; RV32I-NEXT: # %bb.6: # %test7
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: blt a0, a3, .LBB0_12
-; RV32I-NEXT: j .LBB0_7
-; RV32I-NEXT: .LBB0_7: # %test8
+; RV32I-NEXT: # %bb.7: # %test8
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: bge a0, a3, .LBB0_12
-; RV32I-NEXT: j .LBB0_8
-; RV32I-NEXT: .LBB0_8: # %test9
+; RV32I-NEXT: # %bb.8: # %test9
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: bltu a0, a3, .LBB0_12
-; RV32I-NEXT: j .LBB0_9
-; RV32I-NEXT: .LBB0_9: # %test10
+; RV32I-NEXT: # %bb.9: # %test10
; RV32I-NEXT: lw a3, 0(a1)
; RV32I-NEXT: bgeu a0, a3, .LBB0_12
-; RV32I-NEXT: j .LBB0_10
-; RV32I-NEXT: .LBB0_10: # %test11
+; RV32I-NEXT: # %bb.10: # %test11
; RV32I-NEXT: lw a0, 0(a1)
; RV32I-NEXT: andi a0, a2, 1
; RV32I-NEXT: bnez a0, .LBB0_12
-; RV32I-NEXT: j .LBB0_11
-; RV32I-NEXT: .LBB0_11: # %test12
+; RV32I-NEXT: # %bb.11: # %test12
; RV32I-NEXT: lw a0, 0(a1)
; RV32I-NEXT: .LBB0_12: # %end
; RV32I-NEXT: lw s0, 8(sp)
Modified: llvm/trunk/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll?rev=322222&r1=322221&r2=322222&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll Wed Jan 10 12:47:00 2018
@@ -107,15 +107,12 @@ define i8 @test_cttz_i8(i8 %a) nounwind
; RV32I-NEXT: sw ra, 12(sp)
; RV32I-NEXT: sw s0, 8(sp)
; RV32I-NEXT: addi s0, sp, 16
-; RV32I-NEXT: mv a1, a0
-; RV32I-NEXT: addi a0, zero, 8
-; RV32I-NEXT: andi a2, a1, 255
-; RV32I-NEXT: beqz a2, .LBB3_2
-; RV32I-NEXT: j .LBB3_1
-; RV32I-NEXT: .LBB3_1: # %cond.false
-; RV32I-NEXT: addi a0, a1, -1
-; RV32I-NEXT: not a1, a1
-; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: andi a1, a0, 255
+; RV32I-NEXT: beqz a1, .LBB3_1
+; RV32I-NEXT: # %bb.2: # %cond.false
+; RV32I-NEXT: addi a1, a0, -1
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: lui a1, 349525
; RV32I-NEXT: addi a1, a1, 1365
; RV32I-NEXT: srli a2, a0, 1
@@ -138,7 +135,10 @@ define i8 @test_cttz_i8(i8 %a) nounwind
; RV32I-NEXT: addi a2, a2, %lo(__mulsi3)
; RV32I-NEXT: jalr a2
; RV32I-NEXT: srli a0, a0, 24
-; RV32I-NEXT: .LBB3_2: # %cond.end
+; RV32I-NEXT: j .LBB3_3
+; RV32I-NEXT: .LBB3_1:
+; RV32I-NEXT: addi a0, zero, 8
+; RV32I-NEXT: .LBB3_3: # %cond.end
; RV32I-NEXT: lw s0, 8(sp)
; RV32I-NEXT: lw ra, 12(sp)
; RV32I-NEXT: addi sp, sp, 16
@@ -154,17 +154,14 @@ define i16 @test_cttz_i16(i16 %a) nounwi
; RV32I-NEXT: sw ra, 12(sp)
; RV32I-NEXT: sw s0, 8(sp)
; RV32I-NEXT: addi s0, sp, 16
-; RV32I-NEXT: mv a1, a0
-; RV32I-NEXT: addi a0, zero, 16
-; RV32I-NEXT: lui a2, 16
-; RV32I-NEXT: addi a2, a2, -1
-; RV32I-NEXT: and a2, a1, a2
-; RV32I-NEXT: beqz a2, .LBB4_2
-; RV32I-NEXT: j .LBB4_1
-; RV32I-NEXT: .LBB4_1: # %cond.false
-; RV32I-NEXT: addi a0, a1, -1
-; RV32I-NEXT: not a1, a1
-; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: and a1, a0, a1
+; RV32I-NEXT: beqz a1, .LBB4_1
+; RV32I-NEXT: # %bb.2: # %cond.false
+; RV32I-NEXT: addi a1, a0, -1
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: lui a1, 349525
; RV32I-NEXT: addi a1, a1, 1365
; RV32I-NEXT: srli a2, a0, 1
@@ -187,7 +184,10 @@ define i16 @test_cttz_i16(i16 %a) nounwi
; RV32I-NEXT: addi a2, a2, %lo(__mulsi3)
; RV32I-NEXT: jalr a2
; RV32I-NEXT: srli a0, a0, 24
-; RV32I-NEXT: .LBB4_2: # %cond.end
+; RV32I-NEXT: j .LBB4_3
+; RV32I-NEXT: .LBB4_1:
+; RV32I-NEXT: addi a0, zero, 16
+; RV32I-NEXT: .LBB4_3: # %cond.end
; RV32I-NEXT: lw s0, 8(sp)
; RV32I-NEXT: lw ra, 12(sp)
; RV32I-NEXT: addi sp, sp, 16
@@ -203,14 +203,11 @@ define i32 @test_cttz_i32(i32 %a) nounwi
; RV32I-NEXT: sw ra, 12(sp)
; RV32I-NEXT: sw s0, 8(sp)
; RV32I-NEXT: addi s0, sp, 16
-; RV32I-NEXT: mv a1, a0
-; RV32I-NEXT: addi a0, zero, 32
-; RV32I-NEXT: beqz a1, .LBB5_2
-; RV32I-NEXT: j .LBB5_1
-; RV32I-NEXT: .LBB5_1: # %cond.false
-; RV32I-NEXT: addi a0, a1, -1
-; RV32I-NEXT: not a1, a1
-; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: beqz a0, .LBB5_1
+; RV32I-NEXT: # %bb.2: # %cond.false
+; RV32I-NEXT: addi a1, a0, -1
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: lui a1, 349525
; RV32I-NEXT: addi a1, a1, 1365
; RV32I-NEXT: srli a2, a0, 1
@@ -233,7 +230,10 @@ define i32 @test_cttz_i32(i32 %a) nounwi
; RV32I-NEXT: addi a2, a2, %lo(__mulsi3)
; RV32I-NEXT: jalr a2
; RV32I-NEXT: srli a0, a0, 24
-; RV32I-NEXT: .LBB5_2: # %cond.end
+; RV32I-NEXT: j .LBB5_3
+; RV32I-NEXT: .LBB5_1:
+; RV32I-NEXT: addi a0, zero, 32
+; RV32I-NEXT: .LBB5_3: # %cond.end
; RV32I-NEXT: lw s0, 8(sp)
; RV32I-NEXT: lw ra, 12(sp)
; RV32I-NEXT: addi sp, sp, 16
@@ -249,13 +249,10 @@ define i32 @test_ctlz_i32(i32 %a) nounwi
; RV32I-NEXT: sw ra, 12(sp)
; RV32I-NEXT: sw s0, 8(sp)
; RV32I-NEXT: addi s0, sp, 16
-; RV32I-NEXT: mv a1, a0
-; RV32I-NEXT: addi a0, zero, 32
-; RV32I-NEXT: beqz a1, .LBB6_2
-; RV32I-NEXT: j .LBB6_1
-; RV32I-NEXT: .LBB6_1: # %cond.false
-; RV32I-NEXT: srli a0, a1, 1
-; RV32I-NEXT: or a0, a1, a0
+; RV32I-NEXT: beqz a0, .LBB6_1
+; RV32I-NEXT: # %bb.2: # %cond.false
+; RV32I-NEXT: srli a1, a0, 1
+; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: srli a1, a0, 2
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: srli a1, a0, 4
@@ -287,7 +284,10 @@ define i32 @test_ctlz_i32(i32 %a) nounwi
; RV32I-NEXT: addi a2, a2, %lo(__mulsi3)
; RV32I-NEXT: jalr a2
; RV32I-NEXT: srli a0, a0, 24
-; RV32I-NEXT: .LBB6_2: # %cond.end
+; RV32I-NEXT: j .LBB6_3
+; RV32I-NEXT: .LBB6_1:
+; RV32I-NEXT: addi a0, zero, 32
+; RV32I-NEXT: .LBB6_3: # %cond.end
; RV32I-NEXT: lw s0, 8(sp)
; RV32I-NEXT: lw ra, 12(sp)
; RV32I-NEXT: addi sp, sp, 16
@@ -309,58 +309,61 @@ define i64 @test_cttz_i64(i64 %a) nounwi
; RV32I-NEXT: sw s5, 20(sp)
; RV32I-NEXT: sw s6, 16(sp)
; RV32I-NEXT: sw s7, 12(sp)
+; RV32I-NEXT: sw s8, 8(sp)
; RV32I-NEXT: addi s0, sp, 48
-; RV32I-NEXT: mv s1, a1
-; RV32I-NEXT: mv s2, a0
-; RV32I-NEXT: addi a0, s2, -1
-; RV32I-NEXT: not a1, s2
+; RV32I-NEXT: mv s2, a1
+; RV32I-NEXT: mv s3, a0
+; RV32I-NEXT: addi a0, s3, -1
+; RV32I-NEXT: not a1, s3
; RV32I-NEXT: and a0, a1, a0
; RV32I-NEXT: lui a1, 349525
-; RV32I-NEXT: addi s4, a1, 1365
+; RV32I-NEXT: addi s5, a1, 1365
; RV32I-NEXT: srli a1, a0, 1
-; RV32I-NEXT: and a1, a1, s4
+; RV32I-NEXT: and a1, a1, s5
; RV32I-NEXT: sub a0, a0, a1
; RV32I-NEXT: lui a1, 209715
-; RV32I-NEXT: addi s5, a1, 819
-; RV32I-NEXT: and a1, a0, s5
+; RV32I-NEXT: addi s6, a1, 819
+; RV32I-NEXT: and a1, a0, s6
; RV32I-NEXT: srli a0, a0, 2
-; RV32I-NEXT: and a0, a0, s5
+; RV32I-NEXT: and a0, a0, s6
; RV32I-NEXT: add a0, a1, a0
; RV32I-NEXT: srli a1, a0, 4
; RV32I-NEXT: add a0, a0, a1
; RV32I-NEXT: lui a1, 4112
-; RV32I-NEXT: addi s3, a1, 257
+; RV32I-NEXT: addi s4, a1, 257
; RV32I-NEXT: lui a1, %hi(__mulsi3)
-; RV32I-NEXT: addi s6, a1, %lo(__mulsi3)
+; RV32I-NEXT: addi s7, a1, %lo(__mulsi3)
; RV32I-NEXT: lui a1, 61681
-; RV32I-NEXT: addi s7, a1, -241
-; RV32I-NEXT: and a0, a0, s7
-; RV32I-NEXT: mv a1, s3
-; RV32I-NEXT: jalr s6
-; RV32I-NEXT: addi a1, s1, -1
-; RV32I-NEXT: not a2, s1
-; RV32I-NEXT: and a1, a2, a1
-; RV32I-NEXT: srli a2, a1, 1
-; RV32I-NEXT: and a2, a2, s4
-; RV32I-NEXT: sub a1, a1, a2
-; RV32I-NEXT: and a2, a1, s5
-; RV32I-NEXT: srli a1, a1, 2
+; RV32I-NEXT: addi s8, a1, -241
+; RV32I-NEXT: and a0, a0, s8
+; RV32I-NEXT: mv a1, s4
+; RV32I-NEXT: jalr s7
+; RV32I-NEXT: mv s1, a0
+; RV32I-NEXT: addi a0, s2, -1
+; RV32I-NEXT: not a1, s2
+; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: srli a1, a0, 1
; RV32I-NEXT: and a1, a1, s5
-; RV32I-NEXT: add a1, a2, a1
-; RV32I-NEXT: srli a2, a1, 4
-; RV32I-NEXT: add a1, a1, a2
-; RV32I-NEXT: and a1, a1, s7
-; RV32I-NEXT: srli s1, a0, 24
-; RV32I-NEXT: mv a0, a1
-; RV32I-NEXT: mv a1, s3
-; RV32I-NEXT: jalr s6
-; RV32I-NEXT: bnez s2, .LBB7_2
-; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: sub a0, a0, a1
+; RV32I-NEXT: and a1, a0, s6
+; RV32I-NEXT: srli a0, a0, 2
+; RV32I-NEXT: and a0, a0, s6
+; RV32I-NEXT: add a0, a1, a0
+; RV32I-NEXT: srli a1, a0, 4
+; RV32I-NEXT: add a0, a0, a1
+; RV32I-NEXT: and a0, a0, s8
+; RV32I-NEXT: mv a1, s4
+; RV32I-NEXT: jalr s7
+; RV32I-NEXT: bnez s3, .LBB7_1
+; RV32I-NEXT: # %bb.2:
; RV32I-NEXT: srli a0, a0, 24
-; RV32I-NEXT: addi s1, a0, 32
-; RV32I-NEXT: .LBB7_2:
-; RV32I-NEXT: mv a0, s1
+; RV32I-NEXT: addi a0, a0, 32
+; RV32I-NEXT: j .LBB7_3
+; RV32I-NEXT: .LBB7_1:
+; RV32I-NEXT: srli a0, s1, 24
+; RV32I-NEXT: .LBB7_3:
; RV32I-NEXT: mv a1, zero
+; RV32I-NEXT: lw s8, 8(sp)
; RV32I-NEXT: lw s7, 12(sp)
; RV32I-NEXT: lw s6, 16(sp)
; RV32I-NEXT: lw s5, 20(sp)
@@ -509,58 +512,61 @@ define i64 @test_cttz_i64_zero_undef(i64
; RV32I-NEXT: sw s5, 20(sp)
; RV32I-NEXT: sw s6, 16(sp)
; RV32I-NEXT: sw s7, 12(sp)
+; RV32I-NEXT: sw s8, 8(sp)
; RV32I-NEXT: addi s0, sp, 48
-; RV32I-NEXT: mv s1, a1
-; RV32I-NEXT: mv s2, a0
-; RV32I-NEXT: addi a0, s2, -1
-; RV32I-NEXT: not a1, s2
+; RV32I-NEXT: mv s2, a1
+; RV32I-NEXT: mv s3, a0
+; RV32I-NEXT: addi a0, s3, -1
+; RV32I-NEXT: not a1, s3
; RV32I-NEXT: and a0, a1, a0
; RV32I-NEXT: lui a1, 349525
-; RV32I-NEXT: addi s4, a1, 1365
+; RV32I-NEXT: addi s5, a1, 1365
; RV32I-NEXT: srli a1, a0, 1
-; RV32I-NEXT: and a1, a1, s4
+; RV32I-NEXT: and a1, a1, s5
; RV32I-NEXT: sub a0, a0, a1
; RV32I-NEXT: lui a1, 209715
-; RV32I-NEXT: addi s5, a1, 819
-; RV32I-NEXT: and a1, a0, s5
+; RV32I-NEXT: addi s6, a1, 819
+; RV32I-NEXT: and a1, a0, s6
; RV32I-NEXT: srli a0, a0, 2
-; RV32I-NEXT: and a0, a0, s5
+; RV32I-NEXT: and a0, a0, s6
; RV32I-NEXT: add a0, a1, a0
; RV32I-NEXT: srli a1, a0, 4
; RV32I-NEXT: add a0, a0, a1
; RV32I-NEXT: lui a1, 4112
-; RV32I-NEXT: addi s3, a1, 257
+; RV32I-NEXT: addi s4, a1, 257
; RV32I-NEXT: lui a1, %hi(__mulsi3)
-; RV32I-NEXT: addi s6, a1, %lo(__mulsi3)
+; RV32I-NEXT: addi s7, a1, %lo(__mulsi3)
; RV32I-NEXT: lui a1, 61681
-; RV32I-NEXT: addi s7, a1, -241
-; RV32I-NEXT: and a0, a0, s7
-; RV32I-NEXT: mv a1, s3
-; RV32I-NEXT: jalr s6
-; RV32I-NEXT: addi a1, s1, -1
-; RV32I-NEXT: not a2, s1
-; RV32I-NEXT: and a1, a2, a1
-; RV32I-NEXT: srli a2, a1, 1
-; RV32I-NEXT: and a2, a2, s4
-; RV32I-NEXT: sub a1, a1, a2
-; RV32I-NEXT: and a2, a1, s5
-; RV32I-NEXT: srli a1, a1, 2
+; RV32I-NEXT: addi s8, a1, -241
+; RV32I-NEXT: and a0, a0, s8
+; RV32I-NEXT: mv a1, s4
+; RV32I-NEXT: jalr s7
+; RV32I-NEXT: mv s1, a0
+; RV32I-NEXT: addi a0, s2, -1
+; RV32I-NEXT: not a1, s2
+; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: srli a1, a0, 1
; RV32I-NEXT: and a1, a1, s5
-; RV32I-NEXT: add a1, a2, a1
-; RV32I-NEXT: srli a2, a1, 4
-; RV32I-NEXT: add a1, a1, a2
-; RV32I-NEXT: and a1, a1, s7
-; RV32I-NEXT: srli s1, a0, 24
-; RV32I-NEXT: mv a0, a1
-; RV32I-NEXT: mv a1, s3
-; RV32I-NEXT: jalr s6
-; RV32I-NEXT: bnez s2, .LBB11_2
-; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: sub a0, a0, a1
+; RV32I-NEXT: and a1, a0, s6
+; RV32I-NEXT: srli a0, a0, 2
+; RV32I-NEXT: and a0, a0, s6
+; RV32I-NEXT: add a0, a1, a0
+; RV32I-NEXT: srli a1, a0, 4
+; RV32I-NEXT: add a0, a0, a1
+; RV32I-NEXT: and a0, a0, s8
+; RV32I-NEXT: mv a1, s4
+; RV32I-NEXT: jalr s7
+; RV32I-NEXT: bnez s3, .LBB11_1
+; RV32I-NEXT: # %bb.2:
; RV32I-NEXT: srli a0, a0, 24
-; RV32I-NEXT: addi s1, a0, 32
-; RV32I-NEXT: .LBB11_2:
-; RV32I-NEXT: mv a0, s1
+; RV32I-NEXT: addi a0, a0, 32
+; RV32I-NEXT: j .LBB11_3
+; RV32I-NEXT: .LBB11_1:
+; RV32I-NEXT: srli a0, s1, 24
+; RV32I-NEXT: .LBB11_3:
; RV32I-NEXT: mv a1, zero
+; RV32I-NEXT: lw s8, 8(sp)
; RV32I-NEXT: lw s7, 12(sp)
; RV32I-NEXT: lw s6, 16(sp)
; RV32I-NEXT: lw s5, 20(sp)
Modified: llvm/trunk/test/CodeGen/RISCV/jumptable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/jumptable.ll?rev=322222&r1=322221&r2=322222&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/jumptable.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/jumptable.ll Wed Jan 10 12:47:00 2018
@@ -10,42 +10,37 @@ define void @jt(i32 %in, i32* %out) {
; RV32I-NEXT: sw s0, 8(sp)
; RV32I-NEXT: addi s0, sp, 16
; RV32I-NEXT: addi a2, zero, 2
-; RV32I-NEXT: blt a2, a0, .LBB0_3
-; RV32I-NEXT: j .LBB0_1
-; RV32I-NEXT: .LBB0_1: # %entry
+; RV32I-NEXT: blt a2, a0, .LBB0_4
+; RV32I-NEXT: # %bb.1: # %entry
; RV32I-NEXT: addi a3, zero, 1
-; RV32I-NEXT: beq a0, a3, .LBB0_5
-; RV32I-NEXT: j .LBB0_2
-; RV32I-NEXT: .LBB0_2: # %entry
-; RV32I-NEXT: beq a0, a2, .LBB0_6
-; RV32I-NEXT: j .LBB0_9
-; RV32I-NEXT: .LBB0_6: # %bb2
+; RV32I-NEXT: beq a0, a3, .LBB0_8
+; RV32I-NEXT: # %bb.2: # %entry
+; RV32I-NEXT: bne a0, a2, .LBB0_10
+; RV32I-NEXT: # %bb.3: # %bb2
; RV32I-NEXT: addi a0, zero, 3
; RV32I-NEXT: sw a0, 0(a1)
-; RV32I-NEXT: j .LBB0_9
-; RV32I-NEXT: .LBB0_3: # %entry
-; RV32I-NEXT: addi a3, zero, 3
-; RV32I-NEXT: beq a0, a3, .LBB0_7
-; RV32I-NEXT: j .LBB0_4
+; RV32I-NEXT: j .LBB0_10
; RV32I-NEXT: .LBB0_4: # %entry
+; RV32I-NEXT: addi a3, zero, 3
+; RV32I-NEXT: beq a0, a3, .LBB0_9
+; RV32I-NEXT: # %bb.5: # %entry
; RV32I-NEXT: addi a2, zero, 4
-; RV32I-NEXT: beq a0, a2, .LBB0_8
-; RV32I-NEXT: j .LBB0_9
-; RV32I-NEXT: .LBB0_8: # %bb4
+; RV32I-NEXT: bne a0, a2, .LBB0_10
+; RV32I-NEXT: # %bb.6: # %bb4
; RV32I-NEXT: addi a0, zero, 1
; RV32I-NEXT: sw a0, 0(a1)
-; RV32I-NEXT: .LBB0_9: # %exit
+; RV32I-NEXT: j .LBB0_10
+; RV32I-NEXT: .LBB0_8: # %bb1
+; RV32I-NEXT: addi a0, zero, 4
+; RV32I-NEXT: sw a0, 0(a1)
+; RV32I-NEXT: j .LBB0_10
+; RV32I-NEXT: .LBB0_9: # %bb3
+; RV32I-NEXT: sw a2, 0(a1)
+; RV32I-NEXT: .LBB0_10: # %exit
; RV32I-NEXT: lw s0, 8(sp)
; RV32I-NEXT: lw ra, 12(sp)
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
-; RV32I-NEXT: .LBB0_5: # %bb1
-; RV32I-NEXT: addi a0, zero, 4
-; RV32I-NEXT: sw a0, 0(a1)
-; RV32I-NEXT: j .LBB0_9
-; RV32I-NEXT: .LBB0_7: # %bb3
-; RV32I-NEXT: sw a2, 0(a1)
-; RV32I-NEXT: j .LBB0_9
entry:
switch i32 %in, label %exit [
i32 1, label %bb1
Modified: llvm/trunk/test/CodeGen/RISCV/select-cc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/select-cc.ll?rev=322222&r1=322221&r2=322222&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/select-cc.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/select-cc.ll Wed Jan 10 12:47:00 2018
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv32 -disable-block-placement -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefix=RV32I %s
define i32 @foo(i32 %a, i32 *%b) {
More information about the llvm-commits
mailing list