diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td @@ -802,15 +802,32 @@ (CMIX GPR:$rs1, GPR:$rs2, GPR:$rs3)>; def : Pat<(riscv_selectcc GPR:$rs2, (XLenVT 0), (XLenVT 17), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>; +} // Predicates = [HasStdExtZbt] // fshl and fshr concatenate their operands in the same order. fsr and fsl // instruction use different orders. fshl will return its first operand for // shift of zero, fshr will return its second operand. fsl and fsr both return // $rs1 so the patterns need to have different operand orders. +// +// fshl and fshr only read the lower log2(xlen) bits of the shift amount, but +// fsl/fsr instructions read log2(xlen)+1 bits. DAG combine may have removed +// an AND mask on the shift amount that we need to add back to avoid a one in +// the extra bit. +// FIXME: If we can prove that the extra bit in the shift amount is zero, we +// don't need this mask. +let Predicates = [HasStdExtZbt, IsRV32] in { +def : Pat<(fshl GPR:$rs1, GPR:$rs3, GPR:$rs2), + (FSL GPR:$rs1, (ANDI GPR:$rs2, 31), GPR:$rs3)>; +def : Pat<(fshr GPR:$rs3, GPR:$rs1, GPR:$rs2), + (FSR GPR:$rs1, (ANDI GPR:$rs2, 31), GPR:$rs3)>; +} +let Predicates = [HasStdExtZbt, IsRV64] in { def : Pat<(fshl GPR:$rs1, GPR:$rs3, GPR:$rs2), - (FSL GPR:$rs1, GPR:$rs2, GPR:$rs3)>; + (FSL GPR:$rs1, (ANDI GPR:$rs2, 63), GPR:$rs3)>; def : Pat<(fshr GPR:$rs3, GPR:$rs1, GPR:$rs2), - (FSR GPR:$rs1, GPR:$rs2, GPR:$rs3)>; + (FSR GPR:$rs1, (ANDI GPR:$rs2, 63), GPR:$rs3)>; +} +let Predicates = [HasStdExtZbt] in { def : Pat<(fshr GPR:$rs3, GPR:$rs1, uimmlog2xlen:$shamt), (FSRI GPR:$rs1, GPR:$rs3, uimmlog2xlen:$shamt)>; // We can use FSRI for fshl by immediate if we subtract the immediate from @@ -1019,11 +1036,11 @@ def : Pat<(sext_inreg (fshl GPR:$rs1, (shl GPR:$rs3, (i64 32)), (and GPR:$rs2, (i64 31))), i32), - (FSLW GPR:$rs1, GPR:$rs2, GPR:$rs3)>; + (FSLW GPR:$rs1, (ANDI GPR:$rs2, 31), GPR:$rs3)>; def : Pat<(sext_inreg (fshr GPR:$rs3, (shl GPR:$rs1, (i64 32)), (or GPR:$rs2, (i64 32))), i32), - (FSRW GPR:$rs1, GPR:$rs2, GPR:$rs3)>; + (FSRW GPR:$rs1, (ANDI GPR:$rs2, 31), GPR:$rs3)>; def : Pat<(sext_inreg (fshr GPR:$rs3, (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt), i32), diff --git a/llvm/test/CodeGen/RISCV/rv32Zbt.ll b/llvm/test/CodeGen/RISCV/rv32Zbt.ll --- a/llvm/test/CodeGen/RISCV/rv32Zbt.ll +++ b/llvm/test/CodeGen/RISCV/rv32Zbt.ll @@ -131,11 +131,13 @@ ; ; RV32IB-LABEL: fshl_i32: ; RV32IB: # %bb.0: +; RV32IB-NEXT: andi a2, a2, 31 ; RV32IB-NEXT: fsl a0, a0, a1, a2 ; RV32IB-NEXT: ret ; ; RV32IBT-LABEL: fshl_i32: ; RV32IBT: # %bb.0: +; RV32IBT-NEXT: andi a2, a2, 31 ; RV32IBT-NEXT: fsl a0, a0, a1, a2 ; RV32IBT-NEXT: ret %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c) @@ -315,11 +317,13 @@ ; ; RV32IB-LABEL: fshr_i32: ; RV32IB: # %bb.0: +; RV32IB-NEXT: andi a2, a2, 31 ; RV32IB-NEXT: fsr a0, a1, a0, a2 ; RV32IB-NEXT: ret ; ; RV32IBT-LABEL: fshr_i32: ; RV32IBT: # %bb.0: +; RV32IBT-NEXT: andi a2, a2, 31 ; RV32IBT-NEXT: fsr a0, a1, a0, a2 ; RV32IBT-NEXT: ret %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c) diff --git a/llvm/test/CodeGen/RISCV/rv64Zbt.ll b/llvm/test/CodeGen/RISCV/rv64Zbt.ll --- a/llvm/test/CodeGen/RISCV/rv64Zbt.ll +++ b/llvm/test/CodeGen/RISCV/rv64Zbt.ll @@ -120,11 +120,13 @@ ; ; RV64IB-LABEL: fshl_i32: ; RV64IB: # %bb.0: +; RV64IB-NEXT: andi a2, a2, 31 ; RV64IB-NEXT: fslw a0, a0, a1, a2 ; RV64IB-NEXT: ret ; ; RV64IBT-LABEL: fshl_i32: ; RV64IBT: # %bb.0: +; RV64IBT-NEXT: andi a2, a2, 31 ; RV64IBT-NEXT: fslw a0, a0, a1, a2 ; RV64IBT-NEXT: ret %1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c) @@ -145,11 +147,13 @@ ; ; RV64IB-LABEL: fshl_i64: ; RV64IB: # %bb.0: +; RV64IB-NEXT: andi a2, a2, 63 ; RV64IB-NEXT: fsl a0, a0, a1, a2 ; RV64IB-NEXT: ret ; ; RV64IBT-LABEL: fshl_i64: ; RV64IBT: # %bb.0: +; RV64IBT-NEXT: andi a2, a2, 63 ; RV64IBT-NEXT: fsl a0, a0, a1, a2 ; RV64IBT-NEXT: ret %1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %b, i64 %c) @@ -172,11 +176,13 @@ ; ; RV64IB-LABEL: fshr_i32: ; RV64IB: # %bb.0: +; RV64IB-NEXT: andi a2, a2, 31 ; RV64IB-NEXT: fsrw a0, a1, a0, a2 ; RV64IB-NEXT: ret ; ; RV64IBT-LABEL: fshr_i32: ; RV64IBT: # %bb.0: +; RV64IBT-NEXT: andi a2, a2, 31 ; RV64IBT-NEXT: fsrw a0, a1, a0, a2 ; RV64IBT-NEXT: ret %1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c) @@ -197,11 +203,13 @@ ; ; RV64IB-LABEL: fshr_i64: ; RV64IB: # %bb.0: +; RV64IB-NEXT: andi a2, a2, 63 ; RV64IB-NEXT: fsr a0, a1, a0, a2 ; RV64IB-NEXT: ret ; ; RV64IBT-LABEL: fshr_i64: ; RV64IBT: # %bb.0: +; RV64IBT-NEXT: andi a2, a2, 63 ; RV64IBT-NEXT: fsr a0, a1, a0, a2 ; RV64IBT-NEXT: ret %1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %b, i64 %c)