@@ -2098,18 +2098,6 @@ ValueCategory MLIRScanner::VisitBinAssign(BinaryOperator *E) {
2098
2098
return RHS;
2099
2099
}
2100
2100
2101
- static bool isSigned (QualType Ty) {
2102
- // TODO note assumptions made here about unsigned / unordered
2103
- bool SignedType = true ;
2104
- if (const auto *Bit = dyn_cast<clang::BuiltinType>(Ty)) {
2105
- if (Bit->isUnsignedInteger ())
2106
- SignedType = false ;
2107
- if (Bit->isSignedInteger ())
2108
- SignedType = true ;
2109
- }
2110
- return SignedType;
2111
- }
2112
-
2113
2101
class BinOpInfo {
2114
2102
public:
2115
2103
BinOpInfo (ValueCategory LHS, ValueCategory RHS, QualType Ty,
@@ -2577,39 +2565,62 @@ static void informNoOverflowCheck(LangOptions::SignedOverflowBehaviorTy SOB,
2577
2565
}
2578
2566
2579
2567
ValueCategory MLIRScanner::EmitBinMul (const BinOpInfo &Info) {
2580
- auto LHSVal = Info.getLHS ().getValue (Builder);
2581
- auto RHSVal = Info.getRHS ().getValue (Builder);
2582
- if (LHSVal.getType ().isa <mlir::FloatType>())
2583
- return ValueCategory (Builder.create <arith::MulFOp>(Loc, LHSVal, RHSVal),
2584
- /* isReference*/ false );
2585
- return ValueCategory (Builder.create <arith::MulIOp>(Loc, LHSVal, RHSVal),
2586
- /* isReference*/ false );
2568
+ const auto Loc = getMLIRLocation (Info.getExpr ()->getExprLoc ());
2569
+ const auto LHS = Info.getLHS ();
2570
+ const auto RHS = Info.getRHS ().val ;
2571
+
2572
+ if (Info.getType ()->isSignedIntegerOrEnumerationType ()) {
2573
+ informNoOverflowCheck (
2574
+ Glob.getCGM ().getLangOpts ().getSignedOverflowBehavior (), " mul" );
2575
+ return LHS.Mul (Builder, Loc, RHS);
2576
+ }
2577
+
2578
+ assert (!Info.getType ()->isConstantMatrixType () && " Not yet implemented" );
2579
+
2580
+ if (mlirclang::isFPOrFPVectorTy (LHS.val .getType ()))
2581
+ return LHS.FMul (Builder, Loc, RHS);
2582
+ return LHS.Mul (Builder, Loc, RHS);
2587
2583
}
2588
2584
2589
2585
ValueCategory MLIRScanner::EmitBinDiv (const BinOpInfo &Info) {
2590
- auto LHSVal = Info.getLHS ().getValue (Builder);
2591
- auto RHSVal = Info.getRHS ().getValue (Builder);
2592
- if (LHSVal.getType ().isa <mlir::FloatType>())
2593
- return ValueCategory (Builder.create <arith::DivFOp>(Loc, LHSVal, RHSVal),
2594
- /* isReference*/ false );
2595
- if (isSigned (Info.getType ()))
2596
- return ValueCategory (Builder.create <arith::DivSIOp>(Loc, LHSVal, RHSVal),
2597
- /* isReference*/ false );
2598
- return ValueCategory (Builder.create <arith::DivUIOp>(Loc, LHSVal, RHSVal),
2599
- /* isReference*/ false );
2586
+ mlirclang::warning ()
2587
+ << " Not checking division by zero nor signed integer overflow.\n " ;
2588
+
2589
+ assert (!Info.getType ()->isConstantMatrixType () && " Not implemented" );
2590
+
2591
+ const auto Loc = getMLIRLocation (Info.getExpr ()->getExprLoc ());
2592
+ const auto LHS = Info.getLHS ();
2593
+ const auto RHS = Info.getRHS ().val ;
2594
+ if (mlirclang::isFPOrFPVectorTy (LHS.val .getType ())) {
2595
+ const auto &LangOpts = Glob.getCGM ().getLangOpts ();
2596
+ const auto &CodeGenOpts = Glob.getCGM ().getCodeGenOpts ();
2597
+ if ((LangOpts.OpenCL && !CodeGenOpts.OpenCLCorrectlyRoundedDivSqrt ) ||
2598
+ (LangOpts.HIP && LangOpts.CUDAIsDevice &&
2599
+ !CodeGenOpts.HIPCorrectlyRoundedDivSqrt )) {
2600
+ // OpenCL v1.1 s7.4: minimum accuracy of single precision / is 2.5ulp
2601
+ // OpenCL v1.2 s5.6.4.2: The -cl-fp32-correctly-rounded-divide-sqrt
2602
+ // build option allows an application to specify that single precision
2603
+ // floating-point divide (x/y and 1/x) and sqrt used in the program
2604
+ // source are correctly rounded.
2605
+ mlirclang::warning () << " Not applying OpenCL/HIP precision options.\n " ;
2606
+ }
2607
+ return LHS.FDiv (Builder, Loc, RHS);
2608
+ }
2609
+ if (Info.getType ()->hasUnsignedIntegerRepresentation ())
2610
+ return LHS.UDiv (Builder, Loc, RHS);
2611
+ return LHS.SDiv (Builder, Loc, RHS);
2600
2612
}
2601
2613
2602
2614
ValueCategory MLIRScanner::EmitBinRem (const BinOpInfo &Info) {
2603
- auto LHSVal = Info.getLHS ().getValue (Builder);
2604
- auto RHSVal = Info.getRHS ().getValue (Builder);
2605
- if (LHSVal.getType ().isa <mlir::FloatType>())
2606
- return ValueCategory (Builder.create <arith::RemFOp>(Loc, LHSVal, RHSVal),
2607
- /* isReference*/ false );
2608
- if (isSigned (Info.getType ()))
2609
- return ValueCategory (Builder.create <arith::RemSIOp>(Loc, LHSVal, RHSVal),
2610
- /* isReference*/ false );
2611
- return ValueCategory (Builder.create <arith::RemUIOp>(Loc, LHSVal, RHSVal),
2612
- /* isReference*/ false );
2615
+ mlirclang::warning ()
2616
+ << " Not checking division by zero nor signed integer overflow.\n " ;
2617
+
2618
+ const auto Loc = getMLIRLocation (Info.getExpr ()->getExprLoc ());
2619
+ const auto LHS = Info.getLHS ();
2620
+ const auto RHS = Info.getRHS ().val ;
2621
+ if (Info.getType ()->hasUnsignedIntegerRepresentation ())
2622
+ return LHS.URem (Builder, Loc, RHS);
2623
+ return LHS.SRem (Builder, Loc, RHS);
2613
2624
}
2614
2625
2615
2626
// / Casts index of subindex operation conditionally.
@@ -2821,57 +2832,102 @@ ValueCategory MLIRScanner::EmitBinSub(const BinOpInfo &Info) {
2821
2832
return DiffInChars.ExactSDiv (Builder, Loc, Divisor);
2822
2833
}
2823
2834
2835
+ static mlir::Value GetWidthMinusOneValue (mlir::OpBuilder &Builder,
2836
+ mlir::Location Loc, mlir::Value LHS,
2837
+ mlir::Value RHS) {
2838
+ auto Ty = LHS.getType ();
2839
+ IntegerType IntTy;
2840
+ if (auto VT = Ty.dyn_cast <mlir::VectorType>())
2841
+ IntTy = VT.getElementType ().cast <IntegerType>();
2842
+ else
2843
+ IntTy = Ty.cast <IntegerType>();
2844
+
2845
+ const auto WidthMinusOne = IntTy.getWidth () - 1 ;
2846
+ ValueCategory Val{
2847
+ Builder.createOrFold <arith::ConstantIntOp>(Loc, WidthMinusOne, IntTy),
2848
+ false };
2849
+ if (auto VT = Ty.dyn_cast <mlir::VectorType>())
2850
+ Val = Val.Splat (Builder, Loc, VT);
2851
+ return Val.val ;
2852
+ }
2853
+
2854
+ ValueCategory MLIRScanner::ConstrainShiftValue (ValueCategory LHS,
2855
+ ValueCategory RHS) {
2856
+ IntegerType Ty;
2857
+ if (auto VT = LHS.val .getType ().dyn_cast <mlir::VectorType>())
2858
+ Ty = VT.getElementType ().cast <IntegerType>();
2859
+ else
2860
+ Ty = LHS.val .getType ().cast <IntegerType>();
2861
+
2862
+ if (llvm::isPowerOf2_64 (Ty.getWidth ()))
2863
+ return RHS.And (Builder, Loc,
2864
+ GetWidthMinusOneValue (Builder, Loc, LHS.val , RHS.val ));
2865
+ return RHS.URem (Builder, Loc,
2866
+ Builder.createOrFold <arith::ConstantIntOp>(
2867
+ Loc, Ty.getWidth (), RHS.val .getType ()));
2868
+ }
2869
+
2824
2870
ValueCategory MLIRScanner::EmitBinShl (const BinOpInfo &Info) {
2825
- auto LHSVal = Info.getLHS ().getValue (Builder);
2826
- auto RHSVal = Info.getRHS ().getValue (Builder);
2827
- auto PrevTy = RHSVal.getType ().cast <mlir::IntegerType>();
2828
- auto PostTy = LHSVal.getType ().cast <mlir::IntegerType>();
2829
- if (PrevTy.getWidth () < PostTy.getWidth ())
2830
- RHSVal = Builder.create <arith::ExtUIOp>(Loc, PostTy, RHSVal);
2831
- if (PrevTy.getWidth () > PostTy.getWidth ())
2832
- RHSVal = Builder.create <arith::TruncIOp>(Loc, PostTy, RHSVal);
2833
- assert (LHSVal.getType () == RHSVal.getType ());
2834
- return ValueCategory (Builder.create <arith::ShLIOp>(Loc, LHSVal, RHSVal),
2835
- /* isReference*/ false );
2871
+ const auto Loc = getMLIRLocation (Info.getExpr ()->getExprLoc ());
2872
+ auto LHS = Info.getLHS ();
2873
+ auto RHS = Info.getRHS ();
2874
+
2875
+ // LLVM requires the LHS and RHS to be the same type: promote or truncate the
2876
+ // RHS to the same size as the LHS.
2877
+ if (LHS.val .getType () != RHS.val .getType ())
2878
+ RHS = RHS.IntCast (Builder, Loc, LHS.val .getType (), /* IsSigned*/ false );
2879
+
2880
+ if (Glob.getCGM ().getLangOpts ().OpenCL ) {
2881
+ this ->Loc = Loc;
2882
+ RHS = ConstrainShiftValue (LHS, RHS);
2883
+ } else {
2884
+ mlirclang::warning () << " Not performing SHL checks\n " ;
2885
+ }
2886
+
2887
+ return LHS.Shl (Builder, Loc, RHS.val );
2836
2888
}
2837
2889
2838
2890
ValueCategory MLIRScanner::EmitBinShr (const BinOpInfo &Info) {
2839
- auto LHSVal = Info.getLHS ().getValue (Builder);
2840
- auto RHSVal = Info.getRHS ().getValue (Builder);
2841
- auto PrevTy = RHSVal.getType ().cast <mlir::IntegerType>();
2842
- auto PostTy = LHSVal.getType ().cast <mlir::IntegerType>();
2843
- if (PrevTy.getWidth () < PostTy.getWidth ())
2844
- RHSVal = Builder.create <mlir::arith::ExtUIOp>(Loc, PostTy, RHSVal);
2845
- if (PrevTy.getWidth () > PostTy.getWidth ())
2846
- RHSVal = Builder.create <mlir::arith::TruncIOp>(Loc, PostTy, RHSVal);
2847
- assert (LHSVal.getType () == RHSVal.getType ());
2848
- if (isSigned (Info.getExpr ()->getType ()))
2849
- return ValueCategory (Builder.create <arith::ShRSIOp>(Loc, LHSVal, RHSVal),
2850
- /* isReference*/ false );
2851
- return ValueCategory (Builder.create <arith::ShRUIOp>(Loc, LHSVal, RHSVal),
2852
- /* isReference*/ false );
2891
+ const auto Loc = getMLIRLocation (Info.getExpr ()->getExprLoc ());
2892
+ auto LHS = Info.getLHS ();
2893
+ auto RHS = Info.getRHS ();
2894
+
2895
+ // LLVM requires the LHS and RHS to be the same type: promote or truncate the
2896
+ // RHS to the same size as the LHS.
2897
+ if (LHS.val .getType () != RHS.val .getType ())
2898
+ RHS = RHS.IntCast (Builder, Loc, LHS.val .getType (), /* IsSigned*/ false );
2899
+
2900
+ if (Glob.getCGM ().getLangOpts ().OpenCL ) {
2901
+ this ->Loc = Loc;
2902
+ RHS = ConstrainShiftValue (LHS, RHS);
2903
+ } else {
2904
+ mlirclang::warning () << " Not performing SHL checks\n " ;
2905
+ }
2906
+
2907
+ if (Info.getType ()->hasUnsignedIntegerRepresentation ())
2908
+ return LHS.LShr (Builder, Loc, RHS.val );
2909
+ return LHS.AShr (Builder, Loc, RHS.val );
2853
2910
}
2854
2911
2855
2912
ValueCategory MLIRScanner::EmitBinAnd (const BinOpInfo &Info) {
2856
- return ValueCategory (
2857
- Builder. create <arith::AndIOp>(Loc, Info.getLHS (). getValue (Builder),
2858
- Info.getRHS (). getValue (Builder)),
2859
- /* isReference */ false );
2913
+ const auto Loc = getMLIRLocation (Info. getExpr ()-> getExprLoc ());
2914
+ auto LHS = Info.getLHS ();
2915
+ auto RHS = Info.getRHS ();
2916
+ return LHS. And (Builder, Loc, RHS. val );
2860
2917
}
2861
2918
2862
2919
ValueCategory MLIRScanner::EmitBinXor (const BinOpInfo &Info) {
2863
- return ValueCategory (
2864
- Builder. create <arith::XOrIOp>(Loc, Info.getLHS (). getValue (Builder),
2865
- Info.getRHS (). getValue (Builder)),
2866
- /* isReference */ false );
2920
+ const auto Loc = getMLIRLocation (Info. getExpr ()-> getExprLoc ());
2921
+ auto LHS = Info.getLHS ();
2922
+ auto RHS = Info.getRHS ();
2923
+ return LHS. Xor (Builder, Loc, RHS. val );
2867
2924
}
2868
2925
2869
2926
ValueCategory MLIRScanner::EmitBinOr (const BinOpInfo &Info) {
2870
- // TODO short circuit
2871
- return ValueCategory (
2872
- Builder.create <arith::OrIOp>(Loc, Info.getLHS ().getValue (Builder),
2873
- Info.getRHS ().getValue (Builder)),
2874
- /* isReference*/ false );
2927
+ const auto Loc = getMLIRLocation (Info.getExpr ()->getExprLoc ());
2928
+ auto LHS = Info.getLHS ();
2929
+ auto RHS = Info.getRHS ();
2930
+ return LHS.Or (Builder, Loc, RHS.val );
2875
2931
}
2876
2932
2877
2933
#define HANDLEUNARYOP (OP ) \
0 commit comments