Skip to content

Commit c9ced05

Browse files
authored
Merge pull request #10113 from swiftlang/egorzhdan/20240723-workaround-gvn-pt2
🍒[cxx-interop] Workaround a template instantiation issue, part 2
2 parents a3e32cd + dbd2f41 commit c9ced05

File tree

2 files changed

+138
-136
lines changed
  • llvm
    • include/llvm/Transforms/Scalar
    • lib/Transforms/Scalar

2 files changed

+138
-136
lines changed

llvm/include/llvm/Transforms/Scalar/GVN.h

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/ADT/SmallVector.h"
2222
#include "llvm/IR/Dominators.h"
2323
#include "llvm/IR/InstrTypes.h"
24+
#include "llvm/IR/IntrinsicInst.h"
2425
#include "llvm/IR/PassManager.h"
2526
#include "llvm/IR/ValueHandle.h"
2627
#include "llvm/Support/Allocator.h"
@@ -432,4 +433,141 @@ struct llvm::GVNPass::Expression {
432433
}
433434
};
434435

436+
437+
/// Represents a particular available value that we know how to materialize.
438+
/// Materialization of an AvailableValue never fails. An AvailableValue is
439+
/// implicitly associated with a rematerialization point which is the
440+
/// location of the instruction from which it was formed.
441+
struct llvm::gvn::AvailableValue {
442+
enum class ValType {
443+
SimpleVal, // A simple offsetted value that is accessed.
444+
LoadVal, // A value produced by a load.
445+
MemIntrin, // A memory intrinsic which is loaded from.
446+
UndefVal, // A UndefValue representing a value from dead block (which
447+
// is not yet physically removed from the CFG).
448+
SelectVal, // A pointer select which is loaded from and for which the load
449+
// can be replace by a value select.
450+
};
451+
452+
/// Val - The value that is live out of the block.
453+
Value *Val;
454+
/// Kind of the live-out value.
455+
ValType Kind;
456+
457+
/// Offset - The byte offset in Val that is interesting for the load query.
458+
unsigned Offset = 0;
459+
/// V1, V2 - The dominating non-clobbered values of SelectVal.
460+
Value *V1 = nullptr, *V2 = nullptr;
461+
462+
static AvailableValue get(Value *V, unsigned Offset = 0) {
463+
AvailableValue Res;
464+
Res.Val = V;
465+
Res.Kind = ValType::SimpleVal;
466+
Res.Offset = Offset;
467+
return Res;
468+
}
469+
470+
static AvailableValue getMI(MemIntrinsic *MI, unsigned Offset = 0) {
471+
AvailableValue Res;
472+
Res.Val = MI;
473+
Res.Kind = ValType::MemIntrin;
474+
Res.Offset = Offset;
475+
return Res;
476+
}
477+
478+
static AvailableValue getLoad(LoadInst *Load, unsigned Offset = 0) {
479+
AvailableValue Res;
480+
Res.Val = Load;
481+
Res.Kind = ValType::LoadVal;
482+
Res.Offset = Offset;
483+
return Res;
484+
}
485+
486+
static AvailableValue getUndef() {
487+
AvailableValue Res;
488+
Res.Val = nullptr;
489+
Res.Kind = ValType::UndefVal;
490+
Res.Offset = 0;
491+
return Res;
492+
}
493+
494+
static AvailableValue getSelect(SelectInst *Sel, Value *V1, Value *V2) {
495+
AvailableValue Res;
496+
Res.Val = Sel;
497+
Res.Kind = ValType::SelectVal;
498+
Res.Offset = 0;
499+
Res.V1 = V1;
500+
Res.V2 = V2;
501+
return Res;
502+
}
503+
504+
bool isSimpleValue() const { return Kind == ValType::SimpleVal; }
505+
bool isCoercedLoadValue() const { return Kind == ValType::LoadVal; }
506+
bool isMemIntrinValue() const { return Kind == ValType::MemIntrin; }
507+
bool isUndefValue() const { return Kind == ValType::UndefVal; }
508+
bool isSelectValue() const { return Kind == ValType::SelectVal; }
509+
510+
Value *getSimpleValue() const {
511+
assert(isSimpleValue() && "Wrong accessor");
512+
return Val;
513+
}
514+
515+
LoadInst *getCoercedLoadValue() const {
516+
assert(isCoercedLoadValue() && "Wrong accessor");
517+
return cast<LoadInst>(Val);
518+
}
519+
520+
MemIntrinsic *getMemIntrinValue() const {
521+
assert(isMemIntrinValue() && "Wrong accessor");
522+
return cast<MemIntrinsic>(Val);
523+
}
524+
525+
SelectInst *getSelectValue() const {
526+
assert(isSelectValue() && "Wrong accessor");
527+
return cast<SelectInst>(Val);
528+
}
529+
530+
/// Emit code at the specified insertion point to adjust the value defined
531+
/// here to the specified type. This handles various coercion cases.
532+
Value *MaterializeAdjustedValue(LoadInst *Load, Instruction *InsertPt,
533+
GVNPass &gvn) const;
534+
};
535+
536+
/// Represents an AvailableValue which can be rematerialized at the end of
537+
/// the associated BasicBlock.
538+
struct llvm::gvn::AvailableValueInBlock {
539+
/// BB - The basic block in question.
540+
BasicBlock *BB = nullptr;
541+
542+
/// AV - The actual available value
543+
AvailableValue AV;
544+
545+
static AvailableValueInBlock get(BasicBlock *BB, AvailableValue &&AV) {
546+
AvailableValueInBlock Res;
547+
Res.BB = BB;
548+
Res.AV = std::move(AV);
549+
return Res;
550+
}
551+
552+
static AvailableValueInBlock get(BasicBlock *BB, Value *V,
553+
unsigned Offset = 0) {
554+
return get(BB, AvailableValue::get(V, Offset));
555+
}
556+
557+
static AvailableValueInBlock getUndef(BasicBlock *BB) {
558+
return get(BB, AvailableValue::getUndef());
559+
}
560+
561+
static AvailableValueInBlock getSelect(BasicBlock *BB, SelectInst *Sel,
562+
Value *V1, Value *V2) {
563+
return get(BB, AvailableValue::getSelect(Sel, V1, V2));
564+
}
565+
566+
/// Emit code at the end of this block to adjust the value defined here to
567+
/// the specified type. This handles various coercion cases.
568+
Value *MaterializeAdjustedValue(LoadInst *Load, GVNPass &gvn) const {
569+
return AV.MaterializeAdjustedValue(Load, BB->getTerminator(), gvn);
570+
}
571+
};
572+
435573
#endif // LLVM_TRANSFORMS_SCALAR_GVN_H

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 0 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -155,142 +155,6 @@ template <> struct DenseMapInfo<GVNPass::Expression> {
155155

156156
} // end namespace llvm
157157

158-
/// Represents a particular available value that we know how to materialize.
159-
/// Materialization of an AvailableValue never fails. An AvailableValue is
160-
/// implicitly associated with a rematerialization point which is the
161-
/// location of the instruction from which it was formed.
162-
struct llvm::gvn::AvailableValue {
163-
enum class ValType {
164-
SimpleVal, // A simple offsetted value that is accessed.
165-
LoadVal, // A value produced by a load.
166-
MemIntrin, // A memory intrinsic which is loaded from.
167-
UndefVal, // A UndefValue representing a value from dead block (which
168-
// is not yet physically removed from the CFG).
169-
SelectVal, // A pointer select which is loaded from and for which the load
170-
// can be replace by a value select.
171-
};
172-
173-
/// Val - The value that is live out of the block.
174-
Value *Val;
175-
/// Kind of the live-out value.
176-
ValType Kind;
177-
178-
/// Offset - The byte offset in Val that is interesting for the load query.
179-
unsigned Offset = 0;
180-
/// V1, V2 - The dominating non-clobbered values of SelectVal.
181-
Value *V1 = nullptr, *V2 = nullptr;
182-
183-
static AvailableValue get(Value *V, unsigned Offset = 0) {
184-
AvailableValue Res;
185-
Res.Val = V;
186-
Res.Kind = ValType::SimpleVal;
187-
Res.Offset = Offset;
188-
return Res;
189-
}
190-
191-
static AvailableValue getMI(MemIntrinsic *MI, unsigned Offset = 0) {
192-
AvailableValue Res;
193-
Res.Val = MI;
194-
Res.Kind = ValType::MemIntrin;
195-
Res.Offset = Offset;
196-
return Res;
197-
}
198-
199-
static AvailableValue getLoad(LoadInst *Load, unsigned Offset = 0) {
200-
AvailableValue Res;
201-
Res.Val = Load;
202-
Res.Kind = ValType::LoadVal;
203-
Res.Offset = Offset;
204-
return Res;
205-
}
206-
207-
static AvailableValue getUndef() {
208-
AvailableValue Res;
209-
Res.Val = nullptr;
210-
Res.Kind = ValType::UndefVal;
211-
Res.Offset = 0;
212-
return Res;
213-
}
214-
215-
static AvailableValue getSelect(SelectInst *Sel, Value *V1, Value *V2) {
216-
AvailableValue Res;
217-
Res.Val = Sel;
218-
Res.Kind = ValType::SelectVal;
219-
Res.Offset = 0;
220-
Res.V1 = V1;
221-
Res.V2 = V2;
222-
return Res;
223-
}
224-
225-
bool isSimpleValue() const { return Kind == ValType::SimpleVal; }
226-
bool isCoercedLoadValue() const { return Kind == ValType::LoadVal; }
227-
bool isMemIntrinValue() const { return Kind == ValType::MemIntrin; }
228-
bool isUndefValue() const { return Kind == ValType::UndefVal; }
229-
bool isSelectValue() const { return Kind == ValType::SelectVal; }
230-
231-
Value *getSimpleValue() const {
232-
assert(isSimpleValue() && "Wrong accessor");
233-
return Val;
234-
}
235-
236-
LoadInst *getCoercedLoadValue() const {
237-
assert(isCoercedLoadValue() && "Wrong accessor");
238-
return cast<LoadInst>(Val);
239-
}
240-
241-
MemIntrinsic *getMemIntrinValue() const {
242-
assert(isMemIntrinValue() && "Wrong accessor");
243-
return cast<MemIntrinsic>(Val);
244-
}
245-
246-
SelectInst *getSelectValue() const {
247-
assert(isSelectValue() && "Wrong accessor");
248-
return cast<SelectInst>(Val);
249-
}
250-
251-
/// Emit code at the specified insertion point to adjust the value defined
252-
/// here to the specified type. This handles various coercion cases.
253-
Value *MaterializeAdjustedValue(LoadInst *Load, Instruction *InsertPt,
254-
GVNPass &gvn) const;
255-
};
256-
257-
/// Represents an AvailableValue which can be rematerialized at the end of
258-
/// the associated BasicBlock.
259-
struct llvm::gvn::AvailableValueInBlock {
260-
/// BB - The basic block in question.
261-
BasicBlock *BB = nullptr;
262-
263-
/// AV - The actual available value
264-
AvailableValue AV;
265-
266-
static AvailableValueInBlock get(BasicBlock *BB, AvailableValue &&AV) {
267-
AvailableValueInBlock Res;
268-
Res.BB = BB;
269-
Res.AV = std::move(AV);
270-
return Res;
271-
}
272-
273-
static AvailableValueInBlock get(BasicBlock *BB, Value *V,
274-
unsigned Offset = 0) {
275-
return get(BB, AvailableValue::get(V, Offset));
276-
}
277-
278-
static AvailableValueInBlock getUndef(BasicBlock *BB) {
279-
return get(BB, AvailableValue::getUndef());
280-
}
281-
282-
static AvailableValueInBlock getSelect(BasicBlock *BB, SelectInst *Sel,
283-
Value *V1, Value *V2) {
284-
return get(BB, AvailableValue::getSelect(Sel, V1, V2));
285-
}
286-
287-
/// Emit code at the end of this block to adjust the value defined here to
288-
/// the specified type. This handles various coercion cases.
289-
Value *MaterializeAdjustedValue(LoadInst *Load, GVNPass &gvn) const {
290-
return AV.MaterializeAdjustedValue(Load, BB->getTerminator(), gvn);
291-
}
292-
};
293-
294158
//===----------------------------------------------------------------------===//
295159
// ValueTable Internal Functions
296160
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)