diff --git a/llvm/include/llvm/Analysis/ConstantFolding.h b/llvm/include/llvm/Analysis/ConstantFolding.h index 1b194b07e8678..fd885a8c0ea3e 100644 --- a/llvm/include/llvm/Analysis/ConstantFolding.h +++ b/llvm/include/llvm/Analysis/ConstantFolding.h @@ -174,7 +174,8 @@ Constant *ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, /// ones, all undef or all poison), return the corresponding uniform value in /// the new type. If the value is not uniform or the result cannot be /// represented, return null. -Constant *ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty); +Constant *ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty, + const DataLayout &DL); /// canConstantFoldCallTo - Return true if its even possible to fold a call to /// the specified function. diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 90da3390eab32..8b7031e7fe4a6 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -106,7 +106,7 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) { "Invalid constantexpr bitcast!"); // Catch the obvious splat cases. - if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy)) + if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy, DL)) return Res; if (auto *VTy = dyn_cast(C->getType())) { @@ -342,7 +342,7 @@ bool llvm::IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, } Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, - const DataLayout &DL) { + const DataLayout &DL) { do { Type *SrcTy = C->getType(); if (SrcTy == DestTy) @@ -355,7 +355,7 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, // Catch the obvious splat cases (since all-zeros can coerce non-integral // pointers legally). - if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy)) + if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy, DL)) return Res; // 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, return PoisonValue::get(Ty); // Try an offset-independent fold of a uniform value. - if (Constant *Result = ConstantFoldLoadFromUniformValue(C, Ty)) + if (Constant *Result = ConstantFoldLoadFromUniformValue(C, Ty, DL)) return Result; // Try hard to fold loads from bitcasted strange and non-type-safe things. @@ -745,7 +745,7 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, // If this load comes from anywhere in a uniform constant global, the value // is always the same, regardless of the loaded offset. - return ConstantFoldLoadFromUniformValue(GV->getInitializer(), Ty); + return ConstantFoldLoadFromUniformValue(GV->getInitializer(), Ty, DL); } Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, @@ -754,11 +754,16 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, return ConstantFoldLoadFromConstPtr(C, Ty, Offset, DL); } -Constant *llvm::ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty) { +Constant *llvm::ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty, + const DataLayout &DL) { if (isa(C)) return PoisonValue::get(Ty); if (isa(C)) return UndefValue::get(Ty); + // If padding is needed when storing C to memory, then it isn't considered as + // uniform. + if (!DL.typeSizeEqualsStoreSize(C->getType())) + return nullptr; if (C->isNullValue() && !Ty->isX86_MMXTy() && !Ty->isX86_AMXTy()) return Constant::getNullValue(Ty); if (C->isAllOnesValue() && diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 08050becd2df8..201472a3f10c2 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -6960,8 +6960,8 @@ Value *llvm::simplifyLoadInst(LoadInst *LI, Value *PtrOp, // If GlobalVariable's initializer is uniform, then return the constant // regardless of its offset. - if (Constant *C = - ConstantFoldLoadFromUniformValue(GV->getInitializer(), LI->getType())) + if (Constant *C = ConstantFoldLoadFromUniformValue(GV->getInitializer(), + LI->getType(), Q.DL)) return C; // Try to convert operand into a constant by stripping offsets while looking diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 5d1a783b2996d..72a2aadc204ba 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -275,7 +275,7 @@ AA::getInitialValueForObj(Attributor &A, const AbstractAttribute &QueryingAA, return ConstantFoldLoadFromConst(Initializer, &Ty, Offset, DL); } - return ConstantFoldLoadFromUniformValue(Initializer, &Ty); + return ConstantFoldLoadFromUniformValue(Initializer, &Ty, DL); } bool AA::isValidInScope(const Value &V, const Function *Scope) { diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 42828b4f41680..c92b5d82fc85a 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -296,7 +296,7 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV, // A load from a uniform value is always the same, regardless of any // applied offset. Type *Ty = LI->getType(); - if (Constant *Res = ConstantFoldLoadFromUniformValue(Init, Ty)) { + if (Constant *Res = ConstantFoldLoadFromUniformValue(Init, Ty, DL)) { LI->replaceAllUsesWith(Res); EraseFromParent(LI); continue; diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll b/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll index 3bc301743a183..d4c49faf91b09 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll @@ -407,12 +407,45 @@ define ptr addrspace(2) @load_non_integral_ptr_from_i8_data() { define i8 @load_i8_from_i1() { ; CHECK-LABEL: @load_i8_from_i1( -; CHECK-NEXT: ret i8 -1 +; CHECK-NEXT: [[V:%.*]] = load i8, ptr @g_i1, align 1 +; CHECK-NEXT: ret i8 [[V]] ; %v = load i8, ptr @g_i1 ret i8 %v } +@global9 = internal constant i9 -1 + +; Reproducer for https://github.com/llvm/llvm-project/issues/81793 +define i8 @load_i8_from_i9() { +; CHECK-LABEL: @load_i8_from_i9( +; CHECK-NEXT: [[V:%.*]] = load i8, ptr @global9, align 1 +; CHECK-NEXT: ret i8 [[V]] +; + %v = load i8, ptr @global9 + ret i8 %v +} + +define i9 @load_i9_from_i9() { +; CHECK-LABEL: @load_i9_from_i9( +; CHECK-NEXT: ret i9 -1 +; + %v = load i9, ptr @global9 + ret i9 %v +} + +; Reproducer for https://github.com/llvm/llvm-project/issues/81793 +define i16 @load_i16_from_i17_store(ptr %p) { +; CHECK-LABEL: @load_i16_from_i17_store( +; CHECK-NEXT: store i17 -1, ptr [[P:%.*]], align 4 +; CHECK-NEXT: [[V:%.*]] = load i16, ptr @global9, align 2 +; CHECK-NEXT: ret i16 [[V]] +; + store i17 -1, ptr %p + %v = load i16, ptr @global9 + ret i16 %v +} + @global128 = internal constant i128 1125899906842625 define i128 @load-128bit(){ ; CHECK-LABEL: @load-128bit(