diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 1d24535156e863..e4920c351ccafb 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -708,7 +708,8 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, // is all undef or zero, we know what it loads. if (auto *GV = dyn_cast(getUnderlyingObject(C))) { if (GV->isConstant() && GV->hasDefinitiveInitializer()) { - if (GV->getInitializer()->isNullValue()) + if (GV->getInitializer()->isNullValue() && !Ty->isX86_MMXTy() && + !Ty->isX86_AMXTy()) return Constant::getNullValue(Ty); if (isa(GV->getInitializer())) return UndefValue::get(Ty); diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index c3aab6122726f7..b1f3ff15c97b2f 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -305,8 +305,9 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV, else if (auto *LI = dyn_cast(U)) { // A load from zeroinitializer is always zeroinitializer, regardless of // any applied offset. - if (Init->isNullValue()) { - LI->replaceAllUsesWith(Constant::getNullValue(LI->getType())); + Type *Ty = LI->getType(); + if (Init->isNullValue() && !Ty->isX86_MMXTy() && !Ty->isX86_AMXTy()) { + LI->replaceAllUsesWith(Constant::getNullValue(Ty)); EraseFromParent(LI); continue; } @@ -316,8 +317,7 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV, PtrOp = PtrOp->stripAndAccumulateConstantOffsets( DL, Offset, /* AllowNonInbounds */ true); if (PtrOp == GV) { - if (auto *Value = ConstantFoldLoadFromConst(Init, LI->getType(), - Offset, DL)) { + if (auto *Value = ConstantFoldLoadFromConst(Init, Ty, Offset, DL)) { LI->replaceAllUsesWith(Value); EraseFromParent(LI); } diff --git a/llvm/test/Transforms/GlobalOpt/x86_mmx_load.ll b/llvm/test/Transforms/GlobalOpt/x86_mmx_load.ll new file mode 100644 index 00000000000000..3b1fa8cd73f612 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/x86_mmx_load.ll @@ -0,0 +1,12 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -globalopt < %s | FileCheck %s + +@m64 = internal global <1 x i64> zeroinitializer + +define i32 @load_mmx() { +; CHECK-LABEL: @load_mmx( +; CHECK-NEXT: ret i32 0 +; + %temp = load x86_mmx, x86_mmx* bitcast (<1 x i64>* @m64 to x86_mmx*) + ret i32 0 +} diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll b/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll index 0938078dc47bae..a825ff66377fae 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll @@ -280,3 +280,16 @@ define { i64, i64 } @test_load_struct() { %v = load { i64, i64 }, { i64, i64 }* @g3 ret { i64, i64 } %v } + +@m64 = internal constant [2 x i64] zeroinitializer +@idx = external global i32 + +; This should not try to create an x86_mmx null value. +define x86_mmx @load_mmx() { +; CHECK-LABEL: @load_mmx( +; CHECK-NEXT: [[TEMP:%.*]] = load x86_mmx, x86_mmx* bitcast (i64* getelementptr ([2 x i64], [2 x i64]* @m64, i64 0, i64 ptrtoint (i32* @idx to i64)) to x86_mmx*), align 8 +; CHECK-NEXT: ret x86_mmx [[TEMP]] +; + %temp = load x86_mmx, x86_mmx* bitcast (i64* getelementptr ([2 x i64], [2 x i64]* @m64, i64 0, i64 ptrtoint (i32* @idx to i64)) to x86_mmx*) + ret x86_mmx %temp +}