forked from OSchip/llvm-project
[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:
parent
f099330094
commit
70472f34b2
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue