[MergeFunc] Fix comparison of constant expressions

Functions using different constant expressions were incorrectly
merged, because a lot of state was missing from the comparison,
including the opcode, the comparison predicate, the GEP element
type, as well as the inbounds, inrange and nowrap poison flags.
This commit is contained in:
Nikita Popov
2023-12-20 15:05:42 +01:00
parent 6cd296ed85
commit 8b8f2ef06e
2 changed files with 61 additions and 5 deletions

View File

@@ -405,6 +405,8 @@ int FunctionComparator::cmpConstants(const Constant *L,
case Value::ConstantExprVal: {
const ConstantExpr *LE = cast<ConstantExpr>(L);
const ConstantExpr *RE = cast<ConstantExpr>(R);
if (int Res = cmpNumbers(LE->getOpcode(), RE->getOpcode()))
return Res;
unsigned NumOperandsL = LE->getNumOperands();
unsigned NumOperandsR = RE->getNumOperands();
if (int Res = cmpNumbers(NumOperandsL, NumOperandsR))
@@ -414,6 +416,29 @@ int FunctionComparator::cmpConstants(const Constant *L,
cast<Constant>(RE->getOperand(i))))
return Res;
}
if (LE->isCompare())
if (int Res = cmpNumbers(LE->getPredicate(), RE->getPredicate()))
return Res;
if (auto *GEPL = dyn_cast<GEPOperator>(LE)) {
auto *GEPR = cast<GEPOperator>(RE);
if (int Res = cmpTypes(GEPL->getSourceElementType(),
GEPR->getSourceElementType()))
return Res;
if (int Res = cmpNumbers(GEPL->isInBounds(), GEPR->isInBounds()))
return Res;
if (int Res = cmpNumbers(GEPL->getInRangeIndex().value_or(unsigned(-1)),
GEPR->getInRangeIndex().value_or(unsigned(-1))))
return Res;
}
if (auto *OBOL = dyn_cast<OverflowingBinaryOperator>(LE)) {
auto *OBOR = cast<OverflowingBinaryOperator>(RE);
if (int Res =
cmpNumbers(OBOL->hasNoUnsignedWrap(), OBOR->hasNoUnsignedWrap()))
return Res;
if (int Res =
cmpNumbers(OBOL->hasNoSignedWrap(), OBOR->hasNoSignedWrap()))
return Res;
}
return 0;
}
case Value::BlockAddressVal: {

View File

@@ -7,11 +7,6 @@
;.
; CHECK: @g1 = external unnamed_addr global i8
; CHECK: @g2 = external unnamed_addr global i8
; CHECK: @f2 = unnamed_addr alias i1 (), ptr @f1
; CHECK: @f4 = unnamed_addr alias ptr (), ptr @f3
; CHECK: @f5 = unnamed_addr alias ptr (), ptr @f3
; CHECK: @f7 = unnamed_addr alias i64 (), ptr @f6
; CHECK: @f8 = unnamed_addr alias i64 (), ptr @f6
;.
define i1 @f1() unnamed_addr {
; CHECK-LABEL: define i1 @f1() unnamed_addr {
@@ -21,6 +16,9 @@ define i1 @f1() unnamed_addr {
}
define i1 @f2() unnamed_addr {
; CHECK-LABEL: define i1 @f2() unnamed_addr {
; CHECK-NEXT: ret i1 icmp ne (ptr @g1, ptr @g2)
;
ret i1 icmp ne (ptr @g1, ptr @g2)
}
@@ -32,10 +30,16 @@ define ptr @f3() unnamed_addr {
}
define ptr @f4() unnamed_addr {
; CHECK-LABEL: define ptr @f4() unnamed_addr {
; CHECK-NEXT: ret ptr getelementptr (i16, ptr @g1, i64 2)
;
ret ptr getelementptr (i16, ptr @g1, i64 2)
}
define ptr @f5() unnamed_addr {
; CHECK-LABEL: define ptr @f5() unnamed_addr {
; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g1, i64 2)
;
ret ptr getelementptr (i8, ptr @g1, i64 2)
}
@@ -47,9 +51,36 @@ define i64 @f6() unnamed_addr {
}
define i64 @f7() unnamed_addr {
; CHECK-LABEL: define i64 @f7() unnamed_addr {
; CHECK-NEXT: ret i64 add (i64 ptrtoint (ptr @g1 to i64), i64 1)
;
ret i64 add (i64 ptrtoint (ptr @g1 to i64), i64 1)
}
define i64 @f8() unnamed_addr {
; CHECK-LABEL: define i64 @f8() unnamed_addr {
; CHECK-NEXT: ret i64 sub (i64 ptrtoint (ptr @g1 to i64), i64 1)
;
ret i64 sub (i64 ptrtoint (ptr @g1 to i64), i64 1)
}
define ptr @f10() unnamed_addr {
; CHECK-LABEL: define ptr @f10() unnamed_addr {
; CHECK-NEXT: ret ptr getelementptr ([4 x i32], ptr @g1, i64 0, inrange i64 1)
;
ret ptr getelementptr ([4 x i32], ptr @g1, i64 0, inrange i64 1)
}
define ptr @f11() unnamed_addr {
; CHECK-LABEL: define ptr @f11() unnamed_addr {
; CHECK-NEXT: ret ptr getelementptr ([4 x i32], ptr @g1, i64 0, i64 1)
;
ret ptr getelementptr ([4 x i32], ptr @g1, i64 0, i64 1)
}
define ptr @f12() unnamed_addr {
; CHECK-LABEL: define ptr @f12() unnamed_addr {
; CHECK-NEXT: ret ptr getelementptr ([4 x i32], ptr @g1, inrange i64 0, i64 1)
;
ret ptr getelementptr ([4 x i32], ptr @g1, inrange i64 0, i64 1)
}