Skip to content

Commit 70472f3

Browse files
committed
[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
1 parent f099330 commit 70472f3

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

llvm/lib/Transforms/Scalar/Reassociate.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,24 @@ static Value *NegateValue(Value *V, Instruction *BI,
920920
return NewNeg;
921921
}
922922

923+
/// If we have (X|Y), and iff X and Y have no common bits set,
924+
/// transform this into (X+Y) to allow arithmetics reassociation.
925+
static BinaryOperator *ConvertOrWithNoCommonBitsToAdd(Instruction *Or) {
926+
// Convert an or into an add.
927+
BinaryOperator *New =
928+
CreateAdd(Or->getOperand(0), Or->getOperand(1), "", Or, Or);
929+
New->setHasNoSignedWrap();
930+
New->setHasNoUnsignedWrap();
931+
New->takeName(Or);
932+
933+
// Everyone now refers to the add instruction.
934+
Or->replaceAllUsesWith(New);
935+
New->setDebugLoc(Or->getDebugLoc());
936+
937+
LLVM_DEBUG(dbgs() << "Converted or into an add: " << *New << '\n');
938+
return New;
939+
}
940+
923941
/// Return true if we should break up this subtract of X-Y into (X + -Y).
924942
static bool ShouldBreakUpSubtract(Instruction *Sub) {
925943
// If this is a negation, we can't split it up!
@@ -2116,6 +2134,18 @@ void ReassociatePass::OptimizeInst(Instruction *I) {
21162134
if (I->getType()->isIntegerTy(1))
21172135
return;
21182136

2137+
// If this is a bitwise or instruction of operands
2138+
// with no common bits set, convert it to X+Y.
2139+
if (I->getOpcode() == Instruction::Or &&
2140+
haveNoCommonBitsSet(I->getOperand(0), I->getOperand(1),
2141+
I->getModule()->getDataLayout(), /*AC=*/nullptr, I,
2142+
/*DT=*/nullptr)) {
2143+
Instruction *NI = ConvertOrWithNoCommonBitsToAdd(I);
2144+
RedoInsts.insert(I);
2145+
MadeChange = true;
2146+
I = NI;
2147+
}
2148+
21192149
// If this is a subtract instruction which is not already in negate form,
21202150
// see if we can convert it to X+-Y.
21212151
if (I->getOpcode() == Instruction::Sub) {

llvm/test/Transforms/Reassociate/add-like-or.ll

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ define i32 @test1(i32 %a, i32 %b) {
1717
define i32 @test2(i32 %x) {
1818
; CHECK-LABEL: @test2(
1919
; CHECK-NEXT: [[X_NUMLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true), [[RNG0:!range !.*]]
20-
; CHECK-NEXT: [[RES:%.*]] = or i32 [[X_NUMLZ]], -32
20+
; CHECK-NEXT: [[RES:%.*]] = add nuw nsw i32 [[X_NUMLZ]], -32
2121
; CHECK-NEXT: ret i32 [[RES]]
2222
;
2323
%x.numlz = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true), !range !0
@@ -29,9 +29,8 @@ define i32 @test2(i32 %x) {
2929
define i32 @test3(i32 %x, i32 %bit) {
3030
; CHECK-LABEL: @test3(
3131
; CHECK-NEXT: [[X_NUMLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true), [[RNG0]]
32-
; CHECK-NEXT: [[ZERO_MINUS_X_NUMACTIVEBITS:%.*]] = or i32 [[X_NUMLZ]], -32
33-
; CHECK-NEXT: [[BIT_PLUS_ONE:%.*]] = add i32 [[BIT:%.*]], 1
34-
; CHECK-NEXT: [[RES:%.*]] = add i32 [[BIT_PLUS_ONE]], [[ZERO_MINUS_X_NUMACTIVEBITS]]
32+
; CHECK-NEXT: [[BIT_PLUS_ONE:%.*]] = add i32 [[BIT:%.*]], -31
33+
; CHECK-NEXT: [[RES:%.*]] = add i32 [[BIT_PLUS_ONE]], [[X_NUMLZ]]
3534
; CHECK-NEXT: ret i32 [[RES]]
3635
;
3736
%x.numlz = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true), !range !0

0 commit comments

Comments
 (0)