Index: include/llvm/Analysis/TargetTransformInfoImpl.h =================================================================== --- include/llvm/Analysis/TargetTransformInfoImpl.h +++ include/llvm/Analysis/TargetTransformInfoImpl.h @@ -807,15 +807,9 @@ return static_cast(this)->getCallCost(F, Arguments); } - if (const CastInst *CI = dyn_cast(U)) { - // Result of a cmp instruction is often extended (to be used by other - // cmp instructions, logical or return instructions). These are usually - // nop on most sane targets. - if (isa(CI->getOperand(0))) - return TTI::TCC_Free; - if (isa(CI) || isa(CI) || isa(CI)) - return static_cast(this)->getExtCost(CI, Operands.back()); - } + if (isa(U) || isa(U) || isa(U)) + return static_cast(this)->getExtCost(cast(U), + Operands.back()); return static_cast(this)->getOperationCost( Operator::getOpcode(U), U->getType(), Index: test/Analysis/CostModel/SystemZ/getUserCost_ext_i1.ll =================================================================== --- /dev/null +++ test/Analysis/CostModel/SystemZ/getUserCost_ext_i1.ll @@ -0,0 +1,95 @@ +; RUN: opt < %s -mtriple=s390x-unknown-linux -mcpu=z13 -o - -loop-unroll \ +; RUN: -debug-only=loop-unroll 2>&1 | FileCheck %s +; REQUIRES: asserts +; +; Check that getUserCost() does not return TCC_Free (0 cost) for extensions +; of i1. This function is called by CodeMetrics and seems to be a poor-mans +; alternative to the methods CostModel is using. There is no direct way of +; testing the costs for the instructions, but one way is to make a small loop +; and run loop-unroller and see what the loop size is. +; +; Phis are free, but the other instructions in for.body are not. Test that +; extensions of i1 is counted as 1 (and not 0) by checking that the sum is 5. + +; CHECK: fun0 +; CHECK: Loop Size = 5 +; CHECK: fun1 +; CHECK: Loop Size = 5 +; CHECK: fun2 +; CHECK: Loop Size = 5 +; CHECK: fun3 +; CHECK: Loop Size = 5 + +define i64 @fun0(i64 %n, i32 %v) { +entry: + %cmp0 = icmp slt i32 %v, 0 + br label %for.body + +for.body: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] + %S = phi i64 [ 0, %entry], [ %a, %for.body ] + %conv = zext i1 %cmp0 to i64 + %a = add i64 %S, %conv + %iv.next = add nuw nsw i64 %iv, 1 + %cmp = icmp slt i64 %iv.next, %n + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret i64 %S +} + +define i64 @fun1(i64 %n, i32 %v) { +entry: + %cmp0 = icmp slt i32 %v, 0 + br label %for.body + +for.body: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] + %S = phi i64 [ 0, %entry], [ %a, %for.body ] + %conv = sext i1 %cmp0 to i64 + %a = add i64 %S, %conv + %iv.next = add nuw nsw i64 %iv, 1 + %cmp = icmp slt i64 %iv.next, %n + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret i64 %S +} + +define double @fun2(i64 %n, i32 %v) { +entry: + %cmp0 = icmp slt i32 %v, 0 + br label %for.body + +for.body: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] + %S = phi double [ 0.0, %entry], [ %fpadd, %for.body ] + %conv = uitofp i1 %cmp0 to double + %fpadd = fadd double %S, %conv + %iv.next = add nuw nsw i64 %iv, 1 + %cmp = icmp slt i64 %iv.next, %n + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret double %S +} + +define double @fun3(i64 %n, i32 %v) { +entry: + %cmp0 = icmp slt i32 %v, 0 + br label %for.body + +for.body: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] + %S = phi double [ 0.0, %entry], [ %fpadd, %for.body ] + %conv = sitofp i1 %cmp0 to double + %fpadd = fadd double %S, %conv + %iv.next = add nuw nsw i64 %iv, 1 + %cmp = icmp slt i64 %iv.next, %n + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret double %S +} + +