[PATCH] R600/SI: Fix V_FRACT hw bug on SI

Matt Arsenault Matthew.Arsenault at amd.com
Thu Feb 26 16:01:16 PST 2015


On 02/26/2015 03:42 PM, Marek Olšák wrote:
> +  case AMDGPUIntrinsic::AMDGPU_fract:
> +  case AMDGPUIntrinsic::AMDIL_fraction: // Legacy name.
> +    if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS) {
> +      SDValue Op1 = Op.getOperand(1);
> +      SDValue UpperBound = DAG.getConstantFP(BitsToFloat(0x3f7fffff), VT);
> +
> +      // Hardware bug: V_FRACT returns 1.0 for a very small negative input.
> +      // Workaround:
> +      //     isnan(Op1) ? Op1        : min(fract(Op1), 0x3f7fffff) =
> +      // then simplifying...
> +      //     isnan(Op1) ? fract(Op1) : min(fract(Op1), 0x3f7fffff) =
> +      //     0x3f7fffff < fract(Op1) ? 0x3f7fffff : fract(Op1) =
> +      //     fmin_legacy(0x3f7fffff, fract(Op1))
> +      SDValue Frc = DAG.getNode(AMDGPUISD::FRACT, DL, VT, Op1);
> +      return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, UpperBound, Frc);
> +    } else
> +      return DAG.getNode(AMDGPUISD::FRACT, DL, VT, Op.getOperand(1));
I don't think this should be implemented in the lowering of the 
intrinsic. I believe this would be better handled by an instruction 
pattern (which for this it looks like it's possible, but maybe not. 
Alternatively in AMDGPUISelDAGToDAG). The first reason is other custom 
lowerings in the future may want to emit the fract node, and those would 
not be handled correctly. The second reason is partially that I think 
this intrinsic should be removed since it's easy to match the x - 
floor(x) pattern and the rest of the compiler understands those 
instructions. There might be special cases that the instruction doesn't 
handle correctly that I'm not aware of which would be a reason to keep it.

Actually, why isn't the workaround to expand it as x - floor(x)? Then 
the intrinsic could be expanded that way, and the workaround would be to 
just not match that pattern on SI.

-Matt




More information about the llvm-commits mailing list