Skip to content

Commit

Permalink
Lower OpFNegate directly to fneg (#2739)
Browse files Browse the repository at this point in the history
Update SPIRVReader to lower OpFNegate directly to fneg.
By doing this the code in SpirvLowerMath can be updated to remove the change to
add a canonicalize for any fneg.

The motivation for this is that InstCombine can introduce fneg
instructions (after some recent upstream llvm changes) and in this case we don't
want to blindly add a canonicalize as this invalidates e.g. xor 0x8000000 val ->
fneg val.

It makes more sense to handle the requirement to treat OpFNegate as a floating
point instruction at the point it is lowered (llvm fneg is not, hence the reason
we may need the canonicalize intrinsic).
  • Loading branch information
dstutt authored Oct 3, 2023
1 parent 22cce3f commit 1aebd12
Show file tree
Hide file tree
Showing 4 changed files with 6 additions and 14 deletions.
9 changes: 0 additions & 9 deletions llpc/lower/llpcSpirvLowerMath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,15 +475,6 @@ bool SpirvLowerMathFloatOp::runImpl(Module &module) {
return m_changed;
}

// =====================================================================================================================
// Visits unary operator instruction.
//
// @param unaryOp : Unary operator instruction
void SpirvLowerMathFloatOp::visitUnaryOperator(UnaryOperator &unaryOp) {
if (unaryOp.getOpcode() == Instruction::FNeg)
flushDenormIfNeeded(&unaryOp);
}

// =====================================================================================================================
// Visits binary operator instruction.
//
Expand Down
1 change: 0 additions & 1 deletion llpc/lower/llpcSpirvLowerMath.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ class SpirvLowerMathFloatOp : public SpirvLowerMath,
bool runImpl(llvm::Module &module);

virtual void visitBinaryOperator(llvm::BinaryOperator &binaryOp);
virtual void visitUnaryOperator(llvm::UnaryOperator &unaryOp);
virtual void visitCallInst(llvm::CallInst &callInst);
virtual void visitFPTruncInst(llvm::FPTruncInst &fptruncInst);

Expand Down
2 changes: 1 addition & 1 deletion llpc/test/shaderdb/core/OpFNegate_TestMat2X3_lit.frag
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void main()
/*
; RUN: amdllpc -v %gfxip %s | FileCheck -check-prefix=SHADERTEST %s
; SHADERTEST-LABEL: {{^// LLPC}} SPIRV-to-LLVM translation results
; SHADERTEST-COUNT-2: fsub reassoc nnan nsz arcp contract afn <3 x float>
; SHADERTEST-COUNT-2: fneg reassoc nnan nsz arcp contract afn <3 x float>
; SHADERTEST: AMDLLPC SUCCESS
*/
// END_SHADERTEST
8 changes: 5 additions & 3 deletions llpc/translator/lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5362,10 +5362,12 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *bv, Function *f, Bas
}
case OpFNegate: {
SPIRVUnary *bc = static_cast<SPIRVUnary *>(bv);
// Implement -x as -0.0 - x.
Value *negZero = ConstantFP::getNegativeZero(transType(bc->getType()));
auto fNeg = BinaryOperator::CreateFSub(negZero, transValue(bc->getOperand(0), f, bb), bv->getName(), bb);
Value *val0 = transValue(bc->getOperand(0), f, bb);
auto fNeg = getBuilder()->CreateFNeg(val0);
setFastMathFlags(fNeg);
// Since OpFNegate is considered a floating point instruction, we must take
// that into account (since LLVM fneg is not).
fNeg = flushDenorm(fNeg);
return mapValue(bv, fNeg);
}

Expand Down

0 comments on commit 1aebd12

Please sign in to comment.