[llvm] d4940c0 - [InstCombine] fix miscompile from urem/udiv transform with constant expression
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 29 14:14:42 PDT 2022
Author: Sanjay Patel
Date: 2022-07-29T17:14:30-04:00
New Revision: d4940c0f3d433ca5bab66d1e6a5170059c38a10a
URL: https://github.com/llvm/llvm-project/commit/d4940c0f3d433ca5bab66d1e6a5170059c38a10a
DIFF: https://github.com/llvm/llvm-project/commit/d4940c0f3d433ca5bab66d1e6a5170059c38a10a.diff
LOG: [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 bb789381fc11cce (D36988).
See issue #56810 for a C source example that exposed the bug.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
llvm/test/Transforms/InstCombine/udivrem-change-width.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 08e430694a730..abe15e2bda241 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -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;
diff --git a/llvm/test/Transforms/InstCombine/udivrem-change-width.ll b/llvm/test/Transforms/InstCombine/udivrem-change-width.ll
index 522950257b11f..88e31a29aa0f2 100644
--- a/llvm/test/Transforms/InstCombine/udivrem-change-width.ll
+++ b/llvm/test/Transforms/InstCombine/udivrem-change-width.ll
@@ -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]]
;
More information about the llvm-commits
mailing list