{"record":{"id":"c23ea7a00c86bc10","repo":"jax-ml/jax","slug":"types-must-match-got-high-type-and-low-type","errorCode":null,"errorMessage":"Types must match, got {high.type} and {low.type}","messagePattern":"Types must match, got (.+?) and (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/experimental/mosaic/gpu/utils.py","lineNumber":2048,"sourceCode":"    raise ValueError(\"Only 32-bit scalar types supported\")\n  if isinstance(x.type, ir.IntegerType):\n    pass\n  elif isinstance(x.type, ir.F32Type):\n    if get_arch().major != 10:\n      raise ValueError(\"F32 redux only supported on Blackwell GPUs\")\n  else:\n    raise NotImplementedError(x.type)\n  assert mask.type == i32\n  extra_kwargs: dict[str, Any] = {}\n  if kind == ReductionKind.FMAX or kind == ReductionKind.FMIN:\n    extra_kwargs = dict(nan=True)\n  return nvvm.redux_sync(x, kind, mask, **extra_kwargs)\n\n\ndef prmt(high: ir.Value, low: ir.Value, permutation: ir.Value):\n  i32 = ir.IntegerType.get_signless(32)\n  if (result_type := high.type) != low.type:\n    raise ValueError(f\"Types must match, got {high.type} and {low.type}\")\n  if high.type != i32:\n    high = bitcast(high, i32)\n  if low.type != i32:\n    low = bitcast(low, i32)\n  if permutation.type != i32:\n    permutation = bitcast(permutation, i32)\n  result = llvm.inline_asm(\n      i32, [high, low, permutation], \"prmt.b32 $0, $1, $2, $3;\", \"=r,r,r,r\"\n  )\n  assert isinstance(result, ir.Value)\n  return bitcast(result, result_type)\n\n\ndef bitcast(x: ir.Value, new_type: ir.Type):\n  if x.type == new_type:\n    return x\n  if (x_bw := bitwidth(x.type)) != (new_bw := bitwidth(new_type)):\n    raise ValueError(","sourceCodeStart":2030,"sourceCodeEnd":2066,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/experimental/mosaic/gpu/utils.py#L2030-L2066","documentation":"prmt (byte permute) combines two 32-bit registers, so both operands must have the same type. If high.type != low.type the types cannot be interpreted uniformly and it raises before the bitcasts to i32.","triggerScenarios":"Calling prmt(high, low, perm) with mixed operand types, e.g. high of type i32 and low of type f32, or vector<2xi16> vs i32.","commonSituations":"Assembling a permute from values produced by different pipeline stages (one bitcast, one raw); refactoring shared code where operand dtypes drifted apart.","solutions":["Bitcast one operand so both share the same type before calling prmt (prmt itself bitcasts to i32 afterwards, but requires equal input types)","Ensure upstream producers emit a consistent 32-bit type","Add a debug print/assert on high.type and low.type near the call site"],"exampleFix":"# before\nprmt(high=f32_val, low=i32_val, perm=perm)\n# after\nprmt(high=bitcast(f32_val, ir.IntegerType.get_signless(32)), low=i32_val, perm=perm)","handlingStrategy":"validation","validationCode":"assert high.type == low.type, f'prmt operand mismatch: {high.type} vs {low.type}'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Bitcast operands to a common 32-bit type at the call site","Assert equality of producer output types in tests"],"tags":["mosaic-gpu","prmt","type-mismatch"],"backgroundTag":"operand-type-mismatch","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}