nouveau/codegen: set dType to S32 for OP_NEG U32

It doesn't make sense to do an OP_NEG from U32 to U32. This was
manifested on nv50 in glsl-fs-atan-3 which was generating a

UMAD TEMP[0].x, TEMP[0].xxxx, -TEMP[5].xxxx, TEMP[0].xxxx

instruction. (For some reason, nvc0 causes a different shader to be
generated.) This led to a

cvt neg u32 $r1 u32 $r1

Which did not yield the desired result. This changes the final output to

cvt neg s32 $r1 u32 $r1

which produces the desired output and the piglit tests passes. My
assumption is that this is also what we want on nvc0, but could not test
as there was no suitable shader that generated the problem instruction.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
This commit is contained in:
Ilia Mirkin 2014-01-10 17:58:37 -05:00 committed by Maarten Lankhorst
parent 45b64e52f4
commit 18d97a8df7
3 changed files with 27 additions and 7 deletions

View file

@ -808,6 +808,14 @@ CodeEmitterGK110::emitCVT(const Instruction *i)
break;
}
DataType dType;
if (i->op == OP_NEG && i->dType == TYPE_U32)
dType = TYPE_S32;
else
dType = i->dType;
uint32_t op;
if (f2f) op = 0x254;
@ -824,10 +832,10 @@ CodeEmitterGK110::emitCVT(const Instruction *i)
emitRoundMode(rnd, 32 + 10, f2f ? (32 + 13) : -1);
code[0] |= typeSizeofLog2(i->dType) << 10;
code[0] |= typeSizeofLog2(dType) << 10;
code[0] |= typeSizeofLog2(i->sType) << 12;
if (isSignedIntType(i->dType))
if (isSignedIntType(dType))
code[0] |= 0x4000;
if (isSignedIntType(i->sType))
code[0] |= 0x8000;

View file

@ -1106,6 +1106,7 @@ CodeEmitterNV50::emitCVT(const Instruction *i)
{
const bool f2f = isFloatType(i->dType) && isFloatType(i->sType);
RoundMode rnd;
DataType dType;
switch (i->op) {
case OP_CEIL: rnd = f2f ? ROUND_PI : ROUND_P; break;
@ -1116,9 +1117,14 @@ CodeEmitterNV50::emitCVT(const Instruction *i)
break;
}
if (i->op == OP_NEG && i->dType == TYPE_U32)
dType = TYPE_S32;
else
dType = i->dType;
code[0] = 0xa0000000;
switch (i->dType) {
switch (dType) {
case TYPE_F64:
switch (i->sType) {
case TYPE_F64: code[1] = 0xc4404000; break;

View file

@ -921,6 +921,7 @@ void
CodeEmitterNVC0::emitCVT(Instruction *i)
{
const bool f2f = isFloatType(i->dType) && isFloatType(i->sType);
DataType dType;
switch (i->op) {
case OP_CEIL: i->rnd = f2f ? ROUND_PI : ROUND_P; break;
@ -934,13 +935,18 @@ CodeEmitterNVC0::emitCVT(Instruction *i)
const bool abs = (i->op == OP_ABS) || i->src(0).mod.abs();
const bool neg = (i->op == OP_NEG) || i->src(0).mod.neg();
if (i->op == OP_NEG && i->dType == TYPE_U32)
dType = TYPE_S32;
else
dType = i->dType;
if (i->encSize == 8) {
emitForm_B(i, HEX64(10000000, 00000004));
roundMode_C(i);
// cvt u16 f32 sets high bits to 0, so we don't have to use Value::Size()
code[0] |= util_logbase2(typeSizeof(i->dType)) << 20;
code[0] |= util_logbase2(typeSizeof(dType)) << 20;
code[0] |= util_logbase2(typeSizeof(i->sType)) << 23;
if (sat)
@ -953,12 +959,12 @@ CodeEmitterNVC0::emitCVT(Instruction *i)
if (i->ftz)
code[1] |= 1 << 23;
if (isSignedIntType(i->dType))
if (isSignedIntType(dType))
code[0] |= 0x080;
if (isSignedIntType(i->sType))
code[0] |= 0x200;
if (isFloatType(i->dType)) {
if (isFloatType(dType)) {
if (!isFloatType(i->sType))
code[1] |= 0x08000000;
} else {
@ -971,7 +977,7 @@ CodeEmitterNVC0::emitCVT(Instruction *i)
if (i->op == OP_CEIL || i->op == OP_FLOOR || i->op == OP_TRUNC) {
code[0] = 0x298;
} else
if (isFloatType(i->dType)) {
if (isFloatType(dType)) {
if (isFloatType(i->sType))
code[0] = 0x098;
else