[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