diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -121,6 +121,7 @@ AssemblerPredicate<(all_of FeatureStdExtZba), "'Zba' (Address Generation Instructions)">; def NotHasStdExtZba : Predicate<"!Subtarget->hasStdExtZba()">; +def NotHasStdExtZbs : Predicate<"!Subtarget->hasStdExtZbs()">; def FeatureStdExtZbb : SubtargetFeature<"zbb", "HasStdExtZbb", "true", 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 @@ -166,6 +166,14 @@ let OperandNamespace = "RISCVOp"; } +// A 6-bit constant greater than 32. +def uimmlt11 : ImmLeafis64Bit()) + return isUInt<6>(Imm) && Imm < 11; + return isUInt<5>(Imm) && Imm < 11; +}]>; + + def uimm2 : Operand { let ParserMatchClass = UImmAsmOperand<2>; let DecoderMethod = "decodeUImmOperand<2>"; @@ -373,6 +381,12 @@ N->getValueType(0)); }]>; +// Return an immediate value plus 32. +def ImmPow2: SDNodeXFormgetTargetConstant(2 << (N->getSExtValue()), SDLoc(N), + N->getValueType(0)); +}]>; + // Return an immediate value plus 32. def ImmPlus32 : SDNodeXFormgetTargetConstant(N->getSExtValue() + 32, SDLoc(N), @@ -1177,6 +1191,9 @@ def PseudoAddTPRel : Pseudo<(outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [], "add", "$rd, $rs1, $rs2, $src">; +let Predicates = [NotHasStdExtZbs] in +def : Pat<(and (not (srl GPR:$rs1, uimmlt11:$shamt)), (XLenVT 1)), + (SLTIU (ANDI GPR:$rs1, (ImmPow2 uimmlt11:$shamt)), (XLenVT 1))>; /// FrameIndex calculations diff --git a/llvm/test/CodeGen/RISCV/rv32zbs.ll b/llvm/test/CodeGen/RISCV/rv32zbs.ll --- a/llvm/test/CodeGen/RISCV/rv32zbs.ll +++ b/llvm/test/CodeGen/RISCV/rv32zbs.ll @@ -358,9 +358,8 @@ define i32 @bexti_xor_i32(i32 %a) nounwind { ; RV32I-LABEL: bexti_xor_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: srli a0, a0, 7 -; RV32I-NEXT: not a0, a0 -; RV32I-NEXT: andi a0, a0, 1 +; RV32I-NEXT: andi a0, a0, 256 +; RV32I-NEXT: seqz a0, a0 ; RV32I-NEXT: ret ; ; RV32ZBS-LABEL: bexti_xor_i32: @@ -374,12 +373,30 @@ ret i32 %and } -define i64 @bexti_xor_i64(i64 %a) nounwind { -; RV32I-LABEL: bexti_xor_i64: +define i32 @bexti_xor_i32_11(i32 %a) nounwind { +; RV32I-LABEL: bexti_xor_i32_11: ; RV32I: # %bb.0: -; RV32I-NEXT: srli a0, a0, 7 +; RV32I-NEXT: srli a0, a0, 11 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: andi a0, a0, 1 +; RV32I-NEXT: ret +; +; RV32ZBS-LABEL: bexti_xor_i32_11: +; RV32ZBS: # %bb.0: +; RV32ZBS-NEXT: bexti a0, a0, 11 +; RV32ZBS-NEXT: xori a0, a0, 1 +; RV32ZBS-NEXT: ret + %shr = lshr i32 %a, 11 + %not = xor i32 %shr, -1 + %and = and i32 %not, 1 + ret i32 %and +} + +define i64 @bexti_xor_i64(i64 %a) nounwind { +; RV32I-LABEL: bexti_xor_i64: +; RV32I: # %bb.0: +; RV32I-NEXT: andi a0, a0, 256 +; RV32I-NEXT: seqz a0, a0 ; RV32I-NEXT: li a1, 0 ; RV32I-NEXT: ret ; @@ -395,12 +412,32 @@ ret i64 %and } -define i32 @bexti_xor_i32_1(i32 %a) nounwind { -; RV32I-LABEL: bexti_xor_i32_1: +define i64 @bexti_xor_i64_11(i64 %a) nounwind { +; RV32I-LABEL: bexti_xor_i64_11: ; RV32I: # %bb.0: -; RV32I-NEXT: srli a0, a0, 7 +; RV32I-NEXT: srli a0, a0, 11 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: andi a0, a0, 1 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; +; RV32ZBS-LABEL: bexti_xor_i64_11: +; RV32ZBS: # %bb.0: +; RV32ZBS-NEXT: bexti a0, a0, 11 +; RV32ZBS-NEXT: xori a0, a0, 1 +; RV32ZBS-NEXT: li a1, 0 +; RV32ZBS-NEXT: ret + %shr = lshr i64 %a, 11 + %not = xor i64 %shr, -1 + %and = and i64 %not, 1 + ret i64 %and +} + +define i32 @bexti_xor_i32_1(i32 %a) nounwind { +; RV32I-LABEL: bexti_xor_i32_1: +; RV32I: # %bb.0: +; RV32I-NEXT: andi a0, a0, 256 +; RV32I-NEXT: seqz a0, a0 ; RV32I-NEXT: ret ; ; RV32ZBS-LABEL: bexti_xor_i32_1: @@ -417,9 +454,8 @@ define i64 @bexti_xor_i64_1(i64 %a) nounwind { ; RV32I-LABEL: bexti_xor_i64_1: ; RV32I: # %bb.0: -; RV32I-NEXT: srli a0, a0, 7 -; RV32I-NEXT: not a0, a0 -; RV32I-NEXT: andi a0, a0, 1 +; RV32I-NEXT: andi a0, a0, 256 +; RV32I-NEXT: seqz a0, a0 ; RV32I-NEXT: li a1, 0 ; RV32I-NEXT: ret ; diff --git a/llvm/test/CodeGen/RISCV/rv64zbs.ll b/llvm/test/CodeGen/RISCV/rv64zbs.ll --- a/llvm/test/CodeGen/RISCV/rv64zbs.ll +++ b/llvm/test/CodeGen/RISCV/rv64zbs.ll @@ -441,9 +441,8 @@ define signext i32 @bexti_xor_i32(i32 signext %a) nounwind { ; RV64I-LABEL: bexti_xor_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: srli a0, a0, 7 -; RV64I-NEXT: not a0, a0 -; RV64I-NEXT: andi a0, a0, 1 +; RV64I-NEXT: andi a0, a0, 256 +; RV64I-NEXT: seqz a0, a0 ; RV64I-NEXT: ret ; ; RV64ZBS-LABEL: bexti_xor_i32: @@ -457,14 +456,32 @@ ret i32 %and } -define i64 @bexti_xor_i64(i64 %a) nounwind { -; RV64I-LABEL: bexti_xor_i64: +define signext i32 @bexti_xor_i32_11(i32 signext %a) nounwind { +; RV64I-LABEL: bexti_xor_i32_11: ; RV64I: # %bb.0: -; RV64I-NEXT: srli a0, a0, 7 +; RV64I-NEXT: srli a0, a0, 11 ; RV64I-NEXT: not a0, a0 ; RV64I-NEXT: andi a0, a0, 1 ; RV64I-NEXT: ret ; +; RV64ZBS-LABEL: bexti_xor_i32_11: +; RV64ZBS: # %bb.0: +; RV64ZBS-NEXT: bexti a0, a0, 11 +; RV64ZBS-NEXT: xori a0, a0, 1 +; RV64ZBS-NEXT: ret + %shr = lshr i32 %a, 11 + %not = xor i32 %shr, -1 + %and = and i32 %not, 1 + ret i32 %and +} + +define i64 @bexti_xor_i64(i64 %a) nounwind { +; RV64I-LABEL: bexti_xor_i64: +; RV64I: # %bb.0: +; RV64I-NEXT: andi a0, a0, 256 +; RV64I-NEXT: seqz a0, a0 +; RV64I-NEXT: ret +; ; RV64ZBS-LABEL: bexti_xor_i64: ; RV64ZBS: # %bb.0: ; RV64ZBS-NEXT: bexti a0, a0, 7 @@ -476,14 +493,32 @@ ret i64 %and } -define signext i32 @bexti_xor_i32_1(i32 signext %a) nounwind { -; RV64I-LABEL: bexti_xor_i32_1: +define i64 @bexti_xor_i64_11(i64 %a) nounwind { +; RV64I-LABEL: bexti_xor_i64_11: ; RV64I: # %bb.0: -; RV64I-NEXT: srli a0, a0, 7 +; RV64I-NEXT: srli a0, a0, 11 ; RV64I-NEXT: not a0, a0 ; RV64I-NEXT: andi a0, a0, 1 ; RV64I-NEXT: ret ; +; RV64ZBS-LABEL: bexti_xor_i64_11: +; RV64ZBS: # %bb.0: +; RV64ZBS-NEXT: bexti a0, a0, 11 +; RV64ZBS-NEXT: xori a0, a0, 1 +; RV64ZBS-NEXT: ret + %shr = lshr i64 %a, 11 + %not = xor i64 %shr, -1 + %and = and i64 %not, 1 + ret i64 %and +} + +define signext i32 @bexti_xor_i32_1(i32 signext %a) nounwind { +; RV64I-LABEL: bexti_xor_i32_1: +; RV64I: # %bb.0: +; RV64I-NEXT: andi a0, a0, 256 +; RV64I-NEXT: seqz a0, a0 +; RV64I-NEXT: ret +; ; RV64ZBS-LABEL: bexti_xor_i32_1: ; RV64ZBS: # %bb.0: ; RV64ZBS-NEXT: bexti a0, a0, 7 @@ -498,9 +533,8 @@ define i64 @bexti_xor_i64_1(i64 %a) nounwind { ; RV64I-LABEL: bexti_xor_i64_1: ; RV64I: # %bb.0: -; RV64I-NEXT: srli a0, a0, 7 -; RV64I-NEXT: not a0, a0 -; RV64I-NEXT: andi a0, a0, 1 +; RV64I-NEXT: andi a0, a0, 256 +; RV64I-NEXT: seqz a0, a0 ; RV64I-NEXT: ret ; ; RV64ZBS-LABEL: bexti_xor_i64_1: