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 @@ -144,6 +144,20 @@ let OperandNamespace = "RISCVOp"; } +// A 12-bit signed immediate plus one where the imm range will be -2047~2048. +def simm12_plus1 : Operand, ImmLeaf(Imm) && Imm != -2048) || Imm == 2048;}]> { + let ParserMatchClass = SImmAsmOperand<12>; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeSImmOperand<12>"; + let MCOperandPredicate = [{ + int64_t Imm; + if (MCOp.evaluateAsConstantImm(Imm)) + return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048; + return MCOp.isBareSymbolRef(); + }]; +} + // A 13-bit signed immediate where the least significant bit is zero. def simm13_lsb0 : Operand { let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; @@ -296,6 +310,12 @@ SDLoc(N), N->getValueType(0)); }]>; +// Return the negation of an immediate value. +def NegImm : SDNodeXFormgetTargetConstant(-N->getSExtValue(), SDLoc(N), + N->getValueType(0)); +}]>; + //===----------------------------------------------------------------------===// // Instruction Formats //===----------------------------------------------------------------------===// @@ -857,12 +877,12 @@ // handled by a RISC-V instruction. def : Pat<(seteq GPR:$rs1, 0), (SLTIU GPR:$rs1, 1)>; def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>; -def : Pat<(seteq GPR:$rs1, simm12:$imm12), - (SLTIU (XORI GPR:$rs1, simm12:$imm12), 1)>; +def : Pat<(seteq GPR:$rs1, simm12_plus1:$imm12), + (SLTIU (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)), 1)>; def : Pat<(setne GPR:$rs1, 0), (SLTU X0, GPR:$rs1)>; def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>; -def : Pat<(setne GPR:$rs1, simm12:$imm12), - (SLTU X0, (XORI GPR:$rs1, simm12:$imm12))>; +def : Pat<(setne GPR:$rs1, simm12_plus1:$imm12), + (SLTU X0, (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)))>; def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>; def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>; def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>; diff --git a/llvm/test/CodeGen/RISCV/i32-icmp.ll b/llvm/test/CodeGen/RISCV/i32-icmp.ll --- a/llvm/test/CodeGen/RISCV/i32-icmp.ll +++ b/llvm/test/CodeGen/RISCV/i32-icmp.ll @@ -19,7 +19,7 @@ define i32 @icmp_eq_constant(i32 %a) nounwind { ; RV32I-LABEL: icmp_eq_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: xori a0, a0, 42 +; RV32I-NEXT: addi a0, a0, -42 ; RV32I-NEXT: seqz a0, a0 ; RV32I-NEXT: ret %1 = icmp eq i32 %a, 42 @@ -27,6 +27,40 @@ ret i32 %2 } +define i32 @icmp_eq_constant_2048(i32 %a) nounwind { +; RV32I-LABEL: icmp_eq_constant_2048: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a0, a0, -2048 +; RV32I-NEXT: seqz a0, a0 +; RV32I-NEXT: ret + %1 = icmp eq i32 %a, 2048 + %2 = zext i1 %1 to i32 + ret i32 %2 +} + +define i32 @icmp_eq_constant_neg_2048(i32 %a) nounwind { +; RV32I-LABEL: icmp_eq_constant_neg_2048: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a1, zero, -2048 +; RV32I-NEXT: xor a0, a0, a1 +; RV32I-NEXT: seqz a0, a0 +; RV32I-NEXT: ret + %1 = icmp eq i32 %a, -2048 + %2 = zext i1 %1 to i32 + ret i32 %2 +} + +define i32 @icmp_eq_constant_neg_2047(i32 %a) nounwind { +; RV32I-LABEL: icmp_eq_constant_neg_2047: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a0, a0, 2047 +; RV32I-NEXT: seqz a0, a0 +; RV32I-NEXT: ret + %1 = icmp eq i32 %a, -2047 + %2 = zext i1 %1 to i32 + ret i32 %2 +} + define i32 @icmp_eqz(i32 %a) nounwind { ; RV32I-LABEL: icmp_eqz: ; RV32I: # %bb.0: @@ -51,7 +85,7 @@ define i32 @icmp_ne_constant(i32 %a) nounwind { ; RV32I-LABEL: icmp_ne_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: xori a0, a0, 42 +; RV32I-NEXT: addi a0, a0, -42 ; RV32I-NEXT: snez a0, a0 ; RV32I-NEXT: ret %1 = icmp ne i32 %a, 42 @@ -59,6 +93,29 @@ ret i32 %2 } +define i32 @icmp_ne_constant_2048(i32 %a) nounwind { +; RV32I-LABEL: icmp_ne_constant_2048: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a0, a0, -2048 +; RV32I-NEXT: snez a0, a0 +; RV32I-NEXT: ret + %1 = icmp ne i32 %a, 2048 + %2 = zext i1 %1 to i32 + ret i32 %2 +} + +define i32 @icmp_ne_constant_neg_2048(i32 %a) nounwind { +; RV32I-LABEL: icmp_ne_constant_neg_2048: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a1, zero, -2048 +; RV32I-NEXT: xor a0, a0, a1 +; RV32I-NEXT: snez a0, a0 +; RV32I-NEXT: ret + %1 = icmp ne i32 %a, -2048 + %2 = zext i1 %1 to i32 + ret i32 %2 +} + define i32 @icmp_nez(i32 %a) nounwind { ; RV32I-LABEL: icmp_nez: ; RV32I: # %bb.0: diff --git a/llvm/test/CodeGen/RISCV/setcc-logic.ll b/llvm/test/CodeGen/RISCV/setcc-logic.ll --- a/llvm/test/CodeGen/RISCV/setcc-logic.ll +++ b/llvm/test/CodeGen/RISCV/setcc-logic.ll @@ -102,9 +102,9 @@ define i1 @and_icmps_const_not1bit_diff(i32 %x) nounwind { ; RV32I-LABEL: and_icmps_const_not1bit_diff: ; RV32I: # %bb.0: -; RV32I-NEXT: xori a1, a0, 44 +; RV32I-NEXT: addi a1, a0, -44 ; RV32I-NEXT: snez a1, a1 -; RV32I-NEXT: xori a0, a0, 92 +; RV32I-NEXT: addi a0, a0, -92 ; RV32I-NEXT: snez a0, a0 ; RV32I-NEXT: and a0, a1, a0 ; RV32I-NEXT: ret @@ -113,9 +113,9 @@ ; RV64I: # %bb.0: ; RV64I-NEXT: slli a0, a0, 32 ; RV64I-NEXT: srli a0, a0, 32 -; RV64I-NEXT: xori a1, a0, 44 +; RV64I-NEXT: addi a1, a0, -44 ; RV64I-NEXT: snez a1, a1 -; RV64I-NEXT: xori a0, a0, 92 +; RV64I-NEXT: addi a0, a0, -92 ; RV64I-NEXT: snez a0, a0 ; RV64I-NEXT: and a0, a1, a0 ; RV64I-NEXT: ret