[Reassociate] Convert `add`-like `or`'s into an `add`'s to allow reassociation

InstCombine is quite aggressive in doing the opposite transform,
folding `add` of operands with no common bits set into an `or`,
and that not many things support that new pattern..

In this case, teaching Reassociate about it is easy,
there's preexisting art for `sub`/`shl`:
just convert such an `or` into an `add`:
https://rise4fun.com/Alive/Xlyv
This commit is contained in:
Roman Lebedev 2020-11-03 22:01:22 +03:00
parent f099330094
commit 70472f34b2
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
2 changed files with 33 additions and 4 deletions

View File

@ -920,6 +920,24 @@ static Value *NegateValue(Value *V, Instruction *BI,
return NewNeg;
}
/// If we have (X|Y), and iff X and Y have no common bits set,
/// transform this into (X+Y) to allow arithmetics reassociation.
static BinaryOperator *ConvertOrWithNoCommonBitsToAdd(Instruction *Or) {
// Convert an or into an add.
BinaryOperator *New =
CreateAdd(Or->getOperand(0), Or->getOperand(1), "", Or, Or);
New->setHasNoSignedWrap();
New->setHasNoUnsignedWrap();
New->takeName(Or);
// Everyone now refers to the add instruction.
Or->replaceAllUsesWith(New);
New->setDebugLoc(Or->getDebugLoc());
LLVM_DEBUG(dbgs() << "Converted or into an add: " << *New << '\n');
return New;
}
/// Return true if we should break up this subtract of X-Y into (X + -Y).
static bool ShouldBreakUpSubtract(Instruction *Sub) {
// If this is a negation, we can't split it up!
@ -2116,6 +2134,18 @@ void ReassociatePass::OptimizeInst(Instruction *I) {
if (I->getType()->isIntegerTy(1))
return;
// If this is a bitwise or instruction of operands
// with no common bits set, convert it to X+Y.
if (I->getOpcode() == Instruction::Or &&
haveNoCommonBitsSet(I->getOperand(0), I->getOperand(1),
I->getModule()->getDataLayout(), /*AC=*/nullptr, I,
/*DT=*/nullptr)) {
Instruction *NI = ConvertOrWithNoCommonBitsToAdd(I);
RedoInsts.insert(I);
MadeChange = true;
I = NI;
}
// If this is a subtract instruction which is not already in negate form,
// see if we can convert it to X+-Y.
if (I->getOpcode() == Instruction::Sub) {

View File

@ -17,7 +17,7 @@ define i32 @test1(i32 %a, i32 %b) {
define i32 @test2(i32 %x) {
; CHECK-LABEL: @test2(
; CHECK-NEXT: [[X_NUMLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true), [[RNG0:!range !.*]]
; CHECK-NEXT: [[RES:%.*]] = or i32 [[X_NUMLZ]], -32
; CHECK-NEXT: [[RES:%.*]] = add nuw nsw i32 [[X_NUMLZ]], -32
; CHECK-NEXT: ret i32 [[RES]]
;
%x.numlz = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true), !range !0
@ -29,9 +29,8 @@ define i32 @test2(i32 %x) {
define i32 @test3(i32 %x, i32 %bit) {
; CHECK-LABEL: @test3(
; CHECK-NEXT: [[X_NUMLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true), [[RNG0]]
; CHECK-NEXT: [[ZERO_MINUS_X_NUMACTIVEBITS:%.*]] = or i32 [[X_NUMLZ]], -32
; CHECK-NEXT: [[BIT_PLUS_ONE:%.*]] = add i32 [[BIT:%.*]], 1
; CHECK-NEXT: [[RES:%.*]] = add i32 [[BIT_PLUS_ONE]], [[ZERO_MINUS_X_NUMACTIVEBITS]]
; CHECK-NEXT: [[BIT_PLUS_ONE:%.*]] = add i32 [[BIT:%.*]], -31
; CHECK-NEXT: [[RES:%.*]] = add i32 [[BIT_PLUS_ONE]], [[X_NUMLZ]]
; CHECK-NEXT: ret i32 [[RES]]
;
%x.numlz = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true), !range !0