Why should I know this?

SubclassOptionalData 본문

LLVM-STUDY

SubclassOptionalData

die4taoam 2023. 12. 11. 04:20

 

LLVM 에는 최적화를 위한 부가 데이터가 있다.

 

value.h

protected:
/// Hold subclass data that can be dropped.
///
/// This member is similar to SubclassData, however it is for holding
/// information which may be used to aid optimization, but which may be
/// cleared to zero without affecting conservative interpretation.
unsigned char SubclassOptionalData : 7;

SubClassOptionalData

 

 

or disjoint

 

disjoint는 or 최적화를 위한 부가정보를 담고 있다.

/// An or instruction, which can be marked as "disjoint", indicating that the
/// inputs don't have a 1 in the same bit position. Meaning this instruction
/// can also be treated as an add.
class PossiblyDisjointInst : public BinaryOperator {

 

주석의 설명과 같이 disjoint는 or의 두 인자가 서로 다른 비트로 구성되어 있는 경우에 세팅되게 된다.

 

최근에 disjoint 를 적용한 패치

https://github.com/llvm/llvm-project/pull/74467

 

[SCEV] Use or disjoint flag by nikic · Pull Request #74467 · llvm/llvm-project

Use the disjoint flag to convert or to add instead of calling the haveNoCommonBitsSet() ValueTracking query. This ensures that we can reliably undo add -> or canonicalization, even in cases where t...

github.com

 

패치 본문에 나오는 것처럼


case Instruction::Or: {
// Convert or disjoint into add nuw nsw.
if (cast<PossiblyDisjointInst>(Op)->isDisjoint())
return BinaryOp(Instruction::Add, Op->getOperand(0), Op->getOperand(1),
/*IsNSW=*/true, /*IsNUW=*/true);
return BinaryOp(Op);
}

 

or이 disjoint인 경우 Add 연산을 리턴하는 코드이다.

이전코드는 직접 비트를 검사했었다.

case Instruction::Or: {
// LLVM loves to convert `add` of operands with no common bits
// into an `or`. But SCEV really doesn't deal with `or` that well,
// so try extra hard to recognize this `or` as an `add`.
if (haveNoCommonBitsSet(Op->getOperand(0), Op->getOperand(1),
SimplifyQuery(DL, &DT, &AC, CxtI)))
return BinaryOp(Instruction::Add, Op->getOperand(0), Op->getOperand(1),
/*IsNSW=*/true, /*IsNUW=*/true);
return BinaryOp(Op);
}
 

 

disjoint 는 다음과 같이 세팅되거나

InstCombineSimplifyDemanded.cpp:267

// Infer disjoint flag if no common bits are set.
if (!cast<PossiblyDisjointInst>(I)->isDisjoint()) {
WithCache<const Value *> LHSCache(I->getOperand(0), LHSKnown),
RHSCache(I->getOperand(1), RHSKnown);
if (haveNoCommonBitsSet(LHSCache, RHSCache, SQ.getWithInstruction(I))) {
cast<PossiblyDisjointInst>(I)->setIsDisjoint(true);
return I;
}
}
 

 

다음처럼 최적화 과정에서 생성된다.

InstCombineSimplifyDemanded.cpp:311

// If all of the demanded bits are known to be zero on one side or the
// other, turn this into an *inclusive* or.
// e.g. (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0
if (DemandedMask.isSubsetOf(RHSKnown.Zero | LHSKnown.Zero)) {
Instruction *Or =
BinaryOperator::CreateOr(I->getOperand(0), I->getOperand(1));
if (DemandedMask.isAllOnes())
cast<PossiblyDisjointInst>(Or)->setIsDisjoint(true);
Or->takeName(I);
return InsertNewInstWith(Or, I->getIterator());
}

 

 

'LLVM-STUDY' 카테고리의 다른 글

LLVM 내부에서 활용되는 논리식 모음  (0) 2023.12.15
[TODO] DomConditionCache  (0) 2023.12.11
computeKnownBits & KnownBits 관련 예제  (0) 2023.12.05
byval  (0) 2023.11.07
LLVM Study 관련 팁  (0) 2023.10.25
Comments