[GVN] Respect fast-math-flags on fcmps
We assumed that flags were only present on binary operators. This is not true, they may also be present on calls and fcmps. llvm-svn: 267113
This commit is contained in:
parent
68318e0414
commit
d0ce8f1485
|
@ -217,32 +217,41 @@ void Instruction::copyFastMathFlags(const Instruction *I) {
|
|||
void Instruction::copyIRFlags(const Value *V) {
|
||||
// Copy the wrapping flags.
|
||||
if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
|
||||
setHasNoSignedWrap(OB->hasNoSignedWrap());
|
||||
setHasNoUnsignedWrap(OB->hasNoUnsignedWrap());
|
||||
if (isa<OverflowingBinaryOperator>(this)) {
|
||||
setHasNoSignedWrap(OB->hasNoSignedWrap());
|
||||
setHasNoUnsignedWrap(OB->hasNoUnsignedWrap());
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the exact flag.
|
||||
if (auto *PE = dyn_cast<PossiblyExactOperator>(V))
|
||||
setIsExact(PE->isExact());
|
||||
if (isa<PossiblyExactOperator>(this))
|
||||
setIsExact(PE->isExact());
|
||||
|
||||
// Copy the fast-math flags.
|
||||
if (auto *FP = dyn_cast<FPMathOperator>(V))
|
||||
copyFastMathFlags(FP->getFastMathFlags());
|
||||
if (isa<FPMathOperator>(this))
|
||||
copyFastMathFlags(FP->getFastMathFlags());
|
||||
}
|
||||
|
||||
void Instruction::andIRFlags(const Value *V) {
|
||||
if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
|
||||
setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap());
|
||||
setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap());
|
||||
if (isa<OverflowingBinaryOperator>(this)) {
|
||||
setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap());
|
||||
setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap());
|
||||
}
|
||||
}
|
||||
|
||||
if (auto *PE = dyn_cast<PossiblyExactOperator>(V))
|
||||
setIsExact(isExact() & PE->isExact());
|
||||
if (isa<PossiblyExactOperator>(this))
|
||||
setIsExact(isExact() & PE->isExact());
|
||||
|
||||
if (auto *FP = dyn_cast<FPMathOperator>(V)) {
|
||||
FastMathFlags FM = getFastMathFlags();
|
||||
FM &= FP->getFastMathFlags();
|
||||
copyFastMathFlags(FM);
|
||||
if (isa<FPMathOperator>(this)) {
|
||||
FastMathFlags FM = getFastMathFlags();
|
||||
FM &= FP->getFastMathFlags();
|
||||
copyFastMathFlags(FM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1725,30 +1725,29 @@ bool GVN::processAssumeIntrinsic(IntrinsicInst *IntrinsicI) {
|
|||
}
|
||||
|
||||
static void patchReplacementInstruction(Instruction *I, Value *Repl) {
|
||||
auto *ReplInst = dyn_cast<Instruction>(Repl);
|
||||
if (!ReplInst)
|
||||
return;
|
||||
|
||||
// Patch the replacement so that it is not more restrictive than the value
|
||||
// being replaced.
|
||||
BinaryOperator *Op = dyn_cast<BinaryOperator>(I);
|
||||
BinaryOperator *ReplOp = dyn_cast<BinaryOperator>(Repl);
|
||||
if (Op && ReplOp)
|
||||
ReplOp->andIRFlags(Op);
|
||||
ReplInst->andIRFlags(I);
|
||||
|
||||
if (Instruction *ReplInst = dyn_cast<Instruction>(Repl)) {
|
||||
// FIXME: If both the original and replacement value are part of the
|
||||
// same control-flow region (meaning that the execution of one
|
||||
// guarantees the execution of the other), then we can combine the
|
||||
// noalias scopes here and do better than the general conservative
|
||||
// answer used in combineMetadata().
|
||||
// FIXME: If both the original and replacement value are part of the
|
||||
// same control-flow region (meaning that the execution of one
|
||||
// guarantees the execution of the other), then we can combine the
|
||||
// noalias scopes here and do better than the general conservative
|
||||
// answer used in combineMetadata().
|
||||
|
||||
// In general, GVN unifies expressions over different control-flow
|
||||
// regions, and so we need a conservative combination of the noalias
|
||||
// scopes.
|
||||
static const unsigned KnownIDs[] = {
|
||||
LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope,
|
||||
LLVMContext::MD_noalias, LLVMContext::MD_range,
|
||||
LLVMContext::MD_fpmath, LLVMContext::MD_invariant_load,
|
||||
LLVMContext::MD_invariant_group};
|
||||
combineMetadata(ReplInst, I, KnownIDs);
|
||||
}
|
||||
// In general, GVN unifies expressions over different control-flow
|
||||
// regions, and so we need a conservative combination of the noalias
|
||||
// scopes.
|
||||
static const unsigned KnownIDs[] = {
|
||||
LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope,
|
||||
LLVMContext::MD_noalias, LLVMContext::MD_range,
|
||||
LLVMContext::MD_fpmath, LLVMContext::MD_invariant_load,
|
||||
LLVMContext::MD_invariant_group};
|
||||
combineMetadata(ReplInst, I, KnownIDs);
|
||||
}
|
||||
|
||||
static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl) {
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
; RUN: opt -gvn -S < %s | FileCheck %s
|
||||
|
||||
declare void @use(i1)
|
||||
|
||||
define void @test1(float %x, float %y) {
|
||||
entry:
|
||||
%cmp1 = fcmp nnan oeq float %y, %x
|
||||
%cmp2 = fcmp oeq float %x, %y
|
||||
call void @use(i1 %cmp1)
|
||||
call void @use(i1 %cmp2)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define void @test1(
|
||||
; CHECK: %[[cmp:.*]] = fcmp oeq float %y, %x
|
||||
; CHECK-NEXT: call void @use(i1 %[[cmp]])
|
||||
; CHECK-NEXT: call void @use(i1 %[[cmp]])
|
||||
; CHECK-NEXT: ret void
|
Loading…
Reference in New Issue