summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp22
-rw-r--r--llvm/unittests/Analysis/ValueTrackingTest.cpp42
2 files changed, 59 insertions, 5 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 352b0fbd4dc..7de719579ad 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3750,14 +3750,26 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
return {SPF_UNKNOWN, SPNB_NA, false};
}
-static Constant *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2,
- Instruction::CastOps *CastOp) {
+static Value *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2,
+ Instruction::CastOps *CastOp) {
CastInst *CI = dyn_cast<CastInst>(V1);
Constant *C = dyn_cast<Constant>(V2);
- if (!CI || !C)
+ CastInst *CI2 = dyn_cast<CastInst>(V2);
+ if (!CI)
return nullptr;
*CastOp = CI->getOpcode();
+ if (CI2) {
+ // If V1 and V2 are both the same cast from the same type, we can look
+ // through V1.
+ if (CI2->getOpcode() == CI->getOpcode() &&
+ CI2->getSrcTy() == CI->getSrcTy())
+ return CI2->getOperand(0);
+ return nullptr;
+ } else if (!C) {
+ return nullptr;
+ }
+
if (isa<SExtInst>(CI) && CmpI->isSigned()) {
Constant *T = ConstantExpr::getTrunc(C, CI->getSrcTy());
// This is only valid if the truncated value can be sign-extended
@@ -3817,11 +3829,11 @@ SelectPatternResult llvm::matchSelectPattern(Value *V,
// Deal with type mismatches.
if (CastOp && CmpLHS->getType() != TrueVal->getType()) {
- if (Constant *C = lookThroughCast(CmpI, TrueVal, FalseVal, CastOp))
+ if (Value *C = lookThroughCast(CmpI, TrueVal, FalseVal, CastOp))
return ::matchSelectPattern(Pred, FMF, CmpLHS, CmpRHS,
cast<CastInst>(TrueVal)->getOperand(0), C,
LHS, RHS);
- if (Constant *C = lookThroughCast(CmpI, FalseVal, TrueVal, CastOp))
+ if (Value *C = lookThroughCast(CmpI, FalseVal, TrueVal, CastOp))
return ::matchSelectPattern(Pred, FMF, CmpLHS, CmpRHS,
C, cast<CastInst>(FalseVal)->getOperand(0),
LHS, RHS);
diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index b5ad01968b9..1512ad0fd86 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -146,3 +146,45 @@ TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {
// But this should be, because we've ignored signed zeroes.
expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
}
+
+TEST_F(MatchSelectPatternTest, DoubleCastU) {
+ parseAssembly(
+ "define i32 @test(i8 %a, i8 %b) {\n"
+ " %1 = icmp ult i8 %a, %b\n"
+ " %2 = zext i8 %a to i32\n"
+ " %3 = zext i8 %b to i32\n"
+ " %A = select i1 %1, i32 %2, i32 %3\n"
+ " ret i32 %A\n"
+ "}\n");
+ // We should be able to look through the situation where we cast both operands
+ // to the select.
+ expectPattern({SPF_UMIN, SPNB_NA, false});
+}
+
+TEST_F(MatchSelectPatternTest, DoubleCastS) {
+ parseAssembly(
+ "define i32 @test(i8 %a, i8 %b) {\n"
+ " %1 = icmp slt i8 %a, %b\n"
+ " %2 = sext i8 %a to i32\n"
+ " %3 = sext i8 %b to i32\n"
+ " %A = select i1 %1, i32 %2, i32 %3\n"
+ " ret i32 %A\n"
+ "}\n");
+ // We should be able to look through the situation where we cast both operands
+ // to the select.
+ expectPattern({SPF_SMIN, SPNB_NA, false});
+}
+
+TEST_F(MatchSelectPatternTest, DoubleCastBad) {
+ parseAssembly(
+ "define i32 @test(i8 %a, i8 %b) {\n"
+ " %1 = icmp ult i8 %a, %b\n"
+ " %2 = zext i8 %a to i32\n"
+ " %3 = sext i8 %b to i32\n"
+ " %A = select i1 %1, i32 %2, i32 %3\n"
+ " ret i32 %A\n"
+ "}\n");
+ // We should be able to look through the situation where we cast both operands
+ // to the select.
+ expectPattern({SPF_UNKNOWN, SPNB_NA, false});
+}
OpenPOWER on IntegriCloud