Skip to content

Commit 7677453

Browse files
authored
[ConstantFolding] Do not consider padded-in-memory types as uniform (llvm#81854)
Teaching ConstantFoldLoadFromUniformValue that types that are padded in memory can't be considered as uniform. Using the big hammer to prevent optimizations when loading from a constant for which DataLayout::typeSizeEqualsStoreSize would return false. Main problem solved would be something like this: store i17 -1, ptr %p, align 4 %v = load i8, ptr %p, align 1 If for example the i17 occupies 32 bits in memory, then LLVM IR doesn't really tell where the padding goes. And even if we assume that the 15 most significant bits are padding, then they should be considered as undefined (even if LLVM backend typically would pad with zeroes). Anyway, for a big-endian target the load would read those most significant bits, which aren't guaranteed to be one's. So it would be wrong to constant fold the load as returning -1. If LLVM IR had been more explicit about the placement of padding, then we could allow the constant fold of the load in the example, but only for little-endian. Fixes: llvm#81793
1 parent 8416586 commit 7677453

File tree

6 files changed

+51
-12
lines changed

6 files changed

+51
-12
lines changed

llvm/include/llvm/Analysis/ConstantFolding.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ Constant *ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty,
174174
/// ones, all undef or all poison), return the corresponding uniform value in
175175
/// the new type. If the value is not uniform or the result cannot be
176176
/// represented, return null.
177-
Constant *ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty);
177+
Constant *ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty,
178+
const DataLayout &DL);
178179

179180
/// canConstantFoldCallTo - Return true if its even possible to fold a call to
180181
/// the specified function.

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
106106
"Invalid constantexpr bitcast!");
107107

108108
// Catch the obvious splat cases.
109-
if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy))
109+
if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy, DL))
110110
return Res;
111111

112112
if (auto *VTy = dyn_cast<VectorType>(C->getType())) {
@@ -342,7 +342,7 @@ bool llvm::IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV,
342342
}
343343

344344
Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
345-
const DataLayout &DL) {
345+
const DataLayout &DL) {
346346
do {
347347
Type *SrcTy = C->getType();
348348
if (SrcTy == DestTy)
@@ -355,7 +355,7 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
355355

356356
// Catch the obvious splat cases (since all-zeros can coerce non-integral
357357
// pointers legally).
358-
if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy))
358+
if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy, DL))
359359
return Res;
360360

361361
// If the type sizes are the same and a cast is legal, just directly
@@ -709,7 +709,7 @@ Constant *llvm::ConstantFoldLoadFromConst(Constant *C, Type *Ty,
709709
return PoisonValue::get(Ty);
710710

711711
// Try an offset-independent fold of a uniform value.
712-
if (Constant *Result = ConstantFoldLoadFromUniformValue(C, Ty))
712+
if (Constant *Result = ConstantFoldLoadFromUniformValue(C, Ty, DL))
713713
return Result;
714714

715715
// Try hard to fold loads from bitcasted strange and non-type-safe things.
@@ -745,7 +745,7 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty,
745745

746746
// If this load comes from anywhere in a uniform constant global, the value
747747
// is always the same, regardless of the loaded offset.
748-
return ConstantFoldLoadFromUniformValue(GV->getInitializer(), Ty);
748+
return ConstantFoldLoadFromUniformValue(GV->getInitializer(), Ty, DL);
749749
}
750750

751751
Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty,
@@ -754,11 +754,16 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty,
754754
return ConstantFoldLoadFromConstPtr(C, Ty, Offset, DL);
755755
}
756756

