[llvm] [RISCV][GISel] Support f32/f64 ldexp. (PR #117941)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 27 15:38:36 PST 2024
https://github.com/topperc created https://github.com/llvm/llvm-project/pull/117941
The existing libcall lowering in LegalizerHelper.cpp did not account
for one operand being integer. Reuse the G_FPOWI code to fix this.
>From 0d7105ce3ca88a5939fecc6805bcf2cf994ab099 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 27 Nov 2024 14:32:40 -0800
Subject: [PATCH 1/4] [RISCV][GISel] Support f32/f64 powi.
Need to force libcall legalization to treat the integer argument
as signed so that it can be promoted to XLen in call lowering for RV64.
Alternatively we could promote the operand before converting to libcall,
but going through call lowering is closer to what SelectionDAG does.
---
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 3 +-
.../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 2 +
.../RISCV/GlobalISel/float-intrinsics.ll | 42 +++++++++++++++++++
.../GlobalISel/legalizer-info-validation.mir | 4 +-
4 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 709eb2525a6577..dd424afd0a909f 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1290,9 +1290,10 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
return UnableToLegalize;
}
auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
- std::initializer_list<CallLowering::ArgInfo> Args = {
+ SmallVector<CallLowering::ArgInfo, 2> Args = {
{MI.getOperand(1).getReg(), HLTy, 0},
{MI.getOperand(2).getReg(), ITy, 1}};
+ Args[1].Flags[0].setSExt();
LegalizeResult Status =
createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), HLTy, 0},
Args, LocObserver, &MI);
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index a4e03be98c696d..005d88a1731232 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -579,6 +579,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH,
G_FTANH})
.libcallFor({s32, s64});
+ getActionDefinitionsBuilder(G_FPOWI)
+ .libcallFor({{s32, s32}});
getActionDefinitionsBuilder(G_VASTART).customFor({p0});
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll b/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
index 16b0a2fc2f396d..7098493b2b56d3 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
@@ -48,6 +48,48 @@ define float @sqrt_f32(float %a) nounwind {
ret float %1
}
+define float @powi_f32(float %a, i32 %b) nounwind {
+; RV32IF-LABEL: powi_f32:
+; RV32IF: # %bb.0:
+; RV32IF-NEXT: addi sp, sp, -16
+; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IF-NEXT: call __powisf2
+; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IF-NEXT: addi sp, sp, 16
+; RV32IF-NEXT: ret
+;
+; RV64IF-LABEL: powi_f32:
+; RV64IF: # %bb.0:
+; RV64IF-NEXT: addi sp, sp, -16
+; RV64IF-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IF-NEXT: sext.w a0, a0
+; RV64IF-NEXT: call __powisf2
+; RV64IF-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IF-NEXT: addi sp, sp, 16
+; RV64IF-NEXT: ret
+;
+; RV32I-LABEL: powi_f32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __powisf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: powi_f32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sext.w a1, a1
+; RV64I-NEXT: call __powisf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call float @llvm.powi.f32.i32(float %a, i32 %b)
+ ret float %1
+}
+
define float @sin_f32(float %a) nounwind {
; RV32IF-LABEL: sin_f32:
; RV32IF: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index 719ea38cbb9c52..f14c806607c710 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -481,8 +481,8 @@
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FPOWI (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
-# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. the first uncovered type index: 2, OK
+# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FEXP (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
>From 7b62f0018bf659222562530add567e4d7291dbec Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 27 Nov 2024 15:07:48 -0800
Subject: [PATCH 2/4] fixup! clang-format
---
llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 005d88a1731232..0f1cb8be159b4b 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -579,8 +579,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH,
G_FTANH})
.libcallFor({s32, s64});
- getActionDefinitionsBuilder(G_FPOWI)
- .libcallFor({{s32, s32}});
+ getActionDefinitionsBuilder(G_FPOWI).libcallFor({{s32, s32}});
getActionDefinitionsBuilder(G_VASTART).customFor({p0});
>From 247ecd6ec315bdbe8c029bec8621b0ddacf5928a Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 27 Nov 2024 15:18:57 -0800
Subject: [PATCH 3/4] fixup! Add f64 support
---
.../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 2 +-
.../RISCV/GlobalISel/double-intrinsics.ll | 46 ++++++++++++++++++-
2 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 0f1cb8be159b4b..8de9e3be8d36ea 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -579,7 +579,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH,
G_FTANH})
.libcallFor({s32, s64});
- getActionDefinitionsBuilder(G_FPOWI).libcallFor({{s32, s32}});
+ getActionDefinitionsBuilder(G_FPOWI).libcallFor({{s32, s32}, {s64, s32}});
getActionDefinitionsBuilder(G_VASTART).customFor({p0});
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll b/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
index 79814fd4820696..2d00a10dc56b49 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
@@ -39,6 +39,48 @@ define double @sqrt_f64(double %a) nounwind {
ret double %1
}
+define double @powi_f64(double %a, i32 %b) nounwind {
+; RV32IFD-LABEL: powi_f64:
+; RV32IFD: # %bb.0:
+; RV32IFD-NEXT: addi sp, sp, -16
+; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IFD-NEXT: call __powidf2
+; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IFD-NEXT: addi sp, sp, 16
+; RV32IFD-NEXT: ret
+;
+; RV64IFD-LABEL: powi_f64:
+; RV64IFD: # %bb.0:
+; RV64IFD-NEXT: addi sp, sp, -16
+; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IFD-NEXT: sext.w a0, a0
+; RV64IFD-NEXT: call __powidf2
+; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IFD-NEXT: addi sp, sp, 16
+; RV64IFD-NEXT: ret
+;
+; RV32I-LABEL: powi_f64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __powidf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: powi_f64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sext.w a1, a1
+; RV64I-NEXT: call __powidf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call double @llvm.powi.f64.i32(double %a, i32 %b)
+ ret double %1
+}
+
declare double @llvm.sin.f64(double)
define double @sin_f64(double %a) nounwind {
@@ -1001,11 +1043,11 @@ define i1 @isnan_d_fpclass(double %x) {
; RV32I-NEXT: addi a3, a2, -1
; RV32I-NEXT: lui a2, 524032
; RV32I-NEXT: and a1, a1, a3
-; RV32I-NEXT: beq a1, a2, .LBB24_2
+; RV32I-NEXT: beq a1, a2, .LBB25_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: sltu a0, a2, a1
; RV32I-NEXT: ret
-; RV32I-NEXT: .LBB24_2:
+; RV32I-NEXT: .LBB25_2:
; RV32I-NEXT: snez a0, a0
; RV32I-NEXT: ret
;
>From 54241fe48b2b358bb5c6cb10db118d2c2dc6cac7 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 27 Nov 2024 15:35:45 -0800
Subject: [PATCH 4/4] [RISCV][GISel] Support f32/f64 ldexp.
The existing libcall lowering in LegalizerHelper.cpp did not account
for one operand being integer. Reuse the G_FPOWI code to fix this.
---
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 4 +-
.../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 3 +-
.../RISCV/GlobalISel/double-intrinsics.ll | 43 +++++++++++++++++++
.../RISCV/GlobalISel/float-intrinsics.ll | 42 ++++++++++++++++++
.../GlobalISel/legalizer-info-validation.mir | 5 ++-
5 files changed, 92 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index dd424afd0a909f..d4323cd728437e 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1233,7 +1233,6 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
case TargetOpcode::G_FLOG10:
case TargetOpcode::G_FLOG:
case TargetOpcode::G_FLOG2:
- case TargetOpcode::G_FLDEXP:
case TargetOpcode::G_FEXP:
case TargetOpcode::G_FEXP2:
case TargetOpcode::G_FEXP10:
@@ -1279,7 +1278,8 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
MI.eraseFromParent();
return Legalized;
}
- case TargetOpcode::G_FPOWI: {
+ case TargetOpcode::G_FPOWI:
+ case TargetOpcode::G_FLDEXP: {
LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
unsigned Size = LLTy.getSizeInBits();
Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 8de9e3be8d36ea..a8052839b5c6a0 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -579,7 +579,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH,
G_FTANH})
.libcallFor({s32, s64});
- getActionDefinitionsBuilder(G_FPOWI).libcallFor({{s32, s32}, {s64, s32}});
+ getActionDefinitionsBuilder({G_FPOWI, G_FLDEXP})
+ .libcallFor({{s32, s32}, {s64, s32}});
getActionDefinitionsBuilder(G_VASTART).customFor({p0});
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll b/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
index 2d00a10dc56b49..04bfbbb6e694f4 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/double-intrinsics.ll
@@ -1103,6 +1103,49 @@ define double @tan_f64(double %a) nounwind {
%1 = call double @llvm.tan.f64(double %a)
ret double %1
}
+
+define double @ldexp_double(double %x, i32 %y) nounwind {
+; RV32IFD-LABEL: ldexp_double:
+; RV32IFD: # %bb.0:
+; RV32IFD-NEXT: addi sp, sp, -16
+; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IFD-NEXT: call ldexp
+; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IFD-NEXT: addi sp, sp, 16
+; RV32IFD-NEXT: ret
+;
+; RV64IFD-LABEL: ldexp_double:
+; RV64IFD: # %bb.0:
+; RV64IFD-NEXT: addi sp, sp, -16
+; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IFD-NEXT: sext.w a0, a0
+; RV64IFD-NEXT: call ldexp
+; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IFD-NEXT: addi sp, sp, 16
+; RV64IFD-NEXT: ret
+;
+; RV32I-LABEL: ldexp_double:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call ldexp
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: ldexp_double:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sext.w a1, a1
+; RV64I-NEXT: call ldexp
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %z = call double @llvm.ldexp.f64.i32(double %x, i32 %y)
+ ret double %z
+}
+
define double @asin_f64(double %a) nounwind {
; RV32IFD-LABEL: asin_f64:
; RV32IFD: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll b/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
index 7098493b2b56d3..210bcc7d4c10f0 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/float-intrinsics.ll
@@ -1450,6 +1450,48 @@ define float @tan_f32(float %a) nounwind {
ret float %1
}
+define float @ldexp_float(float %x, i32 %y) nounwind {
+; RV32IF-LABEL: ldexp_float:
+; RV32IF: # %bb.0:
+; RV32IF-NEXT: addi sp, sp, -16
+; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IF-NEXT: call ldexpf
+; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IF-NEXT: addi sp, sp, 16
+; RV32IF-NEXT: ret
+;
+; RV64IF-LABEL: ldexp_float:
+; RV64IF: # %bb.0:
+; RV64IF-NEXT: addi sp, sp, -16
+; RV64IF-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IF-NEXT: sext.w a0, a0
+; RV64IF-NEXT: call ldexpf
+; RV64IF-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IF-NEXT: addi sp, sp, 16
+; RV64IF-NEXT: ret
+;
+; RV32I-LABEL: ldexp_float:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call ldexpf
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: ldexp_float:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sext.w a1, a1
+; RV64I-NEXT: call ldexpf
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %z = call float @llvm.ldexp.f32.i32(float %x, i32 %y)
+ ret float %z
+}
+
define float @asin_f32(float %a) nounwind {
; RV32IF-LABEL: asin_f32:
; RV32IF: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index f14c806607c710..0d9d539a1a80ed 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -508,8 +508,9 @@
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FLDEXP (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
-# DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
+# DEBUG-NEXT: .. the first uncovered type index: 2, OK
+# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FFREXP (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
# DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
More information about the llvm-commits
mailing list