From ac74e7a7806480a000c9a3502405c3dedd8810de Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 17 Oct 2022 15:43:11 +0200 Subject: [PATCH] [InstSimplify] Only check self-simplify in simplifyInstruction() InstSimplify currently checks whether the instruction simplifies back to itself, and returns undef in that case. Generally, this should only occur in unreachable code. However, this was also done for the simplifyInstructionWithOperands() API. In that case, the instruction only serves as a template that provides the opcode and other non-operand data. In this case, simplifying back to the same "instruction" may be expected. This caused PR58401 in conjunction with D134954. As such, move this check into simplifyInstruction() only. The only other caller of simplifyInstructionWithOperands() also handles the self-simplification case explicitly. --- llvm/lib/Analysis/InstructionSimplify.cpp | 153 +++++++++++------------------- 1 file changed, 58 insertions(+), 95 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 7b22984..fe7b63c 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -6375,7 +6375,6 @@ static Value *simplifyInstructionWithOperands(Instruction *I, const SimplifyQuery &SQ, OptimizationRemarkEmitter *ORE) { const SimplifyQuery Q = SQ.CxtI ? SQ : SQ.getWithInstruction(I); - Value *Result = nullptr; switch (I->getOpcode()) { default: @@ -6383,145 +6382,104 @@ static Value *simplifyInstructionWithOperands(Instruction *I, SmallVector NewConstOps(NewOps.size()); transform(NewOps, NewConstOps.begin(), [](Value *V) { return cast(V); }); - Result = ConstantFoldInstOperands(I, NewConstOps, Q.DL, Q.TLI); + return ConstantFoldInstOperands(I, NewConstOps, Q.DL, Q.TLI); } - break; + return nullptr; case Instruction::FNeg: - Result = simplifyFNegInst(NewOps[0], I->getFastMathFlags(), Q); - break; + return simplifyFNegInst(NewOps[0], I->getFastMathFlags(), Q); case Instruction::FAdd: - Result = simplifyFAddInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); - break; + return simplifyFAddInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); case Instruction::Add: - Result = simplifyAddInst( - NewOps[0], NewOps[1], Q.IIQ.hasNoSignedWrap(cast(I)), - Q.IIQ.hasNoUnsignedWrap(cast(I)), Q); - break; + return simplifyAddInst(NewOps[0], NewOps[1], + Q.IIQ.hasNoSignedWrap(cast(I)), + Q.IIQ.hasNoUnsignedWrap(cast(I)), Q); case Instruction::FSub: - Result = simplifyFSubInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); - break; + return simplifyFSubInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); case Instruction::Sub: - Result = simplifySubInst( - NewOps[0], NewOps[1], Q.IIQ.hasNoSignedWrap(cast(I)), - Q.IIQ.hasNoUnsignedWrap(cast(I)), Q); - break; + return simplifySubInst(NewOps[0], NewOps[1], + Q.IIQ.hasNoSignedWrap(cast(I)), + Q.IIQ.hasNoUnsignedWrap(cast(I)), Q); case Instruction::FMul: - Result = simplifyFMulInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); - break; + return simplifyFMulInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); case Instruction::Mul: - Result = simplifyMulInst(NewOps[0], NewOps[1], Q); - break; + return simplifyMulInst(NewOps[0], NewOps[1], Q); case Instruction::SDiv: - Result = simplifySDivInst(NewOps[0], NewOps[1], Q); - break; + return simplifySDivInst(NewOps[0], NewOps[1], Q); case Instruction::UDiv: - Result = simplifyUDivInst(NewOps[0], NewOps[1], Q); - break; + return simplifyUDivInst(NewOps[0], NewOps[1], Q); case Instruction::FDiv: - Result = simplifyFDivInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); - break; + return simplifyFDivInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); case Instruction::SRem: - Result = simplifySRemInst(NewOps[0], NewOps[1], Q); - break; + return simplifySRemInst(NewOps[0], NewOps[1], Q); case Instruction::URem: - Result = simplifyURemInst(NewOps[0], NewOps[1], Q); - break; + return simplifyURemInst(NewOps[0], NewOps[1], Q); case Instruction::FRem: - Result = simplifyFRemInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); - break; + return simplifyFRemInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q); case Instruction::Shl: - Result = simplifyShlInst( - NewOps[0], NewOps[1], Q.IIQ.hasNoSignedWrap(cast(I)), - Q.IIQ.hasNoUnsignedWrap(cast(I)), Q); - break; + return simplifyShlInst(NewOps[0], NewOps[1], + Q.IIQ.hasNoSignedWrap(cast(I)), + Q.IIQ.hasNoUnsignedWrap(cast(I)), Q); case Instruction::LShr: - Result = simplifyLShrInst(NewOps[0], NewOps[1], - Q.IIQ.isExact(cast(I)), Q); - break; + return simplifyLShrInst(NewOps[0], NewOps[1], + Q.IIQ.isExact(cast(I)), Q); case Instruction::AShr: - Result = simplifyAShrInst(NewOps[0], NewOps[1], - Q.IIQ.isExact(cast(I)), Q); - break; + return simplifyAShrInst(NewOps[0], NewOps[1], + Q.IIQ.isExact(cast(I)), Q); case Instruction::And: - Result = simplifyAndInst(NewOps[0], NewOps[1], Q); - break; + return simplifyAndInst(NewOps[0], NewOps[1], Q); case Instruction::Or: - Result = simplifyOrInst(NewOps[0], NewOps[1], Q); - break; + return simplifyOrInst(NewOps[0], NewOps[1], Q); case Instruction::Xor: - Result = simplifyXorInst(NewOps[0], NewOps[1], Q); - break; + return simplifyXorInst(NewOps[0], NewOps[1], Q); case Instruction::ICmp: - Result = simplifyICmpInst(cast(I)->getPredicate(), NewOps[0], - NewOps[1], Q); - break; + return simplifyICmpInst(cast(I)->getPredicate(), NewOps[0], + NewOps[1], Q); case Instruction::FCmp: - Result = simplifyFCmpInst(cast(I)->getPredicate(), NewOps[0], - NewOps[1], I->getFastMathFlags(), Q); - break; + return simplifyFCmpInst(cast(I)->getPredicate(), NewOps[0], + NewOps[1], I->getFastMathFlags(), Q); case Instruction::Select: - Result = simplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q); + return simplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q); break; case Instruction::GetElementPtr: { auto *GEPI = cast(I); - Result = - simplifyGEPInst(GEPI->getSourceElementType(), NewOps[0], - makeArrayRef(NewOps).slice(1), GEPI->isInBounds(), Q); - break; + return simplifyGEPInst(GEPI->getSourceElementType(), NewOps[0], + makeArrayRef(NewOps).slice(1), GEPI->isInBounds(), + Q); } case Instruction::InsertValue: { InsertValueInst *IV = cast(I); - Result = simplifyInsertValueInst(NewOps[0], NewOps[1], IV->getIndices(), Q); - break; - } - case Instruction::InsertElement: { - Result = simplifyInsertElementInst(NewOps[0], NewOps[1], NewOps[2], Q); - break; + return simplifyInsertValueInst(NewOps[0], NewOps[1], IV->getIndices(), Q); } + case Instruction::InsertElement: + return simplifyInsertElementInst(NewOps[0], NewOps[1], NewOps[2], Q); case Instruction::ExtractValue: { auto *EVI = cast(I); - Result = simplifyExtractValueInst(NewOps[0], EVI->getIndices(), Q); - break; - } - case Instruction::ExtractElement: { - Result = simplifyExtractElementInst(NewOps[0], NewOps[1], Q); - break; + return simplifyExtractValueInst(NewOps[0], EVI->getIndices(), Q); } + case Instruction::ExtractElement: + return simplifyExtractElementInst(NewOps[0], NewOps[1], Q); case Instruction::ShuffleVector: { auto *SVI = cast(I); - Result = simplifyShuffleVectorInst( - NewOps[0], NewOps[1], SVI->getShuffleMask(), SVI->getType(), Q); - break; + return simplifyShuffleVectorInst(NewOps[0], NewOps[1], + SVI->getShuffleMask(), SVI->getType(), Q); } case Instruction::PHI: - Result = simplifyPHINode(cast(I), NewOps, Q); - break; - case Instruction::Call: { + return simplifyPHINode(cast(I), NewOps, Q); + case Instruction::Call: // TODO: Use NewOps - Result = simplifyCall(cast(I), Q); - break; - } + return simplifyCall(cast(I), Q); case Instruction::Freeze: - Result = llvm::simplifyFreezeInst(NewOps[0], Q); - break; + return llvm::simplifyFreezeInst(NewOps[0], Q); #define HANDLE_CAST_INST(num, opc, clas) case Instruction::opc: #include "llvm/IR/Instruction.def" #undef HANDLE_CAST_INST - Result = simplifyCastInst(I->getOpcode(), NewOps[0], I->getType(), Q); - break; + return simplifyCastInst(I->getOpcode(), NewOps[0], I->getType(), Q); case Instruction::Alloca: // No simplifications for Alloca and it can't be constant folded. - Result = nullptr; - break; + return nullptr; case Instruction::Load: - Result = simplifyLoadInst(cast(I), NewOps[0], Q); - break; + return simplifyLoadInst(cast(I), NewOps[0], Q); } - - /// If called on unreachable code, the above logic may report that the - /// instruction simplified to itself. Make life easier for users by - /// detecting that case here, returning a safe value instead. - return Result == I ? UndefValue::get(I->getType()) : Result; } Value *llvm::simplifyInstructionWithOperands(Instruction *I, @@ -6536,7 +6494,12 @@ Value *llvm::simplifyInstructionWithOperands(Instruction *I, Value *llvm::simplifyInstruction(Instruction *I, const SimplifyQuery &SQ, OptimizationRemarkEmitter *ORE) { SmallVector Ops(I->operands()); - return ::simplifyInstructionWithOperands(I, Ops, SQ, ORE); + Value *Result = ::simplifyInstructionWithOperands(I, Ops, SQ, ORE); + + /// If called on unreachable code, the instruction may simplify to itself. + /// Make life easier for users by detecting that case here, and returning a + /// safe value instead. + return Result == I ? UndefValue::get(I->getType()) : Result; } /// Implementation of recursive simplification through an instruction's -- 2.7.4