Skip to content

Commit 3ad4ccc

Browse files
committed
[FuncComp]
1 parent 0d3ba08 commit 3ad4ccc

File tree

4 files changed

+106
-38
lines changed

4 files changed

+106
-38
lines changed

llvm/include/llvm/Transforms/Utils/FunctionComparator.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,9 @@ class FunctionComparator {
328328
int cmpOrderings(AtomicOrdering L, AtomicOrdering R) const;
329329
int cmpInlineAsm(const InlineAsm *L, const InlineAsm *R) const;
330330
int cmpAttrs(const AttributeList L, const AttributeList R) const;
331-
int cmpMDNode(const MDNode *L, const MDNode *R) const;
332-
int cmpMetadata(const Metadata *L, const Metadata *R) const;
331+
int cmpMDNode(const MDNode *L, const MDNode *R, bool InValueContext) const;
332+
int cmpMetadata(const Metadata *L, const Metadata *R,
333+
bool InValueContext) const;
333334
int cmpInstMetadata(Instruction const *L, Instruction const *R) const;
334335
int cmpOperandBundlesSchema(const CallBase &LCS, const CallBase &RCS) const;
335336

llvm/lib/IR/Verifier.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3543,6 +3543,31 @@ void Verifier::visitPHINode(PHINode &PN) {
35433543
visitInstruction(PN);
35443544
}
35453545

3546+
/// Returns true of \p MD is valid for as a metadata argument. It must be on of
3547+
/// the following
3548+
/// * a MDNode without cycles (expect self-reference in the first operand),
3549+
/// * MDString,
3550+
/// * ValueAsMetadata.
3551+
static bool isValidMetadataArgument(const Metadata *MD,
3552+
SmallPtrSetImpl<const Metadata *> &Seen) {
3553+
// Potential cycles are not allowed.
3554+
if (!Seen.insert(MD).second)
3555+
return false;
3556+
3557+
if (auto *Node = dyn_cast<MDNode>(MD)) {
3558+
if (Node->getNumOperands() == 0)
3559+
return true;
3560+
ArrayRef<MDOperand> Ops = Node->operands();
3561+
if (Node->getOperand(0) == Node)
3562+
Ops = Ops.drop_front();
3563+
return all_of(Ops, [&](const Metadata *MD) {
3564+
return MD && isValidMetadataArgument(MD, Seen);
3565+
});
3566+
}
3567+
3568+
return isa<MDString>(MD) || isa<ValueAsMetadata>(MD);
3569+
}
3570+
35463571
void Verifier::visitCallBase(CallBase &Call) {
35473572
Check(Call.getCalledOperand()->getType()->isPointerTy(),
35483573
"Called function must be a pointer!", Call);
@@ -3562,6 +3587,19 @@ void Verifier::visitCallBase(CallBase &Call) {
35623587
"Call parameter type does not match function signature!",
35633588
Call.getArgOperand(i), FTy->getParamType(i), Call);
35643589

3590+
// Verify metadata arguments.
3591+
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) {
3592+
auto Arg = Call.getArgOperand(i);
3593+
if (!Arg->getType()->isMetadataTy() || isa<DbgInfoIntrinsic>(Call))
3594+
continue;
3595+
SmallPtrSet<const Metadata *, 4> Seen;
3596+
Check(isValidMetadataArgument(cast<MetadataAsValue>(Arg)->getMetadata(),
3597+
Seen),
3598+
"Function arguments must be string metadata, value-as-metadata or an "
3599+
"MDNode!",
3600+
Call);
3601+
}
3602+
35653603
AttributeList Attrs = Call.getAttributes();
35663604

35673605
Check(verifyAttributeCount(Attrs, Call.arg_size()),

llvm/lib/Transforms/Utils/FunctionComparator.cpp

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -185,38 +185,53 @@ int FunctionComparator::cmpAttrs(const AttributeList L,
185185
return 0;
186186
}
187187

188-
int FunctionComparator::cmpMetadata(const Metadata *L,
189-
const Metadata *R) const {
188+
int FunctionComparator::cmpMetadata(const Metadata *L, const Metadata *R,
189+
bool InValueContext) const {
190190
// TODO: the following routine coerce the metadata contents into constants
191191
// or MDStrings before comparison.
192192
// It ignores any other cases, so that the metadata nodes are considered
193193
// equal even though this is not correct.
194194
// We should structurally compare the metadata nodes to be perfect here.
195195

196+
if (L == R)
197+
return 0;
198+
196199
auto *MDStringL = dyn_cast<MDString>(L);
197200
auto *MDStringR = dyn_cast<MDString>(R);
198-
if (MDStringL && MDStringR) {
199-
if (MDStringL == MDStringR)
200-
return 0;
201+
if (MDStringL && MDStringR)
201202
return MDStringL->getString().compare(MDStringR->getString());
202-
}
203203
if (MDStringR)
204204
return -1;
205205
if (MDStringL)
206206
return 1;
207207

208208
auto *CL = dyn_cast<ConstantAsMetadata>(L);
209209
auto *CR = dyn_cast<ConstantAsMetadata>(R);
210-
if (CL == CR)
211-
return 0;
212-
if (!CL)
210+
if (CL && CR)
211+
return cmpConstants(CL->getValue(), CR->getValue());
212+
if (CR)
213213
return -1;
214-
if (!CR)
214+
if (CL)
215215
return 1;
216-
return cmpConstants(CL->getValue(), CR->getValue());
216+
217+
auto *NodeL = dyn_cast<MDNode>(L);
218+
auto *NodeR = dyn_cast<MDNode>(R);
219+
if (NodeL && NodeR) {
220+
if (InValueContext)
221+
return cmpMDNode(NodeL, NodeR, InValueContext);
222+
} else {
223+
if (NodeR)
224+
return -1;
225+
if (NodeL)
226+
return 1;
227+
}
228+
assert(!InValueContext &&
229+
"all cases must be handled when comparing metadata arguments");
230+
return 0;
217231
}
218232

219-
int FunctionComparator::cmpMDNode(const MDNode *L, const MDNode *R) const {
233+
int FunctionComparator::cmpMDNode(const MDNode *L, const MDNode *R,
234+
bool InValueContext) const {
220235
if (L == R)
221236
return 0;
222237
if (!L)
@@ -231,8 +246,20 @@ int FunctionComparator::cmpMDNode(const MDNode *L, const MDNode *R) const {
231246
// function semantically.
232247
if (int Res = cmpNumbers(L->getNumOperands(), R->getNumOperands()))
233248
return Res;
234-
for (size_t I = 0; I < L->getNumOperands(); ++I)
235-
if (int Res = cmpMetadata(L->getOperand(I), R->getOperand(I)))
249+
250+
size_t StartIdx = 0;
251+
if (L->getNumOperands() > 0) {
252+
if (L->getOperand(0) == L) {
253+
if (R->getOperand(0) != R)
254+
return -1;
255+
StartIdx = 1;
256+
} else if (R->getOperand(0) == R)
257+
return 1;
258+
}
259+
260+
for (size_t I = StartIdx; I < L->getNumOperands(); ++I)
261+
if (int Res =
262+
cmpMetadata(L->getOperand(I), R->getOperand(I), InValueContext))
236263
return Res;
237264
return 0;
238265
}
@@ -254,7 +281,7 @@ int FunctionComparator::cmpInstMetadata(Instruction const *L,
254281
auto const [KeyR, MR] = MDR[I];
255282
if (int Res = cmpNumbers(KeyL, KeyR))
256283
return Res;
257-
if (int Res = cmpMDNode(ML, MR))
284+
if (int Res = cmpMDNode(ML, MR, false))
258285
return Res;
259286
}
260287
return 0;
@@ -722,7 +749,7 @@ int FunctionComparator::cmpOperations(const Instruction *L,
722749
cast<CallInst>(R)->getTailCallKind()))
723750
return Res;
724751
return cmpMDNode(L->getMetadata(LLVMContext::MD_range),
725-
R->getMetadata(LLVMContext::MD_range));
752+
R->getMetadata(LLVMContext::MD_range), false);
726753
}
727754
if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(L)) {
728755
ArrayRef<unsigned> LIndices = IVI->getIndices();
@@ -899,7 +926,7 @@ int FunctionComparator::cmpValues(const Value *L, const Value *R) const {
899926
return 0;
900927

901928
return cmpMetadata(MetadataValueL->getMetadata(),
902-
MetadataValueR->getMetadata());
929+
MetadataValueR->getMetadata(), true);
903930
}
904931

905932
if (MetadataValueL)

llvm/test/Transforms/MergeFunc/metadata-call-arguments.ll

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,48 +55,50 @@ declare i64 @llvm.read_volatile_register.i64(metadata)
5555

5656
!5 = !{!"foo", i64 10}
5757
!6 = !{!"foo", i64 10}
58+
; CHECK-LABEL: define i64 @call_mdtuple_arg_not_equal_1() {
59+
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META0:![0-9]+]])
60+
; CHECK-NEXT: ret i64 [[TMP1]]
61+
;
62+
;
63+
; CHECK-LABEL: define i64 @call_mdtuple_arg_not_equal_2() {
64+
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META1:![0-9]+]])
65+
; CHECK-NEXT: ret i64 [[TMP1]]
66+
;
67+
;
5868
; CHECK-LABEL: define i64 @call_mdtuple_arg_with_cycle_equal_1() {
59-
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META0:![0-9]+]])
69+
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META2:![0-9]+]])
6070
; CHECK-NEXT: ret i64 [[R]]
6171
;
6272
;
6373
; CHECK-LABEL: define i64 @call_mdtuple_arg_with_cycle_equal_2() {
64-
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META1:![0-9]+]])
74+
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META3:![0-9]+]])
6575
; CHECK-NEXT: ret i64 [[R]]
6676
;
6777
;
6878
; CHECK-LABEL: define i64 @call_mdtuple_arg_with_cycle_not_equal_1() {
69-
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META1]])
79+
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META3]])
7080
; CHECK-NEXT: ret i64 [[R]]
7181
;
7282
;
7383
; CHECK-LABEL: define i64 @call_mdtuple_arg_with_cycle_not_equal_2() {
74-
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META2:![0-9]+]])
84+
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META4:![0-9]+]])
7585
; CHECK-NEXT: ret i64 [[R]]
7686
;
7787
;
7888
; CHECK-LABEL: define i64 @call_mdtuple_arg_equal_1() {
79-
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META3:![0-9]+]])
89+
; CHECK-NEXT: [[R:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[META5:![0-9]+]])
8090
; CHECK-NEXT: ret i64 [[R]]
8191
;
8292
;
83-
; CHECK-LABEL: define i64 @call_mdtuple_arg_not_equal_2() {
84-
; CHECK-NEXT: [[TMP1:%.*]] = tail call i64 @call_mdtuple_arg_equal_1()
85-
; CHECK-NEXT: ret i64 [[TMP1]]
86-
;
87-
;
88-
; CHECK-LABEL: define i64 @call_mdtuple_arg_not_equal_1() {
89-
; CHECK-NEXT: [[TMP1:%.*]] = tail call i64 @call_mdtuple_arg_equal_1()
90-
; CHECK-NEXT: ret i64 [[TMP1]]
91-
;
92-
;
9393
; CHECK-LABEL: define i64 @call_mdtuple_arg_equal_2() {
9494
; CHECK-NEXT: [[TMP1:%.*]] = tail call i64 @call_mdtuple_arg_equal_1()
9595
; CHECK-NEXT: ret i64 [[TMP1]]
9696
;
9797
;.
98-
; CHECK: [[META0]] = distinct !{[[META0]], !"foo"}
99-
; CHECK: [[META1]] = distinct !{[[META1]], !"foo"}
100-
; CHECK: [[META2]] = distinct !{[[META2]], !"bar"}
101-
; CHECK: [[META3]] = !{!"foo", i64 10}
98+
; CHECK: [[META0]] = !{!"foo"}
99+
; CHECK: [[META1]] = !{!"bar"}
100+
; CHECK: [[META2]] = distinct !{[[META2]], !"foo"}
101+
; CHECK: [[META3]] = distinct !{[[META3]], !"foo"}
102+
; CHECK: [[META4]] = distinct !{[[META4]], !"bar"}
103+
; CHECK: [[META5]] = !{!"foo", i64 10}
102104
;.

0 commit comments

Comments
 (0)