diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -237,6 +237,11 @@ let OperandNamespace = "RISCVOp"; } +// A 12-bit signed immediate which cannot fit in 6-bit signed immediate, +// but even negative value fit in 12-bit. +def simm12_no6 : ImmLeaf(Imm) && !isInt<6>(Imm) && isInt<12>(-Imm);}]>; + // A 13-bit signed immediate where the least significant bit is zero. def simm13_lsb0 : Operand { let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; @@ -1326,6 +1331,18 @@ defm Select_GPR : SelectCC_GPR_rrirr; +class SelectCompressOpt: Pat<(riscv_selectcc_frag:$select GPR:$lhs, simm12_no6:$Constant, Cond, + GPR:$truev, GPR:$falsev), + (Select_GPR_Using_CC_GPR (ADDI GPR:$lhs, (NegImm simm12:$Constant)), X0, + (IntCCtoRISCVCC $select), GPR:$truev, GPR:$falsev)>; + +def OptForMinSize : Predicate<"MF ? MF->getFunction().hasMinSize() : false">; + +let Predicates = [HasStdExtC, OptForMinSize] in { + def : SelectCompressOpt; + def : SelectCompressOpt; +} + /// Branches and jumps // Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction. @@ -1337,6 +1354,9 @@ (Inst GPR:$rs1, X0, simm13_lsb0:$imm12)>; } +class BrccCompessOpt : Pat<(riscv_brcc GPR:$lhs, simm12_no6:$Constant, Cond, bb:$place), + (Inst (ADDI GPR:$lhs, (NegImm simm12:$Constant)), X0, bb:$place)>; + defm : BccPat; defm : BccPat; defm : BccPat; @@ -1344,6 +1364,11 @@ defm : BccPat; defm : BccPat; +let Predicates = [HasStdExtC, OptForMinSize] in { + def : BrccCompessOpt; + def : BrccCompessOpt; +} + let isBarrier = 1, isBranch = 1, isTerminator = 1 in def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; diff --git a/llvm/test/CodeGen/RISCV/compress-opt-branch.ll b/llvm/test/CodeGen/RISCV/compress-opt-branch.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/compress-opt-branch.ll @@ -0,0 +1,309 @@ +; This test is designed to run 4 times, once with function attribute +c, +; once with function attribute -c for eq/ne in icmp +; The optimization should appear only with +c, otherwise default isel should be +; choosen. +; +; RUN: cat %s | sed 's/CMPCOND/eq/g' | sed 's/RESBRNORMAL/bne/g' | \ +; RUN: sed 's/RESBROPT/c.bnez/g' > %t.compress_eq +; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=+c,+f,+d -filetype=obj \ +; RUN: -disable-block-placement < %t.compress_eq \ +; RUN: | llvm-objdump -d --triple=riscv32 --mattr=+c,+f,+d -M no-aliases - \ +; RUN: | FileCheck -check-prefix=RV32IFDC %t.compress_eq +; +; RUN: cat %s | sed -e 's/CMPCOND/eq/g' | sed -e 's/RESBRNORMAL/bne/g'\ +; RUN: | sed -e 's/RESBROPT/c.bnez/g' > %t.nocompr_eq +; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=-c,+f,+d -filetype=obj \ +; RUN: -disable-block-placement < %t.nocompr_eq \ +; RUN: | llvm-objdump -d --triple=riscv32 --mattr=-c,+f,+d -M no-aliases - \ +; RUN: | FileCheck -check-prefix=RV32IFD %t.nocompr_eq +; +; RUN: cat %s | sed 's/CMPCOND/ne/g' | sed 's/RESBRNORMAL/beq/g' | \ +; RUN: sed 's/RESBROPT/c.beqz/g' > %t.compress_neq +; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=+c,+f,+d -filetype=obj \ +; RUN: -disable-block-placement < %t.compress_neq \ +; RUN: | llvm-objdump -d --triple=riscv32 --mattr=+c,+f,+d -M no-aliases - \ +; RUN: | FileCheck -check-prefix=RV32IFDC %t.compress_neq +; +; RUN: cat %s | sed -e 's/CMPCOND/ne/g' | sed -e 's/RESBRNORMAL/beq/g'\ +; RUN: | sed -e 's/RESBROPT/c.beqz/g' > %t.nocompr_neq +; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=-c,+f,+d -filetype=obj \ +; RUN: -disable-block-placement < %t.nocompr_neq \ +; RUN: | llvm-objdump -d --triple=riscv32 --mattr=-c,+f,+d -M no-aliases - \ +; RUN: | FileCheck -check-prefix=RV32IFD %t.nocompr_neq + + +; constant is small and fit in 6 bit (compress imm) +; RV32IFDC-LABEL: : +; RV32IFDC: c.li [[REG:.*]], 20 +; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 20 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_small_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 20 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is small and fit in 6 bit (compress imm) +; RV32IFDC-LABEL: : +; RV32IFDC: c.li [[REG:.*]], -20 +; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -20 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_small_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -20 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is small and fit in 6 bit (compress imm) +; RV32IFDC-LABEL: : +; RV32IFDC: c.li [[REG:.*]], 31 +; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 31 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_small_edge_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 31 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is small and fit in 6 bit (compress imm) +; RV32IFDC-LABEL: : +; RV32IFDC: c.li [[REG:.*]], -32 +; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -32 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_small_edge_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -32 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], -32 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 32 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_ledge_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 32 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], 33 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -33 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_ledge_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -33 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], -63 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 63 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 63 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], 63 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -63 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -63 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], -2047 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 2047 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_bedge_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 2047 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm), negative value fit in 12 bit too. +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], 2047 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -2047 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_bedge_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -2047 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is big and do not fit in 12 bit (imm), fit in i32 +; RV32IFDC-LABEL: : +; RV32IFDC-NOT: RESBROPT +; --- no compress extension +; nothing to check. +define i32 @f_big_ledge_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 2048 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} + +; constant is big and do not fit in 12 bit (imm), fit in i32 +; RV32IFDC-LABEL: : +; RV32IFDC-NOT: c.beqz +; --- no compress extension +; nothing to check. +define i32 @f_big_ledge_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -2048 + br i1 %cmp, label %if.then, label %if.else +if.then: + %call = shl i32 %in0, 1 + br label %if.end +if.else: + %call2 = add i32 %in0, 42 + br label %if.end + +if.end: + %toRet = phi i32 [ %call, %if.then ], [ %call2, %if.else ] + ret i32 %toRet +} diff --git a/llvm/test/CodeGen/RISCV/compress-opt-select.ll b/llvm/test/CodeGen/RISCV/compress-opt-select.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/compress-opt-select.ll @@ -0,0 +1,201 @@ +; This test is designed to run 4 times, once with function attribute +c, +; once with function attribute -c for eq/ne in icmp +; The optimization should appear only with +c, otherwise default isel should be +; choosen. +; +; RUN: cat %s | sed 's/CMPCOND/eq/g' | sed 's/RESBRNORMAL/beq/g' | \ +; RUN: sed 's/RESBROPT/c.beqz/g' > %t.compress_eq +; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=+c,+f,+d -filetype=obj \ +; RUN: -disable-block-placement < %t.compress_eq \ +; RUN: | llvm-objdump -d --triple=riscv32 --mattr=+c,+f,+d -M no-aliases - \ +; RUN: | FileCheck -check-prefix=RV32IFDC %t.compress_eq +; +; RUN: cat %s | sed -e 's/CMPCOND/eq/g' | sed -e 's/RESBRNORMAL/beq/g'\ +; RUN: | sed -e 's/RESBROPT/c.beqz/g' > %t.nocompr_eq +; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=-c,+f,+d -filetype=obj \ +; RUN: -disable-block-placement < %t.nocompr_eq \ +; RUN: | llvm-objdump -d --triple=riscv32 --mattr=-c,+f,+d -M no-aliases - \ +; RUN: | FileCheck -check-prefix=RV32IFD %t.nocompr_eq +; +; RUN: cat %s | sed 's/CMPCOND/ne/g' | sed 's/RESBRNORMAL/bne/g' | \ +; RUN: sed 's/RESBROPT/c.bnez/g' > %t.compress_neq +; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=+c,+f,+d -filetype=obj \ +; RUN: -disable-block-placement < %t.compress_neq \ +; RUN: | llvm-objdump -d --triple=riscv32 --mattr=+c,+f,+d -M no-aliases - \ +; RUN: | FileCheck -check-prefix=RV32IFDC %t.compress_neq +; +; RUN: cat %s | sed -e 's/CMPCOND/ne/g' | sed -e 's/RESBRNORMAL/bne/g'\ +; RUN: | sed -e 's/RESBROPT/c.bnez/g' > %t.nocompr_neq +; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=-c,+f,+d -filetype=obj \ +; RUN: -disable-block-placement < %t.nocompr_neq \ +; RUN: | llvm-objdump -d --triple=riscv32 --mattr=-c,+f,+d -M no-aliases - \ +; RUN: | FileCheck -check-prefix=RV32IFD %t.nocompr_neq + + +; constant is small and fit in 6 bit (compress imm) +; RV32IFDC-LABEL: : +; RV32IFDC: c.li [[REG:.*]], 20 +; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 20 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_small_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 20 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is small and fit in 6 bit (compress imm) +; RV32IFDC-LABEL: : +; RV32IFDC: c.li [[REG:.*]], -20 +; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -20 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_small_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -20 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is small and fit in 6 bit (compress imm) +; RV32IFDC-LABEL: : +; RV32IFDC: c.li [[REG:.*]], 31 +; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 31 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_small_edge_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 31 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is small and fit in 6 bit (compress imm) +; RV32IFDC-LABEL: : +; RV32IFDC: c.li [[REG:.*]], -32 +; RV32IFDC: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -32 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_small_edge_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -32 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], -32 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 32 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_ledge_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 32 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], 33 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -33 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_ledge_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -33 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], -63 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 63 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 63 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], 63 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -63 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -63 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm) +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], -2047 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, 2047 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_bedge_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 2047 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is medium and not fit in 6 bit (compress imm), +; but fit in 12 bit (imm), negative value fit in 12 bit too. +; RV32IFDC-LABEL: : +; RV32IFDC: addi [[MAYZEROREG:.*]], [[REG:.*]], 2047 +; RV32IFDC: RESBROPT [[MAYZEROREG]], [[PLACE:.*]] +; --- no compress extension +; RV32IFD-LABEL: : +; RV32IFD: addi [[REG:.*]], zero, -2047 +; RV32IFD: RESBRNORMAL [[ANOTHER:.*]], [[REG]], [[PLACE:.*]] +define i32 @f_medium_bedge_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -2047 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is big and do not fit in 12 bit (imm), fit in i32 +; RV32IFDC-LABEL: : +; RV32IFDC-NOT: RESBROPT +; --- no compress extension +; nothing to check. +define i32 @f_big_ledge_pos(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, 2048 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +} + +; constant is big and do not fit in 12 bit (imm), fit in i32 +; RV32IFDC-LABEL: : +; RV32IFDC-NOT: c.beqz +; --- no compress extension +; nothing to check. +define i32 @f_big_ledge_neg(i32 %in0) minsize { + %cmp = icmp CMPCOND i32 %in0, -2048 + %toRet = select i1 %cmp, i32 0, i32 42 + ret i32 %toRet +}