diff --git a/src/nouveau/compiler/nak.rs b/src/nouveau/compiler/nak.rs index ec0c0a2a5eb..8580b7457e4 100644 --- a/src/nouveau/compiler/nak.rs +++ b/src/nouveau/compiler/nak.rs @@ -128,7 +128,7 @@ fn nir_options(_dev: &nv_device_info) -> nir_shader_compiler_options { op.lower_usub_sat = true; // TODO op.lower_iadd_sat = true; // TODO op.use_interpolated_input_intrinsics = true; - op.lower_int64_options = !nir_lower_iadd64; + op.lower_int64_options = !(nir_lower_iadd64 | nir_lower_ineg64); op.lower_ldexp = true; op.lower_fmod = true; op.lower_ffract = true; diff --git a/src/nouveau/compiler/nak_encode_sm70.rs b/src/nouveau/compiler/nak_encode_sm70.rs index 87aef67308b..e47a9bb46ae 100644 --- a/src/nouveau/compiler/nak_encode_sm70.rs +++ b/src/nouveau/compiler/nak_encode_sm70.rs @@ -31,17 +31,15 @@ enum ALUSrc { fn src_mod_has_abs(src_mod: SrcMod) -> bool { match src_mod { - SrcMod::None | SrcMod::FNeg | SrcMod::INeg => false, + SrcMod::None | SrcMod::FNeg | SrcMod::INeg | SrcMod::BNot => false, SrcMod::FAbs | SrcMod::FNegAbs => true, - _ => panic!("Not an ALU source modifier"), } } fn src_mod_has_neg(src_mod: SrcMod) -> bool { match src_mod { SrcMod::None | SrcMod::FAbs => false, - SrcMod::FNeg | SrcMod::FNegAbs | SrcMod::INeg => true, - _ => panic!("Not an ALU source modifier"), + SrcMod::FNeg | SrcMod::FNegAbs | SrcMod::INeg | SrcMod::BNot => true, } } diff --git a/src/nouveau/compiler/nak_from_nir.rs b/src/nouveau/compiler/nak_from_nir.rs index bedee1d27e9..6bbc7d03ce0 100644 --- a/src/nouveau/compiler/nak_from_nir.rs +++ b/src/nouveau/compiler/nak_from_nir.rs @@ -881,7 +881,31 @@ impl<'a> ShaderFromNir<'a> { }); dst[1].into() } - nir_op_ineg => b.ineg(srcs[0]), + nir_op_ineg => { + if alu.def.bit_size == 64 { + let x = srcs[0].as_ssa().unwrap(); + let sum = b.alloc_ssa(RegFile::GPR, 2); + let carry = b.alloc_ssa(RegFile::Pred, 1); + b.push_op(OpIAdd3X { + dst: sum[0].into(), + overflow: [carry.into(), Dst::None], + high: false, + srcs: [0.into(), Src::from(x[0]).ineg(), 0.into()], + carry: [SrcRef::False.into(), SrcRef::False.into()], + }); + b.push_op(OpIAdd3X { + dst: sum[1].into(), + overflow: [Dst::None, Dst::None], + high: true, + srcs: [0.into(), Src::from(x[1]).bnot(), 0.into()], + carry: [carry.into(), SrcRef::False.into()], + }); + sum + } else { + assert!(alu.def.bit_size() == 32); + b.ineg(srcs[0]) + } + } nir_op_inot => { let lop = LogicOp::new_lut(&|x, _, _| !x); if alu.def.bit_size() == 1 {