Skip to content

Commit

Permalink
[RISCV] Implement Hooks to avoid chaining SELECT
Browse files Browse the repository at this point in the history
Summary:
This implements two hooks that attempt to avoid control flow for RISC-V. RISC-V
will lower SELECTs into control flow, which is not a great idea.

The hook `hasMultipleConditionRegisters()` turns off the following
DAGCombiner folds:
    select(C0|C1, x, y) <=> select(C0, x, select(C1, x, y))
    select(C0&C1, x, y) <=> select(C0, select(C1, x, y), y)

The second hook `setJumpIsExpensive` controls a flag that has a similar purpose
and is used in CodeGenPrepare and the SelectionDAGBuilder.

Both of these have the effect of ensuring more logic is done before fewer jumps.

Note: with the `B` extension, we may be able to lower select into a conditional
move instruction, so at some point these hooks will need to be guarded based on
enabled extensions.

Reviewed By: luismarques

Differential Revision: https://reviews.llvm.org/D79268
  • Loading branch information
lenary committed Jul 1, 2020
1 parent c44266d commit 7dc8926
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 97 deletions.
6 changes: 6 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Expand Up @@ -236,6 +236,12 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,

// Effectively disable jump table generation.
setMinimumJumpTableEntries(INT_MAX);

// Jumps are expensive, compared to logic
setJumpIsExpensive();

// We can use any register for comparisons
setHasMultipleConditionRegisters();
}

