Index: llvm/include/llvm/Transforms/InstCombine/InstCombiner.h =================================================================== --- llvm/include/llvm/Transforms/InstCombine/InstCombiner.h +++ llvm/include/llvm/Transforms/InstCombine/InstCombiner.h @@ -43,6 +43,7 @@ /// This class provides both the logic to recursively visit instructions and /// combine them. class LLVM_LIBRARY_VISIBILITY InstCombiner { +protected: /// Only used to call target specific inst combining. TargetTransformInfo &TTI; Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -18,6 +18,7 @@ #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CmpInstAnalysis.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constant.h" @@ -311,6 +312,14 @@ return nullptr; } + // If both cast instructions are free, don't merge them. + auto Opcode = TI->getOpcode(); + if (TTI.getCastInstrCost(Opcode, TI->getType(), FIOpndTy, + TTI.getCastContextHint(TI)) == 0 && + TTI.getCastInstrCost(Opcode, FI->getType(), FIOpndTy, + TTI.getCastContextHint(FI)) == 0) + return nullptr; + // Fold this by inserting a select from the input values. Value *NewSI = Builder.CreateSelect(Cond, TI->getOperand(0), FI->getOperand(0), Index: llvm/test/Transforms/InstCombine/select-ext.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/InstCombine/select-ext.ll @@ -0,0 +1,22 @@ +; RUN: opt -instcombine -mtriple=x86_64-unknown-unknown -S < %s | FileCheck %s + +; If zext has 0 cost, it should not be moved after select. + +; CHECK-LABEL: @foo +; CHECK: [[LD1:%.*]] = load volatile i8, i8* [[PTR1:%.*]] +; CHECK: [[CONV1:%.*]] = zext i8 [[LD1]] to i64 +; CHECK: [[LD2:%.*]] = load volatile i8, i8* [[PTR2:%.*]] +; CHECK: [[CONV2:%.*]] = zext i8 [[LD2]] to i64 +; CHECK: [[RESULT:%.*]] = select i1 [[COND:%.*]], i64 [[CONV2]], i64 [[CONV1]] +; CHECK: ret i64 [[RESULT]] + +define i64 @foo(i8* %p, i1 zeroext %c) { + %ld1 = load volatile i8, i8* %p + %conv = zext i8 %ld1 to i64 + %arrayidx1 = getelementptr inbounds i8, i8* %p, i64 1 + %ld2 = load volatile i8, i8* %arrayidx1 + %conv2 = zext i8 %ld2 to i64 + %cond = select i1 %c, i64 %conv2, i64 %conv + ret i64 %cond +} +