mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-02 07:32:52 +00:00
Implement PR3266 & PR5276, folding:
not (or (icmp, icmp)) -> and(icmp, icmp) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85085 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1125f58efc
commit
863928fc39
@ -631,9 +631,32 @@ static inline Value *dyn_castFNegVal(Value *V) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Value *dyn_castNotVal(Value *V) {
|
/// isFreeToInvert - Return true if the specified value is free to invert (apply
|
||||||
|
/// ~ to). This happens in cases where the ~ can be eliminated.
|
||||||
|
static inline bool isFreeToInvert(Value *V) {
|
||||||
|
// ~(~(X)) -> X.
|
||||||
if (BinaryOperator::isNot(V))
|
if (BinaryOperator::isNot(V))
|
||||||
return BinaryOperator::getNotArgument(V);
|
return true;
|
||||||
|
|
||||||
|
// Constants can be considered to be not'ed values.
|
||||||
|
if (isa<ConstantInt>(V))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Compares can be inverted if they have a single use.
|
||||||
|
if (CmpInst *CI = dyn_cast<CmpInst>(V))
|
||||||
|
return CI->hasOneUse();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Value *dyn_castNotVal(Value *V) {
|
||||||
|
// If this is not(not(x)) don't return that this is a not: we want the two
|
||||||
|
// not's to be folded first.
|
||||||
|
if (BinaryOperator::isNot(V)) {
|
||||||
|
Value *Operand = BinaryOperator::getNotArgument(V);
|
||||||
|
if (!isFreeToInvert(Operand))
|
||||||
|
return Operand;
|
||||||
|
}
|
||||||
|
|
||||||
// Constants can be considered to be not'ed values...
|
// Constants can be considered to be not'ed values...
|
||||||
if (ConstantInt *C = dyn_cast<ConstantInt>(V))
|
if (ConstantInt *C = dyn_cast<ConstantInt>(V))
|
||||||
@ -641,6 +664,8 @@ static inline Value *dyn_castNotVal(Value *V) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// dyn_castFoldableMul - If this value is a multiply that can be folded into
|
// dyn_castFoldableMul - If this value is a multiply that can be folded into
|
||||||
// other computations (because it has a constant operand), return the
|
// other computations (because it has a constant operand), return the
|
||||||
// non-constant operand of the multiply, and set CST to point to the multiplier.
|
// non-constant operand of the multiply, and set CST to point to the multiplier.
|
||||||
@ -4166,7 +4191,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
|||||||
if (Instruction *CastOp = dyn_cast<Instruction>(CI->getOperand(0))) {
|
if (Instruction *CastOp = dyn_cast<Instruction>(CI->getOperand(0))) {
|
||||||
if ((isa<TruncInst>(CI) || isa<BitCastInst>(CI)) &&
|
if ((isa<TruncInst>(CI) || isa<BitCastInst>(CI)) &&
|
||||||
CastOp->getNumOperands() == 2)
|
CastOp->getNumOperands() == 2)
|
||||||
if (ConstantInt *AndCI = dyn_cast<ConstantInt>(CastOp->getOperand(1))) {
|
if (ConstantInt *AndCI =dyn_cast<ConstantInt>(CastOp->getOperand(1))){
|
||||||
if (CastOp->getOpcode() == Instruction::And) {
|
if (CastOp->getOpcode() == Instruction::And) {
|
||||||
// Change: and (cast (and X, C1) to T), C2
|
// Change: and (cast (and X, C1) to T), C2
|
||||||
// into : and (cast X to T), trunc_or_bitcast(C1)&C2
|
// into : and (cast X to T), trunc_or_bitcast(C1)&C2
|
||||||
@ -5064,12 +5089,13 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
|||||||
|
|
||||||
// Is this a ~ operation?
|
// Is this a ~ operation?
|
||||||
if (Value *NotOp = dyn_castNotVal(&I)) {
|
if (Value *NotOp = dyn_castNotVal(&I)) {
|
||||||
// ~(~X & Y) --> (X | ~Y) - De Morgan's Law
|
|
||||||
// ~(~X | Y) === (X & ~Y) - De Morgan's Law
|
|
||||||
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(NotOp)) {
|
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(NotOp)) {
|
||||||
if (Op0I->getOpcode() == Instruction::And ||
|
if (Op0I->getOpcode() == Instruction::And ||
|
||||||
Op0I->getOpcode() == Instruction::Or) {
|
Op0I->getOpcode() == Instruction::Or) {
|
||||||
if (dyn_castNotVal(Op0I->getOperand(1))) Op0I->swapOperands();
|
// ~(~X & Y) --> (X | ~Y) - De Morgan's Law
|
||||||
|
// ~(~X | Y) === (X & ~Y) - De Morgan's Law
|
||||||
|
if (dyn_castNotVal(Op0I->getOperand(1)))
|
||||||
|
Op0I->swapOperands();
|
||||||
if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) {
|
if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) {
|
||||||
Value *NotY =
|
Value *NotY =
|
||||||
Builder->CreateNot(Op0I->getOperand(1),
|
Builder->CreateNot(Op0I->getOperand(1),
|
||||||
@ -5078,6 +5104,19 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
|||||||
return BinaryOperator::CreateOr(Op0NotVal, NotY);
|
return BinaryOperator::CreateOr(Op0NotVal, NotY);
|
||||||
return BinaryOperator::CreateAnd(Op0NotVal, NotY);
|
return BinaryOperator::CreateAnd(Op0NotVal, NotY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ~(X & Y) --> (~X | ~Y) - De Morgan's Law
|
||||||
|
// ~(X | Y) === (~X & ~Y) - De Morgan's Law
|
||||||
|
if (isFreeToInvert(Op0I->getOperand(0)) &&
|
||||||
|
isFreeToInvert(Op0I->getOperand(1))) {
|
||||||
|
Value *NotX =
|
||||||
|
Builder->CreateNot(Op0I->getOperand(0), "notlhs");
|
||||||
|
Value *NotY =
|
||||||
|
Builder->CreateNot(Op0I->getOperand(1), "notrhs");
|
||||||
|
if (Op0I->getOpcode() == Instruction::And)
|
||||||
|
return BinaryOperator::CreateOr(NotX, NotY);
|
||||||
|
return BinaryOperator::CreateAnd(NotX, NotY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,4 +237,19 @@ define i1 @test24(double %X, double %Y) {
|
|||||||
; CHECK: @test24
|
; CHECK: @test24
|
||||||
; CHECK: %bothcond = fcmp uno double %Y, %X ; <i1> [#uses=1]
|
; CHECK: %bothcond = fcmp uno double %Y, %X ; <i1> [#uses=1]
|
||||||
; CHECK: ret i1 %bothcond
|
; CHECK: ret i1 %bothcond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; PR3266 & PR5276
|
||||||
|
define i1 @test25(i32 %A, i32 %B) {
|
||||||
|
%C = icmp eq i32 %A, 0
|
||||||
|
%D = icmp eq i32 %B, 57
|
||||||
|
%E = or i1 %C, %D
|
||||||
|
%F = xor i1 %E, -1
|
||||||
|
ret i1 %F
|
||||||
|
|
||||||
|
; CHECK: @test25
|
||||||
|
; CHECK: icmp ne i32 %A, 0
|
||||||
|
; CHECK-NEXT: icmp ne i32 %B, 57
|
||||||
|
; CHECK-NEXT: %F = and i1
|
||||||
|
; CHECK-NEXT: ret i1 %F
|
||||||
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
; RUN: opt < %s -instcombine -S | not grep {= or}
|
|
||||||
; PR3266
|
|
||||||
; XFAIL: *
|
|
||||||
|
|
||||||
define i1 @foo(i32 %x, i32 %y) nounwind {
|
|
||||||
.summary:
|
|
||||||
%0 = icmp sgt i32 %x, 4 ; <i1> [#uses=1]
|
|
||||||
%1 = icmp sgt i32 %y, 0 ; <i1> [#uses=1]
|
|
||||||
%.demorgan = or i1 %1, %0 ; <i1> [#uses=1]
|
|
||||||
%2 = xor i1 %.demorgan, true ; <i1> [#uses=1]
|
|
||||||
ret i1 %2
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user