diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -2069,6 +2069,20 @@ MD->invalidateCachedPointerInfo(LHS); } + // If (zext X) == N or (sext X) == N, then X == (trunc N). + Value *X; + if (match(LHS, m_ZExtOrSExt(m_Value(X)))) { + unsigned Width = X->getType()->getIntegerBitWidth(); + ConstantInt *CI = dyn_cast(RHS); + if (CI) { + Value *NewRHS = + ConstantInt::get(IntegerType::get(X->getContext(), Width), + CI->getValue().trunc(Width)); + Worklist.push_back(std::make_pair(X, NewRHS)); + continue; + } + } + // Now try to deduce additional equalities from this one. For example, if // the known equality was "(A != B)" == "false" then it follows that A and B // are equal in the scope. Only boolean equalities with an explicit true or diff --git a/llvm/test/Transforms/GVN/zext-eq-const-int.ll b/llvm/test/Transforms/GVN/zext-eq-const-int.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GVN/zext-eq-const-int.ll @@ -0,0 +1,45 @@ +; RUN: opt -gvn -S < %s | FileCheck %s + +define i32 @zext-eq-const-int(i32 %x) { +; CHECK-LABEL: @zext-eq-const-int( +; CHECK: bb9: +; CHECK-NEXT: br i1 true, label %t +; +entry: + %_x = zext i32 %x to i64 + switch i64 %_x, label %bb.end [ + i64 3, label %bb9 + ] + +bb9: + %cond = icmp eq i32 %x, 3 + br i1 %cond, label %t, label %bb.end + +t: + ret i32 42 + +bb.end: + ret i32 9999 +} + +define i32 @sext-eq-const-int(i32 %x) { +; CHECK-LABEL: @sext-eq-const-int( +; CHECK: bb9: +; CHECK-NEXT: br i1 true, label %t +; +entry: + %_x = sext i32 %x to i64 + switch i64 %_x, label %bb.end [ + i64 4294967299, label %bb9 ; 0x1_0000_0003 + ] + +bb9: + %cond = icmp eq i32 %x, 3 + br i1 %cond, label %t, label %bb.end + +t: + ret i32 42 + +bb.end: + ret i32 9999 +}