757-
Constant *llvm::ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty) {
757+
Constant *llvm::ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty,
758+
const DataLayout &DL) {
758759
if (isa<PoisonValue>(C))
759760
return PoisonValue::get(Ty);
760761
if (isa<UndefValue>(C))
761762
return UndefValue::get(Ty);
763+
// If padding is needed when storing C to memory, then it isn't considered as
764+
// uniform.
765+
if (!DL.typeSizeEqualsStoreSize(C->getType()))
766+
return nullptr;
762767
if (C->isNullValue() && !Ty->isX86_MMXTy() && !Ty->isX86_AMXTy())
763768
return Constant::getNullValue(Ty);
764769
if (C->isAllOnesValue() &&

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6960,8 +6960,8 @@ Value *llvm::simplifyLoadInst(LoadInst *LI, Value *PtrOp,
69606960

69616961
// If GlobalVariable's initializer is uniform, then return the constant
69626962
// regardless of its offset.
6963-
if (Constant *C =
6964-
ConstantFoldLoadFromUniformValue(GV->getInitializer(), LI->getType()))
6963+
if (Constant *C = ConstantFoldLoadFromUniformValue(GV->getInitializer(),
6964+
LI->getType(), Q.DL))
69656965
return C;
69666966

69676967
// Try to convert operand into a constant by stripping offsets while looking

llvm/lib/Transforms/IPO/Attributor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ AA::getInitialValueForObj(Attributor &A, const AbstractAttribute &QueryingAA,
275275
return ConstantFoldLoadFromConst(Initializer, &Ty, Offset, DL);
276276
}
277277

278-
return ConstantFoldLoadFromUniformValue(Initializer, &Ty);
278+
return ConstantFoldLoadFromUniformValue(Initializer, &Ty, DL);
279279
}
280280

281281
bool AA::isValidInScope(const Value &V, const Function *Scope) {

llvm/lib/Transforms/IPO/GlobalOpt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV,
296296
// A load from a uniform value is always the same, regardless of any
297297
// applied offset.
298298
Type *Ty = LI->getType();
299-
if (Constant *Res = ConstantFoldLoadFromUniformValue(Init, Ty)) {
299+
if (Constant *Res = ConstantFoldLoadFromUniformValue(Init, Ty, DL)) {
300300
LI->replaceAllUsesWith(Res);
301301
EraseFromParent(LI);
302302
continue;

llvm/test/Transforms/InstSimplify/ConstProp/loads.ll

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,12 +407,45 @@ define ptr addrspace(2) @load_non_integral_ptr_from_i8_data() {
407407

408408
define i8 @load_i8_from_i1() {
409409
; CHECK-LABEL: @load_i8_from_i1(
410-
; CHECK-NEXT: ret i8 -1
410+
; CHECK-NEXT: [[V:%.*]] = load i8, ptr @g_i1, align 1
411+
; CHECK-NEXT: ret i8 [[V]]
411412
;
412413
%v = load i8, ptr @g_i1
413414
ret i8 %v
414415
}
415416

417+
@global9 = internal constant i9 -1
418+
419+
; Reproducer for https://github.com/llvm/llvm-project/issues/81793
420+
define i8 @load_i8_from_i9() {
421+
; CHECK-LABEL: @load_i8_from_i9(
422+
; CHECK-NEXT: [[V:%.*]] = load i8, ptr @global9, align 1
423+
; CHECK-NEXT: ret i8 [[V]]
424+
;
425+
%v = load i8, ptr @global9
426+
ret i8 %v
427+
}
428+
429+
define i9 @load_i9_from_i9() {
430+
; CHECK-LABEL: @load_i9_from_i9(
431+
; CHECK-NEXT: ret i9 -1
432+
;
433+
%v = load i9, ptr @global9
434+
ret i9 %v
435+
}
436+
437+
; Reproducer for https://github.com/llvm/llvm-project/issues/81793
438+
define i16 @load_i16_from_i17_store(ptr %p) {
439+
; CHECK-LABEL: @load_i16_from_i17_store(
440+
; CHECK-NEXT: store i17 -1, ptr [[P:%.*]], align 4
441+
; CHECK-NEXT: [[V:%.*]] = load i16, ptr @global9, align 2
442+
; CHECK-NEXT: ret i16 [[V]]
443+
;
444+
store i17 -1, ptr %p
445+
%v = load i16, ptr @global9
446+
ret i16 %v
447+
}
448+
416449
@global128 = internal constant i128 1125899906842625
417450
define i128 @load-128bit(){
418451
; CHECK-LABEL: @load-128bit(

0 commit comments

Comments
 (0)