-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[SCCP] Remove masking operations #142736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SCCP] Remove masking operations #142736
Conversation
@llvm/pr-subscribers-function-specialization Author: Yingwei Zheng (dtcxzyw) ChangesCVP version: 2d5820c Full diff: https://github.com/llvm/llvm-project/pull/142736.diff 4 Files Affected:
diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index 4535f86f9d68b..f9c075eaa602b 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -20,6 +20,7 @@
#include "llvm/Analysis/ValueLatticeUtils.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -30,6 +31,7 @@
#include <vector>
using namespace llvm;
+using namespace PatternMatch;
#define DEBUG_TYPE "sccp"
@@ -86,7 +88,7 @@ bool SCCPSolver::tryToReplaceWithConstant(Value *V) {
/// Try to use \p Inst's value range from \p Solver to infer the NUW flag.
static bool refineInstruction(SCCPSolver &Solver,
const SmallPtrSetImpl<Value *> &InsertedValues,
- Instruction &Inst) {
+ Instruction &Inst, Statistic &InstRemovedStat) {
bool Changed = false;
auto GetRange = [&Solver, &InsertedValues](Value *Op) {
if (auto *Const = dyn_cast<Constant>(Op))
@@ -99,6 +101,9 @@ static bool refineInstruction(SCCPSolver &Solver,
Op->getType(), /*UndefAllowed=*/false);
};
+ Value *X;
+ const APInt *RHSC;
+
if (isa<OverflowingBinaryOperator>(Inst)) {
if (Inst.hasNoSignedWrap() && Inst.hasNoUnsignedWrap())
return false;
@@ -157,6 +162,15 @@ static bool refineInstruction(SCCPSolver &Solver,
GEPNoWrapFlags::noUnsignedWrap());
Changed = true;
}
+ } else if (match(&Inst, m_And(m_Value(X), m_LowBitMask(RHSC)))) {
+ ConstantRange LRange = GetRange(Inst.getOperand(0));
+ if (!LRange.getUnsignedMax().ule(*RHSC))
+ return false;
+
+ Inst.replaceAllUsesWith(X);
+ Inst.eraseFromParent();
+ ++InstRemovedStat;
+ Changed = true;
}
return Changed;
@@ -249,7 +263,8 @@ bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB,
} else if (replaceSignedInst(*this, InsertedValues, Inst)) {
MadeChanges = true;
++InstReplacedStat;
- } else if (refineInstruction(*this, InsertedValues, Inst)) {
+ } else if (refineInstruction(*this, InsertedValues, Inst,
+ InstRemovedStat)) {
MadeChanges = true;
}
}
diff --git a/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll b/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll
index 8b4dea462757e..207f303b83460 100644
--- a/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll
+++ b/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll
@@ -46,8 +46,7 @@ define void @val_undef_range() {
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
; CHECK: true:
; CHECK-NEXT: call void @use(i1 false)
-; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127
-; CHECK-NEXT: call void @use.i32(i32 [[A_127]])
+; CHECK-NEXT: call void @use.i32(i32 [[A]])
; CHECK-NEXT: ret void
; CHECK: false:
; CHECK-NEXT: ret void
@@ -82,8 +81,7 @@ define void @val_singlecrfromundef_range(i1 %cond) {
; CHECK-NEXT: br label [[TRUE:%.*]]
; CHECK: true:
; CHECK-NEXT: call void @use(i1 false)
-; CHECK-NEXT: [[P_127:%.*]] = and i32 10, 127
-; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
+; CHECK-NEXT: call void @use.i32(i32 10)
; CHECK-NEXT: ret void
;
entry:
@@ -131,8 +129,7 @@ define void @val_undef_to_cr_to_overdef_range(i32 %a, i1 %cond) {
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
; CHECK: true:
; CHECK-NEXT: call void @use(i1 false)
-; CHECK-NEXT: [[P_127:%.*]] = and i32 [[P]], 127
-; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
+; CHECK-NEXT: call void @use.i32(i32 [[P]])
; CHECK-NEXT: ret void
; CHECK: false:
; CHECK-NEXT: ret void
diff --git a/llvm/test/Transforms/SCCP/range-and.ll b/llvm/test/Transforms/SCCP/range-and.ll
index ef8758fcba9e2..f3452f45e1c02 100644
--- a/llvm/test/Transforms/SCCP/range-and.ll
+++ b/llvm/test/Transforms/SCCP/range-and.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --verbose
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=sccp %s | FileCheck %s
declare void @use(i1)
@@ -140,9 +140,8 @@ define i64 @constant_range_and_255_100(i1 %cond, i64 %a) {
; CHECK-NEXT: br label [[BB3]]
; CHECK: bb3:
; CHECK-NEXT: [[P:%.*]] = phi i64 [ [[R_1]], [[BB1]] ], [ [[R_2]], [[BB2]] ]
-; CHECK-NEXT: [[P_AND:%.*]] = and i64 [[P]], 255
; CHECK-NEXT: call void @use(i1 true)
-; CHECK-NEXT: ret i64 [[P_AND]]
+; CHECK-NEXT: ret i64 [[P]]
;
entry:
br i1 %cond, label %bb1, label %bb2
diff --git a/llvm/test/Transforms/SCCP/range-with-undef.ll b/llvm/test/Transforms/SCCP/range-with-undef.ll
index 9b8d415171140..774d95ceff428 100644
--- a/llvm/test/Transforms/SCCP/range-with-undef.ll
+++ b/llvm/test/Transforms/SCCP/range-with-undef.ll
@@ -12,8 +12,7 @@ define i8 @test_binop(i1 %cond, i8 %a) {
; CHECK-NEXT: [[A_EXT:%.*]] = zext i8 [[A]] to i16
; CHECK-NEXT: br label %[[JOIN]]
; CHECK: [[JOIN]]:
-; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ undef, %[[ENTRY]] ], [ [[A_EXT]], %[[IF]] ]
-; CHECK-NEXT: [[AND:%.*]] = and i16 [[PHI]], -1
+; CHECK-NEXT: [[AND:%.*]] = phi i16 [ undef, %[[ENTRY]] ], [ [[A_EXT]], %[[IF]] ]
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i16 [[AND]] to i8
; CHECK-NEXT: ret i8 [[TRUNC]]
;
|
@llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) ChangesCVP version: 2d5820c Full diff: https://github.com/llvm/llvm-project/pull/142736.diff 4 Files Affected:
diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index 4535f86f9d68b..f9c075eaa602b 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -20,6 +20,7 @@
#include "llvm/Analysis/ValueLatticeUtils.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -30,6 +31,7 @@
#include <vector>
using namespace llvm;
+using namespace PatternMatch;
#define DEBUG_TYPE "sccp"
@@ -86,7 +88,7 @@ bool SCCPSolver::tryToReplaceWithConstant(Value *V) {
/// Try to use \p Inst's value range from \p Solver to infer the NUW flag.
static bool refineInstruction(SCCPSolver &Solver,
const SmallPtrSetImpl<Value *> &InsertedValues,
- Instruction &Inst) {
+ Instruction &Inst, Statistic &InstRemovedStat) {
bool Changed = false;
auto GetRange = [&Solver, &InsertedValues](Value *Op) {
if (auto *Const = dyn_cast<Constant>(Op))
@@ -99,6 +101,9 @@ static bool refineInstruction(SCCPSolver &Solver,
Op->getType(), /*UndefAllowed=*/false);
};
+ Value *X;
+ const APInt *RHSC;
+
if (isa<OverflowingBinaryOperator>(Inst)) {
if (Inst.hasNoSignedWrap() && Inst.hasNoUnsignedWrap())
return false;
@@ -157,6 +162,15 @@ static bool refineInstruction(SCCPSolver &Solver,
GEPNoWrapFlags::noUnsignedWrap());
Changed = true;
}
+ } else if (match(&Inst, m_And(m_Value(X), m_LowBitMask(RHSC)))) {
+ ConstantRange LRange = GetRange(Inst.getOperand(0));
+ if (!LRange.getUnsignedMax().ule(*RHSC))
+ return false;
+
+ Inst.replaceAllUsesWith(X);
+ Inst.eraseFromParent();
+ ++InstRemovedStat;
+ Changed = true;
}
return Changed;
@@ -249,7 +263,8 @@ bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB,
} else if (replaceSignedInst(*this, InsertedValues, Inst)) {
MadeChanges = true;
++InstReplacedStat;
- } else if (refineInstruction(*this, InsertedValues, Inst)) {
+ } else if (refineInstruction(*this, InsertedValues, Inst,
+ InstRemovedStat)) {
MadeChanges = true;
}
}
diff --git a/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll b/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll
index 8b4dea462757e..207f303b83460 100644
--- a/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll
+++ b/llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll
@@ -46,8 +46,7 @@ define void @val_undef_range() {
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
; CHECK: true:
; CHECK-NEXT: call void @use(i1 false)
-; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127
-; CHECK-NEXT: call void @use.i32(i32 [[A_127]])
+; CHECK-NEXT: call void @use.i32(i32 [[A]])
; CHECK-NEXT: ret void
; CHECK: false:
; CHECK-NEXT: ret void
@@ -82,8 +81,7 @@ define void @val_singlecrfromundef_range(i1 %cond) {
; CHECK-NEXT: br label [[TRUE:%.*]]
; CHECK: true:
; CHECK-NEXT: call void @use(i1 false)
-; CHECK-NEXT: [[P_127:%.*]] = and i32 10, 127
-; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
+; CHECK-NEXT: call void @use.i32(i32 10)
; CHECK-NEXT: ret void
;
entry:
@@ -131,8 +129,7 @@ define void @val_undef_to_cr_to_overdef_range(i32 %a, i1 %cond) {
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
; CHECK: true:
; CHECK-NEXT: call void @use(i1 false)
-; CHECK-NEXT: [[P_127:%.*]] = and i32 [[P]], 127
-; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
+; CHECK-NEXT: call void @use.i32(i32 [[P]])
; CHECK-NEXT: ret void
; CHECK: false:
; CHECK-NEXT: ret void
diff --git a/llvm/test/Transforms/SCCP/range-and.ll b/llvm/test/Transforms/SCCP/range-and.ll
index ef8758fcba9e2..f3452f45e1c02 100644
--- a/llvm/test/Transforms/SCCP/range-and.ll
+++ b/llvm/test/Transforms/SCCP/range-and.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --verbose
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=sccp %s | FileCheck %s
declare void @use(i1)
@@ -140,9 +140,8 @@ define i64 @constant_range_and_255_100(i1 %cond, i64 %a) {
; CHECK-NEXT: br label [[BB3]]
; CHECK: bb3:
; CHECK-NEXT: [[P:%.*]] = phi i64 [ [[R_1]], [[BB1]] ], [ [[R_2]], [[BB2]] ]
-; CHECK-NEXT: [[P_AND:%.*]] = and i64 [[P]], 255
; CHECK-NEXT: call void @use(i1 true)
-; CHECK-NEXT: ret i64 [[P_AND]]
+; CHECK-NEXT: ret i64 [[P]]
;
entry:
br i1 %cond, label %bb1, label %bb2
diff --git a/llvm/test/Transforms/SCCP/range-with-undef.ll b/llvm/test/Transforms/SCCP/range-with-undef.ll
index 9b8d415171140..774d95ceff428 100644
--- a/llvm/test/Transforms/SCCP/range-with-undef.ll
+++ b/llvm/test/Transforms/SCCP/range-with-undef.ll
@@ -12,8 +12,7 @@ define i8 @test_binop(i1 %cond, i8 %a) {
; CHECK-NEXT: [[A_EXT:%.*]] = zext i8 [[A]] to i16
; CHECK-NEXT: br label %[[JOIN]]
; CHECK: [[JOIN]]:
-; CHECK-NEXT: [[PHI:%.*]] = phi i16 [ undef, %[[ENTRY]] ], [ [[A_EXT]], %[[IF]] ]
-; CHECK-NEXT: [[AND:%.*]] = and i16 [[PHI]], -1
+; CHECK-NEXT: [[AND:%.*]] = phi i16 [ undef, %[[ENTRY]] ], [ [[A_EXT]], %[[IF]] ]
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i16 [[AND]] to i8
; CHECK-NEXT: ret i8 [[TRUNC]]
;
|
@@ -157,6 +162,15 @@ static bool refineInstruction(SCCPSolver &Solver, | |||
GEPNoWrapFlags::noUnsignedWrap()); | |||
Changed = true; | |||
} | |||
} else if (match(&Inst, m_And(m_Value(X), m_LowBitMask(RHSC)))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could try generalizing this away from LowBitMask in a followup. For CVP this reduces compile-time, but for IPSCCP it shouldn't matter.
You can test this locally with the following command:git diff -U0 --pickaxe-regex -S '([^a-zA-Z0-9#_-]undef[^a-zA-Z0-9_-]|UndefValue::get)' 'HEAD~1' HEAD llvm/lib/Transforms/Utils/SCCPSolver.cpp llvm/test/Transforms/SCCP/conditions-ranges-with-undef.ll llvm/test/Transforms/SCCP/range-and.ll llvm/test/Transforms/SCCP/range-with-undef.ll The following files introduce new uses of undef:
Undef is now deprecated and should only be used in the rare cases where no replacement is possible. For example, a load of uninitialized memory yields In tests, avoid using For example, this is considered a bad practice: define void @fn() {
...
br i1 undef, ...
} Please use the following instead: define void @fn(i1 %cond) {
...
br i1 %cond, ...
} Please refer to the Undefined Behavior Manual for more information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/11/builds/16585 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/66/builds/14913 Here is the relevant piece of the build log for the reference
|
CVP version: 2d5820c
Compile-time impact: https://llvm-compile-time-tracker.com/compare.php?from=3ec0c5c7fef03985b43432c6b914c289d8a5435e&to=92b4df90695dd37defdabf8a30f0b0322b648a00&stat=instructions:u