Skip to content

Commit 36d382b

Browse files
committed
[InstCombine] Fold ((C1-zext(X)) & C2) -> zext((C1-X) & C2)
This is valid if C2 fits within the bitwidth of X thanks to two's complement modulo arithmetic. llvm-svn: 292179
1 parent c8cc2be commit 36d382b

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,21 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
13311331
if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, true, I))
13321332
return BinaryOperator::CreateAnd(V, AndRHS);
13331333

1334+
// ((C1-zext(X)) & C2) -> zext((C1-X) & C2) if C2 fits in the bitwidth
1335+
// of X.
1336+
if (auto *ZI = dyn_cast<ZExtInst>(Op0RHS)) {
1337+
auto *X = ZI->getOperand(0);
1338+
ConstantInt *C1;
1339+
if (match(Op0LHS, m_ConstantInt(C1)) &&
1340+
AndRHSMask.isIntN(X->getType()->getScalarSizeInBits())) {
1341+
auto *TruncC1 = ConstantExpr::getTrunc(C1, X->getType());
1342+
auto *Sub = Builder->CreateSub(TruncC1, X);
1343+
auto *TruncC2 = ConstantExpr::getTrunc(AndRHS, X->getType());
1344+
auto *And = Builder->CreateAnd(Sub, TruncC2);
1345+
return new ZExtInst(And, I.getType());
1346+
}
1347+
}
1348+
13341349
// -x & 1 -> x & 1
13351350
if (AndRHSMask == 1 && match(Op0LHS, m_Zero()))
13361351
return BinaryOperator::CreateAnd(Op0RHS, AndRHS);

llvm/test/Transforms/InstCombine/and.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,3 +425,14 @@ define <2 x i32> @PR24942(<2 x i32> %x) {
425425
ret <2 x i32> %and
426426
}
427427

428+
define i64 @test35(i32 %X) {
429+
; CHECK-LABEL: @test35(
430+
; CHECK-NEXT: %[[sub:.*]] = sub i32 0, %X
431+
; CHECK-NEXT: %[[and:.*]] = and i32 %[[sub]], 240
432+
; CHECK-NEXT: %[[cst:.*]] = zext i32 %[[and]] to i64
433+
; CHECK-NEXT: ret i64 %[[cst]]
434+
%zext = zext i32 %X to i64
435+
%zsub = sub i64 0, %zext
436+
%res = and i64 %zsub, 240
437+
ret i64 %res
438+
}

0 commit comments

Comments
 (0)