Dynamically produce (and process) the form, using a data driven design, where the form fields are defined in a data structure (array.) See the following example -
<?php
// recursive trim call-back function
function _trim($val)
{
	if(is_array($val))
	{
		return array_map('_trim',$val);
	} else {
		return trim($val);
	}
}
// define the form fields. the main array index is the field name. 
$fields = [];
$fields['field_A'] = ['label'=>'field name a', 'type'=>'text'];
$fields['field_B'] = ['label'=>'field name b', 'type'=>'select', 'options'=>[1=>'option 1',2=>'option 2']];
// note: if more than one select field uses the same option choices, define the options array separately and use it in as many places as needed
$fields['field_C'] = ['label'=>'field name c', 'type'=>'text'];
// you can add elements to the $fields entries to control dynamic validation and usage logic
$errors = []; // array to hold validation errors
$post = []; // array to hold a trimmed working copy of the current data (if editing existing data, fetch it into $post)
// post method form processing
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
	$post = array_map('_trim',$_POST); // get a trimmed copy of the submitted data - use $post in the remainder of the code
	
	if(isset($post['submit']))
	{
		// examine the submitted data
		echo '<pre>'; print_r($post); echo '</pre>';
		
		// dynamically validate, then use the submitted form data here... store validation errors in the $errors array.
		
	}
}
// at the point of producing the html form/table
$cols = $post['cols'] ?? 1; // default to 1 column
if(isset($post['add']))
{
	$cols++;
}
if(isset($post['sub']) && $cols > 1)
{
	// note: this will remove any values that have been entered in the last column
	$cols--;
}
?>
<form method='post'>
<input type='hidden' name='cols' value='<?php echo $cols; ?>'>
<table border='1'>
<?php
foreach($fields as $name=>$arr)
{
	echo "<tr><td>{$arr['label']}</td>";
	foreach(range(1,$cols) as $col)
	{
		echo "<td>";
		switch ($arr['type'])
		{
			case 'text':
			// use for any of the input types except radio and checkbox, which must be handled differently
			echo "<input type='{$arr['type']}' name='{$name}[$col]' value='".htmlentities($post[$name][$col] ?? '',ENT_QUOTES)."'>";
			break;
			
			case 'select':
			echo "<select name='{$name}[$col]'>";
			foreach($arr['options'] as $value=>$label)
			{
				$sel = isset($post[$name][$col]) && $post[$name][$col] == $value ? ' selected' : '';
				echo "<option value='$value'$sel>$label</option>";
			}
			echo "</select>";
			break;
		}
		echo "</td>";
	}
	echo "</tr>\n";
}
?>
</table>
<input type='submit' name='submit' value='Process'><input type='submit' name='add' value='Add Unit'><input type='submit' name='sub' value='Remove Unit'>
</form>
Note: use css for styling the table (the example uses the old border attribute for simplicity.)