EVT RISCVTargetLowering::getSetCCResultType(const DataLayout &DL, LLVMContext &,
Expand Down
20 changes: 10 additions & 10 deletions llvm/test/CodeGen/RISCV/double-previous-failure.ll
Expand Up @@ -25,19 +25,19 @@ define i32 @main() nounwind {
; RV32IFD-NEXT: fld ft0, 0(sp)
; RV32IFD-NEXT: lui a0, %hi(.LCPI1_0)
; RV32IFD-NEXT: fld ft1, %lo(.LCPI1_0)(a0)
; RV32IFD-NEXT: flt.d a0, ft0, ft1
; RV32IFD-NEXT: bnez a0, .LBB1_3
; RV32IFD-NEXT: # %bb.1: # %entry
; RV32IFD-NEXT: lui a0, %hi(.LCPI1_1)
; RV32IFD-NEXT: fld ft1, %lo(.LCPI1_1)(a0)
; RV32IFD-NEXT: flt.d a0, ft1, ft0
; RV32IFD-NEXT: xori a0, a0, 1
; RV32IFD-NEXT: beqz a0, .LBB1_3
; RV32IFD-NEXT: # %bb.2: # %if.end
; RV32IFD-NEXT: fld ft2, %lo(.LCPI1_1)(a0)
; RV32IFD-NEXT: flt.d a0, ft0, ft1
; RV32IFD-NEXT: not a0, a0
; RV32IFD-NEXT: flt.d a1, ft2, ft0
; RV32IFD-NEXT: xori a1, a1, 1
; RV32IFD-NEXT: and a0, a0, a1
; RV32IFD-NEXT: bnez a0, .LBB1_2
; RV32IFD-NEXT: # %bb.1: # %if.then
; RV32IFD-NEXT: call abort
; RV32IFD-NEXT: .LBB1_2: # %if.end
; RV32IFD-NEXT: mv a0, zero
; RV32IFD-NEXT: call exit
; RV32IFD-NEXT: .LBB1_3: # %if.then
; RV32IFD-NEXT: call abort
entry:
%call = call double @test(double 2.000000e+00)
%cmp = fcmp olt double %call, 2.400000e-01
Expand Down
56 changes: 22 additions & 34 deletions llvm/test/CodeGen/RISCV/select-and.ll
Expand Up @@ -10,34 +10,22 @@
define signext i32 @select_of_and(i1 zeroext %a, i1 zeroext %b, i32 signext %c, i32 signext %d) nounwind {
; RV32I-LABEL: select_of_and:
; RV32I: # %bb.0:
; RV32I-NEXT: beqz a1, .LBB0_3
; RV32I-NEXT: and a1, a0, a1
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: bnez a1, .LBB0_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: beqz a0, .LBB0_4
; RV32I-NEXT: mv a0, a3
; RV32I-NEXT: .LBB0_2:
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: ret
; RV32I-NEXT: .LBB0_3:
; RV32I-NEXT: mv a2, a3
; RV32I-NEXT: bnez a0, .LBB0_2
; RV32I-NEXT: .LBB0_4:
; RV32I-NEXT: mv a2, a3
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: ret
;
; RV64I-LABEL: select_of_and:
; RV64I: # %bb.0:
; RV64I-NEXT: beqz a1, .LBB0_3
; RV64I-NEXT: and a1, a0, a1
; RV64I-NEXT: mv a0, a2
; RV64I-NEXT: bnez a1, .LBB0_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: beqz a0, .LBB0_4
; RV64I-NEXT: mv a0, a3
; RV64I-NEXT: .LBB0_2:
; RV64I-NEXT: mv a0, a2
; RV64I-NEXT: ret
; RV64I-NEXT: .LBB0_3:
; RV64I-NEXT: mv a2, a3
; RV64I-NEXT: bnez a0, .LBB0_2
; RV64I-NEXT: .LBB0_4:
; RV64I-NEXT: mv a2, a3
; RV64I-NEXT: mv a0, a2
; RV64I-NEXT: ret
%1 = and i1 %a, %b
%2 = select i1 %1, i32 %c, i32 %d
Expand All @@ -52,15 +40,15 @@ define signext i32 @if_of_and(i1 zeroext %a, i1 zeroext %b) nounwind {
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp)
; RV32I-NEXT: beqz a0, .LBB1_3
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: beqz a1, .LBB1_3
; RV32I-NEXT: # %bb.2: # %if.then
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: addi a1, zero, 1
; RV32I-NEXT: bne a0, a1, .LBB1_2
; RV32I-NEXT: # %bb.1: # %if.then
; RV32I-NEXT: call both
; RV32I-NEXT: j .LBB1_4
; RV32I-NEXT: .LBB1_3: # %if.else
; RV32I-NEXT: j .LBB1_3
; RV32I-NEXT: .LBB1_2: # %if.else
; RV32I-NEXT: call neither
; RV32I-NEXT: .LBB1_4: # %if.end
; RV32I-NEXT: .LBB1_3: # %if.end
; RV32I-NEXT: lw ra, 12(sp)
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
Expand All @@ -69,15 +57,15 @@ define signext i32 @if_of_and(i1 zeroext %a, i1 zeroext %b) nounwind {
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp)
; RV64I-NEXT: beqz a0, .LBB1_3
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: beqz a1, .LBB1_3
; RV64I-NEXT: # %bb.2: # %if.then
; RV64I-NEXT: and a0, a0, a1
; RV64I-NEXT: addi a1, zero, 1
; RV64I-NEXT: bne a0, a1, .LBB1_2
; RV64I-NEXT: # %bb.1: # %if.then
; RV64I-NEXT: call both
; RV64I-NEXT: j .LBB1_4
; RV64I-NEXT: .LBB1_3: # %if.else
; RV64I-NEXT: j .LBB1_3
; RV64I-NEXT: .LBB1_2: # %if.else
; RV64I-NEXT: call neither
; RV64I-NEXT: .LBB1_4: # %if.end
; RV64I-NEXT: .LBB1_3: # %if.end
; RV64I-NEXT: ld ra, 8(sp)
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
Expand Down
62 changes: 24 additions & 38 deletions llvm/test/CodeGen/RISCV/select-or.ll
Expand Up @@ -10,36 +10,22 @@
define signext i32 @select_of_or(i1 zeroext %a, i1 zeroext %b, i32 signext %c, i32 signext %d) nounwind {
; RV32I-LABEL: select_of_or:
; RV32I: # %bb.0:
; RV32I-NEXT: mv a4, a2
; RV32I-NEXT: beqz a1, .LBB0_3
; RV32I-NEXT: or a1, a0, a1
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: bnez a1, .LBB0_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: beqz a0, .LBB0_4
; RV32I-NEXT: mv a0, a3
; RV32I-NEXT: .LBB0_2:
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: ret
; RV32I-NEXT: .LBB0_3:
; RV32I-NEXT: mv a4, a3
; RV32I-NEXT: bnez a0, .LBB0_2
; RV32I-NEXT: .LBB0_4:
; RV32I-NEXT: mv a2, a4
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: ret
;
; RV64I-LABEL: select_of_or:
; RV64I: # %bb.0:
; RV64I-NEXT: mv a4, a2
; RV64I-NEXT: beqz a1, .LBB0_3
; RV64I-NEXT: or a1, a0, a1
; RV64I-NEXT: mv a0, a2
; RV64I-NEXT: bnez a1, .LBB0_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: beqz a0, .LBB0_4
; RV64I-NEXT: mv a0, a3
; RV64I-NEXT: .LBB0_2:
; RV64I-NEXT: mv a0, a2
; RV64I-NEXT: ret
; RV64I-NEXT: .LBB0_3:
; RV64I-NEXT: mv a4, a3
; RV64I-NEXT: bnez a0, .LBB0_2
; RV64I-NEXT: .LBB0_4:
; RV64I-NEXT: mv a2, a4
; RV64I-NEXT: mv a0, a2
; RV64I-NEXT: ret
%1 = or i1 %a, %b
%2 = select i1 %1, i32 %c, i32 %d
Expand All @@ -54,15 +40,15 @@ define signext i32 @if_of_or(i1 zeroext %a, i1 zeroext %b) nounwind {
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp)
; RV32I-NEXT: bnez a0, .LBB1_3
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: bnez a1, .LBB1_3
; RV32I-NEXT: # %bb.2: # %if.else
; RV32I-NEXT: call neither
; RV32I-NEXT: j .LBB1_4
; RV32I-NEXT: .LBB1_3: # %if.then
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: addi a1, zero, 1
; RV32I-NEXT: bne a0, a1, .LBB1_2
; RV32I-NEXT: # %bb.1: # %if.then
; RV32I-NEXT: call either
; RV32I-NEXT: .LBB1_4: # %if.end
; RV32I-NEXT: j .LBB1_3
; RV32I-NEXT: .LBB1_2: # %if.else
; RV32I-NEXT: call neither
; RV32I-NEXT: .LBB1_3: # %if.end
; RV32I-NEXT: lw ra, 12(sp)
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
Expand All @@ -71,15 +57,15 @@ define signext i32 @if_of_or(i1 zeroext %a, i1 zeroext %b) nounwind {
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp)
; RV64I-NEXT: bnez a0, .LBB1_3
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: bnez a1, .LBB1_3
; RV64I-NEXT: # %bb.2: # %if.else
; RV64I-NEXT: call neither
; RV64I-NEXT: j .LBB1_4
; RV64I-NEXT: .LBB1_3: # %if.then
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: addi a1, zero, 1
; RV64I-NEXT: bne a0, a1, .LBB1_2
; RV64I-NEXT: # %bb.1: # %if.then
; RV64I-NEXT: call either
; RV64I-NEXT: .LBB1_4: # %if.end
; RV64I-NEXT: j .LBB1_3
; RV64I-NEXT: .LBB1_2: # %if.else
; RV64I-NEXT: call neither
; RV64I-NEXT: .LBB1_3: # %if.end
; RV64I-NEXT: ld ra, 8(sp)
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
Expand Down
29 changes: 14 additions & 15 deletions llvm/test/CodeGen/RISCV/zext-with-load-is-free.ll
Expand Up @@ -11,17 +11,16 @@ define i32 @test_zext_i8() nounwind {
; RV32I: # %bb.0: # %entry
; RV32I-NEXT: lui a0, %hi(bytes)
; RV32I-NEXT: lbu a1, %lo(bytes)(a0)
; RV32I-NEXT: addi a2, zero, 136
; RV32I-NEXT: bne a1, a2, .LBB0_3
; RV32I-NEXT: # %bb.1: # %entry
; RV32I-NEXT: addi a0, a0, %lo(bytes)
; RV32I-NEXT: lbu a0, 1(a0)
; RV32I-NEXT: addi a1, zero, 7
; RV32I-NEXT: bne a0, a1, .LBB0_3
; RV32I-NEXT: # %bb.2: # %if.end
; RV32I-NEXT: xori a1, a1, 136
; RV32I-NEXT: xori a0, a0, 7
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: bnez a0, .LBB0_2
; RV32I-NEXT: # %bb.1: # %if.end
; RV32I-NEXT: mv a0, zero
; RV32I-NEXT: ret
; RV32I-NEXT: .LBB0_3: # %if.then
; RV32I-NEXT: .LBB0_2: # %if.then
; RV32I-NEXT: addi a0, zero, 1
; RV32I-NEXT: ret
entry:
Expand All @@ -46,18 +45,18 @@ define i32 @test_zext_i16() nounwind {
; RV32I: # %bb.0: # %entry
; RV32I-NEXT: lui a0, %hi(shorts)
; RV32I-NEXT: lhu a1, %lo(shorts)(a0)
; RV32I-NEXT: lui a2, 16
; RV32I-NEXT: addi a2, a2, -120
; RV32I-NEXT: bne a1, a2, .LBB1_3
; RV32I-NEXT: # %bb.1: # %entry
; RV32I-NEXT: addi a0, a0, %lo(shorts)
; RV32I-NEXT: lhu a0, 2(a0)
; RV32I-NEXT: addi a1, zero, 7
; RV32I-NEXT: bne a0, a1, .LBB1_3
; RV32I-NEXT: # %bb.2: # %if.end
; RV32I-NEXT: lui a2, 16
; RV32I-NEXT: addi a2, a2, -120
; RV32I-NEXT: xor a1, a1, a2
; RV32I-NEXT: xori a0, a0, 7
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: bnez a0, .LBB1_2
; RV32I-NEXT: # %bb.1: # %if.end
; RV32I-NEXT: mv a0, zero
; RV32I-NEXT: ret
; RV32I-NEXT: .LBB1_3: # %if.then
; RV32I-NEXT: .LBB1_2: # %if.then
; RV32I-NEXT: addi a0, zero, 1
; RV32I-NEXT: ret
entry:
Expand Down

0 comments on commit 7dc8926

Please sign in to comment.