def SH3ADD : ALU_rr<0b0010000, 0b110, "sh3add">, Sched<[]>;
} // Predicates = [HasStdExtZba]
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbp] in {
def SLO : ALU_rr<0b0010000, 0b001, "slo">, Sched<[]>;
def SRO : ALU_rr<0b0010000, 0b101, "sro">, Sched<[]>;
-} // Predicates = [HasStdExtZbb]
+} // Predicates = [HasStdExtZbp]
let Predicates = [HasStdExtZbbOrZbp] in {
def ROL : ALU_rr<0b0110000, 0b001, "rol">, Sched<[]>;
def GREV : ALU_rr<0b0110100, 0b101, "grev">, Sched<[]>;
} // Predicates = [HasStdExtZbp]
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbp] in {
def SLOI : RVBShift_ri<0b00100, 0b001, OPC_OP_IMM, "sloi">, Sched<[]>;
def SROI : RVBShift_ri<0b00100, 0b101, OPC_OP_IMM, "sroi">, Sched<[]>;
-} // Predicates = [HasStdExtZbb]
+} // Predicates = [HasStdExtZbp]
let Predicates = [HasStdExtZbbOrZbp] in
def RORI : RVBShift_ri<0b01100, 0b101, OPC_OP_IMM, "rori">, Sched<[]>;
def SH3ADDUW : ALUW_rr<0b0010000, 0b110, "sh3add.uw">, Sched<[]>;
} // Predicates = [HasStdExtZbb, IsRV64]
-let Predicates = [HasStdExtZbb, IsRV64] in {
+let Predicates = [HasStdExtZbp, IsRV64] in {
def SLOW : ALUW_rr<0b0010000, 0b001, "slow">, Sched<[]>;
def SROW : ALUW_rr<0b0010000, 0b101, "srow">, Sched<[]>;
-} // Predicates = [HasStdExtZbb, IsRV64]
+} // Predicates = [HasStdExtZbp, IsRV64]
let Predicates = [HasStdExtZbbOrZbp, IsRV64] in {
def ROLW : ALUW_rr<0b0110000, 0b001, "rolw">, Sched<[]>;
def GREVW : ALUW_rr<0b0110100, 0b101, "grevw">, Sched<[]>;
} // Predicates = [HasStdExtZbp, IsRV64]
-let Predicates = [HasStdExtZbb, IsRV64] in {
+let Predicates = [HasStdExtZbp, IsRV64] in {
def SLOIW : RVBShiftW_ri<0b0010000, 0b001, OPC_OP_IMM_32, "sloiw">, Sched<[]>;
def SROIW : RVBShiftW_ri<0b0010000, 0b101, OPC_OP_IMM_32, "sroiw">, Sched<[]>;
-} // Predicates = [HasStdExtZbb, IsRV64]
+} // Predicates = [HasStdExtZbp, IsRV64]
let Predicates = [HasStdExtZbbOrZbp, IsRV64] in
def RORIW : RVBShiftW_ri<0b0110000, 0b101, OPC_OP_IMM_32, "roriw">, Sched<[]>;
def : Pat<(xor GPR:$rs1, (not GPR:$rs2)), (XNOR GPR:$rs1, GPR:$rs2)>;
} // Predicates = [HasStdExtZbbOrZbp]
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbp] in {
def : Pat<(not (shl (not GPR:$rs1), GPR:$rs2)),
(SLO GPR:$rs1, GPR:$rs2)>;
def : Pat<(not (srl (not GPR:$rs1), GPR:$rs2)),
(SRO GPR:$rs1, GPR:$rs2)>;
-} // Predicates = [HasStdExtZbb]
+} // Predicates = [HasStdExtZbp]
let Predicates = [HasStdExtZbbOrZbp] in {
def : Pat<(rotl GPR:$rs1, GPR:$rs2), (ROL GPR:$rs1, GPR:$rs2)>;
(SBINVI GPR:$rs1, (SBSETINVXForm imm:$mask))>;
}
-let Predicates = [HasStdExtZbb] in {
+let Predicates = [HasStdExtZbp] in {
def : Pat<(SLOIPat GPR:$rs1, uimmlog2xlen:$shamt),
(SLOI GPR:$rs1, uimmlog2xlen:$shamt)>;
def : Pat<(SROIPat GPR:$rs1, uimmlog2xlen:$shamt),
(SROI GPR:$rs1, uimmlog2xlen:$shamt)>;
-} // Predicates = [HasStdExtZbb]
+} // Predicates = [HasStdExtZbp]
// There's no encoding for roli in the current version of the 'B' extension
// (v0.92) as it can be implemented with rori by negating the immediate.
(ADDUW GPR:$rs1, GPR:$rs2)>;
}
-let Predicates = [HasStdExtZbb, IsRV64] in {
+let Predicates = [HasStdExtZbp, IsRV64] in {
def : Pat<(not (riscv_sllw (not GPR:$rs1), GPR:$rs2)),
(SLOW GPR:$rs1, GPR:$rs2)>;
def : Pat<(not (riscv_srlw (not GPR:$rs1), GPR:$rs2)),
(SROW GPR:$rs1, GPR:$rs2)>;
-} // Predicates = [HasStdExtZbb, IsRV64]
+} // Predicates = [HasStdExtZbp, IsRV64]
let Predicates = [HasStdExtZbbOrZbp, IsRV64] in {
def : Pat<(riscv_rolw GPR:$rs1, GPR:$rs2),
} // Predicates = [HasStdExtZbs, IsRV64]
-let Predicates = [HasStdExtZbb, IsRV64] in {
+let Predicates = [HasStdExtZbp, IsRV64] in {
def : Pat<(sext_inreg (SLOIPat GPR:$rs1, uimm5:$shamt), i32),
(SLOIW GPR:$rs1, uimm5:$shamt)>;
def : Pat<(SROIWPat GPR:$rs1, uimm5:$shamt),
(SROIW GPR:$rs1, uimm5:$shamt)>;
-} // Predicates = [HasStdExtZbb, IsRV64]
+} // Predicates = [HasStdExtZbp, IsRV64]
let Predicates = [HasStdExtZbp, IsRV64] in {
def : Pat<(riscv_rorw (riscv_greviw GPR:$rs1, 24), (i64 16)), (GREVIW GPR:$rs1, 8)>;
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32IBB
-define i32 @slo_i32(i32 %a, i32 %b) nounwind {
-; RV32I-LABEL: slo_i32:
-; RV32I: # %bb.0:
-; RV32I-NEXT: not a0, a0
-; RV32I-NEXT: sll a0, a0, a1
-; RV32I-NEXT: not a0, a0
-; RV32I-NEXT: ret
-;
-; RV32IB-LABEL: slo_i32:
-; RV32IB: # %bb.0:
-; RV32IB-NEXT: slo a0, a0, a1
-; RV32IB-NEXT: ret
-;
-; RV32IBB-LABEL: slo_i32:
-; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: slo a0, a0, a1
-; RV32IBB-NEXT: ret
- %neg = xor i32 %a, -1
- %shl = shl i32 %neg, %b
- %neg1 = xor i32 %shl, -1
- ret i32 %neg1
-}
-
-; As we are not matching directly i64 code patterns on RV32 some i64 patterns
-; don't have yet any matching bit manipulation instructions on RV32.
-; This test is presented here in case future expansions of the experimental-b
-; extension introduce instructions suitable for this pattern.
-
-define i64 @slo_i64(i64 %a, i64 %b) nounwind {
-; RV32I-LABEL: slo_i64:
-; RV32I: # %bb.0:
-; RV32I-NEXT: addi a3, a2, -32
-; RV32I-NEXT: not a0, a0
-; RV32I-NEXT: bltz a3, .LBB1_2
-; RV32I-NEXT: # %bb.1:
-; RV32I-NEXT: mv a2, zero
-; RV32I-NEXT: sll a1, a0, a3
-; RV32I-NEXT: j .LBB1_3
-; RV32I-NEXT: .LBB1_2:
-; RV32I-NEXT: not a1, a1
-; RV32I-NEXT: sll a1, a1, a2
-; RV32I-NEXT: addi a3, zero, 31
-; RV32I-NEXT: sub a3, a3, a2
-; RV32I-NEXT: srli a4, a0, 1
-; RV32I-NEXT: srl a3, a4, a3
-; RV32I-NEXT: or a1, a1, a3
-; RV32I-NEXT: sll a2, a0, a2
-; RV32I-NEXT: .LBB1_3:
-; RV32I-NEXT: not a1, a1
-; RV32I-NEXT: not a0, a2
-; RV32I-NEXT: ret
-;
-; RV32IB-LABEL: slo_i64:
-; RV32IB: # %bb.0:
-; RV32IB-NEXT: not a0, a0
-; RV32IB-NEXT: not a1, a1
-; RV32IB-NEXT: sll a1, a1, a2
-; RV32IB-NEXT: addi a3, zero, 31
-; RV32IB-NEXT: sub a3, a3, a2
-; RV32IB-NEXT: srli a4, a0, 1
-; RV32IB-NEXT: srl a3, a4, a3
-; RV32IB-NEXT: or a1, a1, a3
-; RV32IB-NEXT: addi a3, a2, -32
-; RV32IB-NEXT: sll a4, a0, a3
-; RV32IB-NEXT: slti a5, a3, 0
-; RV32IB-NEXT: cmov a1, a5, a1, a4
-; RV32IB-NEXT: sll a0, a0, a2
-; RV32IB-NEXT: srai a2, a3, 31
-; RV32IB-NEXT: and a0, a2, a0
-; RV32IB-NEXT: not a1, a1
-; RV32IB-NEXT: not a0, a0
-; RV32IB-NEXT: ret
-;
-; RV32IBB-LABEL: slo_i64:
-; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: addi a3, a2, -32
-; RV32IBB-NEXT: not a0, a0
-; RV32IBB-NEXT: bltz a3, .LBB1_2
-; RV32IBB-NEXT: # %bb.1:
-; RV32IBB-NEXT: mv a2, zero
-; RV32IBB-NEXT: sll a1, a0, a3
-; RV32IBB-NEXT: j .LBB1_3
-; RV32IBB-NEXT: .LBB1_2:
-; RV32IBB-NEXT: not a1, a1
-; RV32IBB-NEXT: sll a1, a1, a2
-; RV32IBB-NEXT: addi a3, zero, 31
-; RV32IBB-NEXT: sub a3, a3, a2
-; RV32IBB-NEXT: srli a4, a0, 1
-; RV32IBB-NEXT: srl a3, a4, a3
-; RV32IBB-NEXT: or a1, a1, a3
-; RV32IBB-NEXT: sll a2, a0, a2
-; RV32IBB-NEXT: .LBB1_3:
-; RV32IBB-NEXT: not a1, a1
-; RV32IBB-NEXT: not a0, a2
-; RV32IBB-NEXT: ret
- %neg = xor i64 %a, -1
- %shl = shl i64 %neg, %b
- %neg1 = xor i64 %shl, -1
- ret i64 %neg1
-}
-
-define i32 @sro_i32(i32 %a, i32 %b) nounwind {
-; RV32I-LABEL: sro_i32:
-; RV32I: # %bb.0:
-; RV32I-NEXT: not a0, a0
-; RV32I-NEXT: srl a0, a0, a1
-; RV32I-NEXT: not a0, a0
-; RV32I-NEXT: ret
-;
-; RV32IB-LABEL: sro_i32:
-; RV32IB: # %bb.0:
-; RV32IB-NEXT: sro a0, a0, a1
-; RV32IB-NEXT: ret
-;
-; RV32IBB-LABEL: sro_i32:
-; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: sro a0, a0, a1
-; RV32IBB-NEXT: ret
- %neg = xor i32 %a, -1
- %shr = lshr i32 %neg, %b
- %neg1 = xor i32 %shr, -1
- ret i32 %neg1
-}
-
-; As we are not matching directly i64 code patterns on RV32 some i64 patterns
-; don't have yet any matching bit manipulation instructions on RV32.
-; This test is presented here in case future expansions of the experimental-b
-; extension introduce instructions suitable for this pattern.
-
-define i64 @sro_i64(i64 %a, i64 %b) nounwind {
-; RV32I-LABEL: sro_i64:
-; RV32I: # %bb.0:
-; RV32I-NEXT: addi a3, a2, -32
-; RV32I-NEXT: not a1, a1
-; RV32I-NEXT: bltz a3, .LBB3_2
-; RV32I-NEXT: # %bb.1:
-; RV32I-NEXT: mv a2, zero
-; RV32I-NEXT: srl a0, a1, a3
-; RV32I-NEXT: j .LBB3_3
-; RV32I-NEXT: .LBB3_2:
-; RV32I-NEXT: not a0, a0
-; RV32I-NEXT: srl a0, a0, a2
-; RV32I-NEXT: addi a3, zero, 31
-; RV32I-NEXT: sub a3, a3, a2
-; RV32I-NEXT: slli a4, a1, 1
-; RV32I-NEXT: sll a3, a4, a3
-; RV32I-NEXT: or a0, a0, a3
-; RV32I-NEXT: srl a2, a1, a2
-; RV32I-NEXT: .LBB3_3:
-; RV32I-NEXT: not a0, a0
-; RV32I-NEXT: not a1, a2
-; RV32I-NEXT: ret
-;
-; RV32IB-LABEL: sro_i64:
-; RV32IB: # %bb.0:
-; RV32IB-NEXT: not a1, a1
-; RV32IB-NEXT: not a0, a0
-; RV32IB-NEXT: srl a0, a0, a2
-; RV32IB-NEXT: addi a3, zero, 31
-; RV32IB-NEXT: sub a3, a3, a2
-; RV32IB-NEXT: slli a4, a1, 1
-; RV32IB-NEXT: sll a3, a4, a3
-; RV32IB-NEXT: or a0, a0, a3
-; RV32IB-NEXT: addi a3, a2, -32
-; RV32IB-NEXT: srl a4, a1, a3
-; RV32IB-NEXT: slti a5, a3, 0
-; RV32IB-NEXT: cmov a0, a5, a0, a4
-; RV32IB-NEXT: srl a1, a1, a2
-; RV32IB-NEXT: srai a2, a3, 31
-; RV32IB-NEXT: and a1, a2, a1
-; RV32IB-NEXT: not a0, a0
-; RV32IB-NEXT: not a1, a1
-; RV32IB-NEXT: ret
-;
-; RV32IBB-LABEL: sro_i64:
-; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: addi a3, a2, -32
-; RV32IBB-NEXT: not a1, a1
-; RV32IBB-NEXT: bltz a3, .LBB3_2
-; RV32IBB-NEXT: # %bb.1:
-; RV32IBB-NEXT: mv a2, zero
-; RV32IBB-NEXT: srl a0, a1, a3
-; RV32IBB-NEXT: j .LBB3_3
-; RV32IBB-NEXT: .LBB3_2:
-; RV32IBB-NEXT: not a0, a0
-; RV32IBB-NEXT: srl a0, a0, a2
-; RV32IBB-NEXT: addi a3, zero, 31
-; RV32IBB-NEXT: sub a3, a3, a2
-; RV32IBB-NEXT: slli a4, a1, 1
-; RV32IBB-NEXT: sll a3, a4, a3
-; RV32IBB-NEXT: or a0, a0, a3
-; RV32IBB-NEXT: srl a2, a1, a2
-; RV32IBB-NEXT: .LBB3_3:
-; RV32IBB-NEXT: not a0, a0
-; RV32IBB-NEXT: not a1, a2
-; RV32IBB-NEXT: ret
- %neg = xor i64 %a, -1
- %shr = lshr i64 %neg, %b
- %neg1 = xor i64 %shr, -1
- ret i64 %neg1
-}
-
-define i32 @sloi_i32(i32 %a) nounwind {
-; RV32I-LABEL: sloi_i32:
-; RV32I: # %bb.0:
-; RV32I-NEXT: slli a0, a0, 1
-; RV32I-NEXT: ori a0, a0, 1
-; RV32I-NEXT: ret
-;
-; RV32IB-LABEL: sloi_i32:
-; RV32IB: # %bb.0:
-; RV32IB-NEXT: sloi a0, a0, 1
-; RV32IB-NEXT: ret
-;
-; RV32IBB-LABEL: sloi_i32:
-; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: sloi a0, a0, 1
-; RV32IBB-NEXT: ret
- %neg = shl i32 %a, 1
- %neg12 = or i32 %neg, 1
- ret i32 %neg12
-}
-
-define i64 @sloi_i64(i64 %a) nounwind {
-; RV32I-LABEL: sloi_i64:
-; RV32I: # %bb.0:
-; RV32I-NEXT: srli a2, a0, 31
-; RV32I-NEXT: slli a1, a1, 1
-; RV32I-NEXT: or a1, a1, a2
-; RV32I-NEXT: slli a0, a0, 1
-; RV32I-NEXT: ori a0, a0, 1
-; RV32I-NEXT: ret
-;
-; RV32IB-LABEL: sloi_i64:
-; RV32IB: # %bb.0:
-; RV32IB-NEXT: fsri a1, a0, a1, 31
-; RV32IB-NEXT: sloi a0, a0, 1
-; RV32IB-NEXT: ret
-;
-; RV32IBB-LABEL: sloi_i64:
-; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: srli a2, a0, 31
-; RV32IBB-NEXT: slli a1, a1, 1
-; RV32IBB-NEXT: or a1, a1, a2
-; RV32IBB-NEXT: sloi a0, a0, 1
-; RV32IBB-NEXT: ret
- %neg = shl i64 %a, 1
- %neg12 = or i64 %neg, 1
- ret i64 %neg12
-}
-
-define i32 @sroi_i32(i32 %a) nounwind {
-; RV32I-LABEL: sroi_i32:
-; RV32I: # %bb.0:
-; RV32I-NEXT: srli a0, a0, 1
-; RV32I-NEXT: lui a1, 524288
-; RV32I-NEXT: or a0, a0, a1
-; RV32I-NEXT: ret
-;
-; RV32IB-LABEL: sroi_i32:
-; RV32IB: # %bb.0:
-; RV32IB-NEXT: sroi a0, a0, 1
-; RV32IB-NEXT: ret
-;
-; RV32IBB-LABEL: sroi_i32:
-; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: sroi a0, a0, 1
-; RV32IBB-NEXT: ret
- %neg = lshr i32 %a, 1
- %neg12 = or i32 %neg, -2147483648
- ret i32 %neg12
-}
-
-define i64 @sroi_i64(i64 %a) nounwind {
-; RV32I-LABEL: sroi_i64:
-; RV32I: # %bb.0:
-; RV32I-NEXT: slli a2, a1, 31
-; RV32I-NEXT: srli a0, a0, 1
-; RV32I-NEXT: or a0, a0, a2
-; RV32I-NEXT: srli a1, a1, 1
-; RV32I-NEXT: lui a2, 524288
-; RV32I-NEXT: or a1, a1, a2
-; RV32I-NEXT: ret
-;
-; RV32IB-LABEL: sroi_i64:
-; RV32IB: # %bb.0:
-; RV32IB-NEXT: fsri a0, a0, a1, 1
-; RV32IB-NEXT: sroi a1, a1, 1
-; RV32IB-NEXT: ret
-;
-; RV32IBB-LABEL: sroi_i64:
-; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: slli a2, a1, 31
-; RV32IBB-NEXT: srli a0, a0, 1
-; RV32IBB-NEXT: or a0, a0, a2
-; RV32IBB-NEXT: sroi a1, a1, 1
-; RV32IBB-NEXT: ret
- %neg = lshr i64 %a, 1
- %neg12 = or i64 %neg, -9223372036854775808
- ret i64 %neg12
-}
-
declare i32 @llvm.ctlz.i32(i32, i1)
define i32 @ctlz_i32(i32 %a) nounwind {
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
-; RV32I-NEXT: beqz a0, .LBB8_2
+; RV32I-NEXT: beqz a0, .LBB0_2
; RV32I-NEXT: # %bb.1: # %cond.false
; RV32I-NEXT: srli a1, a0, 1
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: addi a1, a1, 257
; RV32I-NEXT: call __mulsi3@plt
; RV32I-NEXT: srli a0, a0, 24
-; RV32I-NEXT: j .LBB8_3
-; RV32I-NEXT: .LBB8_2:
+; RV32I-NEXT: j .LBB0_3
+; RV32I-NEXT: .LBB0_2:
; RV32I-NEXT: addi a0, zero, 32
-; RV32I-NEXT: .LBB8_3: # %cond.end
+; RV32I-NEXT: .LBB0_3: # %cond.end
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
; RV32I-NEXT: and a0, a0, s6
; RV32I-NEXT: mv a1, s0
; RV32I-NEXT: call __mulsi3@plt
-; RV32I-NEXT: bnez s3, .LBB9_2
+; RV32I-NEXT: bnez s3, .LBB1_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: srli a0, a0, 24
; RV32I-NEXT: addi a0, a0, 32
-; RV32I-NEXT: j .LBB9_3
-; RV32I-NEXT: .LBB9_2:
+; RV32I-NEXT: j .LBB1_3
+; RV32I-NEXT: .LBB1_2:
; RV32I-NEXT: srli a0, s2, 24
-; RV32I-NEXT: .LBB9_3:
+; RV32I-NEXT: .LBB1_3:
; RV32I-NEXT: mv a1, zero
; RV32I-NEXT: lw s6, 0(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload
;
; RV32IBB-LABEL: ctlz_i64:
; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: bnez a1, .LBB9_2
+; RV32IBB-NEXT: bnez a1, .LBB1_2
; RV32IBB-NEXT: # %bb.1:
; RV32IBB-NEXT: clz a0, a0
; RV32IBB-NEXT: addi a0, a0, 32
; RV32IBB-NEXT: mv a1, zero
; RV32IBB-NEXT: ret
-; RV32IBB-NEXT: .LBB9_2:
+; RV32IBB-NEXT: .LBB1_2:
; RV32IBB-NEXT: clz a0, a1
; RV32IBB-NEXT: mv a1, zero
; RV32IBB-NEXT: ret
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
-; RV32I-NEXT: beqz a0, .LBB10_2
+; RV32I-NEXT: beqz a0, .LBB2_2
; RV32I-NEXT: # %bb.1: # %cond.false
; RV32I-NEXT: addi a1, a0, -1
; RV32I-NEXT: not a0, a0
; RV32I-NEXT: addi a1, a1, 257
; RV32I-NEXT: call __mulsi3@plt
; RV32I-NEXT: srli a0, a0, 24
-; RV32I-NEXT: j .LBB10_3
-; RV32I-NEXT: .LBB10_2:
+; RV32I-NEXT: j .LBB2_3
+; RV32I-NEXT: .LBB2_2:
; RV32I-NEXT: addi a0, zero, 32
-; RV32I-NEXT: .LBB10_3: # %cond.end
+; RV32I-NEXT: .LBB2_3: # %cond.end
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
; RV32I-NEXT: and a0, a0, s6
; RV32I-NEXT: mv a1, s1
; RV32I-NEXT: call __mulsi3@plt
-; RV32I-NEXT: bnez s4, .LBB11_2
+; RV32I-NEXT: bnez s4, .LBB3_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: srli a0, a0, 24
; RV32I-NEXT: addi a0, a0, 32
-; RV32I-NEXT: j .LBB11_3
-; RV32I-NEXT: .LBB11_2:
+; RV32I-NEXT: j .LBB3_3
+; RV32I-NEXT: .LBB3_2:
; RV32I-NEXT: srli a0, s2, 24
-; RV32I-NEXT: .LBB11_3:
+; RV32I-NEXT: .LBB3_3:
; RV32I-NEXT: mv a1, zero
; RV32I-NEXT: lw s6, 0(sp) # 4-byte Folded Reload
; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload
;
; RV32IBB-LABEL: cttz_i64:
; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: bnez a0, .LBB11_2
+; RV32IBB-NEXT: bnez a0, .LBB3_2
; RV32IBB-NEXT: # %bb.1:
; RV32IBB-NEXT: ctz a0, a1
; RV32IBB-NEXT: addi a0, a0, 32
; RV32IBB-NEXT: mv a1, zero
; RV32IBB-NEXT: ret
-; RV32IBB-NEXT: .LBB11_2:
+; RV32IBB-NEXT: .LBB3_2:
; RV32IBB-NEXT: ctz a0, a0
; RV32IBB-NEXT: mv a1, zero
; RV32IBB-NEXT: ret
define i32 @min_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: min_i32:
; RV32I: # %bb.0:
-; RV32I-NEXT: blt a0, a1, .LBB18_2
+; RV32I-NEXT: blt a0, a1, .LBB10_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: mv a0, a1
-; RV32I-NEXT: .LBB18_2:
+; RV32I-NEXT: .LBB10_2:
; RV32I-NEXT: ret
;
; RV32IB-LABEL: min_i32:
define i64 @min_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: min_i64:
; RV32I: # %bb.0:
-; RV32I-NEXT: beq a1, a3, .LBB19_2
+; RV32I-NEXT: beq a1, a3, .LBB11_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: slt a4, a1, a3
-; RV32I-NEXT: beqz a4, .LBB19_3
-; RV32I-NEXT: j .LBB19_4
-; RV32I-NEXT: .LBB19_2:
+; RV32I-NEXT: beqz a4, .LBB11_3
+; RV32I-NEXT: j .LBB11_4
+; RV32I-NEXT: .LBB11_2:
; RV32I-NEXT: sltu a4, a0, a2
-; RV32I-NEXT: bnez a4, .LBB19_4
-; RV32I-NEXT: .LBB19_3:
+; RV32I-NEXT: bnez a4, .LBB11_4
+; RV32I-NEXT: .LBB11_3:
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: mv a1, a3
-; RV32I-NEXT: .LBB19_4:
+; RV32I-NEXT: .LBB11_4:
; RV32I-NEXT: ret
;
; RV32IB-LABEL: min_i64:
; RV32IBB-LABEL: min_i64:
; RV32IBB: # %bb.0:
; RV32IBB-NEXT: mv a4, a0
-; RV32IBB-NEXT: bge a1, a3, .LBB19_3
+; RV32IBB-NEXT: bge a1, a3, .LBB11_3
; RV32IBB-NEXT: # %bb.1:
-; RV32IBB-NEXT: beq a1, a3, .LBB19_4
-; RV32IBB-NEXT: .LBB19_2:
+; RV32IBB-NEXT: beq a1, a3, .LBB11_4
+; RV32IBB-NEXT: .LBB11_2:
; RV32IBB-NEXT: min a1, a1, a3
; RV32IBB-NEXT: ret
-; RV32IBB-NEXT: .LBB19_3:
+; RV32IBB-NEXT: .LBB11_3:
; RV32IBB-NEXT: mv a0, a2
-; RV32IBB-NEXT: bne a1, a3, .LBB19_2
-; RV32IBB-NEXT: .LBB19_4:
+; RV32IBB-NEXT: bne a1, a3, .LBB11_2
+; RV32IBB-NEXT: .LBB11_4:
; RV32IBB-NEXT: minu a0, a4, a2
; RV32IBB-NEXT: min a1, a1, a3
; RV32IBB-NEXT: ret
define i32 @max_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: max_i32:
; RV32I: # %bb.0:
-; RV32I-NEXT: blt a1, a0, .LBB20_2
+; RV32I-NEXT: blt a1, a0, .LBB12_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: mv a0, a1
-; RV32I-NEXT: .LBB20_2:
+; RV32I-NEXT: .LBB12_2:
; RV32I-NEXT: ret
;
; RV32IB-LABEL: max_i32:
define i64 @max_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: max_i64:
; RV32I: # %bb.0:
-; RV32I-NEXT: beq a1, a3, .LBB21_2
+; RV32I-NEXT: beq a1, a3, .LBB13_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: slt a4, a3, a1
-; RV32I-NEXT: beqz a4, .LBB21_3
-; RV32I-NEXT: j .LBB21_4
-; RV32I-NEXT: .LBB21_2:
+; RV32I-NEXT: beqz a4, .LBB13_3
+; RV32I-NEXT: j .LBB13_4
+; RV32I-NEXT: .LBB13_2:
; RV32I-NEXT: sltu a4, a2, a0
-; RV32I-NEXT: bnez a4, .LBB21_4
-; RV32I-NEXT: .LBB21_3:
+; RV32I-NEXT: bnez a4, .LBB13_4
+; RV32I-NEXT: .LBB13_3:
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: mv a1, a3
-; RV32I-NEXT: .LBB21_4:
+; RV32I-NEXT: .LBB13_4:
; RV32I-NEXT: ret
;
; RV32IB-LABEL: max_i64:
; RV32IBB-LABEL: max_i64:
; RV32IBB: # %bb.0:
; RV32IBB-NEXT: mv a4, a0
-; RV32IBB-NEXT: bge a3, a1, .LBB21_3
+; RV32IBB-NEXT: bge a3, a1, .LBB13_3
; RV32IBB-NEXT: # %bb.1:
-; RV32IBB-NEXT: beq a1, a3, .LBB21_4
-; RV32IBB-NEXT: .LBB21_2:
+; RV32IBB-NEXT: beq a1, a3, .LBB13_4
+; RV32IBB-NEXT: .LBB13_2:
; RV32IBB-NEXT: max a1, a1, a3
; RV32IBB-NEXT: ret
-; RV32IBB-NEXT: .LBB21_3:
+; RV32IBB-NEXT: .LBB13_3:
; RV32IBB-NEXT: mv a0, a2
-; RV32IBB-NEXT: bne a1, a3, .LBB21_2
-; RV32IBB-NEXT: .LBB21_4:
+; RV32IBB-NEXT: bne a1, a3, .LBB13_2
+; RV32IBB-NEXT: .LBB13_4:
; RV32IBB-NEXT: maxu a0, a4, a2
; RV32IBB-NEXT: max a1, a1, a3
; RV32IBB-NEXT: ret
define i32 @minu_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: minu_i32:
; RV32I: # %bb.0:
-; RV32I-NEXT: bltu a0, a1, .LBB22_2
+; RV32I-NEXT: bltu a0, a1, .LBB14_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: mv a0, a1
-; RV32I-NEXT: .LBB22_2:
+; RV32I-NEXT: .LBB14_2:
; RV32I-NEXT: ret
;
; RV32IB-LABEL: minu_i32:
define i64 @minu_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: minu_i64:
; RV32I: # %bb.0:
-; RV32I-NEXT: beq a1, a3, .LBB23_2
+; RV32I-NEXT: beq a1, a3, .LBB15_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: sltu a4, a1, a3
-; RV32I-NEXT: beqz a4, .LBB23_3
-; RV32I-NEXT: j .LBB23_4
-; RV32I-NEXT: .LBB23_2:
+; RV32I-NEXT: beqz a4, .LBB15_3
+; RV32I-NEXT: j .LBB15_4
+; RV32I-NEXT: .LBB15_2:
; RV32I-NEXT: sltu a4, a0, a2
-; RV32I-NEXT: bnez a4, .LBB23_4
-; RV32I-NEXT: .LBB23_3:
+; RV32I-NEXT: bnez a4, .LBB15_4
+; RV32I-NEXT: .LBB15_3:
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: mv a1, a3
-; RV32I-NEXT: .LBB23_4:
+; RV32I-NEXT: .LBB15_4:
; RV32I-NEXT: ret
;
; RV32IB-LABEL: minu_i64:
; RV32IBB-LABEL: minu_i64:
; RV32IBB: # %bb.0:
; RV32IBB-NEXT: mv a4, a0
-; RV32IBB-NEXT: bgeu a1, a3, .LBB23_3
+; RV32IBB-NEXT: bgeu a1, a3, .LBB15_3
; RV32IBB-NEXT: # %bb.1:
-; RV32IBB-NEXT: beq a1, a3, .LBB23_4
-; RV32IBB-NEXT: .LBB23_2:
+; RV32IBB-NEXT: beq a1, a3, .LBB15_4
+; RV32IBB-NEXT: .LBB15_2:
; RV32IBB-NEXT: minu a1, a1, a3
; RV32IBB-NEXT: ret
-; RV32IBB-NEXT: .LBB23_3:
+; RV32IBB-NEXT: .LBB15_3:
; RV32IBB-NEXT: mv a0, a2
-; RV32IBB-NEXT: bne a1, a3, .LBB23_2
-; RV32IBB-NEXT: .LBB23_4:
+; RV32IBB-NEXT: bne a1, a3, .LBB15_2
+; RV32IBB-NEXT: .LBB15_4:
; RV32IBB-NEXT: minu a0, a4, a2
; RV32IBB-NEXT: minu a1, a1, a3
; RV32IBB-NEXT: ret
define i32 @maxu_i32(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: maxu_i32:
; RV32I: # %bb.0:
-; RV32I-NEXT: bltu a1, a0, .LBB24_2
+; RV32I-NEXT: bltu a1, a0, .LBB16_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: mv a0, a1
-; RV32I-NEXT: .LBB24_2:
+; RV32I-NEXT: .LBB16_2:
; RV32I-NEXT: ret
;
; RV32IB-LABEL: maxu_i32:
define i64 @maxu_i64(i64 %a, i64 %b) nounwind {
; RV32I-LABEL: maxu_i64:
; RV32I: # %bb.0:
-; RV32I-NEXT: beq a1, a3, .LBB25_2
+; RV32I-NEXT: beq a1, a3, .LBB17_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: sltu a4, a3, a1
-; RV32I-NEXT: beqz a4, .LBB25_3
-; RV32I-NEXT: j .LBB25_4
-; RV32I-NEXT: .LBB25_2:
+; RV32I-NEXT: beqz a4, .LBB17_3
+; RV32I-NEXT: j .LBB17_4
+; RV32I-NEXT: .LBB17_2:
; RV32I-NEXT: sltu a4, a2, a0
-; RV32I-NEXT: bnez a4, .LBB25_4
-; RV32I-NEXT: .LBB25_3:
+; RV32I-NEXT: bnez a4, .LBB17_4
+; RV32I-NEXT: .LBB17_3:
; RV32I-NEXT: mv a0, a2
; RV32I-NEXT: mv a1, a3
-; RV32I-NEXT: .LBB25_4:
+; RV32I-NEXT: .LBB17_4:
; RV32I-NEXT: ret
;
; RV32IB-LABEL: maxu_i64:
; RV32IBB-LABEL: maxu_i64:
; RV32IBB: # %bb.0:
; RV32IBB-NEXT: mv a4, a0
-; RV32IBB-NEXT: bgeu a3, a1, .LBB25_3
+; RV32IBB-NEXT: bgeu a3, a1, .LBB17_3
; RV32IBB-NEXT: # %bb.1:
-; RV32IBB-NEXT: beq a1, a3, .LBB25_4
-; RV32IBB-NEXT: .LBB25_2:
+; RV32IBB-NEXT: beq a1, a3, .LBB17_4
+; RV32IBB-NEXT: .LBB17_2:
; RV32IBB-NEXT: maxu a1, a1, a3
; RV32IBB-NEXT: ret
-; RV32IBB-NEXT: .LBB25_3:
+; RV32IBB-NEXT: .LBB17_3:
; RV32IBB-NEXT: mv a0, a2
-; RV32IBB-NEXT: bne a1, a3, .LBB25_2
-; RV32IBB-NEXT: .LBB25_4:
+; RV32IBB-NEXT: bne a1, a3, .LBB17_2
+; RV32IBB-NEXT: .LBB17_4:
; RV32IBB-NEXT: maxu a0, a4, a2
; RV32IBB-NEXT: maxu a1, a1, a3
; RV32IBB-NEXT: ret
define i64 @abs_i64(i64 %x) {
; RV32I-LABEL: abs_i64:
; RV32I: # %bb.0:
-; RV32I-NEXT: bgez a1, .LBB27_2
+; RV32I-NEXT: bgez a1, .LBB19_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: snez a2, a0
; RV32I-NEXT: neg a0, a0
; RV32I-NEXT: add a1, a1, a2
; RV32I-NEXT: neg a1, a1
-; RV32I-NEXT: .LBB27_2:
+; RV32I-NEXT: .LBB19_2:
; RV32I-NEXT: ret
;
; RV32IB-LABEL: abs_i64:
;
; RV32IBB-LABEL: abs_i64:
; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: bgez a1, .LBB27_2
+; RV32IBB-NEXT: bgez a1, .LBB19_2
; RV32IBB-NEXT: # %bb.1:
; RV32IBB-NEXT: snez a2, a0
; RV32IBB-NEXT: neg a0, a0
; RV32IBB-NEXT: add a1, a1, a2
; RV32IBB-NEXT: neg a1, a1
-; RV32IBB-NEXT: .LBB27_2:
+; RV32IBB-NEXT: .LBB19_2:
; RV32IBB-NEXT: ret
%abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true)
ret i64 %abs
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbp -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32IBP
+define i32 @slo_i32(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: slo_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: sll a0, a0, a1
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: ret
+;
+; RV32IB-LABEL: slo_i32:
+; RV32IB: # %bb.0:
+; RV32IB-NEXT: slo a0, a0, a1
+; RV32IB-NEXT: ret
+;
+; RV32IBP-LABEL: slo_i32:
+; RV32IBP: # %bb.0:
+; RV32IBP-NEXT: slo a0, a0, a1
+; RV32IBP-NEXT: ret
+ %neg = xor i32 %a, -1
+ %shl = shl i32 %neg, %b
+ %neg1 = xor i32 %shl, -1
+ ret i32 %neg1
+}
+
+; As we are not matching directly i64 code patterns on RV32 some i64 patterns
+; don't have yet any matching bit manipulation instructions on RV32.
+; This test is presented here in case future expansions of the experimental-b
+; extension introduce instructions suitable for this pattern.
+
+define i64 @slo_i64(i64 %a, i64 %b) nounwind {
+; RV32I-LABEL: slo_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a3, a2, -32
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: bltz a3, .LBB1_2
+; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: mv a2, zero
+; RV32I-NEXT: sll a1, a0, a3
+; RV32I-NEXT: j .LBB1_3
+; RV32I-NEXT: .LBB1_2:
+; RV32I-NEXT: not a1, a1
+; RV32I-NEXT: sll a1, a1, a2
+; RV32I-NEXT: addi a3, zero, 31
+; RV32I-NEXT: sub a3, a3, a2
+; RV32I-NEXT: srli a4, a0, 1
+; RV32I-NEXT: srl a3, a4, a3
+; RV32I-NEXT: or a1, a1, a3
+; RV32I-NEXT: sll a2, a0, a2
+; RV32I-NEXT: .LBB1_3:
+; RV32I-NEXT: not a1, a1
+; RV32I-NEXT: not a0, a2
+; RV32I-NEXT: ret
+;
+; RV32IB-LABEL: slo_i64:
+; RV32IB: # %bb.0:
+; RV32IB-NEXT: not a0, a0
+; RV32IB-NEXT: not a1, a1
+; RV32IB-NEXT: sll a1, a1, a2
+; RV32IB-NEXT: addi a3, zero, 31
+; RV32IB-NEXT: sub a3, a3, a2
+; RV32IB-NEXT: srli a4, a0, 1
+; RV32IB-NEXT: srl a3, a4, a3
+; RV32IB-NEXT: or a1, a1, a3
+; RV32IB-NEXT: addi a3, a2, -32
+; RV32IB-NEXT: sll a4, a0, a3
+; RV32IB-NEXT: slti a5, a3, 0
+; RV32IB-NEXT: cmov a1, a5, a1, a4
+; RV32IB-NEXT: sll a0, a0, a2
+; RV32IB-NEXT: srai a2, a3, 31
+; RV32IB-NEXT: and a0, a2, a0
+; RV32IB-NEXT: not a1, a1
+; RV32IB-NEXT: not a0, a0
+; RV32IB-NEXT: ret
+;
+; RV32IBP-LABEL: slo_i64:
+; RV32IBP: # %bb.0:
+; RV32IBP-NEXT: addi a3, a2, -32
+; RV32IBP-NEXT: not a0, a0
+; RV32IBP-NEXT: bltz a3, .LBB1_2
+; RV32IBP-NEXT: # %bb.1:
+; RV32IBP-NEXT: mv a2, zero
+; RV32IBP-NEXT: sll a1, a0, a3
+; RV32IBP-NEXT: j .LBB1_3
+; RV32IBP-NEXT: .LBB1_2:
+; RV32IBP-NEXT: not a1, a1
+; RV32IBP-NEXT: sll a1, a1, a2
+; RV32IBP-NEXT: addi a3, zero, 31
+; RV32IBP-NEXT: sub a3, a3, a2
+; RV32IBP-NEXT: srli a4, a0, 1
+; RV32IBP-NEXT: srl a3, a4, a3
+; RV32IBP-NEXT: or a1, a1, a3
+; RV32IBP-NEXT: sll a2, a0, a2
+; RV32IBP-NEXT: .LBB1_3:
+; RV32IBP-NEXT: not a1, a1
+; RV32IBP-NEXT: not a0, a2
+; RV32IBP-NEXT: ret
+ %neg = xor i64 %a, -1
+ %shl = shl i64 %neg, %b
+ %neg1 = xor i64 %shl, -1
+ ret i64 %neg1
+}
+
+define i32 @sro_i32(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: sro_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: srl a0, a0, a1
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: ret
+;
+; RV32IB-LABEL: sro_i32:
+; RV32IB: # %bb.0:
+; RV32IB-NEXT: sro a0, a0, a1
+; RV32IB-NEXT: ret
+;
+; RV32IBP-LABEL: sro_i32:
+; RV32IBP: # %bb.0:
+; RV32IBP-NEXT: sro a0, a0, a1
+; RV32IBP-NEXT: ret
+ %neg = xor i32 %a, -1
+ %shr = lshr i32 %neg, %b
+ %neg1 = xor i32 %shr, -1
+ ret i32 %neg1
+}
+
+; As we are not matching directly i64 code patterns on RV32 some i64 patterns
+; don't have yet any matching bit manipulation instructions on RV32.
+; This test is presented here in case future expansions of the experimental-b
+; extension introduce instructions suitable for this pattern.
+
+define i64 @sro_i64(i64 %a, i64 %b) nounwind {
+; RV32I-LABEL: sro_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi a3, a2, -32
+; RV32I-NEXT: not a1, a1
+; RV32I-NEXT: bltz a3, .LBB3_2
+; RV32I-NEXT: # %bb.1:
+; RV32I-NEXT: mv a2, zero
+; RV32I-NEXT: srl a0, a1, a3
+; RV32I-NEXT: j .LBB3_3
+; RV32I-NEXT: .LBB3_2:
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: srl a0, a0, a2
+; RV32I-NEXT: addi a3, zero, 31
+; RV32I-NEXT: sub a3, a3, a2
+; RV32I-NEXT: slli a4, a1, 1
+; RV32I-NEXT: sll a3, a4, a3
+; RV32I-NEXT: or a0, a0, a3
+; RV32I-NEXT: srl a2, a1, a2
+; RV32I-NEXT: .LBB3_3:
+; RV32I-NEXT: not a0, a0
+; RV32I-NEXT: not a1, a2
+; RV32I-NEXT: ret
+;
+; RV32IB-LABEL: sro_i64:
+; RV32IB: # %bb.0:
+; RV32IB-NEXT: not a1, a1
+; RV32IB-NEXT: not a0, a0
+; RV32IB-NEXT: srl a0, a0, a2
+; RV32IB-NEXT: addi a3, zero, 31
+; RV32IB-NEXT: sub a3, a3, a2
+; RV32IB-NEXT: slli a4, a1, 1
+; RV32IB-NEXT: sll a3, a4, a3
+; RV32IB-NEXT: or a0, a0, a3
+; RV32IB-NEXT: addi a3, a2, -32
+; RV32IB-NEXT: srl a4, a1, a3
+; RV32IB-NEXT: slti a5, a3, 0
+; RV32IB-NEXT: cmov a0, a5, a0, a4
+; RV32IB-NEXT: srl a1, a1, a2
+; RV32IB-NEXT: srai a2, a3, 31
+; RV32IB-NEXT: and a1, a2, a1
+; RV32IB-NEXT: not a0, a0
+; RV32IB-NEXT: not a1, a1
+; RV32IB-NEXT: ret
+;
+; RV32IBP-LABEL: sro_i64:
+; RV32IBP: # %bb.0:
+; RV32IBP-NEXT: addi a3, a2, -32
+; RV32IBP-NEXT: not a1, a1
+; RV32IBP-NEXT: bltz a3, .LBB3_2
+; RV32IBP-NEXT: # %bb.1:
+; RV32IBP-NEXT: mv a2, zero
+; RV32IBP-NEXT: srl a0, a1, a3
+; RV32IBP-NEXT: j .LBB3_3
+; RV32IBP-NEXT: .LBB3_2:
+; RV32IBP-NEXT: not a0, a0
+; RV32IBP-NEXT: srl a0, a0, a2
+; RV32IBP-NEXT: addi a3, zero, 31
+; RV32IBP-NEXT: sub a3, a3, a2
+; RV32IBP-NEXT: slli a4, a1, 1
+; RV32IBP-NEXT: sll a3, a4, a3
+; RV32IBP-NEXT: or a0, a0, a3
+; RV32IBP-NEXT: srl a2, a1, a2
+; RV32IBP-NEXT: .LBB3_3:
+; RV32IBP-NEXT: not a0, a0
+; RV32IBP-NEXT: not a1, a2
+; RV32IBP-NEXT: ret
+ %neg = xor i64 %a, -1
+ %shr = lshr i64 %neg, %b
+ %neg1 = xor i64 %shr, -1
+ ret i64 %neg1
+}
+
+define i32 @sloi_i32(i32 %a) nounwind {
+; RV32I-LABEL: sloi_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 1
+; RV32I-NEXT: ori a0, a0, 1
+; RV32I-NEXT: ret
+;
+; RV32IB-LABEL: sloi_i32:
+; RV32IB: # %bb.0:
+; RV32IB-NEXT: sloi a0, a0, 1
+; RV32IB-NEXT: ret
+;
+; RV32IBP-LABEL: sloi_i32:
+; RV32IBP: # %bb.0:
+; RV32IBP-NEXT: sloi a0, a0, 1
+; RV32IBP-NEXT: ret
+ %neg = shl i32 %a, 1
+ %neg12 = or i32 %neg, 1
+ ret i32 %neg12
+}
+
+define i64 @sloi_i64(i64 %a) nounwind {
+; RV32I-LABEL: sloi_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: srli a2, a0, 31
+; RV32I-NEXT: slli a1, a1, 1
+; RV32I-NEXT: or a1, a1, a2
+; RV32I-NEXT: slli a0, a0, 1
+; RV32I-NEXT: ori a0, a0, 1
+; RV32I-NEXT: ret
+;
+; RV32IB-LABEL: sloi_i64:
+; RV32IB: # %bb.0:
+; RV32IB-NEXT: fsri a1, a0, a1, 31
+; RV32IB-NEXT: sloi a0, a0, 1
+; RV32IB-NEXT: ret
+;
+; RV32IBP-LABEL: sloi_i64:
+; RV32IBP: # %bb.0:
+; RV32IBP-NEXT: srli a2, a0, 31
+; RV32IBP-NEXT: slli a1, a1, 1
+; RV32IBP-NEXT: or a1, a1, a2
+; RV32IBP-NEXT: sloi a0, a0, 1
+; RV32IBP-NEXT: ret
+ %neg = shl i64 %a, 1
+ %neg12 = or i64 %neg, 1
+ ret i64 %neg12
+}
+
+define i32 @sroi_i32(i32 %a) nounwind {
+; RV32I-LABEL: sroi_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: srli a0, a0, 1
+; RV32I-NEXT: lui a1, 524288
+; RV32I-NEXT: or a0, a0, a1
+; RV32I-NEXT: ret
+;
+; RV32IB-LABEL: sroi_i32:
+; RV32IB: # %bb.0:
+; RV32IB-NEXT: sroi a0, a0, 1
+; RV32IB-NEXT: ret
+;
+; RV32IBP-LABEL: sroi_i32:
+; RV32IBP: # %bb.0:
+; RV32IBP-NEXT: sroi a0, a0, 1
+; RV32IBP-NEXT: ret
+ %neg = lshr i32 %a, 1
+ %neg12 = or i32 %neg, -2147483648
+ ret i32 %neg12
+}
+
+define i64 @sroi_i64(i64 %a) nounwind {
+; RV32I-LABEL: sroi_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a2, a1, 31
+; RV32I-NEXT: srli a0, a0, 1
+; RV32I-NEXT: or a0, a0, a2
+; RV32I-NEXT: srli a1, a1, 1
+; RV32I-NEXT: lui a2, 524288
+; RV32I-NEXT: or a1, a1, a2
+; RV32I-NEXT: ret
+;
+; RV32IB-LABEL: sroi_i64:
+; RV32IB: # %bb.0:
+; RV32IB-NEXT: fsri a0, a0, a1, 1
+; RV32IB-NEXT: sroi a1, a1, 1
+; RV32IB-NEXT: ret
+;
+; RV32IBP-LABEL: sroi_i64:
+; RV32IBP: # %bb.0:
+; RV32IBP-NEXT: slli a2, a1, 31
+; RV32IBP-NEXT: srli a0, a0, 1
+; RV32IBP-NEXT: or a0, a0, a2
+; RV32IBP-NEXT: sroi a1, a1, 1
+; RV32IBP-NEXT: ret
+ %neg = lshr i64 %a, 1
+ %neg12 = or i64 %neg, -9223372036854775808
+ ret i64 %neg12
+}
+
define i32 @gorc1_i32(i32 %a) nounwind {
; RV32I-LABEL: gorc1_i32:
; RV32I: # %bb.0:
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64IBB
-define signext i32 @slo_i32(i32 signext %a, i32 signext %b) nounwind {
-; RV64I-LABEL: slo_i32:
-; RV64I: # %bb.0:
-; RV64I-NEXT: not a0, a0
-; RV64I-NEXT: sllw a0, a0, a1
-; RV64I-NEXT: not a0, a0
-; RV64I-NEXT: ret
-;
-; RV64IB-LABEL: slo_i32:
-; RV64IB: # %bb.0:
-; RV64IB-NEXT: slow a0, a0, a1
-; RV64IB-NEXT: ret
-;
-; RV64IBB-LABEL: slo_i32:
-; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: slow a0, a0, a1
-; RV64IBB-NEXT: ret
- %neg = xor i32 %a, -1
- %shl = shl i32 %neg, %b
- %neg1 = xor i32 %shl, -1
- ret i32 %neg1
-}
-
-define i64 @slo_i64(i64 %a, i64 %b) nounwind {
-; RV64I-LABEL: slo_i64:
-; RV64I: # %bb.0:
-; RV64I-NEXT: not a0, a0
-; RV64I-NEXT: sll a0, a0, a1
-; RV64I-NEXT: not a0, a0
-; RV64I-NEXT: ret
-;
-; RV64IB-LABEL: slo_i64:
-; RV64IB: # %bb.0:
-; RV64IB-NEXT: slo a0, a0, a1
-; RV64IB-NEXT: ret
-;
-; RV64IBB-LABEL: slo_i64:
-; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: slo a0, a0, a1
-; RV64IBB-NEXT: ret
- %neg = xor i64 %a, -1
- %shl = shl i64 %neg, %b
- %neg1 = xor i64 %shl, -1
- ret i64 %neg1
-}
-
-define signext i32 @sro_i32(i32 signext %a, i32 signext %b) nounwind {
-; RV64I-LABEL: sro_i32:
-; RV64I: # %bb.0:
-; RV64I-NEXT: not a0, a0
-; RV64I-NEXT: srlw a0, a0, a1
-; RV64I-NEXT: not a0, a0
-; RV64I-NEXT: ret
-;
-; RV64IB-LABEL: sro_i32:
-; RV64IB: # %bb.0:
-; RV64IB-NEXT: srow a0, a0, a1
-; RV64IB-NEXT: ret
-;
-; RV64IBB-LABEL: sro_i32:
-; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: srow a0, a0, a1
-; RV64IBB-NEXT: ret
- %neg = xor i32 %a, -1
- %shr = lshr i32 %neg, %b
- %neg1 = xor i32 %shr, -1
- ret i32 %neg1
-}
-
-define i64 @sro_i64(i64 %a, i64 %b) nounwind {
-; RV64I-LABEL: sro_i64:
-; RV64I: # %bb.0:
-; RV64I-NEXT: not a0, a0
-; RV64I-NEXT: srl a0, a0, a1
-; RV64I-NEXT: not a0, a0
-; RV64I-NEXT: ret
-;
-; RV64IB-LABEL: sro_i64:
-; RV64IB: # %bb.0:
-; RV64IB-NEXT: sro a0, a0, a1
-; RV64IB-NEXT: ret
-;
-; RV64IBB-LABEL: sro_i64:
-; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: sro a0, a0, a1
-; RV64IBB-NEXT: ret
- %neg = xor i64 %a, -1
- %shr = lshr i64 %neg, %b
- %neg1 = xor i64 %shr, -1
- ret i64 %neg1
-}
-
-define signext i32 @sloi_i32(i32 signext %a) nounwind {
-; RV64I-LABEL: sloi_i32:
-; RV64I: # %bb.0:
-; RV64I-NEXT: slli a0, a0, 1
-; RV64I-NEXT: ori a0, a0, 1
-; RV64I-NEXT: sext.w a0, a0
-; RV64I-NEXT: ret
-;
-; RV64IB-LABEL: sloi_i32:
-; RV64IB: # %bb.0:
-; RV64IB-NEXT: sloiw a0, a0, 1
-; RV64IB-NEXT: ret
-;
-; RV64IBB-LABEL: sloi_i32:
-; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: sloiw a0, a0, 1
-; RV64IBB-NEXT: ret
- %neg = shl i32 %a, 1
- %neg12 = or i32 %neg, 1
- ret i32 %neg12
-}
-
-define i64 @sloi_i64(i64 %a) nounwind {
-; RV64I-LABEL: sloi_i64:
-; RV64I: # %bb.0:
-; RV64I-NEXT: slli a0, a0, 1
-; RV64I-NEXT: ori a0, a0, 1
-; RV64I-NEXT: ret
-;
-; RV64IB-LABEL: sloi_i64:
-; RV64IB: # %bb.0:
-; RV64IB-NEXT: sloi a0, a0, 1
-; RV64IB-NEXT: ret
-;
-; RV64IBB-LABEL: sloi_i64:
-; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: sloi a0, a0, 1
-; RV64IBB-NEXT: ret
- %neg = shl i64 %a, 1
- %neg12 = or i64 %neg, 1
- ret i64 %neg12
-}
-
-define signext i32 @sroi_i32(i32 signext %a) nounwind {
-; RV64I-LABEL: sroi_i32:
-; RV64I: # %bb.0:
-; RV64I-NEXT: srli a0, a0, 1
-; RV64I-NEXT: lui a1, 524288
-; RV64I-NEXT: or a0, a0, a1
-; RV64I-NEXT: ret
-;
-; RV64IB-LABEL: sroi_i32:
-; RV64IB: # %bb.0:
-; RV64IB-NEXT: sroiw a0, a0, 1
-; RV64IB-NEXT: ret
-;
-; RV64IBB-LABEL: sroi_i32:
-; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: sroiw a0, a0, 1
-; RV64IBB-NEXT: ret
- %neg = lshr i32 %a, 1
- %neg12 = or i32 %neg, -2147483648
- ret i32 %neg12
-}
-
-; This is similar to the type legalized version of sroiw but the mask is 0 in
-; the upper bits instead of 1 so the result is not sign extended. Make sure we
-; don't match it to sroiw.
-define i64 @sroiw_bug(i64 %a) nounwind {
-; RV64I-LABEL: sroiw_bug:
-; RV64I: # %bb.0:
-; RV64I-NEXT: srli a0, a0, 1
-; RV64I-NEXT: addi a1, zero, 1
-; RV64I-NEXT: slli a1, a1, 31
-; RV64I-NEXT: or a0, a0, a1
-; RV64I-NEXT: ret
-;
-; RV64IB-LABEL: sroiw_bug:
-; RV64IB: # %bb.0:
-; RV64IB-NEXT: srli a0, a0, 1
-; RV64IB-NEXT: sbseti a0, a0, 31
-; RV64IB-NEXT: ret
-;
-; RV64IBB-LABEL: sroiw_bug:
-; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: srli a0, a0, 1
-; RV64IBB-NEXT: addi a1, zero, 1
-; RV64IBB-NEXT: slli a1, a1, 31
-; RV64IBB-NEXT: or a0, a0, a1
-; RV64IBB-NEXT: ret
- %neg = lshr i64 %a, 1
- %neg12 = or i64 %neg, 2147483648
- ret i64 %neg12
-}
-
-define i64 @sroi_i64(i64 %a) nounwind {
-; RV64I-LABEL: sroi_i64:
-; RV64I: # %bb.0:
-; RV64I-NEXT: srli a0, a0, 1
-; RV64I-NEXT: addi a1, zero, -1
-; RV64I-NEXT: slli a1, a1, 63
-; RV64I-NEXT: or a0, a0, a1
-; RV64I-NEXT: ret
-;
-; RV64IB-LABEL: sroi_i64:
-; RV64IB: # %bb.0:
-; RV64IB-NEXT: sroi a0, a0, 1
-; RV64IB-NEXT: ret
-;
-; RV64IBB-LABEL: sroi_i64:
-; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: sroi a0, a0, 1
-; RV64IBB-NEXT: ret
- %neg = lshr i64 %a, 1
- %neg12 = or i64 %neg, -9223372036854775808
- ret i64 %neg12
-}
-
declare i32 @llvm.ctlz.i32(i32, i1)
define signext i32 @ctlz_i32(i32 signext %a) nounwind {
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
-; RV64I-NEXT: beqz a0, .LBB9_2
+; RV64I-NEXT: beqz a0, .LBB0_2
; RV64I-NEXT: # %bb.1: # %cond.false
; RV64I-NEXT: srliw a1, a0, 1
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
; RV64I-NEXT: addi a0, a0, -32
-; RV64I-NEXT: j .LBB9_3
-; RV64I-NEXT: .LBB9_2:
+; RV64I-NEXT: j .LBB0_3
+; RV64I-NEXT: .LBB0_2:
; RV64I-NEXT: addi a0, zero, 32
-; RV64I-NEXT: .LBB9_3: # %cond.end
+; RV64I-NEXT: .LBB0_3: # %cond.end
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
-; RV64I-NEXT: beqz a0, .LBB10_2
+; RV64I-NEXT: beqz a0, .LBB1_2
; RV64I-NEXT: # %bb.1: # %cond.false
; RV64I-NEXT: srli a1, a0, 1
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
-; RV64I-NEXT: j .LBB10_3
-; RV64I-NEXT: .LBB10_2:
+; RV64I-NEXT: j .LBB1_3
+; RV64I-NEXT: .LBB1_2:
; RV64I-NEXT: addi a0, zero, 64
-; RV64I-NEXT: .LBB10_3: # %cond.end
+; RV64I-NEXT: .LBB1_3: # %cond.end
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
-; RV64I-NEXT: beqz a0, .LBB11_2
+; RV64I-NEXT: beqz a0, .LBB2_2
; RV64I-NEXT: # %bb.1: # %cond.false
; RV64I-NEXT: addi a1, a0, -1
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
-; RV64I-NEXT: j .LBB11_3
-; RV64I-NEXT: .LBB11_2:
+; RV64I-NEXT: j .LBB2_3
+; RV64I-NEXT: .LBB2_2:
; RV64I-NEXT: addi a0, zero, 32
-; RV64I-NEXT: .LBB11_3: # %cond.end
+; RV64I-NEXT: .LBB2_3: # %cond.end
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
-; RV64I-NEXT: beqz a0, .LBB12_2
+; RV64I-NEXT: beqz a0, .LBB3_2
; RV64I-NEXT: # %bb.1: # %cond.false
; RV64I-NEXT: addi a1, a0, -1
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: addi a1, a1, 257
; RV64I-NEXT: call __muldi3@plt
; RV64I-NEXT: srli a0, a0, 56
-; RV64I-NEXT: j .LBB12_3
-; RV64I-NEXT: .LBB12_2:
+; RV64I-NEXT: j .LBB3_3
+; RV64I-NEXT: .LBB3_2:
; RV64I-NEXT: addi a0, zero, 64
-; RV64I-NEXT: .LBB12_3: # %cond.end
+; RV64I-NEXT: .LBB3_3: # %cond.end
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
define signext i32 @min_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: min_i32:
; RV64I: # %bb.0:
-; RV64I-NEXT: blt a0, a1, .LBB19_2
+; RV64I-NEXT: blt a0, a1, .LBB10_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
-; RV64I-NEXT: .LBB19_2:
+; RV64I-NEXT: .LBB10_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: min_i32:
define i64 @min_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: min_i64:
; RV64I: # %bb.0:
-; RV64I-NEXT: blt a0, a1, .LBB20_2
+; RV64I-NEXT: blt a0, a1, .LBB11_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
-; RV64I-NEXT: .LBB20_2:
+; RV64I-NEXT: .LBB11_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: min_i64:
define signext i32 @max_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: max_i32:
; RV64I: # %bb.0:
-; RV64I-NEXT: blt a1, a0, .LBB21_2
+; RV64I-NEXT: blt a1, a0, .LBB12_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
-; RV64I-NEXT: .LBB21_2:
+; RV64I-NEXT: .LBB12_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: max_i32:
define i64 @max_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: max_i64:
; RV64I: # %bb.0:
-; RV64I-NEXT: blt a1, a0, .LBB22_2
+; RV64I-NEXT: blt a1, a0, .LBB13_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
-; RV64I-NEXT: .LBB22_2:
+; RV64I-NEXT: .LBB13_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: max_i64:
define signext i32 @minu_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: minu_i32:
; RV64I: # %bb.0:
-; RV64I-NEXT: bltu a0, a1, .LBB23_2
+; RV64I-NEXT: bltu a0, a1, .LBB14_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
-; RV64I-NEXT: .LBB23_2:
+; RV64I-NEXT: .LBB14_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: minu_i32:
define i64 @minu_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: minu_i64:
; RV64I: # %bb.0:
-; RV64I-NEXT: bltu a0, a1, .LBB24_2
+; RV64I-NEXT: bltu a0, a1, .LBB15_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
-; RV64I-NEXT: .LBB24_2:
+; RV64I-NEXT: .LBB15_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: minu_i64:
define signext i32 @maxu_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: maxu_i32:
; RV64I: # %bb.0:
-; RV64I-NEXT: bltu a1, a0, .LBB25_2
+; RV64I-NEXT: bltu a1, a0, .LBB16_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
-; RV64I-NEXT: .LBB25_2:
+; RV64I-NEXT: .LBB16_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: maxu_i32:
define i64 @maxu_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: maxu_i64:
; RV64I: # %bb.0:
-; RV64I-NEXT: bltu a1, a0, .LBB26_2
+; RV64I-NEXT: bltu a1, a0, .LBB17_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: mv a0, a1
-; RV64I-NEXT: .LBB26_2:
+; RV64I-NEXT: .LBB17_2:
; RV64I-NEXT: ret
;
; RV64IB-LABEL: maxu_i64:
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbp -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64IBP
+define signext i32 @slo_i32(i32 signext %a, i32 signext %b) nounwind {
+; RV64I-LABEL: slo_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: not a0, a0
+; RV64I-NEXT: sllw a0, a0, a1
+; RV64I-NEXT: not a0, a0
+; RV64I-NEXT: ret
+;
+; RV64IB-LABEL: slo_i32:
+; RV64IB: # %bb.0:
+; RV64IB-NEXT: slow a0, a0, a1
+; RV64IB-NEXT: ret
+;
+; RV64IBP-LABEL: slo_i32:
+; RV64IBP: # %bb.0:
+; RV64IBP-NEXT: slow a0, a0, a1
+; RV64IBP-NEXT: ret
+ %neg = xor i32 %a, -1
+ %shl = shl i32 %neg, %b
+ %neg1 = xor i32 %shl, -1
+ ret i32 %neg1
+}
+
+define i64 @slo_i64(i64 %a, i64 %b) nounwind {
+; RV64I-LABEL: slo_i64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: not a0, a0
+; RV64I-NEXT: sll a0, a0, a1
+; RV64I-NEXT: not a0, a0
+; RV64I-NEXT: ret
+;
+; RV64IB-LABEL: slo_i64:
+; RV64IB: # %bb.0:
+; RV64IB-NEXT: slo a0, a0, a1
+; RV64IB-NEXT: ret
+;
+; RV64IBP-LABEL: slo_i64:
+; RV64IBP: # %bb.0:
+; RV64IBP-NEXT: slo a0, a0, a1
+; RV64IBP-NEXT: ret
+ %neg = xor i64 %a, -1
+ %shl = shl i64 %neg, %b
+ %neg1 = xor i64 %shl, -1
+ ret i64 %neg1
+}
+
+define signext i32 @sro_i32(i32 signext %a, i32 signext %b) nounwind {
+; RV64I-LABEL: sro_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: not a0, a0
+; RV64I-NEXT: srlw a0, a0, a1
+; RV64I-NEXT: not a0, a0
+; RV64I-NEXT: ret
+;
+; RV64IB-LABEL: sro_i32:
+; RV64IB: # %bb.0:
+; RV64IB-NEXT: srow a0, a0, a1
+; RV64IB-NEXT: ret
+;
+; RV64IBP-LABEL: sro_i32:
+; RV64IBP: # %bb.0:
+; RV64IBP-NEXT: srow a0, a0, a1
+; RV64IBP-NEXT: ret
+ %neg = xor i32 %a, -1
+ %shr = lshr i32 %neg, %b
+ %neg1 = xor i32 %shr, -1
+ ret i32 %neg1
+}
+
+define i64 @sro_i64(i64 %a, i64 %b) nounwind {
+; RV64I-LABEL: sro_i64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: not a0, a0
+; RV64I-NEXT: srl a0, a0, a1
+; RV64I-NEXT: not a0, a0
+; RV64I-NEXT: ret
+;
+; RV64IB-LABEL: sro_i64:
+; RV64IB: # %bb.0:
+; RV64IB-NEXT: sro a0, a0, a1
+; RV64IB-NEXT: ret
+;
+; RV64IBP-LABEL: sro_i64:
+; RV64IBP: # %bb.0:
+; RV64IBP-NEXT: sro a0, a0, a1
+; RV64IBP-NEXT: ret
+ %neg = xor i64 %a, -1
+ %shr = lshr i64 %neg, %b
+ %neg1 = xor i64 %shr, -1
+ ret i64 %neg1
+}
+
+define signext i32 @sloi_i32(i32 signext %a) nounwind {
+; RV64I-LABEL: sloi_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: slli a0, a0, 1
+; RV64I-NEXT: ori a0, a0, 1
+; RV64I-NEXT: sext.w a0, a0
+; RV64I-NEXT: ret
+;
+; RV64IB-LABEL: sloi_i32:
+; RV64IB: # %bb.0:
+; RV64IB-NEXT: sloiw a0, a0, 1
+; RV64IB-NEXT: ret
+;
+; RV64IBP-LABEL: sloi_i32:
+; RV64IBP: # %bb.0:
+; RV64IBP-NEXT: sloiw a0, a0, 1
+; RV64IBP-NEXT: ret
+ %neg = shl i32 %a, 1
+ %neg12 = or i32 %neg, 1
+ ret i32 %neg12
+}
+
+define i64 @sloi_i64(i64 %a) nounwind {
+; RV64I-LABEL: sloi_i64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: slli a0, a0, 1
+; RV64I-NEXT: ori a0, a0, 1
+; RV64I-NEXT: ret
+;
+; RV64IB-LABEL: sloi_i64:
+; RV64IB: # %bb.0:
+; RV64IB-NEXT: sloi a0, a0, 1
+; RV64IB-NEXT: ret
+;
+; RV64IBP-LABEL: sloi_i64:
+; RV64IBP: # %bb.0:
+; RV64IBP-NEXT: sloi a0, a0, 1
+; RV64IBP-NEXT: ret
+ %neg = shl i64 %a, 1
+ %neg12 = or i64 %neg, 1
+ ret i64 %neg12
+}
+
+define signext i32 @sroi_i32(i32 signext %a) nounwind {
+; RV64I-LABEL: sroi_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: srli a0, a0, 1
+; RV64I-NEXT: lui a1, 524288
+; RV64I-NEXT: or a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64IB-LABEL: sroi_i32:
+; RV64IB: # %bb.0:
+; RV64IB-NEXT: sroiw a0, a0, 1
+; RV64IB-NEXT: ret
+;
+; RV64IBP-LABEL: sroi_i32:
+; RV64IBP: # %bb.0:
+; RV64IBP-NEXT: sroiw a0, a0, 1
+; RV64IBP-NEXT: ret
+ %neg = lshr i32 %a, 1
+ %neg12 = or i32 %neg, -2147483648
+ ret i32 %neg12
+}
+
+; This is similar to the type legalized version of sroiw but the mask is 0 in
+; the upper bits instead of 1 so the result is not sign extended. Make sure we
+; don't match it to sroiw.
+define i64 @sroiw_bug(i64 %a) nounwind {
+; RV64I-LABEL: sroiw_bug:
+; RV64I: # %bb.0:
+; RV64I-NEXT: srli a0, a0, 1
+; RV64I-NEXT: addi a1, zero, 1
+; RV64I-NEXT: slli a1, a1, 31
+; RV64I-NEXT: or a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64IB-LABEL: sroiw_bug:
+; RV64IB: # %bb.0:
+; RV64IB-NEXT: srli a0, a0, 1
+; RV64IB-NEXT: sbseti a0, a0, 31
+; RV64IB-NEXT: ret
+;
+; RV64IBP-LABEL: sroiw_bug:
+; RV64IBP: # %bb.0:
+; RV64IBP-NEXT: srli a0, a0, 1
+; RV64IBP-NEXT: addi a1, zero, 1
+; RV64IBP-NEXT: slli a1, a1, 31
+; RV64IBP-NEXT: or a0, a0, a1
+; RV64IBP-NEXT: ret
+ %neg = lshr i64 %a, 1
+ %neg12 = or i64 %neg, 2147483648
+ ret i64 %neg12
+}
+
+define i64 @sroi_i64(i64 %a) nounwind {
+; RV64I-LABEL: sroi_i64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: srli a0, a0, 1
+; RV64I-NEXT: addi a1, zero, -1
+; RV64I-NEXT: slli a1, a1, 63
+; RV64I-NEXT: or a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64IB-LABEL: sroi_i64:
+; RV64IB: # %bb.0:
+; RV64IB-NEXT: sroi a0, a0, 1
+; RV64IB-NEXT: ret
+;
+; RV64IBP-LABEL: sroi_i64:
+; RV64IBP: # %bb.0:
+; RV64IBP-NEXT: sroi a0, a0, 1
+; RV64IBP-NEXT: ret
+ %neg = lshr i64 %a, 1
+ %neg12 = or i64 %neg, -9223372036854775808
+ ret i64 %neg12
+}
+
define signext i32 @gorc1_i32(i32 signext %a) nounwind {
; RV64I-LABEL: gorc1_i32:
; RV64I: # %bb.0:
# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-b,experimental-zbb < %s 2>&1 | FileCheck %s
-# Too few operands
-slo t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-# Too few operands
-sro t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-# Too few operands
-sloi t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-# Immediate operand out of range
-sloi t0, t1, 32 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
-sloi t0, t1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
-# Too few operands
-sroi t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-# Immediate operand out of range
-sroi t0, t1, 32 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
-sroi t0, t1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
# Too many operands
clz t0, t1, t2 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction
# Too many operands
# RUN: | llvm-objdump --mattr=+experimental-zbb -d -r - \
# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
-# CHECK-ASM-AND-OBJ: slo t0, t1, t2
-# CHECK-ASM: encoding: [0xb3,0x12,0x73,0x20]
-slo t0, t1, t2
-# CHECK-ASM-AND-OBJ: sro t0, t1, t2
-# CHECK-ASM: encoding: [0xb3,0x52,0x73,0x20]
-sro t0, t1, t2
-# CHECK-ASM-AND-OBJ: sloi t0, t1, 0
-# CHECK-ASM: encoding: [0x93,0x12,0x03,0x20]
-sloi t0, t1, 0
-# CHECK-ASM-AND-OBJ: sroi t0, t1, 0
-# CHECK-ASM: encoding: [0x93,0x52,0x03,0x20]
-sroi t0, t1, 0
# CHECK-ASM-AND-OBJ: clz t0, t1
# CHECK-ASM: encoding: [0x93,0x12,0x03,0x60]
clz t0, t1
# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-b,experimental-zbp < %s 2>&1 | FileCheck %s
# Too few operands
+slo t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+# Too few operands
+sro t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+# Too few operands
+sloi t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+# Immediate operand out of range
+sloi t0, t1, 32 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
+sloi t0, t1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
+# Too few operands
+sroi t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+# Immediate operand out of range
+sroi t0, t1, 32 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
+sroi t0, t1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
+# Too few operands
gorc t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
# Too few operands
grev t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
# RUN: | llvm-objdump --mattr=+experimental-zbp -d -r - \
# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# CHECK-ASM-AND-OBJ: slo t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x12,0x73,0x20]
+slo t0, t1, t2
+# CHECK-ASM-AND-OBJ: sro t0, t1, t2
+# CHECK-ASM: encoding: [0xb3,0x52,0x73,0x20]
+sro t0, t1, t2
+# CHECK-ASM-AND-OBJ: sloi t0, t1, 0
+# CHECK-ASM: encoding: [0x93,0x12,0x03,0x20]
+sloi t0, t1, 0
+# CHECK-ASM-AND-OBJ: sroi t0, t1, 0
+# CHECK-ASM: encoding: [0x93,0x52,0x03,0x20]
+sroi t0, t1, 0
# CHECK-ASM-AND-OBJ: gorc t0, t1, t2
# CHECK-ASM: encoding: [0xb3,0x52,0x73,0x28]
gorc t0, t1, t2
# RUN: not llvm-mc -triple riscv64 -mattr=+experimental-b,experimental-zbb < %s 2>&1 | FileCheck %s
-# Too few operands
-slow t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-# Too few operands
-srow t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-# Too few operands
-sloiw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-# Immediate operand out of range
-sloiw t0, t1, 32 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
-sloiw t0, t1, -1 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
-# Too few operands
-sroiw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-# Immediate operand out of range
-sroiw t0, t1, 32 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
-sroiw t0, t1, -1 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
# Too many operands
clzw t0, t1, t2 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
# Too many operands
# RUN: | llvm-objdump --mattr=+experimental-zbb -d -r - \
# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
-# CHECK-ASM-AND-OBJ: slow t0, t1, t2
-# CHECK-ASM: encoding: [0xbb,0x12,0x73,0x20]
-slow t0, t1, t2
-# CHECK-ASM-AND-OBJ: srow t0, t1, t2
-# CHECK-ASM: encoding: [0xbb,0x52,0x73,0x20]
-srow t0, t1, t2
-# CHECK-ASM-AND-OBJ: sloiw t0, t1, 0
-# CHECK-ASM: encoding: [0x9b,0x12,0x03,0x20]
-sloiw t0, t1, 0
-# CHECK-ASM-AND-OBJ: sroiw t0, t1, 0
-# CHECK-ASM: encoding: [0x9b,0x52,0x03,0x20]
-sroiw t0, t1, 0
# CHECK-ASM-AND-OBJ: clzw t0, t1
# CHECK-ASM: encoding: [0x9b,0x12,0x03,0x60]
clzw t0, t1
# RUN: not llvm-mc -triple riscv64 -mattr=+experimental-b,experimental-zbp < %s 2>&1 | FileCheck %s
# Too few operands
+slow t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+# Too few operands
+srow t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+# Too few operands
+sloiw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+# Immediate operand out of range
+sloiw t0, t1, 32 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
+sloiw t0, t1, -1 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
+# Too few operands
+sroiw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+# Immediate operand out of range
+sroiw t0, t1, 32 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
+sroiw t0, t1, -1 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
+# Too few operands
gorcw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
# Too few operands
grevw t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
# RUN: | llvm-objdump --mattr=+experimental-zbp -d -r - \
# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# CHECK-ASM-AND-OBJ: slow t0, t1, t2
+# CHECK-ASM: encoding: [0xbb,0x12,0x73,0x20]
+slow t0, t1, t2
+# CHECK-ASM-AND-OBJ: srow t0, t1, t2
+# CHECK-ASM: encoding: [0xbb,0x52,0x73,0x20]
+srow t0, t1, t2
+# CHECK-ASM-AND-OBJ: sloiw t0, t1, 0
+# CHECK-ASM: encoding: [0x9b,0x12,0x03,0x20]
+sloiw t0, t1, 0
+# CHECK-ASM-AND-OBJ: sroiw t0, t1, 0
+# CHECK-ASM: encoding: [0x9b,0x52,0x03,0x20]
+sroiw t0, t1, 0
# CHECK-ASM-AND-OBJ: gorcw t0, t1, t2
# CHECK-ASM: encoding: [0xbb,0x52,0x73,0x28]
gorcw t0, t1, t2