[InstCombine] fix miscompile from urem/udiv transform with constant expression
The isa<Constant> check could misfire on an instruction with 2 constant
operands. This bug was introduced with bb789381fc (D36988).
See issue #56810 for a C source example that exposed the bug.
This commit is contained in:
@@ -1008,8 +1008,7 @@ static Instruction *narrowUDivURem(BinaryOperator &I,
|
||||
}
|
||||
|
||||
Constant *C;
|
||||
if ((match(N, m_OneUse(m_ZExt(m_Value(X)))) && match(D, m_Constant(C))) ||
|
||||
(match(D, m_OneUse(m_ZExt(m_Value(X)))) && match(N, m_Constant(C)))) {
|
||||
if (match(N, m_OneUse(m_ZExt(m_Value(X)))) && match(D, m_Constant(C))) {
|
||||
// If the constant is the same in the smaller type, use the narrow version.
|
||||
Constant *TruncC = ConstantExpr::getTrunc(C, X->getType());
|
||||
if (ConstantExpr::getZExt(TruncC, Ty) != C)
|
||||
@@ -1017,11 +1016,17 @@ static Instruction *narrowUDivURem(BinaryOperator &I,
|
||||
|
||||
// udiv (zext X), C --> zext (udiv X, C')
|
||||
// urem (zext X), C --> zext (urem X, C')
|
||||
return new ZExtInst(Builder.CreateBinOp(Opcode, X, TruncC), Ty);
|
||||
}
|
||||
if (match(D, m_OneUse(m_ZExt(m_Value(X)))) && match(N, m_Constant(C))) {
|
||||
// If the constant is the same in the smaller type, use the narrow version.
|
||||
Constant *TruncC = ConstantExpr::getTrunc(C, X->getType());
|
||||
if (ConstantExpr::getZExt(TruncC, Ty) != C)
|
||||
return nullptr;
|
||||
|
||||
// udiv C, (zext X) --> zext (udiv C', X)
|
||||
// urem C, (zext X) --> zext (urem C', X)
|
||||
Value *NarrowOp = isa<Constant>(D) ? Builder.CreateBinOp(Opcode, X, TruncC)
|
||||
: Builder.CreateBinOp(Opcode, TruncC, X);
|
||||
return new ZExtInst(NarrowOp, Ty);
|
||||
return new ZExtInst(Builder.CreateBinOp(Opcode, TruncC, X), Ty);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
@@ -287,13 +287,13 @@ define i32 @udiv_constexpr(i8 %a) {
|
||||
ret i32 %d
|
||||
}
|
||||
|
||||
; FIXME: This is a miscompile (minimal form of PR56810)
|
||||
; minimal form of PR56810
|
||||
|
||||
@g1 = external global [1 x i8]
|
||||
|
||||
define i32 @udiv_const_constexpr(i8 %a) {
|
||||
; CHECK-LABEL: @udiv_const_constexpr(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = udiv i8 ptrtoint ([1 x i8]* @g1 to i8), 42
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = udiv i8 42, ptrtoint ([1 x i8]* @g1 to i8)
|
||||
; CHECK-NEXT: [[D:%.*]] = zext i8 [[TMP1]] to i32
|
||||
; CHECK-NEXT: ret i32 [[D]]
|
||||
;
|
||||
@@ -301,13 +301,13 @@ define i32 @udiv_const_constexpr(i8 %a) {
|
||||
ret i32 %d
|
||||
}
|
||||
|
||||
; FIXME: This is a miscompile (minimal form of PR56810)
|
||||
; minimal form of PR56810
|
||||
|
||||
@g2 = external global [1 x i8]
|
||||
|
||||
define i32 @urem_const_constexpr(i8 %a) {
|
||||
; CHECK-LABEL: @urem_const_constexpr(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = urem i8 ptrtoint ([1 x i8]* @g2 to i8), 42
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = urem i8 42, ptrtoint ([1 x i8]* @g2 to i8)
|
||||
; CHECK-NEXT: [[D:%.*]] = zext i8 [[TMP1]] to i32
|
||||
; CHECK-NEXT: ret i32 [[D]]
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user